其他 – 永夜 https://www.shuijingwanwq.com 没有不值得去解决的问题,也没有不值得去学习的技术! Fri, 17 Apr 2026 04:11:15 +0000 zh-Hans hourly 1 https://wordpress.org/?v=7.0 中国国内(成都)办理护照的流程 https://www.shuijingwanwq.com/2026/04/17/9541/ https://www.shuijingwanwq.com/2026/04/17/9541/#respond Fri, 17 Apr 2026 04:10:28 +0000 https://www.shuijingwanwq.com/?p=9541 浏览量: 369

1、现在办的是哪种护照?办理的是:普通护照(因私护照)

2、办理方式(最推荐)
✅ 方式:线上预约 + 线下办理(主流)

3、第一步:预约,微信小程序:移民局12367,中国公民服务 – 现场办证预约 – 选择办理网点。如图1

第一步:预约,微信小程序:移民局12367,中国公民服务 - 现场办证预约 - 选择办理网点。

4、办证类型(多选) 普通护照 往来港澳通行证和签注 往来台湾通行证和签注,选择普通护照。如图2

办证类型(多选) 普通护照 往来港澳通行证和签注 往来台湾通行证和签注,选择普通护照。

5、前往地及出境事由(必选),出境事由 👉 旅游 ✔(最常用、最稳)前往地 👉 新加坡 / 马来西亚 / 泰国(任选一个)。如图3

前往地及出境事由(必选),出境事由 👉 旅游 ✔(最常用、最稳)前往地 👉 新加坡 / 马来西亚 / 泰国(任选一个)。

6、核对在线预约信息。如图4

核对在线预约信息。

7、在高新区出入境大厅,先排队领取 中国公民出入境证件申请表、成都高新区政务服务中心 排队号码。如图5

在高新区出入境大厅,先排队领取 中国公民出入境证件申请表、成都高新区政务服务中心 排队号码。
oplus_3145760

8、在窗口办理完毕后,领取 因私出境证件受理回执。我 4月1号 办理,发现要到 4月13号 才能够领取护照了,工本费 120 元人民币。如图6

在窗口办理完毕后,领取 因私出境证件受理回执。我 4月1号 办理,发现要到 4月13号 才能够领取护照了,工本费 120 元人民币。
oplus_3145760

9、在 4月15日,我去办理网点的一楼大厅的出入境自助领证机领取护照。只需要带上身份证就可以。如图7

在 4月15日,我去办理网点的一楼大厅的出入境自助领证机领取护照。只需要带上身份证就可以。

10、护照从出证口出来。护照样子如图8

护照从出证口出来。护照样子
]]>
https://www.shuijingwanwq.com/2026/04/17/9541/feed/ 0
开启智能锁(乐开、0key)的指纹功能的流程 https://www.shuijingwanwq.com/2024/10/14/8827/ https://www.shuijingwanwq.com/2024/10/14/8827/#respond Mon, 14 Oct 2024 07:40:34 +0000 https://www.shuijingwanwq.com/?p=8827 浏览量: 657

1、从物业处要到了设置指紋的流程图。如图1

从物业处要到了设置指纹的流程图

图1

2、但是 管理员 密码不清楚究竟是什么了。找到说明手册,发现也只有一个重置密码。如图2

但是 管理员 密码不清楚究竟是什么了。找到说明手册,发现也只有一个重置密码。

图2

3、从说明手册的登记密码中,终于找到了管理员密码的相关说明。出厂状态下,登记密码时,登记的前2组密码为管理员密码,其余皆为用户密码。由于我只登记了一个开门的密码,那么这个密码理论上来说就是管理员密码。如图3

从说明手册的登记密码中,终于找到了管理员密码的相关说明。出厂状态下,登记密码时,登记的前2组密码为管理员密码,其余皆为用户密码。由于我只登记了一个开门的密码,那么这个密码理论上来说就是管理员密码。

图3

4、最后按了 6 次指纹,指纹开启成功。之前的密码是 8 位数字,然后再加上最后的 #,开门时要按 9 次按键。现在有了指纹后,只需要一次按键就可以开门了。相对于平时的密码开门来说,确实快捷了许多。

]]>
https://www.shuijingwanwq.com/2024/10/14/8827/feed/ 0
自行车骑行时,不断发出金属碰撞的声音的解决 https://www.shuijingwanwq.com/2023/11/07/8169/ https://www.shuijingwanwq.com/2023/11/07/8169/#respond Tue, 07 Nov 2023 01:40:14 +0000 https://www.shuijingwanwq.com/?p=8169 浏览量: 70

1、自行车骑行时,不断发出金属碰撞的声音。当停下车时,自行转动链条,可以模拟出来。如视频1

2、仔细观察发现,原因应该是链条脱落所导致了。如图2

仔细观察发现,原因应该是链条脱落所导致了

图2

3、先手动将链条重新嵌入转轮上,然后转动链条,让其自动全部嵌入转轮上。

4、然后问题得到解决。不再发出声音了。

5、发现仍然没有彻底解决,最后决定找一家维修自行车的店铺,最后发现问题根源出在中轴上,中轴中的轴承已经腐蚀了一些。如图3

发现仍然没有彻底解决,最后决定找一家维修自行车的店铺,最后发现问题根源出在中轴上,中轴中的轴承已经腐蚀了一些

图3

6、重新换了一个中轴后,新的中轴采用与共享单车一样技术,与以前的中轴技术不一样,以前的中轴里面包含一些钢珠了。问题得到彻底解决。如图4

重新换了一个中轴后,新的中轴采用与共享单车一样技术,与以前的中轴技术不一样,以前的中轴里面包含一些钢珠了。问题得到彻底解决

图4

]]>
https://www.shuijingwanwq.com/2023/11/07/8169/feed/ 0
将成都公积金的按年提取协议转签为按月提取协议 https://www.shuijingwanwq.com/2023/08/08/7931/ https://www.shuijingwanwq.com/2023/08/08/7931/#respond Tue, 08 Aug 2023 01:29:14 +0000 https://www.shuijingwanwq.com/?p=7931 浏览量: 173

1、计划将成都公积金的按年提取协议转签为按月提取协议。参考:如何将按年提取协议转签按月提取协议?成都公积金中心解答

2、如何将按年提取协议转签按月提取协议?可通过成都公积金手机APP自助办理。需先在“个人业务—委托提取解约”办理按年提取协议解约,再在“提取业务—按月提取还贷签(解)约”办理按月提取协议签约。

3、为了保险起见,我决定等待按年提取公积金后,再进行按年提取协议解约。以避免出现公积金账户中有一年左右的金额永远无法提取出来的尴尬局面。

4、当收取到按年提取公积金短信后,短信内容如下:您尾号2909的储蓄卡7月10日1时26分收入人民币xx元,活期余额xx元。附言:成都住房公积金管理中心代付。[建设银行]。如图1

当收取到按年提取公积金短信后,短信内容如下:您尾号2909的储蓄卡7月10日1时26分收入人民币xx元,活期余额xx元。附言:成都住房公积金管理中心代付。[建设银行]

图1

5、在成都公积金APP中,打开 个人业务 – 委托提取解约。如图2

在成都公积金APP中,打开 个人业务 - 委托提取解约

图2

6、提示:您无法办理该业务,原因如下 1、存在未办结委托提取业务 2、职工存在多笔生效中的协议,不支持线上解约!。如图3

提示:您无法办理该业务,原因如下 1、存在未办结委托提取业务 2、职工存在多笔生效中的协议,不支持线上解约!

图3

7、先打客服电话,说是因为是组合贷款,所以无法在 APP 中解约。让我线下办理,需要带上身份证、公积金银行卡、还房贷的银行卡、房贷合同、户口本等。最终还是决定线下办理,先在 APP 中预约周六去办理。便民服务 – 预约。如图4

先打客服电话,说是因为是组合贷款,所以无法在 APP 中解约。让我线下办理,需要带上身份证、公积金银行卡、还房贷的银行卡、房贷合同、户口本等。最终还是决定线下办理,先在 APP 中预约周六去办理。便民服务 - 预约

图4

8、我要预约 – 新增。如图5

我要预约 - 新增

图5

9、我要预约 – 填写预约信息。如图6

我要预约 - 填写预约信息

图6

10、预约成功提示。如图7

预约成功提示

图7

11、收到短信内容如下:【成都住房公积金管理中心】您好,您已成功预约在【城南服务大厅】的【2023-07-15】的【提取】业务,预约时间段为当日的【13:00-14:30】,请携带相关证件按时到达。如图8

收到短信内容如下:【成都住房公积金管理中心】您好,您已成功预约在【城南服务大厅】的【2023-07-15】的【提取】业务,预约时间段为当日的【13:00-14:30】,请携带相关证件按时到达

图8

12、在线下柜台处,工作人员先给我解约了一个委托,当只剩下一个委托后。让我直接在成都公积金APP中,打开 个人业务 – 委托提取解约,已经可以进入解约流程。最后发现相关证件仅用到了身份证与银行卡。如图9

在线上柜台处,工作人员先给我解约了一个委托,当只剩下一个委托后。让我直接在成都公积金APP中,打开 个人业务 - 委托提取解约,已经可以进入解约流程

图9

13、终止协议业务办理确认书。如图10

终止协议业务办理确认书

图10

14、委托提取解约审批成功! 如图11

委托提取解约审批成功!

图11

15、在“提取业务—按月提取还贷签(解)约”办理按月提取协议签约,按月提取还贷签约。提示:只允许录入缴存人信息! 重新编辑一下相关信息,就可以正常进入下一流程。如图12

在“提取业务—按月提取还贷签(解)约”办理按月提取协议签约,按月提取还贷签约。提示:只允许录入缴存人信息! 重新编辑一下相关信息,就可以正常进入下一流程

图12

16、按月提取还款签约,贷款类型 – 组合贷款,签约类型 – 终止协议。如图13

按月提取还款签约,贷款类型 - 组合贷款,签约类型 - 终止协议

图13

17、账户变动通知 尊敬的王 X,您申请的按月提取偿还贷款本息签约业务已办理成功!咨询电话028-12329。如图14

账户变动通知 尊敬的王 X,您申请的按月提取偿还贷款本息签约业务已办理成功!咨询电话028-12329

图14

18、然后每个月在还款时,会自动抵扣每月所缴纳的公积金金额,剩下的部分再从银行卡扣款。收到短信内容如下:[成都住房公积金管理中心]尊敬的王 X,您已偿还公积金贷款本息 xxx 元。其中公积金抵扣 xxx 元,银行卡扣款511.38元,剩余0.0元未还。如有未还金额请于今日足额还款,否则将影响您的个人征信。如已足额还款,请忽略。咨询电话028-12329。如图15

然后每个月在还款时,会自动抵扣每月所缴纳的公积金金额,剩下的部分再从银行卡扣款。收到短信内容如下:[成都住房公积金管理中心]尊敬的王 X,您已偿还公积金贷款本息 xxx 元。其中公积金抵扣 xxx 元,银行卡扣款511.38元,剩余0.0元未还。如有未还金额请于今日足额还款,否则将影响您的个人征信。如已足额还款,请忽略。咨询电话028-12329

图15

]]>
https://www.shuijingwanwq.com/2023/08/08/7931/feed/ 0
在四川开具无犯罪记录证明的网上办理流程 https://www.shuijingwanwq.com/2023/02/08/7393/ https://www.shuijingwanwq.com/2023/02/08/7393/#respond Wed, 08 Feb 2023 01:32:40 +0000 https://www.shuijingwanwq.com/?p=7393 浏览量: 324

1、下载 天府通办 APP,发现竟然在应用宝中搜索不到。最后在一加手机自带的软件商店中才搜索到。如图1

下载 天府通办 APP,发现竟然在应用宝中搜索不到。最后在一加手机自带的软件商店中才搜索到

图1

2、认证登录 天府通办 APP 后,点击我的,进入电子证照的全部。如图2

认证登录 天府通办 APP 后,点击我的,进入电子证照的全部

图2

3、选择证明类,添加证明。如图3

选择证明类,添加证明

图3

4、按种类,个人证照下选择无犯罪记录证明。如图4

按种类,个人证照下选择无犯罪记录证明

图4

5、申请用途,3个选项:就业、留学、移民,按照实际情况选择。如图5

申请用途,3个选项:就业、留学、移民,按照实际情况选择

图5

6、提交成功,正在审核中。如图6

提交成功,正在审核中

图6

7、昨天晚上提交,今天早上进入 APP 中查看审核状态,发现已经办理成功。由户口所在地的派出所开具。如图7

昨天晚上提交,今天早上进入 APP 中查看审核状态,发现已经办理成功。由户口所在地的派出所开具

图7

]]>
https://www.shuijingwanwq.com/2023/02/08/7393/feed/ 0
笔记本电脑 ( ThinkPad T570 ) 耳机有声音,外放无声音的解决 https://www.shuijingwanwq.com/2021/11/28/5509/ https://www.shuijingwanwq.com/2021/11/28/5509/#respond Sun, 28 Nov 2021 03:44:15 +0000 https://www.shuijingwanwq.com/?p=5509 浏览量: 334

1、笔记本电脑 ( ThinkPad T570 ) 耳机有声音,外放无声音。确认之前外放是有声音的。

2、打开联想服务网址:https://newsupport.lenovo.com.cn/ 。搜索:t570,选择:ThinkPad T570。如图1

打开联想服务网址:https://newsupport.lenovo.com.cn/ 。搜索:t570,选择:ThinkPad T570。

图1

3、在新打开的页面中,点击:驱动下载。如图2

在新打开的页面中,点击:驱动下载。

图2

4、展开 声卡 ,显示:Realtek声卡驱动程序(Windows 10 64-bit 1607 及之后版本),下载并安装。文件名:Audio-n1va114w.exe。如图3

展开 声卡 ,显示:Realtek声卡驱动程序(Windows 10 64-bit 1607 及之后版本),下载并安装。文件名:Audio-n1va114w.exe。

图3

5、展开 热键 ,显示:Hotkey热键驱动程序(Windows 10 64-bit),下载并安装。文件名:SIhotkey-r0yvu35w.exe。如图4

展开 热键 ,显示:Hotkey热键驱动程序(Windows 10 64-bit),下载并安装。文件名:SIhotkey-r0yvu35w.exe。

图4

6、重启电脑后,耳机有声音,外放有声音。

 

]]>
https://www.shuijingwanwq.com/2021/11/28/5509/feed/ 0
笔记本电脑 ( ThinkPad T570 ) 无法充电的排查分析 https://www.shuijingwanwq.com/2021/11/11/5464/ https://www.shuijingwanwq.com/2021/11/11/5464/#respond Thu, 11 Nov 2021 02:47:40 +0000 https://www.shuijingwanwq.com/?p=5464 浏览量: 119

1、笔记本电脑电源无法充电。已经确定插上了电源。如图1

笔记本电脑电源无法充电。已经确定插上了电源。

图1

2、电脑上鼠标右键单击电源打开选项中单击电源选项。如图2

电脑上鼠标右键单击电源打开选项中单击电源选项。

图2

3、打开电源选项窗口中。现有的计划是:鲁大师,决定切换为:平衡 (推荐)。如图3

打开电源选项窗口中。现有的计划是:鲁大师,决定切换为:平衡 (推荐)。

图3

4、在 鲁大师 中查看电池信息,正常状态。如图4

在 鲁大师 中查看电池信息,正常状态。

图4

5、机身左侧依次配有 电源接口、USB 3.0接口 以及 雷电3接口。现在充电使用的是 雷电3接口。如图5

机身左侧依次配有 电源接口、USB 3.0接口 以及 雷电3接口。现在充电使用的是 雷电3接口。

图5

6、现在怀疑或者 电源适配器 损坏,或者 雷电3接口 损坏。本想寻找一个同样的电源适配器来测试一下。无奈找不到。不得不到联想售后去验证。联想售后经过验证,确定是 雷电3接口 损坏。如果要维修,涉及到主板。费用为 600+,且需要等待几天。由于急用电脑,最终决定重买一个电源适配器,适用于 电源接口 的充电。费用为 200+。如图6

现在怀疑或者 电源适配器 损坏,或者 雷电3接口 损坏。本想寻找一个同样的电源适配器来测试一下。无奈找不到。不得不到联想售后去验证。联想售后经过验证,确定是 雷电3接口 损坏。如果要维修,涉及到主板。费用为 600+,且需要等待几天。由于急用电脑,最终决定重买一个电源适配器,适用于 电源接口 的充电。费用为 200+。

图6

7、使用新的电源适配器连接 电源接口。可以正常充电。电源图标上存在插头标识。如图7

使用新的电源适配器连接 电源接口。可以正常充电。电源图标上存在插头标识。

图7

]]>
https://www.shuijingwanwq.com/2021/11/11/5464/feed/ 0
发布视频稿件至哔哩哔哩时,提示:稿件分区错误的分析排查 https://www.shuijingwanwq.com/2020/07/24/4304/ https://www.shuijingwanwq.com/2020/07/24/4304/#respond Fri, 24 Jul 2020 12:25:33 +0000 https://www.shuijingwanwq.com/?p=4304 浏览量: 224

1、发布视频稿件至哔哩哔哩时,提示:稿件分区错误。如图1

发布视频稿件至哔哩哔哩时,提示:稿件分区错误。

图1

2、分析出此篇发布失败的文章,所选择的分类是:资讯 – 综合。如图2

分析出此篇发布失败的文章,所选择的分类是:资讯 - 综合。

图2

3、发布成功的稿件,所选择的分类是:生活 – 其他。如图3

发布成功的稿件,所选择的分类是:生活 - 其他。

图3

4、当前发布稿件的帐号等级:大会员。距离转正会员 还差一点点!。如图4

当前发布稿件的帐号等级:大会员。距离转正会员 还差一点点!。

图4

5、在哔哩哔哩创作中心,在选择分区时,存在:生活 – 其他。但是不存在:资讯 – 综合。如图5

在哔哩哔哩创作中心,在选择分区时,存在:生活 - 其他。但是不存在:资讯 - 综合。

图5

6、分析结果,既然创作中心的分区中无法选择:资讯 – 综合。那么通过接口的方式,自然会报错:稿件分区错误。换了一个帐号登录,是媒体号,其分区是存在:资讯 – 综合 的。如图6

分析结果,既然创作中心的分区中无法选择:资讯 - 综合。那么通过接口的方式,自然会报错:稿件分区错误。换了一个帐号登录,是媒体号,其分区是存在:资讯 - 综合 的。

图6

7、后续争取基于会员的等级即时获取文章分类,避免让用户选择固定的文章分类数据。从而避免再次出现:稿件分区错误 的情形。

]]>
https://www.shuijingwanwq.com/2020/07/24/4304/feed/ 0
一个用户对于一个资源的是否具有一系列操作权限的判断的重构 https://www.shuijingwanwq.com/2020/04/18/4106/ https://www.shuijingwanwq.com/2020/04/18/4106/#respond Sat, 18 Apr 2020 09:32:56 +0000 https://www.shuijingwanwq.com/?p=4106 浏览量: 96 1、在获取资源列表的接口中,响应参数:actions,决定了当前用户对于一个资源的是否具有某个操作权限,值为 1 表示具有,值为 0 表示不具有。如图1
在获取资源列表的接口中,响应参数:actions,决定了当前用户对于一个资源的是否具有某个操作权限,值为 1 表示具有,值为 0 表示不具有。

图1



    "actions": {
        "enable": 0,
        "plan_task_create": 0,
        "disable": 1,
        "edit": 1,
        "update": 1,
        "submit": 1,
        "pass": 0,
        "refuse": 0,
        "return": 0,
        "view": 1,
        "delete": 1,
        "plan_task_index": 0,
        "review_opinion": 0,
        "invite": 0,
        "invite_accept": 0,
        "invite_refuse": 0,
        "plan_log_index": 1,
        "plan_resource_index": 0
    },


2、接口文档说明,如图2
接口文档说明

图2

3、当调用删除资源的接口时,判断用户是否具有资源的操作权限:删除选题,删除 2 个资源,如图3
当调用删除资源的接口时,判断用户是否具有资源的操作权限:删除选题,删除 2 个资源

图3



        // 判断用户是否具有资源的操作权限:删除选题(场景:编辑选题、指派任务等操作时,判断选题ID的存在性、操作按钮的显示与否(我的选题(获取选题列表)))
        PlanService::isActionAllow(explode(';', $id), Plan::ACTION_DELETE, $identity);


4、判断逻辑分为 2 个步骤,第 1 个步骤为:判断用户是否为选题的所有者(场景:编辑选题、指派任务等操作时,判断选题ID的存在性(我的选题(获取选题列表))),即资源列表中是否存在对应的资源 ID,如果不存在,则抛出异常,SQL 如下


    /**
     * 判断用户是否为选题的所有者(场景:编辑选题、指派任务等操作时,判断选题ID的存在性(我的选题(获取选题列表)))
     *
     * @param array $ids 多个选题ID
     * 格式如下:[1, 2, 3]
     * @param object $identity 当前用户的身份实例
     *
     * @return array $models 多个选题对象
     *
     * @throws NotFoundHttpException if the model cannot be found
     */
    public static function isHaveIdentityOwner($ids, $identity) {
        /* @var $haveQuery PlanQuery */
        // 获取查询对象(我的选题(获取选题列表))
        $haveQuery = Plan::getHaveQuery($identity);

        $models = $haveQuery
            ->orderBy([Plan::tableName() . '.id' => SORT_DESC])
            ->andWhere(['in', Plan::tableName() . '.id', $ids])
            ->indexBy('id')
            ->all();

        if (!empty($models)) {
            // ID的数量与模型资源数量是否相等,如果不相等,响应失败
            $flipIds = array_flip($ids);
            if (count($models) == count($flipIds)) {
                return $models;
            } else {
                $ids = implode(';', array_keys(array_diff_key($flipIds, $models)));
            }
        } else {
            $ids = implode(';', $ids);
        }

        throw new NotFoundHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202080'), ['ids' => $ids])), 202080);
    }




SELECT `pa_plan`.* FROM `pa_plan` LEFT JOIN `pa_config_column` ON `pa_plan`.`config_column_id` = `pa_config_column`.`id` LEFT JOIN `pa_config_column_user` `ccu_plan_create` ON `pa_plan`.`config_column_id` = `ccu_plan_create`.`config_column_id` AND `pa_plan`.`create_user_id` = `ccu_plan_create`.`user_id` LEFT JOIN `pa_plan_attended_user_relation` ON `pa_plan`.`id` = `pa_plan_attended_user_relation`.`plan_id` LEFT JOIN `pa_config_column_user` `ccu_plan_relation` ON `pa_plan_attended_user_relation`.`config_column_id` = `ccu_plan_relation`.`config_column_id` AND `pa_plan_attended_user_relation`.`relation_user_id` = `ccu_plan_relation`.`user_id` LEFT JOIN `pa_plan_group_relation` ON `pa_plan`.`id` = `pa_plan_group_relation`.`plan_id` LEFT JOIN `pa_config_column_user` `ccu_plan_accepted` ON `pa_plan_group_relation`.`config_column_id` = `ccu_plan_accepted`.`config_column_id` AND `pa_plan_group_relation`.`accepted_user_id` = `ccu_plan_accepted`.`user_id` WHERE (`pa_config_column`.`is_deleted`=0) AND (`pa_plan`.`is_deleted`=0) AND (((`pa_plan`.`group_id`='c10e87f39873512a16727e17f57456a5') AND (`pa_plan`.`create_user_id`='1') AND (`ccu_plan_create`.`is_deleted`=0)) OR ((`pa_plan`.`group_id`='c10e87f39873512a16727e17f57456a5') AND (`pa_plan_attended_user_relation`.`relation_user_id`='1') AND (FIND_IN_SET('1', `pa_plan_attended_user_relation`.role)) AND (`pa_plan_attended_user_relation`.`is_deleted`=0) AND (`ccu_plan_relation`.`is_deleted`=0)) OR ((`pa_plan`.`group_id`='c10e87f39873512a16727e17f57456a5') AND (`pa_plan`.`config_column_id`=2)) OR ((`pa_plan`.`is_not_isolated`=1) AND (`pa_plan_group_relation`.`relation_group_id`='c10e87f39873512a16727e17f57456a5') AND (`pa_plan_group_relation`.`is_inviter`=0) AND (`pa_plan_group_relation`.`is_deleted`=0) AND ((`pa_plan_group_relation`.`accepted_status` IN (0, 2)) OR ((`pa_plan_group_relation`.`accepted_status`=1) AND (`pa_plan_group_relation`.`accepted_user_id`='1') AND (`ccu_plan_accepted`.`is_deleted`=0)) OR ((`pa_plan_group_relation`.`accepted_status`=1) AND (`pa_plan`.`config_column_id`=2))))) AND (`pa_plan`.`id` IN ('38', '39')) GROUP BY `pa_plan`.`id` ORDER BY `pa_plan`.`id` DESC


5、如果需要删除的资源 ID 皆存在资源列表中,即确认用户为资源的所有者。判断用户是否具有资源的操作权限(场景:编辑选题、指派任务等操作时,判断操作按钮的显示与否(我的选题(获取选题列表)))。如果不具有,则抛出异常,如果具有,由执行后续的操作。


    /**
     * 判断用户是否具有资源的操作权限(场景:编辑选题、指派任务等操作时,判断操作按钮的显示与否(我的选题(获取选题列表)))
     *
     * @param array|object $item 选题数组
     * @param string $action 资源的操作权限
     * 格式如下:update
     * @param array $configColumns 栏目配置列表
     * @param int $configColumnUserStatus 栏目人员状态
     * @param array $planTaskCreatePlanAttendedUserRelations 基于 关联的用户ID、角色包含执行(负责)、多个选题ID 查找资源列表(场景:我的选题列表中,当前用户可指派任务的资源列表)
     * @param array $inviteAcceptPlanGroupRelations 基于 关联的租户ID、多个选题ID 查找资源列表(场景:我的选题列表中,当前租户可接受邀请/拒绝邀请的资源列表)
     * @param array $planTaskCreatePlanGroupRelations 基于 关联的租户ID、多个选题ID 查找资源列表(场景:我的选题列表中,当前租户可指派任务的资源列表)
     * @param array $isColumnManagerPlanIds 当前用户身为栏目负责人下的选题ID列表
     * @param object $identity 当前用户的身份实例
     *
     * @return int $isActionShow 0:无;1:有
     */
    public static function isActionShow($item, $action, $configColumns, $configColumnUserStatus, $planTaskCreatePlanAttendedUserRelations, $inviteAcceptPlanGroupRelations, $planTaskCreatePlanGroupRelations, $isColumnManagerPlanIds, $identity) {
        $isActionShow = 0;
        if ($action == Plan::ACTION_ENABLE) {
            // 启用选题的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && (选题创建用户ID为当前登录用户ID || 栏目人员配置角色标识包含栏目负责人标识) && 选题状态,0:禁用)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds)) && $item['status'] == Plan::STATUS_DISABLED) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_PLAN_TASK_CREATE) {
            // 指派任务的权限,0:无;1:有(栏目状态,1:启用 && 栏目人员状态,1:启用 && ((选题的租户ID为当前租户ID && 选题与参与用户的关联模型的关联的用户ID为当前登录用户ID && 选题与参与用户的关联模型的角色包含执行(负责) && 选题与参与用户的关联模型是否被删除,0:否 && 栏目人员是否被删除,0:否) || 栏目人员配置角色标识包含栏目负责人标识) && 选题状态,3:通过;5:指派;6:完成 && (选题的租户ID为当前租户ID || (选题的是否联合,1:是 && 选题与租户的关联模型的关联的租户ID为当前租户ID && 选题与租户的关联模型的是否邀请者,0:否 && 选题与租户的关联模型的接受状态,1:已接受 && 选题与租户的关联模型是否被删除,0:否 && 选题与租户的关联模型的状态,1:启用)))
            if ($configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && (isset($planTaskCreatePlanAttendedUserRelations[$item['id']]) || in_array($item['id'], $isColumnManagerPlanIds)) && in_array($item['status'], [Plan::STATUS_PASSED, Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED]) && ($item['group_id'] == $identity->group_id || isset($planTaskCreatePlanGroupRelations[$item['id']]))) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_DISABLE) {
            // 禁用选题的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && (选题创建用户ID为当前登录用户ID || 栏目人员配置角色标识包含栏目负责人标识) && 选题状态,1:编辑;2:待审;3:通过;4:拒绝;5:指派;6:完成)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds)) && in_array($item['status'], [Plan::STATUS_EDITED, Plan::STATUS_WAITING_REVIEW, Plan::STATUS_PASSED, Plan::STATUS_REFUSED, Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED])) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_EDIT) {
            // 编辑选题的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && (选题创建用户ID为当前登录用户ID || 栏目人员配置角色标识包含栏目负责人标识) && 选题状态,1:编辑;2:待审;3:通过;4:拒绝;5:指派;6:完成)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds)) && in_array($item['status'], [Plan::STATUS_EDITED, Plan::STATUS_WAITING_REVIEW, Plan::STATUS_PASSED, Plan::STATUS_REFUSED, Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED])) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_UPDATE) {
            // 更新选题的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && (选题创建用户ID为当前登录用户ID || 栏目人员配置角色标识包含栏目负责人标识) && 选题状态,1:编辑;2:待审;3:通过;4:拒绝;5:指派;6:完成)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds)) && in_array($item['status'], [Plan::STATUS_EDITED, Plan::STATUS_WAITING_REVIEW, Plan::STATUS_PASSED, Plan::STATUS_REFUSED, Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED])) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_SUBMIT) {
            // 提交审核选题的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && (选题创建用户ID为当前登录用户ID || 栏目人员配置角色标识包含栏目负责人标识) && 选题状态,1:编辑;4:拒绝)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds)) && in_array($item['status'], [Plan::STATUS_EDITED, Plan::STATUS_REFUSED])) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_PASS) {
            // 通过选题的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && 栏目人员配置角色标识包含栏目负责人标识 && 选题状态,2:待审)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && in_array($item['id'], $isColumnManagerPlanIds) && $item['status'] == Plan::STATUS_WAITING_REVIEW) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_REFUSE) {
            // 拒绝选题的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && 栏目人员配置角色标识包含栏目负责人标识 && 选题状态,2:待审)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && in_array($item['id'], $isColumnManagerPlanIds) && $item['status'] == Plan::STATUS_WAITING_REVIEW) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_RETURN) {
            // 退回选题的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && 栏目人员配置角色标识包含栏目负责人标识 && 选题状态,3:通过;5:指派)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && in_array($item['id'], $isColumnManagerPlanIds) && in_array($item['status'], [Plan::STATUS_PASSED, Plan::STATUS_ASSIGNED])) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_VIEW) {
            // 详情的权限,0:无;1:有()
            $isActionShow = 1;
        } elseif ($action == Plan::ACTION_DELETE) {
            // 删除选题的权限,0:无;1:有(选题的租户ID为当前租户ID && (选题创建用户ID为当前登录用户ID || 栏目人员配置角色标识包含栏目负责人标识))
            if($item['group_id'] == $identity->group_id && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds))){
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_PLAN_TASK_INDEX) {
            // 相关任务的权限,0:无;1:有(选题状态,3:通过;5:指派;6:完成)
            if (in_array($item['status'], [Plan::STATUS_PASSED, Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED])) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_REVIEW_OPINION) {
            // 审核意见的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && (选题创建用户ID为当前登录用户ID || 栏目人员配置角色标识包含栏目负责人标识) && 选题状态,4:拒绝)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds)) && $item['status'] == Plan::STATUS_REFUSED) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_INVITE) {
            // 邀请的权限,0:无;1:有(选题的租户ID为当前租户ID && 栏目状态,1:启用 && 栏目人员状态,1:启用 && (选题创建用户ID为当前登录用户ID || 栏目人员配置角色标识包含栏目负责人标识) && 选题的是否联合,1:是 && 选题状态,3:通过;5:指派;6:完成)
            if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds)) && $item['is_united'] == Plan::IS_UNITED_YES && in_array($item['status'], [Plan::STATUS_PASSED, Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED])) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_INVITE_ACCEPT) {
            // 同意邀请的权限,0:无;1:有
            if ($configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && isset($inviteAcceptPlanGroupRelations[$item['id']]) && in_array($item['status'], [Plan::STATUS_PASSED, Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED])) {
                $isActionShow = 1;
            }
        } elseif ($action == Plan::ACTION_INVITE_REFUSE) {
            // 拒绝邀请的权限,0:无;1:有
            if ($configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && isset($inviteAcceptPlanGroupRelations[$item['id']]) && in_array($item['status'], [Plan::STATUS_PASSED, Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED])) {
                $isActionShow = 0;
            }
        } elseif ($action == Plan::ACTION_PLAN_LOG_INDEX) {
            // 选题日志的权限,0:无;1:有()
            $isActionShow = 1;
        } elseif ($action == Plan::ACTION_PLAN_RESOURCE_INDEX) {
            // 选题素材的权限,0:无;1:有(选题状态,5:指派;6:完成)
            if (in_array($item['status'], [Plan::STATUS_ASSIGNED, Plan::STATUS_COMPLETED])) {
                $isActionShow = 1;
            }
        }
        return $isActionShow;
    }


6、由于新增加了选题资源的一些列表接口,因此,导致第 1 个步骤:判断用户是否为选题的所有者(场景:编辑选题、指派任务等操作时,判断选题ID的存在性(我的选题(获取选题列表))),需要兼容多个列表,进而导致多个 SQL。存在一定的难度,而且后续不可控。因此,最终决定,简化第 1 个步骤,完善第 2 个步骤。如图4
由于新增加了选题资源的一些列表接口,因此,导致第 1 个步骤:判断用户是否为选题的所有者(场景:编辑选题、指派任务等操作时,判断选题ID的存在性(我的选题(获取选题列表))),需要兼容多个列表,进而导致多个 SQL。存在一定的难度,而且后续不可控。因此,最终决定,简化第 1 个步骤,完善第 2 个步骤。

图4

7、以启用选题举例,调整前的规则:


( 7 ) actions['enable']:启用选题
( 
    选题的租户ID为当前租户ID &&
    栏目状态,1:启用 &&
    栏目人员状态,1:启用 &&
    (
        选题创建用户ID为当前登录用户ID ||
        栏目人员配置角色标识包含栏目负责人标识
    ) &&
    选题状态,0:禁用
)




    if ($item['group_id'] == $identity->group_id && $configColumns[$item['config_column_id']]['status'] == ConfigColumn::STATUS_ENABLED && $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED && ($item['create_user_id'] == $identity->id || in_array($item['id'], $isColumnManagerPlanIds)) && $item['status'] == Plan::STATUS_DISABLED) {
        $isActionShow = 1;
    }


8、以启用选题举例,调整后的规则:


( 7 ) actions['enable']:启用选题
(
    选题状态,0:禁用 &&
    (
        是否下发,0:否 && 
        栏目是否被删除,0:否 &&
        栏目人员是否被删除,0:否 &&
        栏目状态,1:启用 &&
        栏目人员状态,1:启用 &&
        选题的租户ID为当前租户ID &&
        (
            选题创建用户ID为当前登录用户ID ||
            栏目人员配置角色标识包含栏目负责人标识
        )
    ) ||
    (
        是否下发,1:是 &&
        选题的租户ID为当前租户ID &&
        选题创建用户ID为当前登录用户ID
    )
)




    if ($item['status'] == Plan::STATUS_DISABLED &&
        (
            $item['is_send_down'] == Plan::IS_SEND_DOWN_NO &&
            $configColumnIsDeleted == ConfigColumn::IS_DELETED_NO &&
            $configColumnUserIsDeleted == ConfigColumnUser::IS_DELETED_NO &&
            $configColumnStatus == ConfigColumn::STATUS_ENABLED &&
            $configColumnUserStatus == ConfigColumnUser::STATUS_ENABLED &&
            $item['group_id'] == $identity->group_id &&
            (
                $item['create_user_id'] == $identity->id ||
                in_array($item['id'], $isColumnManagerPlanIds)
            )
        ) ||
        (
            $item['is_send_down'] == Plan::IS_SEND_DOWN_YES &&
            $item['group_id'] == $identity->group_id &&
            $item['create_user_id'] == $identity->id
        )
    ) {
        $isActionShow = 1;
    }


9、删除 16 与 43 时,由于第 1 个步骤验证失败,响应如下,如图5
删除 16 与 43 时,由于第 1 个步骤验证失败,响应如下

图5



{
    "name": "Not Found",
    "message": "选题ID:16,不存在于我的选题列表中",
    "code": 202080,
    "status": 404,
    "type": "yii\\web\\NotFoundHttpException"
}


10、简化第 1 个步骤,且调整第 2 个步骤后,删除 16 与 43 时,由于由于第 1 个步骤验证成功,且第 2 个步骤验证失败,响应如下,如图6
简化第 1 个步骤,且调整第 2 个步骤后,删除 16 与 43 时,由于由于第 1 个步骤验证成功,且第 2 个步骤验证失败,响应如下

图6




    /**
     * 判断用户是否为选题的所有者(场景:编辑选题、指派任务等操作时,判断选题ID的存在性(我的选题、待审核选题、相关选题)))
     *
     * @param array $ids 多个选题ID
     * 格式如下:[1, 2, 3]
     *
     * @return array $models 多个选题对象
     *
     * @throws NotFoundHttpException if the model cannot be found
     */
    public static function isIndexIdentityOwner($ids) {
        $models = Plan::find()
            ->where(['in', Plan::tableName() . '.id', $ids])
            ->isDeletedNo()
            ->indexBy('id')
            ->all();

        if (!empty($models)) {
            // ID的数量与模型资源数量是否相等,如果不相等,响应失败
            $flipIds = array_flip($ids);
            if (count($models) == count($flipIds)) {
                return $models;
            } else {
                $ids = implode(';', array_keys(array_diff_key($flipIds, $models)));
            }
        } else {
            $ids = implode(';', $ids);
        }

        throw new NotFoundHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202080'), ['ids' => $ids])), 202080);
    }

    /**
     * 判断用户是否具有资源的操作权限(场景:编辑选题、指派任务等操作时,判断选题ID的存在性、操作按钮的显示与否(我的选题(获取选题列表)))
     *
     * @param array $ids 多个选题ID
     * 格式如下:[1, 2, 3]
     * @param string $action 资源的操作权限
     * 格式如下:update
     * @param object $identity 当前用户的身份实例
     *
     * @return bool
     *
     * @throws NotFoundHttpException if the model cannot be found
     * @throws UnprocessableEntityHttpException
     */
    public static function isActionAllow($ids, $action, $identity) {
        // 判断用户是否为选题的所有者(场景:编辑选题、指派任务等操作时,判断选题ID的存在性(我的选题、待审核选题、相关选题)))
        $models = static::isIndexIdentityOwner($ids);

        $serialize = static::getPlanSerializer($models, $identity);

        /* 查询当前分页的栏目配置列表 */
        $configColumns = $serialize['configColumns'];

        /* 查询当前分页的栏目人员配置列表 */
        $configColumnUsers = $serialize['configColumnUsers'];

        // 基于 关联的用户ID、角色包含执行(负责)、多个选题ID 查找资源列表(场景:我的选题列表中,当前用户可指派任务的资源列表)
        $planTaskCreatePlanAttendedUserRelations = $serialize['planTaskCreatePlanAttendedUserRelations'];

        // 基于 关联的租户ID、多个选题ID 查找资源列表(场景:我的选题列表中,当前租户可接受邀请/拒绝邀请的资源列表)
        $inviteAcceptPlanGroupRelations = $serialize['inviteAcceptPlanGroupRelations'];

        // 基于 关联的租户ID、多个选题ID 查找资源列表(场景:我的选题列表中,当前租户可指派任务的资源列表)
        $planTaskCreatePlanGroupRelations = $serialize['planTaskCreatePlanGroupRelations'];

        /* 查询多个选题对象的角色包含执行(负责)、状态为启用的选题与参与用户的关联列表 */
        $planAttendedUserRoleExecs = $serialize['planAttendedUserRoleExecs'];

        /* 查询当前分页的框架服务控制台用户列表 */
        $redisCmcConsoleUsers = $serialize['redisCmcConsoleUsers'];

        /* 当前用户身为栏目负责人下的选题ID列表 */
        $isColumnManagerPlanIds = $serialize['isColumnManagerPlanIds'];

        // 不具有相关操作权限的选题ID
        $ids = [];
        /* @var $model Plan */
        foreach ($models as $key => $model) {

            // 栏目人员状态
            $configColumnUserStatus = $configColumnUsers[$model->config_column_id . '_' . $identity->id]['status'] ?? ConfigColumnUser::STATUS_DISABLED;

            // 权限,0:无;1:有
            $isActionAllow = static::isActionShow($model, $action, $configColumns, $configColumnUsers, $planTaskCreatePlanAttendedUserRelations, $inviteAcceptPlanGroupRelations, $planTaskCreatePlanGroupRelations, $isColumnManagerPlanIds, $identity);

            if ($isActionAllow == 0) {
                $ids[] = $model->id;
            }
        }

        if (!empty($ids)) {
            $ids = implode(';', $ids);
            throw new UnprocessableEntityHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202081'), ['ids' => $ids, 'action' => $action])), 202081);
        }

        return true;
    }




SELECT * FROM `pa_plan` WHERE (`pa_plan`.`id` IN ('16', '43')) AND (`is_deleted`=0)




{
    "name": "Unprocessable entity",
    "message": "当前用户不具有选题ID:16,的权限:enable",
    "code": 202081,
    "status": 422,
    "type": "yii\\web\\UnprocessableEntityHttpException"
}


11、其他的操作权限皆遵循上述类似的规则调整。便能够实现完整的操作权限控制,且降低了判断的性能开销。]]>
https://www.shuijingwanwq.com/2020/04/18/4106/feed/ 0
在 honor 手机中,使用手机管家删除 钉钉 的文件与数据后,打开 钉钉 黑屏 https://www.shuijingwanwq.com/2020/02/12/3931/ https://www.shuijingwanwq.com/2020/02/12/3931/#respond Wed, 12 Feb 2020 03:59:55 +0000 https://www.shuijingwanwq.com/?p=3931 浏览量: 92

1、在 honor 手机中,使用手机管家删除 钉钉 的文件与数据(全部勾选后删除),如图1

在 honor 手机中,使用手机管家删除 钉钉 的文件与数据(全部勾选后删除)

图1

2、打开 钉钉 黑屏,或者一直停留在启动界面(仅显示 钉钉 logo),如图2

打开 钉钉 黑屏,或者一直停留在启动界面(仅显示 钉钉 logo)

图2

3、支付宝与微信,也使用手机管家删除了全部的文件与数据,仍然可以正常启动软件的。最后没有法子,只好卸载了 钉钉,再重新安装,才能够启动 钉钉 了。

]]>
https://www.shuijingwanwq.com/2020/02/12/3931/feed/ 0