Compare commits

..

228 Commits

Author SHA1 Message Date
dd8f3584c7 车辆管理,有责任险审核权限的展示‘保额’且必填 2026-02-12 17:55:55 +08:00
a136eeff91 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-02-03 17:34:35 +08:00
9c2c57120b CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-02-03 17:34:32 +08:00
f7b37f7a0b CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-02-03 17:34:30 +08:00
f5c2d1687f CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-02-03 17:34:28 +08:00
a56824ff73 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-02-03 17:34:26 +08:00
b33ecb5a1e CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-02-03 17:34:24 +08:00
af9d7cdbf2 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-02-03 17:34:23 +08:00
1834a1a838 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-02-03 17:34:22 +08:00
3438a7f9b3 Revert "CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求"
This reverts commit dc94c6d261.
2026-01-29 21:32:39 +08:00
edbc60d3f3 Revert "CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求"
This reverts commit 31d1388890.
2026-01-29 21:32:36 +08:00
914249cc3a Revert "CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求"
This reverts commit 14a14e2c87.
2026-01-29 21:32:33 +08:00
1217b7671c Revert "CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求"
This reverts commit 62f2c166c6.
2026-01-29 21:32:31 +08:00
bd3e358ec7 Revert "CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求"
This reverts commit d18fec1ddc.
2026-01-29 21:32:26 +08:00
9788542b38 Revert "CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求"
This reverts commit 3a6d0878aa.
2026-01-29 21:32:22 +08:00
65a53ab267 Revert "CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求"
This reverts commit 87546848d2.
2026-01-29 21:32:19 +08:00
0f70e55e66 Revert "CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求"
This reverts commit fed4ae6edf.
2026-01-29 21:32:18 +08:00
e800ee1b7e VConsole去除 2026-01-29 11:26:56 +08:00
3fbcc7a125 VConsole调试 2026-01-29 10:24:25 +08:00
c90bf52b4d CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-28 11:15:51 +08:00
c9ac87b104 CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-28 10:02:18 +08:00
47fdf8f528 CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-27 16:28:33 +08:00
9192625165 CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-27 15:31:31 +08:00
5ebbce5c1f CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-27 15:29:56 +08:00
dc5327c8e4 h5链接替换33 2026-01-27 15:16:25 +08:00
044832a8f7 CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-27 15:12:39 +08:00
19c5809af2 CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-27 15:02:42 +08:00
d41684d7ed h5(返回) 2026-01-27 14:38:30 +08:00
60445b1523 h5链接替换-文件替换 2026-01-27 14:33:40 +08:00
534ef90f2e CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-27 14:23:15 +08:00
f8484391b8 CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-27 14:16:08 +08:00
414f2cd320 h5修改 2026-01-27 14:12:49 +08:00
d12ef20726 CRM_26-01-29#story#8070,调度APP-司机信息复制-仅子公司 2026-01-27 14:11:25 +08:00
ed7ce35a91 h5链接替换 2026-01-26 10:23:14 +08:00
6b5bc0494c 服务商人员,电话格式验证规则同步系统后台 2026-01-22 16:57:27 +08:00
fed4ae6edf CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-01-22 13:21:45 +08:00
87546848d2 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-01-22 13:14:30 +08:00
3a6d0878aa CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-01-22 13:12:08 +08:00
d18fec1ddc CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-01-22 11:48:20 +08:00
62f2c166c6 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-01-22 11:33:59 +08:00
14a14e2c87 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-01-22 10:56:15 +08:00
8a457952fa CRM_26-01-29#task#13363,潜在服务商审核-财务信息-h5做必填 2026-01-21 13:56:14 +08:00
c657f3b5ac 省市修改 2026-01-19 17:22:25 +08:00
31d1388890 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-01-15 17:40:24 +08:00
dc94c6d261 CRM_26-01-22#story#7966,关于在打通系统中责任险信息关联的需求 2026-01-15 16:07:45 +08:00
97c86dbee3 二手拖车车源发布成功后关闭弹窗 2026-01-15 15:45:46 +08:00
18ad0e0b2e 潜在服务商信息查询,开户许可证为空时展示优化 2026-01-14 17:31:55 +08:00
f77b0fc53d 潜在服务商信息查询,开户许可证为空时展示优化 2026-01-14 17:26:27 +08:00
8dee7c54df 数据处理 2026-01-12 18:12:57 +08:00
89cd821276 司机管理获取列表前清空列表 2026-01-12 17:56:50 +08:00
276a0b982e 司机管理获取列表前清空列表 2026-01-12 17:45:46 +08:00
b2119b4fd7 司机管理获取列表前清空列表 2026-01-12 17:45:27 +08:00
63b6028690 司机管理获取列表前清空列表 2026-01-12 17:45:17 +08:00
22bf45eda2 VConsole添加 2026-01-12 17:33:40 +08:00
9083f4ff30 CRM_26-01-13#story#7762,潜在服务商增加财务结算信息的需求--曹智龙 2026-01-12 15:19:32 +08:00
783910ba84 CRM_26-01-13#story#7852,为推进人车梳理工作优化调度APP车辆、司机管理功能的需求 2026-01-12 11:17:01 +08:00
ccf61a73ee CRM_26-01-13#story#7852,为推进人车梳理工作优化调度APP车辆、司机管理功能的需求 2026-01-09 14:02:14 +08:00
c6b23f6bb3 CRM_26-01-13#story#7762,潜在服务商增加财务结算信息的需求,许可证回显 2026-01-09 11:42:53 +08:00
d1eb15ed15 CRM_26-01-13#story#7762,潜在服务商增加财务结算信息的需求--曹智龙 2026-01-08 15:21:37 +08:00
c5fca0a4f1 CRM_26-01-13#story#7762,潜在服务商增加财务结算信息的需求--曹智龙 2026-01-07 15:49:51 +08:00
247d087c48 CRM_26-01-13#story#7762,潜在服务商增加财务结算信息的需求--曹智龙 2026-01-07 15:11:23 +08:00
3ba634d602 CRM_26-01-13#story#7762,潜在服务商增加财务结算信息的需求--曹智龙 2026-01-07 14:53:27 +08:00
58f1f5033d VConsole去除 2026-01-04 17:41:09 +08:00
c8400442a5 微信号更改添加判断 2026-01-04 16:37:05 +08:00
6dbb1377be 确认已添加接口返回null时不做任何处理 2026-01-04 16:01:58 +08:00
847fdc48c6 确认已添加接口返回null时不做任何处理 2026-01-04 15:53:21 +08:00
234853b603 vConsole添加 2026-01-04 15:45:56 +08:00
91b3c069ad 下载app接口替换 2025-12-30 10:41:46 +08:00
0732fdcb8e 人员确认添加二次弹框 2025-12-29 19:04:58 +08:00
64b2099c8b 调度h5的连接下载 2025-12-29 17:45:44 +08:00
ac08b52038 确认信息无误提示语更改 2025-12-29 13:17:10 +08:00
ebfb553829 VConsole去除 2025-12-29 13:12:22 +08:00
77335a1850 确认信息无误添加必填项判断 2025-12-29 13:11:15 +08:00
159ce0fbde 跳转app路径更换 2025-12-28 13:01:48 +08:00
1cc79ba5f5 h5链接替换 2025-12-28 12:04:21 +08:00
c3bdcc8251 样式兼容 2025-12-26 14:12:57 +08:00
78bfd97e0c h5立即打开修改(下方文字修改) 2025-12-26 14:05:36 +08:00
ca5bb1520b h5立即打开修改 2025-12-26 13:52:41 +08:00
cf6d94d54f kpi修改 2025-12-26 13:43:19 +08:00
5845ae76da h5分享链接 2025-12-26 13:43:19 +08:00
0d2082ebaf CRM_25-12-23#story#7473,服务商系统、微信号的输入框只读 2025-12-24 10:21:31 +08:00
0208136ac4 车辆审批需求,责任险可查看 2025-12-23 10:53:47 +08:00
a2907a9fd1 车辆审批需求,责任险可查看 2025-12-23 10:37:39 +08:00
c7a1d95346 车辆审批需求,责任险可查看,保存时添加车辆状态字段 2025-12-23 10:23:52 +08:00
911bf1f5e0 车辆审批需求,车辆新增一个车辆状态为‘ 否-服务商停用’ 2025-12-23 09:21:01 +08:00
a3fd0d6f46 CRM_25-12-23#story#7473,服务商系统,添加是否是主账号判断 2025-12-22 19:51:08 +08:00
6fe09d9674 CRM_25-12-23#story#7473,服务商系统,添加是否是主账号判断 2025-12-22 19:47:44 +08:00
44552c5d35 CRM_25-12-23#story#7473,服务商系统,添加是否是主账号判断 2025-12-22 19:44:35 +08:00
75b727d8b2 车辆审批需求,去除比较提交审批接口,使用原本保存接口,新增canSubmitApproval字段,默认true 2025-12-22 17:19:54 +08:00
4eb791c9c6 CRM_25-12-23#story#7473,服务商系统、调度APP新增服务商人员确认的功能 2025-12-22 13:08:25 +08:00
44e1af7262 CRM_25-12-23#story#7473,服务商系统、调度APP新增服务商人员确认的功能 2025-12-22 13:08:10 +08:00
e0f90ca3b2 VConsole日志添加 2025-12-22 10:02:27 +08:00
7e73da59eb CRM_25-12-23#story#7473,服务商系统、调度APP新增服务商人员确认的功能 2025-12-19 14:16:12 +08:00
361f7f16f8 车辆审批提交,去除备注填写,直接走接口 2025-12-18 18:04:58 +08:00
4734f236cf 车辆审批提交,去除备注填写,直接走接口 2025-12-18 17:33:49 +08:00
89cf401882 CRM_25-12-23#story#7473,服务商系统、调度APP新增服务商人员确认 2025-12-18 14:15:04 +08:00
0fc9be28d1 CRM_25-12-23#story#7473,服务商系统、调度APP新增服务商人员确认 2025-12-17 21:53:36 +08:00
1a567dee57 CRM_25-12-09#story#7474,服务商师傅和车辆修改的审批 2025-12-17 16:19:24 +08:00
ecb87e5bc9 CRM_25-12-23#story#7473,服务商系统、调度APP新增服务商人员确认的功能 2025-12-17 16:19:02 +08:00
193e9c8006 kpi修改 2025-12-17 15:55:56 +08:00
94376c91b8 调度h5续保更新条件修改 2025-12-17 15:55:56 +08:00
23984e78ec CRM_25-12-23#story#7473,服务商系统、调度APP新增服务商人员确认的功能 2025-12-17 11:37:59 +08:00
1f2af86b96 去除VConsole 2025-12-16 13:16:06 +08:00
2c344eb2f5 车辆提交审批 2025-12-16 09:23:31 +08:00
552b56d5da CRM_25-12-23#story#7473,服务商系统、调度APP新增服务商人员确认的功能 2025-12-15 13:07:55 +08:00
f9acd76fcf 报备样式修改 2025-12-12 11:40:04 +08:00
b5f30b4c77 CRM_25-12-16#story#7744,调度APP报备调整 2025-12-11 09:54:24 +08:00
b9830e80eb 潜在服务商修改 2025-12-08 13:45:22 +08:00
5bc7c6b1e3 CRM_25-12-09#story#7474,服务商师傅和车辆修改的审批--曹智龙 2025-12-08 10:11:26 +08:00
5a56d4fe1c CRM_25-12-09#story#7474,服务商师傅和车辆修改的审批--曹智龙 2025-12-08 09:57:01 +08:00
f7f9bb7fd0 换UI修改 2025-12-05 11:17:45 +08:00
05ac89814c 遗漏 2025-12-04 13:57:27 +08:00
d178be1acd CRM_25-12-09#story#7686,调度APP中救援责任险参保咨询问题优化 2025-12-04 11:38:34 +08:00
f0576476e9 CRM_25-12-09#story#7697,调度APP的车辆录入功能的漏洞 2025-12-04 11:38:34 +08:00
01e2f9ca8d CRM_25-12-09#story#7484,供应商培训材料问答编辑优化-去除调试 2025-12-04 10:40:32 +08:00
f9d72ee3cc CRM_25-12-09#story#7484,供应商培训材料问答编辑优化-数量统一 2025-12-04 10:26:56 +08:00
0102cc2899 CRM_25-12-09#story#7484,供应商培训材料问答编辑优化-添加调试 2025-12-04 10:18:30 +08:00
7f0109bfcc 调度h5修改 2025-12-04 10:07:00 +08:00
f3716466e9 CRM_25-12-09#story#7484,供应商培训材料问答编辑优化-添加调试 2025-12-04 09:40:31 +08:00
811f232a73 CRM_25-12-09#story#7484,供应商培训材料问答编辑优化--敖煜 2025-12-03 15:12:47 +08:00
72fe6cc266 bugfix 修改2 2025-12-01 13:06:10 +08:00
75cf3db960 bugfix 修改 2025-12-01 11:30:32 +08:00
19ad185126 CRM_25-11-18#story#7366,服务商KPI界面需求2025.9.11(样式调整 resize) 2025-11-27 17:08:58 +08:00
bb7ad8deb1 CRM_25-11-18#story#7366,服务商KPI界面需求2025.9.11(样式调整)(回退) 2025-11-27 16:50:00 +08:00
abd5657366 CRM_25-11-18#story#7366,服务商KPI界面需求2025.9.11(样式调整) 2025-11-27 16:33:14 +08:00
6e7a5a4b42 CRM_25-11-18#story#7366,服务商KPI界面需求2025.9.11 2025-11-27 15:00:34 +08:00
2c61085515 story#7552 潜在服务商,省禁用 2025-11-27 14:42:53 +08:00
55321e5dc5 报备--修改--换插件 2025-11-27 14:25:36 +08:00
327d40318b 报备修改 2025-11-26 10:38:08 +08:00
5eefaa2223 报备修改 2025-11-26 09:33:01 +08:00
ff0e25cfd0 报备修改 2025-11-25 16:27:27 +08:00
ed324d1140 工单详情,当司机号码不存在,剩余信息向上调整,样式优化 2025-11-18 14:38:01 +08:00
0d5ae66481 story#7552 潜在服务商,服务类型(字段替换) 2025-11-13 09:31:04 +08:00
abffe924ad story#7552 潜在服务商,服务类型-大类换字段 2025-11-12 17:06:55 +08:00
756b84e9de story#7552 潜在服务商,服务类型修改 2025-11-12 13:42:31 +08:00
87e7c30d6c story#7552 潜在服务商--企微二维码,长度限制 2025-11-12 11:29:30 +08:00
3d74bf8442 story#7373 测试数据删除 2025-11-12 11:02:15 +08:00
77b805855b story#7373 车辆类型修改 2025-11-12 10:41:37 +08:00
6cd6b71a66 story#7552 潜在服务商,添加困境服务 2025-11-12 10:04:10 +08:00
3fa9fef447 CRM_25-11-18#story#7552,服务商体系新增潜在服务商--曹智龙 2025-11-12 09:58:27 +08:00
eacb0f3afe story#7373 调度h5 保单填写限制修改 2025-11-06 10:16:39 +08:00
90cd479fea story#7373 调度h5 添加车辆类型 2025-11-05 18:38:29 +08:00
a377ecc5c9 story#7373 关于完善救援责任险管理功能的需求--临期筛选功能 2025-11-04 15:37:01 +08:00
0d695ff407 工单详情,模块1高度调整 2025-11-03 17:49:06 +08:00
4b298dd758 story#7373 关于完善救援责任险管理功能的需求--临期筛选功能 2025-11-03 14:50:33 +08:00
e3fba5d319 司机app使用该请求不挂token 2025-11-01 13:02:43 +08:00
e1569bb742 车辆列表,添加停启用状态更改接口 2025-10-28 18:00:45 +08:00
33b45ad37e 车辆列表,添加停启用状态更改接口 2025-10-28 17:11:19 +08:00
2e8018026f CRM_25-11-12#story#7366,服务商KPI界面需求2025.9.11 (旧的模块删除平安好评率) 2025-10-28 13:32:52 +08:00
a19b14b7d9 潜在服务商--修改按钮 2025-10-24 14:34:48 +08:00
41b43087f1 CRM_25-10-30#story#7373,关于完善救援责任险管理功能的需求--临期筛选功能 2025-10-24 10:25:18 +08:00
f257a9ad2a 潜在服务商修改 2025-10-23 11:39:01 +08:00
f788927da2 潜在服务商修改 2025-10-22 18:04:06 +08:00
769cae6223 潜在服务商修改 2025-10-22 15:12:17 +08:00
c2c319bfe8 潜在服务商修改 2025-10-22 15:02:46 +08:00
f622bb6d45 潜在服务商修改 2025-10-22 14:23:11 +08:00
954b792532 潜在服务商 2025-10-22 13:49:49 +08:00
45588f346f headers中添加Authorization 2025-10-17 11:41:53 +08:00
aeb011efbe CRM_25-10-15#story#7339,服务商在APP中查看救援相关资料内容优化 2025-10-15 16:29:06 +08:00
baa9a9c273 CRM_25-10-23#story#7370,我的车辆中“救援职业责任险”功能的优化需求(调度APP) 2025-10-15 10:38:30 +08:00
5fc794e412 CRM_25-10-23#story#7361,调度app案件信息增加 2025-10-15 10:38:29 +08:00
bb98eff5ae CRM_25-10-15#story#7316,服务商体系新增潜在服务商--曹智龙 2025-10-15 10:38:29 +08:00
97f6e47a00 CRM_25-10-15#story#7339,服务商在APP中查看救援相关资料内容优化 2025-10-13 16:48:13 +08:00
617b08e863 救援职业责任险界面,描述1的文字更改 2025-10-10 09:34:59 +08:00
39c83c71b3 CRM_25-10-15#story#7305#车辆信息梳理的需求-车辆类别选择限制(二) 2025-10-10 09:33:52 +08:00
7c97210d79 CRM_25-10-15#story#7316,服务商体系新增潜在服务商--曹智龙 2025-10-09 14:36:40 +08:00
8f42efe226 换请求方式 2025-09-26 13:10:38 +08:00
f94eee745a 跳转后添加type=invoice 参数 2025-09-26 11:42:22 +08:00
bf7e495b45 培训添加发票参数 2025-09-26 11:05:20 +08:00
f51b0a2aab CRM_25-10-15#story#7305,车辆信息梳理的需求-车辆类别选择限制(二) 2025-09-25 17:47:37 +08:00
d1726e3041 行驶证核验通过--颜色 2025-09-24 16:08:59 +08:00
01b724964d kpi总览界面,拒单明细type值遗漏补充 2025-09-19 15:23:56 +08:00
aabcd9ea29 车辆审核状态不能修改 2025-09-19 13:10:59 +08:00
ad8312f54b kpi总览界面,数据NAN解决 2025-09-18 15:13:08 +08:00
2c9dac15ce kpi总览界面,隐藏两个平安的指标 2025-09-17 21:58:01 +08:00
2e0f372a9b task#9508 大力神更名为随车吊平板车的相关问题 2025-09-17 10:23:30 +08:00
740ad98a99 实名认证接口加参数ump:1 2025-09-15 13:17:41 +08:00
ecc6e23663 VConsole调试删除 2025-09-15 08:58:50 +08:00
6dcc59ea2d 实名认证链接decode测试 2025-09-12 11:43:57 +08:00
f897506e86 实名认证调整 2025-09-12 11:14:41 +08:00
06d530fada 认证页的返回都调转列表页 2025-09-12 11:10:43 +08:00
3f64c42fbf 实名认证返回参数丢失测试解决 2025-09-12 11:01:33 +08:00
1b62e6eebf kpi界面,月日师傅二级tab设为一样 2025-09-12 10:59:19 +08:00
074575b703 kpi界面,月日师傅二级tab设为一样 2025-09-12 10:58:15 +08:00
6d5a91279a 实名认证页,认证结果esignFlag做缓存,添加打印 2025-09-12 10:38:35 +08:00
e9c3befe50 实名认证页,认证结果esignFlag做缓存,添加打印 2025-09-12 10:35:40 +08:00
91f14b9389 实名认证页,认证结果esignFlag做缓存,添加打印 2025-09-12 10:33:01 +08:00
a6dcd9ef03 实名认证页,认证结果esignFlag做缓存,添加打印 2025-09-12 10:27:17 +08:00
77d8bbf27c 实名认证页,认证结果esignFlag做缓存,添加打印 2025-09-12 10:21:55 +08:00
4c90532462 实名认证页,认证结果esignFlag做缓存,添加打印 2025-09-12 10:18:55 +08:00
204d6b354f 实名认证页,认证结果esignFlag做缓存 2025-09-12 10:16:17 +08:00
91aa8f3f05 实名认证页返回都到列表页 2025-09-12 09:22:29 +08:00
9f2b343662 实名认证页代码优化 2025-09-11 23:07:46 +08:00
e02456e807 实名认证页代码优化 2025-09-11 22:35:20 +08:00
ad0094fda2 认证页增加双击不放大功能,滚动条丝滑滚动优化 2025-09-11 17:30:47 +08:00
87263991ff 认证页下一步添加接口 2025-09-11 16:59:10 +08:00
415a0be018 CRM_25-09-25#story#7216,车辆信息梳理的需求-“公车”的服务内容调整 2025-09-11 16:05:08 +08:00
7aefcd8141 kpi催促明细,添加催促次数 2025-09-11 15:58:50 +08:00
6eb407d956 实名认证esignFlag缓存添加 2025-09-11 14:58:07 +08:00
7cfa03bf74 实名认证操作成功后返回到认证列表页 2025-09-11 14:48:37 +08:00
b7ee2bb3d7 实名认证界面加缓存数据 2025-09-11 14:42:49 +08:00
066abdeeb0 救援职业责任险 2025-09-11 14:36:38 +08:00
3b8837ce68 实名认证界面加缓存数据 2025-09-11 14:25:16 +08:00
8f730c7d04 实名认证接口加token参数 2025-09-11 13:05:01 +08:00
56046dc878 实名认证加token参数 2025-09-11 11:52:03 +08:00
da9cc2f588 实名认证加token参数 2025-09-11 11:50:09 +08:00
ab7593ae2d 车辆服务刷新问题 2025-09-11 09:49:06 +08:00
3a7c06ff2f story#7189,跳转加token参数 2025-09-10 16:42:14 +08:00
ab82fa04a6 story#7189,高度调整 2025-09-10 16:09:08 +08:00
695ce00a66 story#7131:调度APP车辆管理功能调整的需求-新增搜索和筛选功能 2025-09-10 15:12:52 +08:00
c6c6f9e6a9 story#7189,type默认'full' 2025-09-10 13:38:52 +08:00
65e5bd2814 kpi率乘以一百 2025-09-10 10:17:11 +08:00
f008ef0d09 kpi字段替换 2025-09-10 10:17:11 +08:00
5ffa3f3d9e 平安聚合时效 2025-09-10 10:17:11 +08:00
1a15772f08 story#7189,认证页radio回显处理 2025-09-10 09:20:41 +08:00
8f066a7bbf kpi首页添加综合打分项 2025-09-10 09:19:38 +08:00
d3e91f584f story#7189,回程车小程序司机端-迁移认证,跳转新的url 2025-09-09 16:59:56 +08:00
d04ed28ec2 story#7189,回程车小程序司机端-迁移认证,添加调试 2025-09-09 16:52:42 +08:00
36db96808a story#7189,回程车小程序司机端-迁移认证 2025-09-09 16:39:28 +08:00
781ef75913 story#7189,回程车小程序司机端-迁移认证页面 2025-09-09 13:33:44 +08:00
e7b0cfb006 司机端培训资料,关键字接受字段更换,切换优化加loading 2025-09-09 13:33:32 +08:00
57b4bc2e59 司机端培训资料,关键字接受字段更换,切换优化加loading 2025-09-09 13:32:12 +08:00
990db65d25 story#7189,回程车小程序司机端-迁移认证页面 2025-09-09 11:01:04 +08:00
cebb173ec4 三分钟联系客户率 2025-09-09 10:37:47 +08:00
8968f4caa9 好评率好评量删除 2025-09-09 10:35:52 +08:00
40ab15266a 车辆信息,修改并且自测 2025-09-08 13:09:10 +08:00
6bc55d7b89 story#7149,服务商KPI模块界面调整 2025-09-05 11:14:12 +08:00
06191163a2 服务商KPI 2025-09-04 09:52:08 +08:00
109 changed files with 141334 additions and 461 deletions

332
package-lock.json generated
View File

@@ -15,9 +15,10 @@
"dayjs": "^1.8.14", "dayjs": "^1.8.14",
"decimal.js": "^10.4.3", "decimal.js": "^10.4.3",
"echarts": "^5.2.2", "echarts": "^5.2.2",
"element-ui": "^2.15.9", "element-ui": "^2.15.13",
"less": "^4.1.3", "less": "^4.1.3",
"less-loader": "^11.1.3", "less-loader": "^11.1.3",
"qrcode": "^1.5.4",
"qs": "^6.11.2", "qs": "^6.11.2",
"sass": "^1.65.1", "sass": "^1.65.1",
"sass-loader": "^13.3.2", "sass-loader": "^13.3.2",
@@ -3350,7 +3351,6 @@
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -4801,6 +4801,15 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true "dev": true
}, },
"node_modules/decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decimal.js": { "node_modules/decimal.js": {
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz", "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz",
@@ -5020,6 +5029,12 @@
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"dev": true "dev": true
}, },
"node_modules/dijkstrajs": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==",
"license": "MIT"
},
"node_modules/dir-glob": { "node_modules/dir-glob": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -5210,8 +5225,7 @@
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
"dev": true
}, },
"node_modules/emojis-list": { "node_modules/emojis-list": {
"version": "3.0.0", "version": "3.0.0",
@@ -6215,7 +6229,6 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"dependencies": { "dependencies": {
"locate-path": "^5.0.0", "locate-path": "^5.0.0",
"path-exists": "^4.0.0" "path-exists": "^4.0.0"
@@ -6370,7 +6383,6 @@
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
"engines": { "engines": {
"node": "6.* || 8.* || >= 10.*" "node": "6.* || 8.* || >= 10.*"
} }
@@ -6992,7 +7004,6 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -7408,7 +7419,6 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"dependencies": { "dependencies": {
"p-locate": "^4.1.0" "p-locate": "^4.1.0"
}, },
@@ -8445,7 +8455,6 @@
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"dependencies": { "dependencies": {
"p-try": "^2.0.0" "p-try": "^2.0.0"
}, },
@@ -8460,7 +8469,6 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"dependencies": { "dependencies": {
"p-limit": "^2.2.0" "p-limit": "^2.2.0"
}, },
@@ -8485,7 +8493,6 @@
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@@ -8582,7 +8589,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -8663,6 +8669,15 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/pngjs": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz",
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==",
"license": "MIT",
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/portfinder": { "node_modules/portfinder": {
"version": "1.0.32", "version": "1.0.32",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
@@ -9394,6 +9409,131 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/qrcode": {
"version": "1.5.4",
"resolved": "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.4.tgz",
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
"license": "MIT",
"dependencies": {
"dijkstrajs": "^1.0.1",
"pngjs": "^5.0.0",
"yargs": "^15.3.1"
},
"bin": {
"qrcode": "bin/qrcode"
},
"engines": {
"node": ">=10.13.0"
}
},
"node_modules/qrcode/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/qrcode/node_modules/camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/qrcode/node_modules/cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
}
},
"node_modules/qrcode/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/qrcode/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/qrcode/node_modules/wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/qrcode/node_modules/y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
"license": "ISC"
},
"node_modules/qrcode/node_modules/yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"license": "MIT",
"dependencies": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/qrcode/node_modules/yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"license": "ISC",
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/qs": { "node_modules/qs": {
"version": "6.11.2", "version": "6.11.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
@@ -9643,7 +9783,6 @@
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -9657,6 +9796,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"license": "ISC"
},
"node_modules/requires-port": { "node_modules/requires-port": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
@@ -10033,6 +10178,12 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"license": "ISC"
},
"node_modules/setprototypeof": { "node_modules/setprototypeof": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -10324,7 +10475,6 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"dependencies": { "dependencies": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -10338,7 +10488,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"dependencies": { "dependencies": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
}, },
@@ -11702,6 +11851,12 @@
"which": "bin/which" "which": "bin/which"
} }
}, },
"node_modules/which-module": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
"license": "ISC"
},
"node_modules/wildcard": { "node_modules/wildcard": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
@@ -14418,8 +14573,7 @@
"ansi-regex": { "ansi-regex": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
"dev": true
}, },
"ansi-styles": { "ansi-styles": {
"version": "3.2.1", "version": "3.2.1",
@@ -15473,6 +15627,11 @@
} }
} }
}, },
"decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="
},
"decimal.js": { "decimal.js": {
"version": "10.4.3", "version": "10.4.3",
"resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz", "resolved": "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz",
@@ -15627,6 +15786,11 @@
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"dev": true "dev": true
}, },
"dijkstrajs": {
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz",
"integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="
},
"dir-glob": { "dir-glob": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -15783,8 +15947,7 @@
"emoji-regex": { "emoji-regex": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
"dev": true
}, },
"emojis-list": { "emojis-list": {
"version": "3.0.0", "version": "3.0.0",
@@ -16545,7 +16708,6 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": { "requires": {
"locate-path": "^5.0.0", "locate-path": "^5.0.0",
"path-exists": "^4.0.0" "path-exists": "^4.0.0"
@@ -16650,8 +16812,7 @@
"get-caller-file": { "get-caller-file": {
"version": "2.0.5", "version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
"dev": true
}, },
"get-intrinsic": { "get-intrinsic": {
"version": "1.2.1", "version": "1.2.1",
@@ -17088,8 +17249,7 @@
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
"dev": true
}, },
"is-glob": { "is-glob": {
"version": "4.0.3", "version": "4.0.3",
@@ -17399,7 +17559,6 @@
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"requires": { "requires": {
"p-locate": "^4.1.0" "p-locate": "^4.1.0"
} }
@@ -18184,7 +18343,6 @@
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": { "requires": {
"p-try": "^2.0.0" "p-try": "^2.0.0"
} }
@@ -18193,7 +18351,6 @@
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"requires": { "requires": {
"p-limit": "^2.2.0" "p-limit": "^2.2.0"
} }
@@ -18211,8 +18368,7 @@
"p-try": { "p-try": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
"dev": true
}, },
"param-case": { "param-case": {
"version": "3.0.4", "version": "3.0.4",
@@ -18292,8 +18448,7 @@
"path-exists": { "path-exists": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
"dev": true
}, },
"path-is-absolute": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
@@ -18350,6 +18505,11 @@
"find-up": "^4.0.0" "find-up": "^4.0.0"
} }
}, },
"pngjs": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz",
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="
},
"portfinder": { "portfinder": {
"version": "1.0.32", "version": "1.0.32",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz",
@@ -18835,6 +18995,96 @@
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA=="
}, },
"qrcode": {
"version": "1.5.4",
"resolved": "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.4.tgz",
"integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==",
"requires": {
"dijkstrajs": "^1.0.1",
"pngjs": "^5.0.0",
"yargs": "^15.3.1"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"requires": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
}
},
"y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
},
"yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"requires": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
}
},
"yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
"qs": { "qs": {
"version": "6.11.2", "version": "6.11.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz",
@@ -19021,8 +19271,7 @@
"require-directory": { "require-directory": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
"dev": true
}, },
"require-from-string": { "require-from-string": {
"version": "2.0.2", "version": "2.0.2",
@@ -19030,6 +19279,11 @@
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true "dev": true
}, },
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
},
"requires-port": { "requires-port": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
@@ -19293,6 +19547,11 @@
"send": "0.18.0" "send": "0.18.0"
} }
}, },
"set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="
},
"setprototypeof": { "setprototypeof": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
@@ -19534,7 +19793,6 @@
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
"requires": { "requires": {
"emoji-regex": "^8.0.0", "emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0", "is-fullwidth-code-point": "^3.0.0",
@@ -19545,7 +19803,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
"requires": { "requires": {
"ansi-regex": "^5.0.1" "ansi-regex": "^5.0.1"
} }
@@ -20524,6 +20781,11 @@
"isexe": "^2.0.0" "isexe": "^2.0.0"
} }
}, },
"which-module": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="
},
"wildcard": { "wildcard": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",

View File

@@ -16,9 +16,10 @@
"dayjs": "^1.8.14", "dayjs": "^1.8.14",
"decimal.js": "^10.4.3", "decimal.js": "^10.4.3",
"echarts": "^5.2.2", "echarts": "^5.2.2",
"element-ui": "^2.15.9", "element-ui": "^2.15.13",
"less": "^4.1.3", "less": "^4.1.3",
"less-loader": "^11.1.3", "less-loader": "^11.1.3",
"qrcode": "^1.5.4",
"qs": "^6.11.2", "qs": "^6.11.2",
"sass": "^1.65.1", "sass": "^1.65.1",
"sass-loader": "^13.3.2", "sass-loader": "^13.3.2",

View File

@@ -32,6 +32,10 @@
</script> </script>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=2560bbf04daef66c810c5e6a97e8c508&plugin=AMap.AutoComplete,AMap.PlaceSearch,AMap.Geolocation,AMap.Geocoder,AMap.Marker,AMap.Driving"></script> <script type="text/javascript" src="https://webapi.amap.com/maps?v=2.0&key=2560bbf04daef66c810c5e6a97e8c508&plugin=AMap.AutoComplete,AMap.PlaceSearch,AMap.Geolocation,AMap.Geocoder,AMap.Marker,AMap.Driving"></script>
<!-- <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>--> <!-- <script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>-->
<script>
window.selfLink = window.location.href;
window.selfSearch = window.location.search;
</script>
<script> <script>
// VConsole 默认会挂载到 `window.VConsole` 上 // VConsole 默认会挂载到 `window.VConsole` 上
// let vConsole = new window.VConsole(); // let vConsole = new window.VConsole();
@@ -52,7 +56,7 @@
if (isMobile) {// 是移动端不变 if (isMobile) {// 是移动端不变
// console.log("是移动端不变") // console.log("是移动端不变")
}else{ }else{
if(window.location.pathname=='/h5/supplier/dispatch/kpiIndex'){ if(window.location.pathname=='/h5/supplier/dispatch/kpiIndex' || window.location.pathname=='/h5/supplier/dispatch/kpiCaseNew'){
// console.log("执行了执行了") // console.log("执行了执行了")
win.addEventListener(resizeEvt, recalc, false); win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false); doc.addEventListener('DOMContentLoaded', recalc, false);

View File

@@ -0,0 +1,160 @@
# 年终总结看板 Dashboard
道路救援服务年终数据可视化看板项目。
## 项目结构
```
dashboard-demo/
├── index.html # 主看板页面支持URL参数动态加载数据
├── data/
│ ├── 供应商年度KPI.xlsx # 服务商KPI数据主数据源
│ ├── 师傅案件top3.xlsx # 案件量TOP3师傅数据
│ ├── 师傅在线top3.xlsx # 在线时长TOP3师傅数据
│ ├── 拒单率最高地区.xlsx # 拒单率最高地区数据
│ └── 拒单率最高时段.xlsx # 拒单率最高时段数据
└── README.md # 项目说明
```
## 功能特性
- 深色主题数据可视化看板
- **直接读取Excel文件**无需转换为JSON
- 支持通过URL参数 `?providerId=XXX` 切换不同服务商
- 右上角下拉框可实时切换服务商自动从Excel读取服务商列表
- 使用 Chart.js 实现饼状图和雷达图
- 使用 SheetJS (xlsx) 解析Excel文件
- 响应式布局,支持不同屏幕尺寸
- 数据与页面分离,便于维护
## 数据指标
看板展示以下数据指标:
1. **总案件量分布**(饼状图)
- 小修、困境、拖车三类案件占比
2. **年度聚合案件量**
3. **案件量TOP3师傅**
4. **车辆平均总在线时长**
5. **在线时长TOP3师傅**
6. **拒单率最高地区**
7. **拒单率最高时段**
8. **APP使用率**
- 年度APP使用率展示
## Excel数据结构
### 1. 供应商年度KPI.xlsx
| 列名 | 说明 |
|------|------|
| 服务商id | 服务商唯一标识 |
| 服务商 | 服务商名称 |
| 完成案件量 | 总案件数量 |
| 拖车完成量 | 拖车案件数 |
| 小修完成量 | 小修案件数 |
| 困境完成量 | 困境案件数 |
| 聚合案件量 | 聚合案件数量 |
| APP使用率. | APP使用率小数形式如0.998 |
| 年度车辆平均总在线时长(小时) | 车辆平均在线时长 |
### 2. 师傅案件top3.xlsx
| 列名 | 说明 |
|------|------|
| 服务商id | 服务商唯一标识 |
| 服务商 | 服务商名称 |
| 服务人员工号 | 师傅姓名/工号 |
| 完成案件量 | 该师傅完成的案件数 |
### 3. 师傅在线top3.xlsx
| 列名 | 说明 |
|------|------|
| 服务商名称 | 服务商名称 |
| 司机姓名 | 师傅姓名 |
| 年度总在线时长(小时) | 在线时长 |
### 4. 拒单率最高地区.xlsx
| 列名 | 说明 |
|------|------|
| 供应商名称 | 服务商名称 |
| 地区 | 拒单率最高的地区 |
| 拒单率 | 拒单率(小数形式) |
### 5. 拒单率最高时段.xlsx
| 列名 | 说明 |
|------|------|
| 供应商名称 | 服务商名称 |
| 时段 | 拒单率最高的时段 |
| 拒单率 | 拒单率(小数形式) |
## 使用方式
### 1. 启动本地服务器
由于页面使用 `fetch` 加载JSON数据需要通过HTTP服务器访问
```bash
cd C:\Users\Administrator\dashboard-demo
# 使用 Python
python -m http.server 8080
# 或使用 Node.js
npx serve .
# 或使用 PHP
php -S localhost:8080
```
### 2. 访问页面
- 默认服务商:`http://localhost:8080`(自动加载第一个服务商)
- 指定服务商:`http://localhost:8080?providerId=1128`使用服务商id
- 切换服务商:使用页面右上角的下拉框
### 3. 更新数据
直接替换 `data/` 目录下的Excel文件即可页面会自动读取最新数据。
服务商列表从Excel自动生成无需手动配置。
## 技术栈
- HTML5 / CSS3
- JavaScript (ES6+)
- Chart.js - 图表库(饼图、雷达图)
- SheetJS (xlsx) - Excel文件解析
- CSS Grid / Flexbox - 布局
## 后续优化方向
- [ ] 添加更多图表类型(柱状图、折线图等)
- [ ] 支持时间范围筛选
- [ ] 添加数据导出功能
- [ ] 移动端适配优化
- [ ] 添加数据加载骨架屏
- [ ] 支持主题切换(深色/浅色)
## 更新日志
### 2025-01-21
- 改为直接读取Excel文件无需JSON转换
- 服务商列表从Excel自动生成
- 将"AB段里程对比"改为"APP使用率"展示
- 新增服务商选择下拉框
### 2025-01-20
- 初始版本
- 实现基础看板布局
- 支持URL参数切换服务商
- 数据JSON化与页面分离

View File

@@ -0,0 +1,47 @@
{
"serviceProviderId": "SP001",
"serviceProviderName": "上海道路救援服务中心",
"year": 2025,
"summary": {
"totalCases": 100,
"caseBreakdown": {
"minorRepair": 20,
"predicament": 20,
"towing": 60
},
"aggregatedCases": 15
},
"topMastersByCases": [
{ "rank": 1, "name": "小王", "cases": 18 },
{ "rank": 2, "name": "小张", "cases": 16 },
{ "rank": 3, "name": "小李", "cases": 12 }
],
"onlineHours": {
"averageTotal": 2920,
"topMasters": [
{ "rank": 1, "name": "小王", "hours": 3230 },
{ "rank": 2, "name": "小张", "hours": 3028 },
{ "rank": 3, "name": "小李", "hours": 2996 }
]
},
"rejectionRate": {
"highestRegion": {
"name": "崇明",
"rate": 21.2
},
"highestTimeSlot": {
"period": "18:00-22:00",
"description": "晚高峰时段"
}
},
"abMileage": {
"highest": {
"region": "崇明",
"distance": 62
},
"lowest": {
"region": "黄浦",
"distance": 6
}
}
}

View File

@@ -0,0 +1,47 @@
{
"serviceProviderId": "SP002",
"serviceProviderName": "浦东汽车救援有限公司",
"year": 2025,
"summary": {
"totalCases": 156,
"caseBreakdown": {
"minorRepair": 35,
"predicament": 41,
"towing": 80
},
"aggregatedCases": 22
},
"topMastersByCases": [
{ "rank": 1, "name": "老陈", "cases": 28 },
{ "rank": 2, "name": "大刘", "cases": 24 },
{ "rank": 3, "name": "阿强", "cases": 19 }
],
"onlineHours": {
"averageTotal": 3150,
"topMasters": [
{ "rank": 1, "name": "老陈", "hours": 3580 },
{ "rank": 2, "name": "大刘", "hours": 3420 },
{ "rank": 3, "name": "阿强", "hours": 3210 }
]
},
"rejectionRate": {
"highestRegion": {
"name": "奉贤",
"rate": 18.5
},
"highestTimeSlot": {
"period": "07:00-09:00",
"description": "早高峰时段"
}
},
"abMileage": {
"highest": {
"region": "金山",
"distance": 55
},
"lowest": {
"region": "静安",
"distance": 8
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

120
src/api/authentication.js Normal file
View File

@@ -0,0 +1,120 @@
import request from '@/utils/http'
// 根据订单 获取报备类型
/*export function getReportListByOrder(key){
return request({
url: '/order/baseDriverReportConfigs/getByOrderId',
method:'GET',
params: key
})
}*/
// 弹框
export function successPopup( data) {
return request({
url: '/returnOrder/wechatDriver/user/successPopup',
method:'POST',
contentType: 'application/x-www-form-urlencoded',
data
})
}
// 认证进度
export function infoVerifyProgress(data){
return request({
url: '/returnOrder/wechatDriver/user/infoVerifyProgress',
method:'POST',
contentType: 'application/json',
data
})
}
// 认证详情
export function driverInfoVerifyDetail(data) {
return request({
url:'/returnOrder/wechatDriver/user/driverInfoVerifyDetail',
method:'POST',
data: data,
contentType: 'application/json',
})
}
// 我的信息
export function getMyInfo(data) {
return request({
url:'/returnOrder/wechatDriver/user/driverDetail',
method:'POST',
data: data,
})
}
// ocr识别
export function ocrRecognize( data) {
return request( {
url:'/returnOrder/wechatDriver/user/ocrRecognize',
data: data,
method:'POST',
contentType: 'application/json'
})
}
// 认证
export function driverInfoVerify( data) {
return request({
url:'/returnOrder/wechatDriver/user/driverInfoVerify',
data: data,
method:'POST',
contentType: 'application/json'
})
}
// 实名认证
export function driverRealName( data) {
return request('/returnOrder/wechatDriver/user/driverRealNameAuth', {
data: data,
method:'POST',
contentType: 'application/json'
})
}
//获取需要确认的人员信息列表
export function getConfirmPerson(key){
return request({
url: '/supplierAppV2/dispatchApp/wechat/getNeedConfirmPersonInfo',
method:'GET',
params: key
})
}
//微信相关 获取联系我 二维码
export function getQrCode(key){
return request({
url: '/supplierAppV2/dispatchApp/wechat/getQrCode',
method:'GET',
params: key
})
}
//获取服务商的确认状态
export function getConfirmStatus(key){
return request({
url: '/supplierAppV2/dispatchApp/wechat/getSupplier',
method:'GET',
params: key
})
}
//确认已添加微信按钮
export function confirmAddWechat(key){
return request({
url: '/supplierAppV2/dispatchApp/wechat/confirmAddWechat',
method:'GET',
params: key
})
}
//确认无误
export function confirm(key){
return request({
url: '/supplierAppV2/dispatchApp/wechat/confirm',
method:'GET',
params: key
})
}
//提交审批
export function submitConfirm( data) {
return request('/supplierAppV2/dispatchApp/wechat/submitConfirm', {
data: data,
method:'POST',
contentType: 'application/json'
})
}

View File

@@ -82,3 +82,40 @@ export function getDriverName(key) {
} }
}); });
} }
export function getVehicleName(key) {
return request({
url: '/supplier/select/vehicle',
method: 'GET',
params: {
key: key ,
}
});
}
// 车辆 总览
export function vehicleTotalInfo(data) {
return request({
url: '/supplier/supplierKPI/querySupplierVehicleStatisticsKpi',
method: 'POST',
data
});
}
// 服务商维度查询车辆
export function vehicleInfoBySupplier(data) {
return request({
url: '/supplier/supplierKPI/querySupplierStatisticsKpiBySupplier',
method: 'POST',
data
});
}
// 车辆维度查询车辆
export function vehicleInfoByVehicle(data) {
return request({
url: '/supplier/supplierKPI/querySupplierVehicleKpi',
method: 'POST',
data
});
}

View File

@@ -18,6 +18,34 @@ export function saveVehicle(data){
data data
}) })
} }
//提交审批车辆信息
export function saveSupplierApproval(data){
return request({
url:'/supplier/approval/saveSupplierDriverVehicleApproval',
method:'POST',
contentType:'application/json',
data
})
}
/*车辆更改状态 /supplierAppV2/dispatchApp/user/enableVehicle*/
export function enableVehicle(data){
return request({
url:'/supplierAppV2/dispatchApp/user/enableVehicle',
method:'POST',
contentType:'application/json',
data
})
}
//编辑车辆信息
export function updateInsurance(data){
return request({
url:'/supplierAppV2/dispatchApp/user/updateInsurance',
method:'POST',
data
})
}
// 获取车辆信息(用于修改时回显的值,只需传vehicleId // 获取车辆信息(用于修改时回显的值,只需传vehicleId
export function getInfoById(data){ export function getInfoById(data){
return request({ return request({
@@ -50,6 +78,61 @@ export function supplierServiceTree(){
method:'POST' method:'POST'
}) })
} }
// 服务商服务能力
export function supplierServicePartTree(data){
return request({
url:'/supplier/approval/getSupplierServiceTree',
method:'POST',
data
})
}
// 申请加入
export function saveSupplier(data){
return request({
url:'/supplier/potential/save',
method:'POST',
data
})
}
// 申请加入
export function auditSupplier(data){
return request({
url:'/supplier/potential/audit',
method:'POST',
data
})
}
// 修改申请信息
export function getSupplierInfo(key){
return request({
url:'/supplier/potential/getById',
method:'GET',
params:key
})
}
// 获取企微二维码
export function getOrCodeInfo(data){
return request({
url:'/agg-api/wxcp/createContactQrCode',
method:'POST',
data
})
}
// 获取是否添加企微结果
export function getContactQrCodeResult(data){
return request({
url:'/agg-api/wxcp/getContactQrCodeResult',
method:'POST',
data
})
}
//司机列表 //司机列表
export function driverList(data){ export function driverList(data){
return request({ return request({
@@ -318,11 +401,20 @@ export function unifiedOCRWithCompress(data){
}) })
} }
export function getArea(data){
return request({
url:'/base/area/tree',
method:'POST',
data
})
}
// 服务商是否培训 // 服务商是否培训
export function jumpPage(data){ export function jumpPage(data){
return request({ return request({
url:'/supplierAppV2/dispatchApp/user/jumpPage', url:'/supplierAppV2/dispatchApp/user/jumpPage',
method:'POST', method:'POST',
contentType:'application/json',
data data
}) })
} }

View File

@@ -77,6 +77,15 @@ export function updateOrderSettlement(data){
data data
}) })
} }
// 获取司机信息
export function getDriverInfo(data){
return request({
url:'/supplierAppV2/dispatchApp/order/getDriverInfo',
method:'POST',
contentType:'application/json',
data
})
}
// 电瓶数量列表 // 电瓶数量列表
export function batteryCountList(){ export function batteryCountList(){
return request({ return request({
@@ -151,4 +160,20 @@ export function dealWithAlarm(data) {
}) })
} }
//获取当前任务信息
export function getConfigByCode(data){
return request({
url: '/base/baseConfig/getConfigByCode',
method:'POST',
data
})
}
//获取最新版本
export function getNewVersion(key){
return request({
url: '/driverApp/app/updateVersion',
method:'GET',
params: key
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 790 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 725 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 727 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
src/assets/greTip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
src/assets/toAppBg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

BIN
src/assets/yelTip.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

View File

@@ -0,0 +1,51 @@
const authenticationRouter = [
{
path: '/auditList',
name: 'auditList',
component: () => import('@/views/rvDriverAuthentication/auditList.vue'),
meta:{
title: '小板运输司机认证',
}
},
{
path: '/personAudit',
name: 'personAudit',
component: () => import('@/views/rvDriverAuthentication/personAudit.vue'),
meta:{
title: '实名认证',
}
},
{
path: '/carAudit',
name: 'carAudit',
component: () => import('@/views/rvDriverAuthentication/carAudit.vue'),
meta:{
title: '驾驶证认证',
}
},
{
path: '/carInfoAudit',
name: 'carInfoAudit',
component: () => import('@/views/rvDriverAuthentication/carInfoAudit.vue'),
meta:{
title: '车辆信息认证',
}
},
{
path: '/bankInfo',
name: 'bankInfo',
component: () => import('@/views/rvDriverAuthentication/bankInfo.vue'),
meta:{
title: '银行卡信息认证',
}
},
{
path: '/personList',
name: 'personList',
component: () => import('@/views/mine/personList.vue'),
meta:{
title: '人员信息',
}
},
]
export default authenticationRouter

View File

@@ -5,11 +5,36 @@ import kpiRouter from './kpi-router'
import invoiceRouter from "@/router/invoice-router"; import invoiceRouter from "@/router/invoice-router";
import secondHandRouter from "@/router/second-hand-router"; import secondHandRouter from "@/router/second-hand-router";
import reportRouter from "@/router/report-router" import reportRouter from "@/router/report-router"
import authenticationRouter from "@/router/authentication-router"
const routes = [ const routes = [
{ {
path: '/', path: '/',
redirect: '/index' redirect: '/index'
}, },
{
path: '/supplierAdd',
name: 'supplierAdd',
component: () => import('@/views/index/supplierAdd'),
meta:{
title: '信息录入',
}
},
{
path: '/supplierAddResult',
name: 'supplierAddResult',
component: () => import('@/views/index/supplierAddResult'),
meta:{
title: '审核中',
}
},
{
path: '/supplierInfo',
name: 'supplierInfo',
component: () => import('@/views/index/supplierInfo'),
meta:{
title: '信息查看',
}
},
{ {
path: '/toDoList', path: '/toDoList',
name: 'toDoList', name: 'toDoList',
@@ -147,6 +172,14 @@ const routes = [
title: '车辆新增或修改' title: '车辆新增或修改'
} }
}, },
{
path: "/continueInsurance",
name: 'continueInsurance',
component: () => import('@/views/index/continueInsurance'),
meta: {
title: '续保更新'
}
},
{ {
path: '/driverManage', path: '/driverManage',
name: 'driverManage', name: 'driverManage',
@@ -291,10 +324,19 @@ const routes = [
title:'电瓶详情' title:'电瓶详情'
} }
}, },
{
path: '/goToApp',
name: 'goToApp',
component:()=>import('@/views/goToApp/goToApp.vue'),
meta: {
title:'电瓶详情'
}
},
...kpiRouter, ...kpiRouter,
...invoiceRouter, ...invoiceRouter,
...secondHandRouter, ...secondHandRouter,
...reportRouter ...reportRouter,
...authenticationRouter
] ]
const router = new VueRouter({ const router = new VueRouter({

View File

@@ -7,5 +7,13 @@ const kpiRouter = [
title: 'kpi首页', title: 'kpi首页',
} }
}, },
{
path: '/kpiCaseNew',
name: 'kpiCaseNew',
component: () => import('@/views/kpi/kpiCaseNew'),
meta:{
title: 'kpi服务商案件&车辆情况',
}
},
] ]
export default kpiRouter export default kpiRouter

View File

@@ -47,4 +47,84 @@ select{
font-size: 14px; font-size: 14px;
color: #000000; color: #000000;
} }
.text_center {
text-align: center;
}
//同意协议勾选
.protocol-list {
display: flex;
//align-items: top;
margin-top: 5px;
justify-content: center;
position: fixed;
bottom: 20px;
text-align: center;
width: 100%;
padding: 20px;
box-sizing: border-box;
.protocol-text {
font-size: 12px;
color: #203152;
line-height: 18px;
//text-align: left;
.linkColor {
color: #3364B7;
word-break: keep-all;
}
}
}
.icon_register {
width: 100%;
height: auto;
}
.mr15 {
margin-right: 15px;
}
.mt20 {
margin-top: 20px;
}
.flex_vertical_center {
display: flex;
align-items: center;
}
.flex {
display: flex;
}
.flex_between {
justify-content: space-between;
}
/*@mixin wh($w,$h) {
width: $w;
height: $h;
}
@mixin flex(){
display: flex;
}
@mixin alignCenter(){
@include flex();
align-items: center;
}
@mixin col(){
@include flex();
flex-direction: column;
}
@mixin colBothCenter(){
@include col();
justify-content: center;
align-items: center;
}
@mixin sizingPadding($t,$r,$b,$l) {
box-sizing: border-box;
padding: $t $r $b $l;
}*/
/*@mixin weigthSize($wei,$size){
font-weight:$wei ;
font-size: $size;
}
@mixin weigthSizeColor($wei,$size,$col){
@include weigthSize($wei,$size);
color: $col;
}*/

View File

@@ -23,6 +23,17 @@
div { div {
padding-top: 8px; padding-top: 8px;
} }
.commonNum{
padding: 2px 5px;
background-color: #9C9C9C;
color: white;
border-radius: 3px;
font-size: 13px;
margin-left: 3px;
}
.notFinish{
background-color: red;
}
.active { .active {
color: #3678FF; color: #3678FF;
position: relative; position: relative;

View File

@@ -1,6 +1,6 @@
@import "@/styles/mixin.scss"; @import "@/styles/mixin.scss";
::v-deep .van-nav-bar__content{ ::v-deep .van-nav-bar__content{
background-color: #3A3A3A !important; //background-color: #3A3A3A !important;
} }
.wrap{ .wrap{
@include wh(100%,100%); @include wh(100%,100%);

43
src/styles/infoShow.scss Normal file
View File

@@ -0,0 +1,43 @@
.carInfo{
margin-top: 10px;
box-sizing: border-box;
width: 100%;
min-height: 151px;
background: #FFFFFF;
padding:8px 23px 17px 30px ;
display: flex;
justify-content: space-between;
.left_wrap,.right_wrap{
display: flex;
flex-direction: column;
justify-content: space-around;
}
.title {
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #323643;
.mar_left{
margin-left: 8px;
}
.star {
color: red;
margin-right: 3px;
}
}
.right_wrap{
align-items: flex-end;
.phone{
font-size: 13px;
font-weight: 500;
color: #323643;
}
input{
font-size: 12px;
text-align: right;
&::-webkit-input-placeholder { /* WebKit browserswebkit内核浏览器 */
color: #A1A1A1;
}
}
}
}

View File

@@ -105,3 +105,32 @@
color: $col; color: $col;
line-height: $hei; line-height: $hei;
} }
@mixin width_height($width,$height){
width: $width;
height: $height;
}
@mixin flex($row,$colum){
display: flex;
justify-content: $row;
align-items: $colum;
}
@mixin center(){
display: flex;
align-items: center;
}
@mixin direction($justify-content){
display: flex;
flex-direction: column;
justify-content: $justify-content;
}
@mixin iconImg($width,$height,$marginRight){
width: $width;
height: $height;
margin-right: $marginRight;
}
@mixin iconImgLeft($width,$height,$marginRight){
width: $width;
height: $height;
margin-left: $marginRight;
}

View File

@@ -42,11 +42,89 @@ const timeFormat=(data) =>{
return formattedDate; return formattedDate;
} }
// 认证状态
const verifyStatus=(id)=> {
const ids = String(id)
const status = {
'0': 1, // 个人信息认证
'-1': 1, // 已注册
'7': 1, // 已发送待认证
'1': 2, // 驾照信息认证
'2': 3, // 车辆信息审核
'3': 4, // 银行卡信息审核
'4': 5, // 认证中
'8': 6, // 审核中
'11': 6, // 审核失败
'12': 6 // 审核成功
}
return status[ids]
}
// 认证状态 简易版
const verifyStatusSimple=(id)=> {
const ids = String(id)
const status = {
'0': 1, // 个人信息认证
'-1': 1, // 已注册
'7': 1, // 已发送待认证
'1': 3, // 驾照信息认证
'2': 3, // 车辆信息审核
'3': 4, // 银行卡信息审核
'4': 5, // 认证中
'8': 6, // 审核中
'11': 6, // 审核失败
'12': 6 // 审核成功
}
return status[ids]
}
// 认证状态
const tipString=(id)=> {
const ids = String(id)
const status = {
'0': { // 个人信息认证
tip: '认证待提交',
button: '待认证'
},
'1': { // 驾照信息认证
tip: '认证待提交',
button: '待认证'
},
'2': { // 车辆信息审核
tip: '认证待提交',
button: '待认证'
},
'3': { // 银行卡信息审核
tip: '认证待提交',
button: '待认证'
},
'4': { // 认证中
tip: '认证待提交',
button: '待认证'
},
'8': { // 审核中
tip: '认证审核中',
button: '审核中'
},
'11': { // 审核失败
tip: '认证审核失败',
button: '审核失败'
},
'12': { // 审核成功
tip: '认证审核成功',
button: '审核成功'
},
}
return status[ids]
}
module.exports = { module.exports = {
formatNumber, formatNumber,
formatDate, formatDate,
leftCopy, leftCopy,
timeFormat, timeFormat,
formatDate1 formatDate1,
verifyStatus,
verifyStatusSimple,
tipString
} }

View File

@@ -19,6 +19,7 @@ if( token ) {
service.interceptors.request.use( service.interceptors.request.use(
config => { config => {
let reqUrl=config.url let reqUrl=config.url
// console.log('config',config)
config.data = config.contentType ? config.data : qs.stringify(config.data) config.data = config.contentType ? config.data : qs.stringify(config.data)
if (config.testFlag) { if (config.testFlag) {
config.data = qs.stringify(config.data, {arrayFormat: 'indices', allowDots: true}) config.data = qs.stringify(config.data, {arrayFormat: 'indices', allowDots: true})
@@ -27,12 +28,17 @@ service.interceptors.request.use(
let token = localStorage.getItem('token'); let token = localStorage.getItem('token');
// let token='eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJBTkNIQU5HIiwidXNlcklkIjo0NTY3MSwibmFtZSI6IuWuieeVhSIsInVzZXJOYW1lIjoiQU5DSEFORyIsInN1cHBsaWVySWQiOjExMjgsImlzWmQiOjAsImV4cCI6MTc1NTQyMjUyNX0.xzDZhaANJFnbeViIHJA0SEtOyTv7Ja3rKmXqRKRuFkc' // let token='eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJBTkNIQU5HIiwidXNlcklkIjo0NTY3MSwibmFtZSI6IuWuieeVhSIsInVzZXJOYW1lIjoiQU5DSEFORyIsInN1cHBsaWVySWQiOjExMjgsImlzWmQiOjAsImV4cCI6MTc1NTQyMjUyNX0.xzDZhaANJFnbeViIHJA0SEtOyTv7Ja3rKmXqRKRuFkc'
// let token='eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJTSEhQWEIiLCJ1c2VySWQiOjU0NzI2LCJuYW1lIjoiI-a1i-ivleWwj-eZveeZvSIsInVzZXJOYW1lIjoiU0hIUFhCIiwic3VwcGxpZXJJZCI6MTAwMDE2NSwiZXhwIjoxNzQ0NTEwNzkwfQ.JPk0OA7slYJN3FIi_uhW4Y0CiWRvl6R1dK8MRTbyhD8' // let token='eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJTSEhQWEIiLCJ1c2VySWQiOjU0NzI2LCJuYW1lIjoiI-a1i-ivleWwj-eZveeZvSIsInVzZXJOYW1lIjoiU0hIUFhCIiwic3VwcGxpZXJJZCI6MTAwMDE2NSwiZXhwIjoxNzQ0NTEwNzkwfQ.JPk0OA7slYJN3FIi_uhW4Y0CiWRvl6R1dK8MRTbyhD8'
if(!(reqUrl=='/supplier/supplierTraining/trainingTask' || reqUrl=='/supplier/supplierTraining/normalList' || reqUrl=='/supplier/supplierTraining/trainingList')){ // if(!(reqUrl=='/supplier/supplierTraining/trainingTask' || reqUrl=='/supplier/supplierTraining/normalList' || reqUrl=='/supplier/supplierTraining/trainingList')){
if (reqUrl=='/supplier/supplierTraining/trainingList' && config?.params?.type==1){
console.log('司机app使用该请求不挂token')
} else {
if(token) { if(token) {
config.headers['Authorization'] = `${token}`; config.headers['Authorization'] = `${token}`;
config.headers['token'] = `${token}`; config.headers['token'] = `${token}`;
} }
} }
// }
return config return config
}, },
error => { error => {
@@ -42,6 +48,7 @@ service.interceptors.request.use(
service.interceptors.response.use( service.interceptors.response.use(
response => { response => {
console.log('response', response.data)
const res = response.data const res = response.data
if ( res.code === 401 || res.code === 400 || res.code == 500) { if ( res.code === 401 || res.code === 400 || res.code == 500) {
Toast(res.msg || 'Error') Toast(res.msg || 'Error')

102
src/utils/kpiMixins.js Normal file
View File

@@ -0,0 +1,102 @@
import dayjs from "dayjs";
export const kpiMixins = {
data() {
return {
isMobile: false,
isZd: '',
current:'2024-10',
supplierId:'',
supplierName:'',
startMonthTime: '',
startTime: '',
endTime: '',
}
},
methods: {
applicateHandle() {
if (window.parent) {
const hasListener = window.parent.dispatchEvent(new Event('checkCloseDialog'));
if (hasListener) {
const data = {
action: 'closeDialog',
message: this.supplierId,
// 其他需要传递的参数
};
window.parent.postMessage(data, '*');
} else {
window.history.back();
}
}
},
toOnlineHours(minutes) {
let _hours = parseInt(minutes / 60);
let _minutes = parseInt(minutes % 60);
return _hours + '时' + _minutes + '分'
},
// 初始化获取当月日期
initDate() {
const today = dayjs(); // 获取当前日期
const currentDay = today.date(); // 获取今天是几号1-31
let targetMonth = today; // 默认目标月份是当前月
if (currentDay === 1) {
targetMonth = today.subtract(1, 'month'); // 上个月
}
this.current = targetMonth.format('YYYY-MM');
this.startTime = targetMonth.startOf('month').format('YYYY-MM-DD HH:mm:ss');
let endTime;
if (targetMonth.isSame(today, 'month')) {
endTime = today.subtract(1, 'day').endOf('day');
} else {
endTime = targetMonth.endOf('month');
}
this.endTime = endTime.format('YYYY-MM-DD HH:mm:ss');
this.startMonthTime=this.getStartTimeFromEndTime(this.endTime)
},
//获取近四个月的开始时间
getStartTimeFromEndTime(endTimeStr) {
const startTime = dayjs(endTimeStr).subtract(3, 'month').startOf('month');
return startTime.format('YYYY-MM-DD HH:mm:ss');
},
padZero(num) {
return num < 10 ? `0${num}` : num;
},
checkMobile() {
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
this.isMobile = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent);
},
// 通用函数,用于处理百分比数据
processPercentage(value) {
value *= 100;
if (value % 1 !== 0) {
value = value.toFixed(2);
}
return value;
},
formatPercentage(value) {
let result = value * 100;
if (Number.isInteger(result)) {
return result.toString() + '%';
} else {
return result.toFixed(2) + '%';
}
},
// 格式化承接案件量数据
formatCurrency(value) {
if (!value) return '';
let num = parseInt(value);
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
},
formatCurrency1(value) {
if (!value) return ''; // 如果值为空,返回空字符串
// 如果值已经包含逗号,直接返回原值
if (value.toString().includes(',')) {
return value;
}
// 否则,添加千分号
let num = parseInt(value);
if (isNaN(num)) return ''; // 如果转换失败,返回空字符串
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
},
}
}

View File

@@ -5,6 +5,12 @@ export const myMixins = {
} }
}, },
methods: { methods: {
showFun() {
if( localStorage.getItem('infoVerify') == 8 || localStorage.getItem('infoVerify') == 12 ) {
return false
}
return true
},
goPage(page, query) { goPage(page, query) {
this.$router.push({ this.$router.push({
name: page, name: page,
@@ -88,6 +94,7 @@ export const myMixins = {
isWebFunc(){ isWebFunc(){
let res=false let res=false
var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); var isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
console.log('isMobile',isMobile)
if (!isMobile) {// 是移动端不变 if (!isMobile) {// 是移动端不变
res=true res=true
} }

View File

@@ -1,6 +1,28 @@
<template> <template>
<div class="wrap"> <div class="wrap">
<div class="navBar"> <div class="navBar">
<van-nav-bar
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="goBack"
>
<template slot="title">
<div v-show="!show">培训文档</div>
<van-field v-model="keyword" placeholder="请输入关键词" v-show="show" @input="getTrainingList"/>
</template>
<template slot="right">
<div class="rightWrap" @click="show = !show">
<img src="@/assets/serach.png" class="img2" v-show="!show"/>
<img src="@/assets/delKey.png" class="img2" v-show="show" @click="initShow"/>
</div>
</template>
</van-nav-bar>
</div>
<!-- <div class="navBar">
<van-nav-bar <van-nav-bar
:border="false" :border="false"
:fixed="true" :fixed="true"
@@ -24,7 +46,8 @@
</template> </template>
</van-nav-bar> </van-nav-bar>
</div> </div>
<div class="statisticContainer"> -->
<!-- <div class="statisticContainer">
<div class="statisticWrap"> <div class="statisticWrap">
<div class="line1"> <div class="line1">
<span>培训统计</span> <span>培训统计</span>
@@ -43,11 +66,12 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>-->
<div class="driver_tab_wrap"> <div class="tab_wrap">
<div v-for="(item, index) in tabArr" :key="index" :class="{'active' : activeIndex == index}" <div v-for="(item, index) in tabArr" :key="index" :class="{'active' : activeIndex == index}"
@click="changeTab(index)"> @click="changeTab(index)">
{{ item.name }} {{ item.name }}<span v-if="item.count" :class="{'commonNum':true,'notFinish':index==2}">{{item.count}}</span>
<!-- {{ item.name }}-->
</div> </div>
</div> </div>
<div class="contentWrap" v-show="!showEmpty"> <div class="contentWrap" v-show="!showEmpty">
@@ -84,12 +108,14 @@ export default {
mixins:[myMixins], mixins:[myMixins],
data(){ data(){
return{ return{
tabArr: [{name: '车型技术参数', status: 1}, {name: '中道服务规范', status:2},{name: '中道小课堂', status: 3}], tabArr: [{name: '全部文档', status: 1,count:0}, {name: '已培训', status:2,count:0},{name: '未培训', status: 3,count:0}],
// tabArr: [{name: '车型技术参数', status: 1}, {name: '中道服务规范', status:2},{name: '中道小课堂', status: 3}],
activeIndex: 0, activeIndex: 0,
pageList:[], pageList:[],
totalList:[], totalList:[],
numInfo:'', numInfo:'',
keyword:'', keyword:'',
serviceTypeName:'',
show:false, show:false,
showEmpty:false, showEmpty:false,
isLoading:false, isLoading:false,
@@ -102,6 +128,7 @@ export default {
this.driverId = urlParams.get('driverId'); this.driverId = urlParams.get('driverId');
this.time=timeFormat(Date.now()) this.time=timeFormat(Date.now())
this.keyword=urlParams.get('keyword') || '' this.keyword=urlParams.get('keyword') || ''
this.serviceTypeName=urlParams.get('serviceTypeName') || ''
this.getTrainingList(); this.getTrainingList();
document.addEventListener('visibilitychange', async ( ) => { document.addEventListener('visibilitychange', async ( ) => {
let state = document.visibilityState let state = document.visibilityState
@@ -113,6 +140,10 @@ export default {
}); });
}, },
methods:{ methods:{
initShow(){
this.keyword= ''
this.getTrainingList()
},
onRefresh() { onRefresh() {
this.getTrainingList() this.getTrainingList()
setTimeout(() => { setTimeout(() => {
@@ -129,21 +160,42 @@ export default {
type:1, type:1,
id:this.driverId, id:this.driverId,
text:this.keyword || '', text:this.keyword || '',
serviceTypeName:this.serviceTypeName || ''
}) })
this.totalList=[] this.totalList=[]
this.pageList=[] this.pageList=[]
this.tabArr[0].count=0
this.tabArr[1].count=0
this.tabArr[2].count=0
this.numInfo=res.data this.numInfo=res.data
this.totalList=res.data.list if(res.data.totalNum){
let result=[] this.tabArr[0].count=res.data.totalNum
}
if(res.data.readNum){
this.tabArr[1].count=res.data.readNum
}
if(res.data.notReadNum){
this.tabArr[2].count=res.data.notReadNum
}
/* this.totalList=res.data.list
if(this.activeIndex === 0){ if(this.activeIndex === 0){
result=this.totalList?.filter(q => q.title === '车型技术参数'); result=this.totalList?.filter(q => q.title === '车型技术参数');
}else if(this.activeIndex === 1){ }else if(this.activeIndex === 1){
result=this.totalList?.filter(q => q.title === '中道服务规范'); result=this.totalList?.filter(q => q.title === '中道服务规范');
}else if(this.activeIndex === 2){ }else if(this.activeIndex === 2){
result=this.totalList?.filter(q => q.title === '中道小课堂'); result=this.totalList?.filter(q => q.title === '中道小课堂');
}*/
let result=[]
this.totalList=res?.data?.list ? res?.data?.list[0]?.materials : []
if(this.activeIndex === 0){
result=this.totalList || []
}else if(this.activeIndex === 1){
result=this.totalList?.filter(item => item.alreadyRead==1) || []
}else if(this.activeIndex === 2){
result=this.totalList?.filter(item => item.alreadyRead!=1) || []
} }
if(result){ if(result){
this.pageList=result[0].materials this.pageList=result
this.time=timeFormat(Date.now()) this.time=timeFormat(Date.now())
} }
if(this.pageList?.length === 0){ if(this.pageList?.length === 0){
@@ -160,6 +212,19 @@ export default {
@import "@/styles/mixin.scss"; @import "@/styles/mixin.scss";
@import "@/styles/docment.scss"; @import "@/styles/docment.scss";
@import "@/styles/driverDocment.scss"; @import "@/styles/driverDocment.scss";
/*::v-deep .van-nav-bar__content{
background-color: #3A3A3A !important;
}*/
.tab_wrap {
.active:after {
width: 37px;
left: 0%;
transform: translateX(0%);
}
.active1:after {
width:48px !important;
}
}
.read{ .read{
padding: 2px 8px; padding: 2px 8px;
border-radius: 5px; border-radius: 5px;

View File

@@ -94,6 +94,7 @@ export default {
showEmpty:false, showEmpty:false,
supplierId:'', supplierId:'',
driverId:'', driverId:'',
serviceTypeName:'',
} }
}, },
mounted() { mounted() {
@@ -103,6 +104,7 @@ export default {
if(this.driverId){ if(this.driverId){
this.keyword=urlParams.get('keyword') || '' this.keyword=urlParams.get('keyword') || ''
} }
this.serviceTypeName=urlParams.get('serviceTypeName') || ''
this.getNormalList() this.getNormalList()
}, },
methods:{ methods:{
@@ -128,6 +130,7 @@ export default {
type:this.supplierId ? 2 : 1, type:this.supplierId ? 2 : 1,
id: this.supplierId ? this.supplierId : this.driverId, id: this.supplierId ? this.supplierId : this.driverId,
text:this.keyword || '', text:this.keyword || '',
serviceTypeName:this.serviceTypeName || ''
}) })
this.totalList=res.data.list this.totalList=res.data.list
let result=[] let result=[]

View File

@@ -22,9 +22,9 @@
</van-nav-bar> </van-nav-bar>
</div> </div>
<div class="tab_wrap"> <div class="tab_wrap">
<div v-for="(item, index) in tabArr" :key="index" :class="{'active' : activeIndex == index}" <div v-for="(item, index) in tabArr" :key="index" :class="{'active' : activeIndex == index,'active1':activeIndex==0}"
@click="changeTab(index)"> @click="changeTab(index)">
{{ item.name }} {{ item.name }}<span v-if="item.count" :class="{'commonNum':true,'notFinish':index==2}">{{item.count}}</span>
</div> </div>
</div> </div>
<div class="contentWrap" v-show="!showEmpty"> <div class="contentWrap" v-show="!showEmpty">
@@ -61,22 +61,30 @@ export default {
mixins:[myMixins], mixins:[myMixins],
data(){ data(){
return{ return{
tabArr: [{name: '车型技术参数', status: 1}, {name: '中道服务规范', status:2},{name: '中道小课堂', status: 3}], tabArr: [{name: '全部文档', status: 1,count:0}, {name: '已培训', status:2,count:0},{name: '未培训', status: 3,count:0}],
activeIndex: 0, activeIndex: 0,
pageNum:1, pageNum:1,
pageSize:10, pageSize:10,
pageList:[], pageList:[],
totalList:[], totalList:[],
keyword:'', keyword:'',
serviceTypeName:'',
show:false, show:false,
showEmpty:false, showEmpty:false,
isLoading:false, isLoading:false,
supplierId:'', supplierId:'',
numInfo:'',
} }
}, },
activated() {
console.log('activated')
},
mounted() { mounted() {
console.log('mounted')
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
this.supplierId = urlParams.get('supplierId'); this.supplierId = urlParams.get('supplierId');
this.keyword=urlParams.get('keyword') || ''
this.serviceTypeName=urlParams.get('serviceTypeName') || ''
this.getTrainingList(); this.getTrainingList();
document.addEventListener('visibilitychange', async ( ) => { document.addEventListener('visibilitychange', async ( ) => {
let state = document.visibilityState let state = document.visibilityState
@@ -104,20 +112,39 @@ export default {
type:2, type:2,
id: this.supplierId, id: this.supplierId,
text:this.keyword || '', text:this.keyword || '',
serviceTypeName:this.serviceTypeName || ''
}) })
this.totalList=[] this.totalList=[]
this.pageList=[] this.pageList=[]
this.totalList=res.data.list this.tabArr[0].count=0
this.tabArr[1].count=0
this.tabArr[2].count=0
this.totalList=res?.data?.list ? res?.data?.list[0]?.materials : []
this.numInfo=res.data
if(res.data.totalNum){
this.tabArr[0].count=res.data.totalNum
}
if(res.data.readNum){
this.tabArr[1].count=res.data.readNum
}
if(res.data.notReadNum){
this.tabArr[2].count=res.data.notReadNum
}
// console.log(' this.totalList',this.totalList)
console.log(' this.tabArr',this.tabArr)
let result=[] let result=[]
if(this.activeIndex === 0){ if(this.activeIndex === 0){
result=this.totalList?.filter(q => q.title === '车型技术参数'); result=this.totalList || []
// result=this.totalList?.filter(q => q.title === '车型技术参数');
}else if(this.activeIndex === 1){ }else if(this.activeIndex === 1){
result=this.totalList?.filter(q => q.title === '中道服务规范'); // result=this.totalList?.filter(q => q.title === '中道服务规范');
result=this.totalList?.filter(item => item.alreadyRead==1) || []
}else if(this.activeIndex === 2){ }else if(this.activeIndex === 2){
result=this.totalList?.filter(q => q.title === '中道小课堂'); result=this.totalList?.filter(item => item.alreadyRead!=1) || []
// result=this.totalList?.filter(q => q.title === '中道小课堂');
} }
if(result){ if(result){
this.pageList=result[0].materials this.pageList=result
} }
if(this.pageList?.length === 0){ if(this.pageList?.length === 0){
this.showEmpty = true this.showEmpty = true
@@ -126,7 +153,7 @@ export default {
} }
}, },
initShow(){ initShow(){
this.keyword= '', this.keyword= ''
this.getTrainingList() this.getTrainingList()
} }
} }
@@ -136,6 +163,16 @@ export default {
@import "@/styles/common.scss"; @import "@/styles/common.scss";
@import "@/styles/mixin.scss"; @import "@/styles/mixin.scss";
@import "@/styles/docment.scss"; @import "@/styles/docment.scss";
.tab_wrap {
.active:after {
width: 37px;
left: 0%;
transform: translateX(0%);
}
.active1:after {
width:48px !important;
}
}
.read{ .read{
padding: 2px 8px; padding: 2px 8px;
border-radius: 5px; border-radius: 5px;

View File

@@ -0,0 +1,73 @@
<template>
<div class="wrap">
<div class="content">
<div class="goToBtn" @click="goAppHandler">立即打开</div>
<div class="content_tip">
<div class="font_cls">如未安装请点击下载</div>
<div class="font_cls">如已安装未自动跳转 <span @click="downLoadHandler">立即下载</span></div>
</div>
</div>
</div>
</template>
<script>
import { getNewVersion } from "@/api/order"
export default {
name: "goToApp",
methods: {
goAppHandler() {
window.location.href = "rvdriver://page/pagesLogin/phoneLogin?source=h5Link";
},
async downLoadHandler() {
getNewVersion({
appType: 5
}).then((res) => {
window.location.href = res?.result?.path
}).catch(() => {
this.$message.error('请求版本失败,请重试');
});
}
}
}
</script>
<style lang="scss" scoped>
.wrap {
width: 100%;
height: 100vh;
background-image: url('@/assets/toAppBg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
}
.content {
width: 100%;
position: fixed;
top: 74vh;
}
.goToBtn {
width: 70%;
height: 45px;
margin-left: 15%;
background: linear-gradient( 270deg, #2347C0 0%, #72A3FF 100%);
border-radius: 23px;
//font-weight: bold;
font-size: 17px;
color: #FFFFFF;
letter-spacing: 2px;
line-height: 45px;
text-align: center;
}
.content_tip {
width: 100%;
margin-top: 15px;
.font_cls {
font-size: 14px;
color: #808080;
line-height: 20px;
text-align: center;
span {
color: #007BE9;
}
}
}
</style>

View File

@@ -0,0 +1,494 @@
<template>
<div class="wrap vehicleAdd">
<div class="navBar">
<van-nav-bar
title="续保更新"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="back"
/>
</div>
<div class="addContentWrap">
<div class="itemContent">
<div class="titleType">
<img class="startImg" src="@/assets/start.png" />
<span>有无投保救援职业责任险或货运险</span>
</div>
<div class="isJoin">
<van-radio-group v-model="hasLiabilityInsurance" @change="isChange" class="joinWrap">
<van-radio :name="1" style="margin-right: 26px">
<img
slot="icon"
slot-scope="props"
:src="props.checked ? activeIcon : inactiveIcon"
>
</van-radio>
<van-radio :name="0">
<img
slot="icon"
slot-scope="props"
:src="props.checked ? activeIcon : inactiveIcon"
>
</van-radio>
</van-radio-group>
</div>
</div>
<span style="color: red">如有投保未投保选不必上传交强险或者商业险等其他保单</span>
<div class="lineBot"></div>
<template v-if="hasLiabilityInsurance == 1">
<div class="itemContent">
<div class="titleType">
<img class="startImg" src="@/assets/start.png" />
<span style="line-height: 20px">请上传救援职业责任险或货运险保单PDF或者关键信息页截图</span>
</div>
<van-uploader
v-model="insurancePictureFiles"
:after-read="insurancePictureFilesHandler"
max-count="1"
:preview-size="54"
accept="image "
/>
</div>
<div class="lineBot"></div>
<div class="itemContent">
<div class="titleType">
<img class="startImg" src="@/assets/start.png" />
<span>承保保司</span>
</div>
<el-select
v-model="insuranceCorp"
value-key="name"
class="elSelect"
collapse-tags="collapse-tags"
placeholder="请选择" style="width: 55%"
>
<el-option
v-for="item in insuranceOptions"
:key="item.name"
:label="item.name"
:value="item.value"
>
</el-option>
</el-select>
</div>
<div class="lineBot"></div>
<div class="itemContent">
<div class="titleType">
<img class="startImg" src="@/assets/start.png" />
<span>保险有效期</span>
</div>
<el-input style="width: 55%" readonly @focus="showDatePicker = true" v-model="dateVal" placeholder="请选择发布日期" :class="{'customSel':true,'customInput':true , 'has-value': dateVal }" >
<template #suffix>
<i
v-if="dateVal"
class="el-icon-circle-close el-input__icon"
@click="dateVal = ''"
></i>
</template>
</el-input>
</div>
<div class="lineBot" v-if="permissonList?.includes('hasInsuranceAudit')"></div>
<div class="itemContent" v-if="permissonList?.includes('hasInsuranceAudit')" style="align-items: center">
<div class="titleType" style="width: 60px">
<img class="startImg" src="@/assets/start.png" />
<span>保费</span>
</div>
<van-field
type="number"
class="vanIpt"
v-model="liabilityInsuranceAmount"
input-align="right"
>
<template slot="right-icon" >
<span style="white-space: nowrap;"></span>
</template>
</van-field>
</div>
<div class="lineBot" v-if="permissonList?.includes('hasInsuranceAudit')"></div>
<div class="itemContent" v-if="permissonList?.includes('hasInsuranceAudit')">
<div class="titleType">
<img class="startImg" src="@/assets/start.png" />
<span>保额</span>
</div>
<div style="display:flex;align-items: center;justify-content: flex-end">
<el-select
v-model="liabilityInsuranceQuota"
value-key="name"
class="elSelect"
collapse-tags="collapse-tags"
placeholder="请选择" style="width: 55%"
>
<el-option
v-for="item in liabilityQuotaOptions"
:key="item.value"
:label="item.value"
:value="item.value"
>
</el-option>
</el-select><span style="margin-right: 16px;opacity: .5;">万元</span>
</div>
<!-- <van-field
type="number"
class="vanIpt"
v-model="liabilityInsuranceQuota"
input-align="right"
>
<template slot="right-icon" >
<span style="white-space: nowrap;">万元 </span>
</template>
</van-field>-->
</div>
</template>
<common-btn title="保存" @submitClick="submitBtn"/>
<van-calendar v-model="showDatePicker" :min-date="minDate"
:max-date="maxDate" type="range" @confirm="onConfirm" />
</div>
</div>
</template>
<script>
import {Dialog} from "vant";
import {myMixins} from "@/utils/myMixins"
import {formatDate1} from "@/utils/common"
import { uploadImage, updateInsurance, getInfoById,userOperationPermissions} from "@/api/mine"
import CommonBtn from "@/components/commonBtn.vue"
export default {
name: "vehicleAdd",
mixins:[myMixins],
data(){
return{
defaultProps: {
children: 'children',
label: 'name'
},
liabilityQuotaOptions:[{value:10},{value:20},{value:30},{value:50},{value:70},{value:80},{value:100},{value:200}],
minDate: new Date(1970, 0, 1), // 设置最小可选日期1970年1月1日
maxDate: new Date(2099, 11, 31), // 设置最大可选日期2099年12月31日
showDatePicker: false,
dateVal: '',
hasLiabilityInsurance: 1, // 有无责任险
activeIcon: require('@/assets/check.png'),
inactiveIcon: require('@/assets/uncheck.png'),
// result: [],
checked: true,
show:false,
imageUrl: require('@/assets/arr_right.png'),
insurancePictureFiles: [],
insurancePicturePhoto: '', // 保单照片
isMultiple: false, // 是否支持多选
insuranceCorp: '',
liabilityInsuranceAmount:'',
liabilityInsuranceQuota:'',
permissonList:[],
insuranceOptions: [{
name: '太平洋',
value: 1
}, {
name: '人保',
value: 2
}, {
name: '平安',
value: 3
}, {
name: '中华联合',
value: 4
}, {
name: '大地',
value: 5
}, {
name: '阳光',
value: 6
}, {
name: '太平',
value: 7
}, {
name: '人寿',
value: 8
}, {
name: '永安',
value: 9
}, {
name: '华安',
value: 10
}, {
name: '申能',
value: 11
}, {
name: '大家',
value: 12
}, {
name: '富德',
value: 13
}, {
name: '其他',
value: 14
}]
}
},
computed: {
},
watch:{
},
async mounted() {
this.id=this.$route.params?.id
await this.getPermissions()
if( this.id){
// await this.vehicleInfo()
}
},
methods:{
back() {
this.$router.push({
name:'vehicleAdd',
params:{
id: this.id
}
})
},
async getPermissions(){
let res = await userOperationPermissions();
this.permissonList = res.data
},
async vehicleInfo(){
let res= await getInfoById({
vehicleId:this.id
})
let result=res.data;
this.id=result.vehicleId
this.insurancePicturePhoto = result.insurancePicturePhoto;
this.hasLiabilityInsurance = result.hasLiabilityInsurance
this.insuranceCorp = result.insuranceCorp;
if(this.insurancePicturePhoto) {
this.insurancePictureFiles = [{url: this.insurancePicturePhoto}]
}
if( result.liabilityInsuranceEndTime && result.liabilityInsuranceStartTime ) {
this.dateVal = formatDate1(result.liabilityInsuranceStartTime) + ' - ' + formatDate1(result.liabilityInsuranceEndTime)
}
},
formatDate(date) {
return `${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}`;
},
onConfirm(date) {
const [start, end] = date;
this.showDatePicker = false;
this.dateVal = `${this.formatDate(start)} - ${this.formatDate(end)}`;
},
formatDateTimeRange(str) {
const [startStr, endStr] = str.split(' - ').map(s => s.trim());
const startDate = new Date(startStr);
const startTime = `${startDate.getFullYear()}-${(startDate.getMonth() + 1).toString().padStart(2, '0')}-${startDate.getDate().toString().padStart(2, '0')} 00:00:00`;
const endDate = new Date(endStr);
const endTime = `${endDate.getFullYear()}-${(endDate.getMonth() + 1).toString().padStart(2, '0')}-${endDate.getDate().toString().padStart(2, '0')} 23:59:59`;
return {
startTime,
endTime
};
},
async insurancePictureFilesHandler(file) {
const formData = new FormData();
formData.append("file" , file.file);
let res = await uploadImage(formData);
this.insurancePicturePhoto = res.data;
},
isChange(e){
this.hasLiabilityInsurance=e
if (e === 0) {
Dialog.confirm({
title: '提醒',
message: '有救援职业责任险车辆会提升案件聚合能力和接单能力。',
confirmButtonText: '我已知晓', // 确认按钮文字,默认为“确认”
showCancelButton: false // 是否显示取消按钮,默认为 true。如果不需要取消按钮可以设置为 false。
})
.then(() => { /* 确认后的操作 */ })
.catch(() => { /* 取消后的操作 */ });
}
},
async submitBtn(){
if(this.hasLiabilityInsurance === null || this.hasLiabilityInsurance === undefined || this.hasLiabilityInsurance === '') { // 有职业责任险,就需要有保单照片
this.$toast('救援职业责任险不能为空')
return
}
if(!this.insurancePicturePhoto && this.hasLiabilityInsurance == 1) { // 有职业责任险,就需要有保单照片
this.$toast('保单照片不能为空')
return
}
if(!this.insuranceCorp && this.hasLiabilityInsurance == 1) { // 有职业责任险,就需要有保单照片
this.$toast('承保保司不能为空')
return
}
if(!this.dateVal && this.hasLiabilityInsurance == 1) { // 有职业责任险,就需要有保单照片
this.$toast('保单有效期不能为空')
return
}
if(this.hasLiabilityInsurance == 1 && this.permissonList?.includes('hasInsuranceAudit') && !this.liabilityInsuranceAmount && this.liabilityInsuranceAmount!=0){
this.$toast('保费不能为空')
return
}
if(this.hasLiabilityInsurance == 1 && !this.liabilityInsuranceQuota && this.permissonList?.includes('hasInsuranceAudit')){
this.$toast('保额不能为空')
return
}
let timeObj;
if(this.dateVal) {
timeObj = this.formatDateTimeRange(this.dateVal)
}
let params = {
id: this.id ? this.id : '',
renewInsureInfo: JSON.stringify({
hasLiabilityInsurance: this.hasLiabilityInsurance,
insurancePictureUrls: this.hasLiabilityInsurance == 1 ? this.insurancePicturePhoto : '',
insuranceCorp: this.hasLiabilityInsurance == 1 ? this.insuranceCorp : '',
liabilityInsuranceStartTime: this.hasLiabilityInsurance == 1 ? (timeObj?.startTime || '' ) : '',
liabilityInsuranceEndTime: this.hasLiabilityInsurance == 1 ? (timeObj?.endTime || '') : '',
liabilityInsuranceQuota:this.liabilityInsuranceQuota || '',
liabilityInsuranceAmount:this.liabilityInsuranceAmount || '',
})
}
await updateInsurance(params)
if(this.id){
this.$toast('修改成功')
}else{
this.$toast('添加成功')
}
setTimeout(()=>{
// this.$router.back();
this.back()
},2000)
}
},
components:{
CommonBtn
}
}
</script>
<style>
.vehicleAdd .van-field__control:disabled {
color: #323643 !important;
-webkit-text-fill-color: #323643 !important;
}
</style>
<style scoped lang="scss">
@import "@/styles/mixin.scss";
@import "@/styles/common.scss";
.mySelect{
@include fontWeightSize(bold,13px);
color: #323643;
appearance: none;
padding-right: 16px;
background: url('@/assets/arrow_bot.png') no-repeat right center / 15px 14px;
}
.checkbox-group {
display: none;
}
.navBar{
margin-bottom: 46px;
}
.wrap{
@include wh(100%,100%);
overflow-y: auto;
}
.addContentWrap{
margin-left: 16px;
.item_content_btn {
padding-right: 25px;
text-align: right;
span {
display: inline-block;
background: #354D93;
padding: 5px 10px;
font-size: 12px;
font-weight: bold;
color: #fff;
border-radius: 4px;
margin-bottom: 5px;
}
}
.itemContent{
@include flexColBet;
line-height: 56px;
box-sizing: border-box;
padding-right: 25px;
.titleType{
@include fontWeightSize(bold,14px);
color: #323643;
}
.isJoin{
display: flex;
.joinWrap{
display: flex;
}
img{
@include widHeiMar(16px,16px,6px)
}
}
.startImg{
@include widHeiMar(6px,6px,3px);
vertical-align: super;
}
input{
border: none;
text-align: right;
@include fontWeightSize(bold,13px);
opacity: .5;
}
}
.lineBot{
@include wh(100%,1px);
background: #E9E9EA;
opacity: 0.6;
}
.serviceType{
@include fontWeightSize(bold,13px);
margin-left: 15px;
.trailerService{
margin-bottom: 10px;
}
.serviceline{
@include flexCenter;
margin-bottom: 10px;
}
.item{
margin: 20px 0;
@include flexCenter;
}
.radioWrap{
margin-left: 10px;
}
.service{
@include colorOpa(#323643,0.7);
line-height: 18px;
white-space: nowrap;
}
.line{
display: inline-block;
@include wh(240px,2px);
opacity: 0.16;
border-bottom: 1px solid;
border-image: linear-gradient(270deg, rgba(217, 217, 217, 0.6), rgba(178, 178, 178, 1), rgba(178, 178, 178, 1), rgba(217, 217, 217, 0.6)) 1 1;
}
img{
@include widHeiMar(16px,16px,12px)
}
}
.btn{
width: 90%;
margin: 40px 0 30px 8px;
}
}
.elSelect ::v-deep .el-input__inner{
border: none !important;
text-align: right !important;
}
.disabled-tree {
pointer-events: none;
opacity: 0.6;
}
</style>

View File

@@ -67,7 +67,7 @@
accept="image " accept="image "
/> />
</div> </div>
<div class="lineBot"></div> <!-- <div class="lineBot"></div>
<div class="itemContent"> <div class="itemContent">
<div class="titleType"> <div class="titleType">
<img class="startImg" src="@/assets/start.png" /> <img class="startImg" src="@/assets/start.png" />
@@ -80,11 +80,12 @@
:preview-size="54" :preview-size="54"
accept="image " accept="image "
/> />
</div> </div>-->
<div class="lineBot"></div> <div class="lineBot"></div>
<div class="itemContent"> <div class="itemContent">
<div class="titleType"> <div class="titleType">
<span>头像</span> <img class="startImg" src="@/assets/start.png" />
<span>免冠正面照</span>
</div> </div>
<van-uploader <van-uploader
v-model="iconList" v-model="iconList"
@@ -307,7 +308,7 @@ export default {
let res = await uploadImage(formData) let res = await uploadImage(formData)
this.drivingLicenceContrary = res.data; this.drivingLicenceContrary = res.data;
}, },
async iconListHandler(file) { // 上传头像 async iconListHandler(file) { // 上传免冠正面照
const formData = new FormData(); const formData = new FormData();
formData.append("file" , file.file); formData.append("file" , file.file);
let res = await uploadImage(formData) let res = await uploadImage(formData)
@@ -399,9 +400,13 @@ export default {
this.$toast('驾驶证首页未上传') this.$toast('驾驶证首页未上传')
return return
} }
if(!this.drivingLicenceContrary) { /* if(!this.drivingLicenceContrary) {
this.$toast('驾驶证副页未上传') this.$toast('驾驶证副页未上传')
return return
}*/
if(!this.icon) {
this.$toast('免冠正面照未上传')
return
} }
let drivingLicenceName=this.drivingLicenceName.replace(/[^\u4e00-\u9fff]+/g, ''); let drivingLicenceName=this.drivingLicenceName.replace(/[^\u4e00-\u9fff]+/g, '');
let driverName=this.driverName.replace(/[^\u4e00-\u9fff]+/g, ''); let driverName=this.driverName.replace(/[^\u4e00-\u9fff]+/g, '');

View File

@@ -18,6 +18,43 @@
</template> </template>
</van-nav-bar> </van-nav-bar>
</div> </div>
<van-search
v-model="searchVal"
show-action
placeholder="请输入司机姓名、电话、身份证号"
@search="resetHandler"
>
<template #action>
<div @click="resetHandler">搜索</div>
</template>
</van-search>
<div class="filterWrap">
<el-select @change="resetHandler" multiple :collapse-tags="true" v-model="idCardStatusList" placeholder="身份证录入状态" :class="{'customSel':true , 'has-value': idCardStatusList }" clearable>
<el-option
v-for="item in idCardStatusListOptions"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
<el-select @change="resetHandler" multiple :collapse-tags="true" v-model="driverLicenseStatusList" placeholder="驾驶证录入状态" :class="{'customSel':true , 'has-value': driverLicenseStatusList }" clearable>
<el-option
v-for="item in driverLicenseStatusListOptions"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
<el-select @change="resetHandler" multiple :collapse-tags="true" v-model="authStatusList" placeholder="认证状态" :class="{'customSel':true , 'has-value': authStatusList }" clearable>
<el-option
v-for="item in authStatesOptions"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
</div>
<div class="wrap_cls">
<van-pull-refresh v-model="isLoading" @refresh="onRefresh"> <van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<van-list <van-list
v-model="loading" v-model="loading"
@@ -25,13 +62,32 @@
finished-text="没有更多了" finished-text="没有更多了"
@load="onLoad" @load="onLoad"
> >
<div class="itemWrap" v-for="(item,index) in driverList" :key="index"> <div class="itemWrap" v-for="(item,index) in driverList" :key="index" @click.stop="updateDriver(item)">
<div class="name-status"> <div class="name-status">
<div class="namephone">{{ item.driverName }} / {{ item.driverPhone }}</div> <div class="namephone">{{ item.driverName }} / {{ item.driverPhone }}
<div class="twoBtn"> <span style="margin-left: 10px" :class="item.states?.code == 1 ? 'statusYes' : 'statusNo'">{{ item.states?.label }}</span>
<button v-if="permissonList.includes('driverModifyBtn')" class="del" @click="handleStatus(item)">{{ item.states?.label == '启用' ? '停用' : '启用' }}</button>
<button v-if="permissonList.includes('driverModifyBtn')" class="revise" @click="updateDriver(item)">修改</button>
</div> </div>
<div class="twoBtn">
<!-- 只有启用状态下才展示停用按钮-->
<button v-if="permissonList.includes('driverModifyBtn') && item.states?.code==1" class="del" @click.stop="handleStatus(item)">停用</button>
<!-- <button v-if="permissonList.includes('driverModifyBtn')" class="revise" @click="updateDriver(item)">修改</button>-->
</div>
</div>
<div class="juhe flex-between">
<span class="zdJuhe">录入状态</span>
<span class="flex-right">
<span class="common_cls" v-if="item.idCardStatusStr" :class="getClass(item.idCardStatus)?.className">{{item.idCardStatusStr}}</span>
<span class="common_cls" v-if="item.driverLicenseStatusStr" :class="getClass(item.driverLicenseStatus)?.className">{{item.driverLicenseStatusStr}}</span>
</span>
<!-- <span class="flex-right" v-if="item.idCardStatusStr">
<span class="common_cls" :class="getClass(item.idCardStatus)?.className">{{item.idCardStatusStr}}</span>
</span>-->
</div>
<div class="juhe flex-between">
<span class="zdJuhe">认证状态</span>
<span class="flex-right" v-if="item.authStatusStr">
<span class="common_cls" :class="getClass(item.authStatusStr)?.className">{{item.authStatusStr}}</span>
</span>
</div> </div>
<div class="" style="display: flex"> <div class="" style="display: flex">
<div class="sex" style="margin-right: 40px"> <div class="sex" style="margin-right: 40px">
@@ -47,22 +103,24 @@
<span class="halfOpci">身份证号:</span> <span class="halfOpci">身份证号:</span>
<span class="allOpci">{{ item.identityCardNumber }}</span> <span class="allOpci">{{ item.identityCardNumber }}</span>
</div> </div>
<div> <van-icon class="arrow_position" v-if="permissonList.includes('driverModifyBtn')" name="arrow" />
<!-- <div>
<span class="halfOpci">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span> <span class="halfOpci">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:</span>
<span :class="item.states?.code == 1 ? 'statusYes' : 'statusNo'">{{ item.states?.label }}</span> <span :class="item.states?.code == 1 ? 'statusYes' : 'statusNo'">{{ item.states?.label }}</span>
</div>-->
</div> </div>
</div>
</van-list> </van-list>
</van-pull-refresh> </van-pull-refresh>
</div> </div>
</div>
</template> </template>
<script> <script>
import {myMixins} from "@/utils/myMixins" import {myMixins} from "@/utils/myMixins"
import {driverList,enableAction,userOperationPermissions} from "@/api/mine" import {driverList, enableAction, userOperationPermissions} from "@/api/mine"
import {Dialog} from "vant";
export default { export default {
name: "driverManage", name: "driverManage",
mixins:[myMixins], mixins:[myMixins],
@@ -79,6 +137,40 @@ export default {
loading: false, loading: false,
finished: false, finished: false,
permissonList:[], permissonList:[],
searchVal:'',
idCardStatusList:[],
driverLicenseStatusList:[],
authStatusList:[],
idCardStatusListOptions: [{
name: '身份证未录入',
value: 0
},{
name: '身份证核验通过',
value: 1
},{
name: '身份证核验不通过',
value: 2
}],
authStatesOptions: [{
name: '免冠正面照未录入',
value: 1
},{
name: '免冠正面照认证通过',
value: 3
},{
name: '免冠正面照认证不通过',
value: 2
}],
driverLicenseStatusListOptions: [{
name: '驾驶证未录入',
value: 0
},{
name: '驾驶证认证通过',
value: 1
},{
name: '驾驶证认证不通过',
value: 2
}],
} }
}, },
mounted() { mounted() {
@@ -88,9 +180,41 @@ export default {
// this.getDriverList() // this.getDriverList()
}, },
methods:{ methods:{
getClass(id) {
const ids = String(id)
const steps = {
0: {
className: 'default_cls'
},
1: {
className: 'success_cls'
},
2: {
className: 'danger_cls'
},
'免冠正面照未录入': {
className: 'default_cls'
},
'免冠正面照认证通过': {
className: 'success_cls'
},
'免冠正面照认证不通过': {
className: 'danger_cls'
},
}
return steps[ids] || { className: 'default_cls' }
},
async resetHandler() {
this.pageNum=1
this.finished = false;
this.total = 0;
await this.getDriverList();
},
async onLoad(){ async onLoad(){
await this.getDriverList() await this.getDriverList()
if (this.total>10){
this.pageNum++; this.pageNum++;
}
// 加载状态结束 // 加载状态结束
this.loading = false; this.loading = false;
// 数据全部加载完成 // 数据全部加载完成
@@ -118,7 +242,11 @@ export default {
async getDriverList(){ async getDriverList(){
let res = await driverList({ let res = await driverList({
pageNum:this.pageNum, pageNum:this.pageNum,
pageSize:this.pageSize pageSize:this.pageSize,
searchVal: this.searchVal,
idCardStatusList: this.idCardStatusList,
driverLicenseStatusList: this.driverLicenseStatusList,
authStatusList: this.authStatusList,
}); });
if(res.code == 200){ if(res.code == 200){
this.total=res.total this.total=res.total
@@ -130,12 +258,11 @@ export default {
this.driverList = preList.concat(arr) this.driverList = preList.concat(arr)
} }
} }
console.log('this.driverList',this.driverList)
}, },
async getPermissions(){ async getPermissions(){
let res = await userOperationPermissions(); let res = await userOperationPermissions();
this.permissonList = res.data this.permissonList = res.data
// console.log("司机管理",this.permissonList.includes('driverAddBtn'))
}, },
async handleStatus(item){ async handleStatus(item){
if(item.states.code === 0){ if(item.states.code === 0){
@@ -143,14 +270,23 @@ export default {
}else{ }else{
this.states = 0 this.states = 0
} }
Dialog.confirm({
message: '当前状态为启用,是否要改为停用?',
}).then(async () => {
await enableAction({ await enableAction({
driverId:item.driverId, driverId:item.driverId,
states:this.states states:this.states
}) })
this.pageNum = 1; this.pageNum = 1;
await this.getDriverList(); await this.getDriverList();
}).catch(() => {
});
}, },
updateDriver(item){ updateDriver(item){
if(!this.permissonList.includes('driverModifyBtn')){//有权限才能修改
return
}
// 在当前组件中进行路由跳转并传递参数对象 // 在当前组件中进行路由跳转并传递参数对象
this.$router.push({ this.$router.push({
name: 'driverAdd', // 目标路由的名称 name: 'driverAdd', // 目标路由的名称
@@ -185,7 +321,7 @@ export default {
.wrap { .wrap {
background: #F4F5F7; background: #F4F5F7;
@include sizingPadding(13px,13px); //@include sizingPadding(13px,13px);
@include wh(100%, 100%); @include wh(100%, 100%);
overflow-y: auto; overflow-y: auto;
} }
@@ -208,7 +344,7 @@ export default {
} }
.itemWrap { .itemWrap {
@include wh(100%, 104px); @include wh(100%, 140px);
@include radiusSizing(6px); @include radiusSizing(6px);
@include fontWeightSize(400, 12px); @include fontWeightSize(400, 12px);
@include flexBetween; @include flexBetween;
@@ -216,6 +352,7 @@ export default {
box-shadow: 0px 2px 10px 0px rgba(216, 216, 216, 0.5); box-shadow: 0px 2px 10px 0px rgba(216, 216, 216, 0.5);
margin-bottom: 10px; margin-bottom: 10px;
padding: 11px 13px 9px 15px; padding: 11px 13px 9px 15px;
position: relative;
.halfOpci { .halfOpci {
opacity: .5; opacity: .5;
margin-right: 5px; margin-right: 5px;
@@ -224,15 +361,15 @@ export default {
opacity: 1; opacity: 1;
} }
.statusNo { .statusNo {
color: #FF0000; color: red;
} }
.statusYes { .statusYes {
color: #09B820 color: green
} }
} }
.name-status { .name-status {
@include flexColBet; @include flexBetCen;
.namephone { .namephone {
@include fontWeightSize(bold, 14px) @include fontWeightSize(bold, 14px)
} }
@@ -256,6 +393,128 @@ export default {
margin-left: 15px; margin-left: 15px;
} }
} }
}
.filterWrap {
width: 100%;
padding-right: 13px;
padding-left: 13px;
display: flex;
overflow-x: auto; /* 允许横向滚动 */
white-space: nowrap; /* 防止子元素换行 */
padding-bottom: 10px;
-webkit-overflow-scrolling: touch; /* 在iOS上平滑滚动 */
scrollbar-width: none; /* Firefox */
padding-bottom: 10px;
/*padding: 10px;*/
margin-bottom: 10px;
background-color: #fff;
box-sizing: border-box;
&::-webkit-scrollbar {
display: none; /* Chrome/Safari */
}
.customSel {
flex: 0 0 auto; /* 防止子元素被压缩 */
width: calc(33% - 5px);
/*width: 100%;*/
height: 25px;
background: #F5F5F5;
border-radius: 4px;
font-size: 10px;
color: #323233;
margin-right: 5px;
::v-deep .el-input__inner{
padding: 0 2px;
height: 25px;
font-size: 10px;
background: #F5F5F5;
border-radius: 4px;
border: none;
}
::v-deep .el-input__icon{
line-height: 25px;
font-size: 10px;
width: 18px;
color: #2A5094;
}
::v-deep .el-input__suffix{
right: 2px;
}
}
.customInput{
/*width: 49%;*/
width: 130px;
}
.has-value ::v-deep .el-input__inner{
background: #F1F6FF ;
color: #007BE9;
font-weight: bold;
padding-left: 8px;
}
.has-value ::v-deep .el-input__icon{
color: #007BE9;
}
.priceSel{
display: flex;
justify-content: space-around;
align-items: center;
color: #C0C4CC;
.iconSpan{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 8px;
}
}
.has-price{
color: #007BE9 !important;
}
}
.wrap_cls {
width: 100%;
padding-left: 13px;
padding-right: 13px;
box-sizing: border-box;
}
.common_cls {
color: #fff;
padding: 4px 8px;
border-radius: 3px;
margin-right: 6px;
}
.default_cls {
background-color: #B0BEC5;
}
.danger_cls {
background-color: red;
}
.success_cls {
background-color: #4CAF50;
}
.info_cls {
background-color: #FF9800;
}
.main_cls {
background-color: #6C9BFF;
}
.arrow_position {
position: absolute;
right: 5px;
top: 50px;
font-size: 20px;
opacity: 0.6;
}
.carType,.zdJuhe{
opacity: .7;
@include fontWeightSize(400,12px);
margin-right: 8px;
}
/*.zdJuhe {
width: 80px;
text-align: right;
margin-left: -10px;
}*/
.flex-between{
line-height: 24px;
} }
</style> </style>

View File

@@ -175,7 +175,7 @@ export default {
confirmButtonColor: '#0E76F4', confirmButtonColor: '#0E76F4',
showCancelButton: false, showCancelButton: false,
}).then(async() => { }).then(async() => {
this.goPage('newTrainingList', { supplierId : this.supplierId }) this.goPage('newTrainingList', { supplierId : this.supplierId, type: 'invoice' })
}).catch(() => { }).catch(() => {
// on cancel // on cancel
}); });
@@ -189,7 +189,9 @@ export default {
this.getNotifyList() this.getNotifyList()
}, },
async getJumpHandler() { async getJumpHandler() {
let res = await jumpPage(); let res = await jumpPage({
type: 'invoice'
});
return res return res
}, },
getMonth(item) { getMonth(item) {

View File

@@ -0,0 +1,648 @@
<template>
<div class="wrap">
<div class="top_banner">
<img src="@/assets/supplier/topBg.png" alt="">
</div>
<van-form @submit="applyAdd">
<div class="content_wrap">
<div class="credentials_info">
<img class="title1" src="@/assets/supplier/title1.png" alt="">
<div class="credentials_wrap">
<div class="credentials_item">
<div class="credentials_title">1.法人身份证人像页</div>
<van-uploader
accept="image/*"
v-model="idFrontPhotoList"
:after-read="idFrontPhotoHandler"
:max-size="5 * 1024 * 1024"
max-count="1">
<div class="custom-background">
<img src="@/assets/supplier/idCardPerson.png" alt="">
</div>
</van-uploader>
</div>
<div class="credentials_item ml2">
<div class="credentials_title">2.法人身份证国徽页</div>
<van-uploader
accept="image/*"
v-model="idBackPhotoList"
:after-read="idBackPhotoHandler"
:max-size="5 * 1024 * 1024"
max-count="1">
<div class="custom-background">
<img src="@/assets/supplier/idCardBack.png" alt="">
</div>
</van-uploader>
</div>
<div class="credentials_item ml2">
<div class="credentials_title">3.营业执照</div>
<van-uploader
accept="image/*"
v-model="companyPhotoList"
:after-read="companyPhotoHandler"
:max-size="5 * 1024 * 1024"
max-count="1">
<div class="custom-background">
<img src="@/assets/supplier/companyPhoto.png" alt="">
</div>
</van-uploader>
</div>
<div class="credentials_item">
<div class="credentials_title">4.开户许可证/基本存款账户信息</div>
<van-uploader
accept="image/*"
v-model="licensePhotoList"
:after-read="licensePhotoHandler"
:max-size="5 * 1024 * 1024"
max-count="1">
<div class="custom-background">
<img src="@/assets/supplier/licensePhoto.png" alt="">
</div>
</van-uploader>
</div>
</div>
</div>
<div class="company_info">
<img class="title2" src="@/assets/supplier/title2.png" alt="">
<div class="company_wrap">
<van-field :border="true" readonly v-model="form.name" class="required" name="name" label="服务商名称" placeholder="请输入" :rules="[{ required: true, message: '请输入服务商名称' }]" />
<van-field :border="true" readonly v-model="form.areaName" class="required" name="areaName" label="注册地址" placeholder="请输入" :rules="[{ required: true, message: '请输入注册地址' }]" />
<van-field :border="true" readonly v-model="form.legalName" class="required" name="legalName" label="法人姓名" placeholder="请输入" :rules="[{ required: true, message: '请输入法人姓名' }]" />
<van-field :border="true" v-model="form.linkName" class="required" name="linkName" label="联系人姓名" placeholder="请输入" :rules="[{ required: true, message: '请输入联系人姓名' }]" />
<van-field :border="true" v-model="form.linkPhone" class="required" name="linkPhone" label="联系电话" placeholder="请输入" :rules="phoneVerify" />
<van-field :border="true" v-model="form.linkEmail" class="required" name="linkEmail" label="邮箱" placeholder="请输入" :rules="emailVerify" />
<van-field :border="true" class="required" name="serviceType" label="服务能力">
<template #input>
<el-tree
show-checkbox
node-key="id"
ref="tree"
:highlight-current="true"
:expand-on-click-node="false"
:data="bigServiceList"
:props="defaultProps">
</el-tree>
</template>
</van-field>
<van-field :border="true" v-model="form.trailCount" name="trailCount" label="拖车数量" placeholder="请输入" />
<van-field :border="true" v-model="form.minorCount" name="minorCount" label="抢修车数量" placeholder="请输入" />
<van-field :border="true" class="required" label="服务区域" placeholder="请选择">
<template #input>
<el-cascader
v-model="form.serviceAreaCode"
:options="areaList"
:props="areaProps"
ref="areaCascader"
popper-class="responsive-cascader"
:popper-append-to-body="false"
filterable
clearable></el-cascader>
</template>
</van-field>
<div class="wei_code_wrap" v-if="form.name && !id">
<div class="wei_title">请先添加企业微信保证申请流程正常进行</div>
<div class="wei_code_bg">
<img v-if="qrCodeUrl" :src="qrCodeUrl" alt="企业微信二维码" />
</div>
</div>
</div>
</div>
</div>
<div class="btn_wrap">
<van-button class="btn" block type="info" :native-type="'submit'">提交申请</van-button>
</div>
</van-form>
<van-popup
v-model="areaShow"
position="bottom"
>
<van-area title="服务区域" :area-list="areaList" :columns-num="3" closeable="true" :value="form.areaCode ? String(form.areaCode) : ''"
@cancel="areaShow = false" @confirm="confirmHandle"/>
</van-popup>
</div>
</template>
<script>
import {leftCopy} from "@/utils/common"
import QRCode from 'qrcode'
import { uploadImage, ocrHandler, unifiedOCRWithCompress, getArea, saveSupplier, getSupplierInfo, getOrCodeInfo, getContactQrCodeResult } from "@/api/mine"
import {myMixins} from "@/utils/myMixins"
import {Dialog} from "vant";
export default {
name: "supplierAdd",
mixins:[myMixins],
data() {
return {
clickFlag: true,
phoneVerify: [{ required: true, message: '请输入联系电话' }, { validator: value => { return /^1[3456789]\d{9}$/.test(value) }, message: '联系电话格式不正确' }],
emailVerify: [{ required: true, message: '请输入邮箱' }, { validator: value => { return /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/.test(value) }, message: '邮箱格式不正确' }],
id:'', //车辆Id
idBackPhotoList: [],
idBackPhoto: '',
idFrontPhotoList: [],
idFrontPhoto: '',
companyPhotoList: [],
licensePhotoList: [],
companyPhoto: '',
licensePhoto:'',
form: {
name: '',
legalName: '',
areaName: '',
linkName: '',
linkPhone: '',
serviceType: '',
trailCount: '',
minorCount: '',
serviceAreaCode: [],
linkEmail:'',
accountInfoDTO:{
dutyParagraph:'',
accountNumber:'',
accountName:'',
accountType:'',
invoiceType:'',
settlementType:'',
shouldRate:'',
realRate:'',
unitName:'',
bankNo:'',
billingPhone:'',
billingAddress:'',
billHead:'',
companyType:'',
}
},
qrCodeUrl: '',
qrCode: '',
areaShow: false,
areaList: [],
supplierServiceList: [],
bigServiceList: [{
id: 1002,
title: '拖车服务'
}, {
id: 1003,
title: '抢修服务'
}, {
id: 1004,
title: '困境救援'
}],
defaultProps: {
children: 'children',
label: 'title',
},
areaProps: { multiple: true, checkStrictly: true, value: 'id',label: 'title', emitPath: false},
configId: '',
wechatId: '',
}
},
async mounted() {
const urlParams = new URLSearchParams(window.location.search);
this.id = this.$route.query.id || urlParams.get('id');
await this.getAreaTree();
if(this.id) {
await this.getInfoHandler();
}
// await this.getSupplierServiceTree();
},
methods: {
async QrCodeHandler() {
await this.QrCodeInfo()
await this.getQrCode();
},
async QrCodeInfo() {
let res = await getOrCodeInfo({
name: this.form.name
});
this.configId = res?.configId;
this.qrCode = res?.qrCode
console.log('idid', res);
},
async getInfoHandler() {
let res = await getSupplierInfo({
id: this.id
});
let _data = res?.data
leftCopy(this.form, {..._data})
this.idFrontPhoto = _data?.idCardFrontUrl;
this.idBackPhoto = _data?.idCardBackUrl;
this.companyPhoto = _data?.businessLicense;
this.licensePhoto = _data?.accountUrl;
this.wechatId = _data?.wechatId
if(this.idFrontPhoto) {
this.idFrontPhotoList = [{ url : this.idFrontPhoto }];
}
if(this.idBackPhoto) {
this.idBackPhotoList = [{ url : this.idBackPhoto }];
}
if(this.companyPhoto) {
this.companyPhotoList = [{ url : this.companyPhoto }];
}
if(this.licensePhoto){
this.licensePhotoList= [{ url : this.licensePhoto }];
}
if( _data.service ) {
this.$refs.tree.setCheckedKeys(_data.service.split(','))
}
if(_data?.serviceAreaCode) {
this.$set(this.form, 'serviceAreaCode', _data?.serviceAreaCode.split(',').map(item => Number(item)));
// this.form.serviceAreaCode = _data?.serviceAreaCode.split(',').map(item => Number(item));
}
},
async applyAdd() {
if( !this.idFrontPhoto ) {
this.$toast('法人身份证人像页未上传')
return
}
if( !this.idBackPhoto ) {
this.$toast('法人身份证国徽页未上传')
return
}
if( !this.companyPhoto ) {
this.$toast('营业执照未上传')
return
}
if( !this.licensePhoto ) {
this.$toast('开户许可证未上传')
return
}
if( !(this.form.serviceAreaCode.length > 0) ) {
this.$toast('服务区域不能为空')
return
}
// this.wechatId='wmOTNXBwAABrvKkE_Fh8ZN8Xm2S9v2wQ'
if(!this.wechatId) {
await this.QrCodeResult();
if( !this.wechatId ) {
this.$toast('请先添加企微再申请')
return
}
}
if( this.$refs.tree.getCheckedKeys().length > 0 ) {
await this.saveHandler()
} else {
this.$toast('服务能力不能为空')
return
}
},
async QrCodeResult() { //获取添加企微结果
let res = await getContactQrCodeResult({
configId: this.configId
});
console.log('resres', res)
this.wechatId = res?.data?.wechatId
},
async saveHandler() {
if( this.clickFlag ) {
try {
this.clickFlag = false
let _node = this.$refs.areaCascader.getCheckedNodes();
let checkArr = [];
_node.map(item => {
checkArr.push(item.data.id)
})
let res = await saveSupplier({
id: this.id,
...this.form,
accountInfoJson:JSON.stringify(this.form.accountInfoDTO),
accountInfoDTO:{},
idCardFrontUrl: this.idFrontPhoto,
idCardBackUrl: this.idBackPhoto,
businessLicense: this.companyPhoto,
accountUrl:this.licensePhoto,
service: this.$refs.tree.getCheckedKeys().join(',') ,
serviceAreaCode: checkArr.join(','),
wechatId: this.wechatId,
});
Dialog.alert({
title: '提示',
message: "操作成功"
}).then(async () => {
this.goPage('supplierAddResult', { id : res?.data })
setTimeout(() => {
this.clickFlag = true
}, 1000)
});
} finally {
setTimeout(() => {
this.clickFlag = true
}, 1000)
}
}
},
async getAreaTree() {
let res = await getArea();
let result = res?.data
result?.map(item=>{
if( item.parentId == 0 ) {
this.$set(item , 'disabled' ,true)
} else {
this.$set(item , 'disabled' ,false)
}
})
this.areaList = result;
},
/*async getSupplierServiceTree(){
let res = await supplierServicePartTree({
serviceTypes: '1002,1003,1004',
treeType: 2
});
this.supplierServiceList=res.data
this.bigServiceList = [];
res.data.map(item => {
let obj = {...item, children: null}
this.bigServiceList.push(obj)
})
},*/
confirmHandle(val){
this.region=[]
val?.forEach(item => this.region.push(item.name))
let code=[]
val?.forEach(item => code.push(item.code))
this.form.areaCode=code[code.length - 1]
this.areaShow=false
},
async getQrCode() {
try {
this.qrCodeUrl = await QRCode.toDataURL(this.qrCode, {
width: 150,
margin: 2,
color: {
dark: '#000000',
light: '#FFFFFF'
},
})
} catch (error) {
console.error('生成二维码失败:', error)
}
},
async idBackPhotoHandler(file) {
const formData = new FormData();
formData.append("file" , file.file);
let res = await uploadImage(formData);
this.idBackPhoto = res.data
},
async idFrontPhotoHandler(file) {
const formData = new FormData();
formData.append("file" , file.file);
let res = await uploadImage(formData);
this.idFrontPhoto = res.data;
await this.idCardOcrHandler();
},
async idCardOcrHandler() { // 身份证正面 ocr识别
this.form.legalName = '';
let res = await ocrHandler({
ocrType: 1,
imageUrl: this.idFrontPhoto,
cardSide: 'FRONT'
})
this.form.legalName = res?.data?.name
},
async companyPhotoHandler(file) {
const formData = new FormData();
formData.append("file" , file.file);
let res = await uploadImage(formData);
this.companyPhoto = res.data
await this.companyOcrHandler()
},
async companyOcrHandler() { // 营业照 ocr识别
this.form.name = '';
this.form.areaName = '';
let res = await unifiedOCRWithCompress({
ocrType: 7,
imageUrl: this.companyPhoto,
cardSide: 'FRONT'
})
this.form.name = res?.data?.name;
this.form.areaName = res?.data?.address
this.form.accountInfoDTO.dutyParagraph=res?.data?.regNum
this.form.accountInfoDTO.unitName = res?.data?.name
this.form.accountInfoDTO.companyType=res?.data?.type
await this.QrCodeHandler();
},
async licensePhotoHandler(file){// 开户许可证
const formData = new FormData();
formData.append("file" , file.file);
let res = await uploadImage(formData);
this.licensePhoto = res.data
await this.licenseOcrHandler()
},
async licenseOcrHandler(){// 开户许可证ocr识别
let res = await ocrHandler({
ocrType: 15,
imageUrl: this.licensePhoto,
})
this.form.accountInfoDTO.accountNumber=res?.data?.accountNumber
this.form.accountInfoDTO.accountName = res?.data?.accountBank
},
},
computed: {
regionText() {
return this.region.length ? `${this.region[0]}/${this.region[1]}/${this.region[2]}` : '请选择所在地区';
}
},
}
</script>
<style scoped lang="scss">
@import "@/styles/mixin.scss";
@import "@/styles/common.scss";
.wrap{
@include wh(100%,100%);
box-sizing: border-box;
padding-bottom: 100px;
overflow-y: auto;
}
.top_banner {
width: 100%;
img {
width: 100%;
height: 169px;
}
}
.content_wrap {
padding: 0 20px;
}
.credentials_info {
//height: 170px;
}
.credentials_wrap {
display: flex;
width: 100%;
margin-top: 10px;
flex-wrap: wrap;
.credentials_item {
width: 32%;
text-align: center;
.credentials_title {
font-size: 12px;
color: #4A4A4A;
padding: 10px 0;
}
.custom-background img {
width: 97px;
height: 64px;
}
}
.ml2 {
margin-left: 2%;
}
}
::v-deep .van-uploader__preview-image {
width: 97px;
height: 64px;
}
.title1 {
width: 106px;
height: 19px;
margin-top: 25px;
}
.title2 {
width: 90px;
height: 18px;
margin-top: 25px;
margin-bottom: 10px;
}
.van-cell.required::before{
content: "";
position: absolute;
color: #F00;
left: 0px;
top: .25rem;
font-size: .3rem;
}
.wei_code_wrap {
margin-top: 10px;
.wei_title {
font-size: 15px;
color: #FF553B;
text-align: center;
}
.wei_code_bg {
width: 163px;
height: 173px;
background-image: url("~@/assets/supplier/weiCodeBg.png");
background-size: 100% 100%;
margin: 8px auto;
display: flex;
align-items: center;
justify-content: center;
}
}
.btn_wrap {
width: 100%;
padding: 15px 0;
position: fixed;
bottom: 0;
background: #F7F7F9;
box-shadow: 0px -7px 24px 0px rgba(0, 0, 0, 0.11);
z-index: 10000 !important;
.btn {
width: calc(100% - 80px);
margin-left: 40px;
height: 46px;
background: #0E76F4;
border-radius: 5px;
font-size: 15px;
color: #FFFFFF;
text-align: center;
line-height: 46px;
}
}
/*::v-deep .el-cascader {
width: 100% !important;
}
::v-deep .el-input__inner {
width: 100% !important;
border: none !important;
padding-left: 0 !important;
background: transparent !important;
}
::v-deep .el-input {
width: 100% !important;
}
::v-deep .el-input__suffix {
right: 0 !important;
}*/
</style>
<style>
.responsive-cascader .el-cascader-menu {
min-width: 100px !important;
}
.responsive-cascader .el-cascader-panel {
font-size: 12px !important;
}
.responsive-cascader .el-cascader-node {
padding-left: 5px !important;
padding-right: 4px !important;
}
/* !* 级联选择器下拉框样式 *!
.responsive-cascader {
width: 90vw !important;
max-width: 400px !important;
left: 50% !important;
transform: translateX(-50%) !important;
}
.responsive-cascader .el-cascader-panel {
display: flex !important;
width: 100% !important;
max-height: 60vh !important;
}
.responsive-cascader .el-cascader-node {
padding: 12px 16px !important;
font-size: 12px !important;
height: 20px !important;
!*min-height: 44px !important;*!
display: flex !important;
align-items: center !important;
}
.responsive-cascader .el-cascader-node__label {
font-size: 12px !important;
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
flex: 1 !important;
}
!* 移动端触摸优化 *!
.responsive-cascader .el-cascader-node {
padding: 6px 6px !important;
}
!* 选中状态 *!
.responsive-cascader .el-cascader-node.in-active-path,
.responsive-cascader .el-cascader-node.is-active {
color: #1989fa !important;
background-color: #f2f8ff !important;
}
!* 移动端适配 *!
@media (max-width: 768px) {
.responsive-cascader {
width: 95vw !important;
max-width: none !important;
}
.responsive-cascader .el-cascader-menu {
width: 33.33% !important;
flex: none !important;
}
.responsive-cascader .el-cascader-node__label {
font-size: 13px !important;
}
}*/
</style>

View File

@@ -0,0 +1,83 @@
<template>
<div class="wrap">
<div class="top-wrap"></div>
<div class="center-info">
<img class="wait_icon" src="@/assets/supplier/successIcon.png" alt="">
<div class="info-tip">信息录入完成请等待审核结果</div>
</div>
<div class="btn_wrap">
<div class="btn" @click="searchInfo">信息查看</div>
</div>
</div>
</template>
<script>
import {myMixins} from "@/utils/myMixins"
export default {
name: "supplierAddResult",
mixins:[myMixins],
data() {
return {
id: '',
}
},
async mounted() {
const urlParams = new URLSearchParams(window.location.search);
this.id = this.$route.query.id || urlParams.get('id');
},
methods: {
searchInfo() {
this.goPage('supplierInfo', { id : this.id })
}
}
}
</script>
<style scoped lang="scss">
@import "@/styles/mixin.scss";
@import "@/styles/common.scss";
.wrap{
@include wh(100%,100%);
box-sizing: border-box;
padding-bottom: 100px;
overflow-y: auto;
background: linear-gradient( 180deg, #FBFDFE 0%, #F6FBFF 73%, #F0F7FF 100%);
backdrop-filter: blur(5.602678571428572px);
}
.top-wrap {
width: 100%;
height: 175px;
background: linear-gradient( 180deg, #DAECFF 0%, rgba(233,243,255,0) 100%);
}
.center-info {
text-align: center;
.wait_icon {
width: 54px;
height: 54px;
margin-bottom: 15px;
}
.info-tip {
font-size: 20px;
font-weight: 500;
color: #2C2A53;
}
}
.btn_wrap {
width: 100%;
padding: 15px 0;
position: fixed;
bottom: 10px;
z-index: 10000 !important;
.btn {
width: calc(100% - 80px);
margin-left: 40px;
height: 46px;
background: #0E76F4;
border-radius: 5px;
font-size: 15px;
color: #FFFFFF;
text-align: center;
line-height: 46px;
}
}
</style>

View File

@@ -0,0 +1,363 @@
<template>
<div class="wrap">
<div class="nav_bar_bg" :class="{ 'status_wait': supplierInfo?.state == 0, 'status_danger': supplierInfo?.state == 99, 'status_success': supplierInfo?.state == 1 }">
<template v-if="supplierInfo?.state == 0">
<div class="status_wrap">
<img class="wait_icon" src="@/assets/supplier/waitIcon.png" alt="">
<span class="wait_status">审批中</span>
</div>
</template>
<template v-if="supplierInfo?.state == 1">
<div class="status_wrap">
<img class="wait_icon" src="@/assets/supplier/successIcon.png" alt="">
<span class="wait_status success_status">恭喜你审核通过</span>
</div>
</template>
<template v-if="supplierInfo?.state == 99">
<div class="status_wrap">
<img class="wait_icon" src="@/assets/supplier/failIcon.png" alt="">
<span class="wait_status danger_status">审核不通过</span>
</div>
<div class="danger_tip">
{{supplierInfo?.failReason}}
</div>
</template>
</div>
<div class="supplier_content">
<div class="credentials_info">
<div class="common_title">证件照信息</div>
<div class="credentials_wrap">
<div class="credentials_item">
<div class="credentials_title">1.法人身份证人像页</div>
<img :src="supplierInfo?.idCardFrontUrl" alt="">
</div>
<div class="credentials_item ml2">
<div class="credentials_title">2.法人身份证国徽页</div>
<img :src="supplierInfo?.idCardBackUrl" alt="">
</div>
<div class="credentials_item ml2">
<div class="credentials_title">3.营业执照</div>
<img :src="supplierInfo?.businessLicense" alt="">
</div>
<div class="credentials_item">
<div class="credentials_title">4.开户许可证/基本存款账户信息</div>
<img v-if="supplierInfo?.accountUrl" :src="supplierInfo?.accountUrl" alt="">
<div v-else class="empty"></div>
</div>
</div>
</div>
<div class="company_info">
<div class="common_title">公司信息</div>
<div class="info_wrap">
<div class="info_item">
<div class="label">服务商名称</div>
<div class="content">{{supplierInfo?.name}}</div>
</div>
<div class="info_item" v-if="supplierInfo?.abbr">
<div class="label">服务商简称</div>
<div class="content">{{supplierInfo?.abbr}}</div>
</div>
<div class="info_item" v-if="supplierInfo?.supplierCode">
<div class="label">服务商编号</div>
<div class="content">{{supplierInfo?.supplierCode}}</div>
</div>
<div class="info_item" v-if="supplierInfo?.areaName">
<div class="label">注册地址</div>
<div class="content">{{supplierInfo?.areaName}}</div>
</div>
<div class="info_item">
<div class="label">法人姓名</div>
<div class="content">{{supplierInfo?.legalName}}</div>
</div>
<div class="info_item">
<div class="label">联系人姓名</div>
<div class="content">{{supplierInfo?.linkName}}</div>
</div>
<div class="info_item">
<div class="label">联系电话</div>
<div class="content">{{supplierInfo?.linkPhone}}</div>
</div>
<div class="info_item">
<div class="label">邮箱</div>
<div class="content">{{supplierInfo?.linkEmail}}</div>
</div>
<div class="info_item">
<div class="label">服务能力</div>
<div class="content service_color">{{supplierInfo?.serviceCategoryName}}</div>
</div>
<div class="info_item">
<div class="label">拖车数量</div>
<div class="content">{{supplierInfo?.trailCount || ''}}</div>
</div>
<div class="info_item">
<div class="label">抢修车数量</div>
<div class="content">{{supplierInfo?.minorCount || ''}}</div>
</div>
<div class="info_item">
<div class="label">服务区域</div>
<div class="content">{{supplierInfo?.serviceAreaName}}</div>
</div>
<template v-if="type == 'audit' && supplierInfo?.state != 1">
<div class="info_item">
<div class="label"><span style="color: red;margin-right: 2px">*</span>审批</div>
<div class="content">
<van-radio-group v-model="form.state" direction="horizontal" icon-size="18px">
<van-radio name="1">审批通过</van-radio>
<van-radio name="99">审批不通过</van-radio>
</van-radio-group>
</div>
</div>
<div class="info_item" v-if="form.state == 1">
<div class="label"><span style="color: red;margin-right: 2px">*</span>服务商简称</div>
<div class="content">
<el-input style="width: 100%" v-model.trim="form.abbr" placeholder="请输入服务商简称"></el-input>
</div>
</div>
<div class="info_item" v-if="form.state == 99">
<div class="label"><span style="color: red;margin-right: 2px">*</span>不通过原因</div>
<div class="content">
<textarea class="report_textarea" rows="4" maxlength="200" show-word-limit placeholder="点击这里输入不通过原因" v-model.trim="form.failReason"></textarea>
</div>
</div>
</template>
</div>
</div>
<div class="btn_wrap" v-if="type == 'show' && supplierInfo?.state == 99 && origin != 'web'">
<div class="btn" @click="goModifyPage">修改信息</div>
</div>
<div class="btn_wrap" v-if="type == 'audit' && supplierInfo?.state != 1">
<div class="btn" v-if="type == 'audit'" @click="auditSupplier"> </div>
</div>
</div>
</div>
</template>
<script>
import { getSupplierInfo, auditSupplier } from "@/api/mine"
import {myMixins} from "@/utils/myMixins"
export default {
name: "supplierInfo",
mixins:[myMixins],
data() {
return {
id:'', //车辆Id
form: {
state: '',
abbr: '',
failReason: '',
},
supplierInfo: {},
type: 'show',
origin: '',
}
},
async mounted() {
const urlParams = new URLSearchParams(window.location.search);
this.id=this.$route.query.id || urlParams.get('id');
this.type=this.$route.query.type || urlParams.get('type') || 'show';
this.origin = this.$route.query.origin || ''
await this.getInfoHandler();
},
methods: {
goModifyPage() {
this.goPage('supplierAdd', { id : this.id })
},
async auditSupplier() {
if( !this.form.state ) {
this.$toast('请选择审批结果')
return
}
if( this.form.state == 99 && !this.form.failReason ) {
this.$toast('请输入不通过原因')
return
}
if( this.form.state == 1 ) {
const reg = /^[\u4e00-\u9fa5]{2}$/;
if(!this.form.abbr) {
this.$toast('请输入服务商简称')
return
}
if(!(reg.test(this.form.abbr))) {
this.$toast('服务商简称请输入两位汉字')
return
}
}
try {
await auditSupplier({
id: this.id,
...this.form,
wechatId: 'test', // 参数将会被去掉
})
} finally {
this.closeParentDialog();
}
},
async getInfoHandler() {
let res = await getSupplierInfo({
id: this.id,
});
this.supplierInfo = res?.data;
},
}
}
</script>
<style scoped lang="scss">
@import "@/styles/mixin.scss";
@import "@/styles/common.scss";
.report_textarea {
width: 100%;
box-sizing: border-box;
border-radius: 6px;
min-height: 95px;
border: 1px solid #E2EAF6;
padding: 10px;
font-size: 13px;
}
.wrap{
@include wh(100%,100%);
box-sizing: border-box;
padding-bottom: 100px;
overflow-y: auto;
}
.nav_bar_bg {
width: 100%;
height: 125px;
padding-top: 50px;
}
.status_wait {
background: linear-gradient( 180deg, #FFE4C9 0%, rgba(255,248,233,0) 100%);
}
.status_success {
background: linear-gradient( 180deg, #DAFFF8 0%, rgba(237,255,233,0) 100%);
}
.status_danger {
background: linear-gradient( 180deg, #FFE8DA 0%, rgba(255,233,233,0) 100%);
}
.status_wrap {
display: flex;
align-items: center;
.wait_icon {
width: 34px;
height: 34px;
margin-left: 31px;
}
.wait_status {
color: #E69B0B;
font-weight: 600;
font-size: 16px;
margin-left: 11px;
}
.success_status {
color: #37B864;
}
.danger_status {
color: #ED440C;
}
}
.danger_tip {
font-size: 12px;
color: #FF553B;
line-height: 18px;
padding-left: 38px;
padding-right: 23px;
margin-top: 5px;
}
.supplier_content {
padding: 0 20px;
width: 100%;
box-sizing: border-box;
}
.common_title {
font-weight: 500;
font-size: 14px;
color: rgba(50, 54, 67, 0.66);
padding-left: 2px;
}
.common_title::after {
content: '';
display: block;
width: 100%;
border: 1px solid;
margin-top: 10px;
opacity: 0.16;
border-image: linear-gradient(270deg, rgba(217, 217, 217, 0.6), rgba(178, 178, 178, 1), rgba(178, 178, 178, 1), rgba(217, 217, 217, 0.6)) 1 1;
}
.credentials_wrap {
display: flex;
width: 100%;
margin-top: 10px;
flex-wrap: wrap;
.credentials_item {
width: 32%;
text-align: center;
.credentials_title {
font-size: 12px;
color: #4A4A4A;
padding: 10px 0;
}
img,.empty{
width: 97px;
height: 64px;
}
.empty{
border: 1px solid silver;
margin-left: 8px;
}
}
.ml2 {
margin-left: 2%;
}
}
.company_info {
margin-top: 20px;
/*.company_wrap {*/
.info_wrap {
margin-top: 10px;
.info_item {
display: flex;
padding: 10px 2px;
.label {
font-size: 13px;
color: rgba(50, 54, 67, 0.6);
width: 90px;
flex-shrink: 0;
}
.content {
font-size: 13px;
color: #323643;
/*font-weight: bold;*/
flex: 1;
}
.service_color {
color: rgba(230, 155, 11, 0.9);
}
}
/*}*/
}
}
.btn_wrap {
width: 100%;
padding: 15px 0;
position: fixed;
bottom: 0;
background: #F7F7F9;
box-shadow: 0px -7px 24px 0px rgba(0, 0, 0, 0.11);
z-index: 10000 !important;
left: 0;
.btn {
width: calc(100% - 80px);
margin-left: 40px;
height: 46px;
background: #0E76F4;
border-radius: 5px;
font-size: 15px;
color: #FFFFFF;
text-align: center;
line-height: 46px;
}
}
</style>

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,57 @@
</template> </template>
</van-nav-bar> </van-nav-bar>
</div> </div>
<van-search
v-model="searchVal"
show-action
placeholder="请输入车辆名称、车牌号、车架号"
@search="resetHandler"
>
<template #action>
<div @click="resetHandler">搜索</div>
</template>
</van-search>
<div class="filterWrap">
<!-- <div >-->
<!--<el-input v-model="searchVal" @blur="resetHandler" placeholder="车辆名称/车牌号/车架号" :class="{'customSel':true,'customInput':true , 'has-value': searchVal }" >
<template #suffix>
<i
v-if="searchVal"
class="el-icon-circle-close el-input__icon"
@click="searchVal = ''"
></i>
</template>
</el-input>-->
<el-select @change="resetHandler" multiple :collapse-tags="true" v-model="authStates" placeholder="认证状态" :class="{'customSel':true , 'has-value': authStates }" clearable>
<el-option
v-for="item in authStatesOptions"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
<el-select @change="resetHandler" multiple :collapse-tags="true" v-model="inputStatusList" placeholder="录入状态" :class="{'customSel':true , 'has-value': inputStatusList }" clearable>
<el-option
v-for="item in inputStatusListOptions"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
<!-- </div>-->
<!-- <div>-->
<el-select @change="resetHandler" multiple :collapse-tags="true" v-model="liabilityInsuranceAuditList" placeholder="职业责任险" :class="{'customSel':true , 'has-value': liabilityInsuranceAuditList }" clearable>
<el-option
v-for="item in insuresOptions"
:key="item.value"
:label="item.name"
:value="item.value">
</el-option>
</el-select>
<!-- </div>-->
</div>
<div class="wrap_cls">
<van-pull-refresh v-model="isLoading" @refresh="onRefresh"> <van-pull-refresh v-model="isLoading" @refresh="onRefresh">
<van-list <van-list
v-model="loading" v-model="loading"
@@ -25,31 +76,52 @@
finished-text="没有更多了" finished-text="没有更多了"
@load="onLoad" @load="onLoad"
> >
<div class="carItem" v-for="(item,index) in vehicleList" :key="index"> <div class="carItem" v-for="(item,index) in vehicleList" :key="index" @click.stop="updateVehicle(item)">
<div class="carCode"> <div class="carCode">
<div class="codeLeft">{{item.plateNumber}} / {{item.vehicleTypeString}}</div> <div class="codeLeft">{{item.plateNumber}} / {{item.vehicleTypeString}}
<div class="twoBtn"> <span class="ml10" :class="{'insuranceSuccess': item.vehicleStatus == 1, 'insuranceDanger': item.vehicleStatus == 2 ,'insuranceGray': !item.vehicleStatus }">{{ item.vehicleStatus == 1 ? '启用' :( item.vehicleStatus == 2 ? '停用' : ( item.vehicleStatus == 12 ? '否-服务商停用' : '无状态')) }} </span>
<button v-if="permissonList.includes('vehicleAddBtn')" class="del" @click="deleteItem(item.vehicleId)">删除</button>
<button v-if="permissonList.includes('vehicleModifyBtn')" class="revise" @click="updateVehicle(item)">修改</button>
</div> </div>
<div class="codeRight" v-if="item.vehicleStatus == 1" @click.stop="updateStatus(item)">停用</div>
</div> </div>
<div class="carType">{{ item.serviceName }}</div> <div class="juhe flex-between">
<div class="juhe"> <span class="zdJuhe">核验认证</span>
<span class="zdJuhe">是否参与中道聚合: </span> <span class="flex-right">
<span :class="item.hasPolymerization.code == 0 ? 'isYes' :'isNo'">{{item.hasPolymerization.label}}</span> <span class="common_cls" v-if="item.inputStatusString" :class="getClass(item.inputStatusString)?.className">{{item.inputStatusString}}</span>
<span class="common_cls" v-if="item.authStateString" :class="getClass(item.authStateString)?.className">{{item.authStateString}}</span>
</span>
</div> </div>
<div class="juhe flex-between">
<span class="zdJuhe">救援责任险</span>
<span class="flex-right" v-if="item.rescueInsurance">
<span class="common_cls" @click.stop="showTip(item.liabilityInsuranceAuditMsg)" :class="getClass(item.rescueInsurance)?.className">{{item.rescueInsurance}}</span>
</span>
</div>
<!-- <div class="juhe flex-between">
<span class="zdJuhe">车辆信息</span>
<span class="flex-right" v-if="item.auditStatusStr">
<span class="common_cls" @click.stop="showTip(item.auditMsg)" :class="getClass(item.auditStatusStr)?.className">{{item.auditStatusStr}}</span>
</span>
</div>-->
<div class="juhe flex-between">
<span class="zdJuhe">最近登录时间</span>
<span class="flex-right">{{item.lastLoginTime}}</span>
</div>
<van-icon class="arrow_position" v-if="permissonList.includes('vehicleModifyBtn')" name="arrow" />
</div> </div>
</van-list> </van-list>
</van-pull-refresh> </van-pull-refresh>
</div>
<van-dialog v-model="show" title="确定删除吗" show-cancel-button @confirm="handleConfirm"></van-dialog> <van-dialog v-model="show" title="确定删除吗" show-cancel-button @confirm="handleConfirm"></van-dialog>
</div> </div>
</template> </template>
<script> <script>
import {Dialog} from "vant";
import { myMixins} from "@/utils/myMixins"; import { myMixins} from "@/utils/myMixins";
import {supplierVehicleList,deleteVehicle,userOperationPermissions} from "@/api/mine" import {supplierVehicleList, deleteVehicle, userOperationPermissions, enableVehicle} from "@/api/mine"
export default { export default {
name: "vehicleManage", name: "vehicleManage",
mixins:[myMixins], mixins:[myMixins],
@@ -64,27 +136,134 @@ export default {
isLoading: false, isLoading: false,
loading: false, loading: false,
finished: false, finished: false,
showPopover: false,
permissonList:[], permissonList:[],
inputStatusList: [],
searchVal: '',
authStates: [],
liabilityInsuranceAuditList: [],
inputStatusListOptions: [{
name: '行驶证未录入',
value: 0
},{
name: '行驶证核验通过',
value: 1
},{
name: '行驶证核验不通过',
value: 2
}],
authStatesOptions: [{
name: '车头照片未录入',
value: 1
},{
name: '车头照片认证通过',
value: 2
},{
name: '车头照片认证不通过',
value: 3
}],
insuresOptions: [{
name: '待审核',
value: 1
},{
name: '有责任险',
value: 2
},{
name: '有货物险',
value: 3
},{
name: '未通过',
value: 4
},{
name: '无',
value: 5
},{
name: '空',
value: 6
},{
name: '原责任险过期',
value: 8
},{
name: '原货物险过期',
value: 9
}],
} }
}, },
mounted() { mounted() {
// this.getVehicleList();
this.getPermissions(); this.getPermissions();
}, },
methods:{ methods:{
showTip(msg) {
Dialog.alert({
title: '未通过原因',
message: msg,
}).then(() => {
});
},
getClass(id) {
const ids = String(id)
const steps = {
'待审核': {
className: 'main_cls'
},
'有责任险': {
className: 'success_cls'
},
'有货物险': {
className: 'info_cls'
},
'未通过': {
className: 'danger_cls'
},
'原责任险过期': {
className: 'danger_cls'
},
'原货物险过期': {
className: 'danger_cls'
},
'无': {
className: 'default_cls'
},
'空': {
className: 'default_cls'
},
'行驶证未录入': {
className: 'default_cls'
},
'行驶证核验通过': {
className: 'success_cls'
},
'行驶证核验不通过': {
className: 'danger_cls'
},
'车头照未录入': {
className: 'default_cls'
},
'车头照认证通过': {
className: 'success_cls'
},
'车头照认证不通过': {
className: 'danger_cls'
}
}
return steps[ids] || { className: 'default_cls' }
},
async onLoad(){ async onLoad(){
await this.getVehicleList() await this.getVehicleList()
if(this.total>10){
this.pageNum++; this.pageNum++;
}
// 加载状态结束 // 加载状态结束
this.loading = false; this.loading = false;
// 数据全部加载完成 // 数据全部加载完成
if (this.vehicleList.length >= this.total) { if (this.vehicleList.length >= this.total) {
this.finished = true; this.finished = true;
} else {
this.finished = false;
} }
}, },
onRefresh() { async onRefresh() {
this.pageNum=1 await this.resetHandler()
// this.getVehicleList()
setTimeout(() => { setTimeout(() => {
this.$toast('刷新成功'); this.$toast('刷新成功');
this.isLoading = false; this.isLoading = false;
@@ -93,7 +272,11 @@ export default {
async getVehicleList(){ async getVehicleList(){
let result = await supplierVehicleList({ let result = await supplierVehicleList({
pageNum:this.pageNum, pageNum:this.pageNum,
pageSize:this.pageSize pageSize:this.pageSize,
searchVal: this.searchVal,
inputStatusList: this.inputStatusList,
authStates: this.authStates,
liabilityInsuranceAuditList: this.liabilityInsuranceAuditList,
}) })
this.total=result.total this.total=result.total
if(this.pageNum == 1){// 第一页直接赋值 if(this.pageNum == 1){// 第一页直接赋值
@@ -121,13 +304,42 @@ export default {
this.pageNum=1 this.pageNum=1
await this.getVehicleList(); await this.getVehicleList();
}, },
async resetHandler() {
this.pageNum=1
this.finished = false;
this.total = 0;
// this.vehicleList = [];
await this.getVehicleList();
},
updateStatus(item){
if(item.vehicleStatus != 1){
return
}
Dialog.confirm({
message: '当前状态为启用,是否要改为停用?',
}).then(async () => {
// on confirm
await enableVehicle({
vehicleId:item.vehicleId,
vehicleStatus:2,
})
this.pageNum=1
await this.getVehicleList()
console.log("item",item)
}).catch(() => {
// on cancel
});
},
updateVehicle(item){//修改 updateVehicle(item){//修改
if( this.permissonList.includes('vehicleModifyBtn') ) {
this.$router.push({ this.$router.push({
name:'vehicleAdd', name:'vehicleAdd',
params:{ params:{
id:item.vehicleId id:item.vehicleId,
supplierId:item.supplierId
} }
}) })
}
}, },
} }
@@ -137,12 +349,41 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/styles/mixin.scss"; @import "@/styles/mixin.scss";
@import "@/styles/common.scss"; @import "@/styles/common.scss";
.ml10 {
margin-left: 10px;
}
.wrap{ .wrap{
background: #F4F5F7; background: #F4F5F7;
@include sizingPadding(13px,13px);
@include wh(100%, 100%); @include wh(100%, 100%);
overflow-y: auto; overflow-y: auto;
} }
.wrap_cls {
width: 100%;
padding-left: 13px;
padding-right: 13px;
box-sizing: border-box;
}
.common_cls {
color: #fff;
padding: 4px 8px;
border-radius: 3px;
margin-right: 6px;
}
.default_cls {
background-color: #B0BEC5;
}
.danger_cls {
background-color: red;
}
.success_cls {
background-color: #4CAF50;
}
.info_cls {
background-color: #FF9800;
}
.main_cls {
background-color: #6C9BFF;
}
.navBar{ .navBar{
margin-bottom: 46px; margin-bottom: 46px;
.rightWrap{ .rightWrap{
@@ -161,20 +402,28 @@ export default {
} }
} }
.carItem{ .carItem{
@include wh(100%,86px); @include wh(100%,120px);
background: #FFFFFF; background: #FFFFFF;
box-shadow: 0px 2px 10px 0px rgba(216,216,216,0.5); box-shadow: 0px 2px 10px 0px rgba(216,216,216,0.5);
@include radiusSizing(6px); @include radiusSizing(6px);
padding: 11px 13px 11px 15px; padding: 11px 13px 11px 15px;
margin-bottom: 10px; margin-bottom: 10px;
@include flexBetween; @include flexBetween;
position: relative;
.carCode{ .carCode{
@include flexColBet; @include flexColBet;
.codeLeft{ .codeLeft{
@include fontWeightSize(bold,14px) @include fontWeightSize(bold,14px)
} }
.codeRight{
padding: 2px 8px;
border: 1px solid #DDDDDD;
border-radius: 3px;
font-weight: bold;
}
.twoBtn{ .twoBtn{
display: flex; display: flex;
align-items: center;
button{ button{
border: none; border: none;
padding: 4px 8px; padding: 4px 8px;
@@ -202,6 +451,11 @@ export default {
opacity: .7; opacity: .7;
@include fontWeightSize(400,12px) @include fontWeightSize(400,12px)
} }
.zdJuhe {
width: 80px;
text-align: right;
margin-left: -10px;
}
.isYes{ .isYes{
color: #09B820; color: #09B820;
@include fontWeightSize(400,12px); @include fontWeightSize(400,12px);
@@ -211,4 +465,125 @@ export default {
@include fontWeightSize(400,12px); @include fontWeightSize(400,12px);
} }
} }
.arrow_position {
position: absolute;
right: 5px;
top: 50px;
font-size: 20px;
opacity: 0.6;
}
.mr10 {
margin-right: 10px;
}
.insuranceMain {
color: #354D93;
}
.insuranceSuccess {
color: green;
}
.insuranceTip {
color: orange;
}
.insuranceDanger {
color: red;
}
.insuranceGray{
color: #aaa;
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
}
.filterWrap {
width: 100%;
padding-right: 13px;
padding-left: 13px;
display: flex;
overflow-x: auto; /* 允许横向滚动 */
white-space: nowrap; /* 防止子元素换行 */
padding-bottom: 10px;
-webkit-overflow-scrolling: touch; /* 在iOS上平滑滚动 */
scrollbar-width: none; /* Firefox */
padding-bottom: 10px;
/*padding: 10px;*/
margin-bottom: 10px;
background-color: #fff;
box-sizing: border-box;
&::-webkit-scrollbar {
display: none; /* Chrome/Safari */
}
.customSel {
flex: 0 0 auto; /* 防止子元素被压缩 */
width: calc(33% - 5px);
/*width: 100%;*/
height: 25px;
background: #F5F5F5;
border-radius: 4px;
font-size: 10px;
color: #323233;
margin-right: 5px;
::v-deep .el-input__inner{
padding: 0 2px;
height: 25px;
font-size: 10px;
background: #F5F5F5;
border-radius: 4px;
border: none;
}
::v-deep .el-input__icon{
line-height: 25px;
font-size: 10px;
width: 18px;
color: #2A5094;
}
::v-deep .el-input__suffix{
right: 2px;
}
}
.customInput{
/*width: 49%;*/
width: 130px;
}
.has-value ::v-deep .el-input__inner{
background: #F1F6FF ;
color: #007BE9;
font-weight: bold;
padding-left: 8px;
}
.has-value ::v-deep .el-input__icon{
color: #007BE9;
}
.priceSel{
display: flex;
justify-content: space-around;
align-items: center;
color: #C0C4CC;
.iconSpan{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 8px;
}
}
.has-price{
color: #007BE9 !important;
}
}
::v-deep .el-select .el-select__tags>span {
display: flex;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.flex-right {
display: flex;
flex: 1;
justify-content: flex-start;
margin-left: 10px;
}
</style> </style>

View File

@@ -1,12 +1,17 @@
<template> <template>
<div class="wrap"> <div class="wrap">
<div class="baseInfo common"> <div class="baseInfo common" :style="{'height':orderDetailInfo.contractParentId == 110 ? '300px' : '240px'}">
<div class="title">基本信息:</div> <div class="title">基本信息:</div>
<div class="line"></div> <div class="line"></div>
<div class="infoWrap fontColor"> <div class="infoWrap fontColor">
<div class="leftTitle"> <div class="leftTitle">
<div class="leftItem">工单编号:</div> <div class="leftItem">工单编号:</div>
<div class="leftItem">合同:</div> <div class="leftItem">合同:</div>
<template v-if="orderDetailInfo.contractParentId == 110">
<div class="leftItem">机构名称:</div>
<div class="leftItem">销售人员:</div>
<div class="leftItem">司机号码:</div>
</template>
<div class="leftItem">结算方式:</div> <div class="leftItem">结算方式:</div>
<div class="leftItem">客户姓名:</div> <div class="leftItem">客户姓名:</div>
<div class="leftItem">客户电话:</div> <div class="leftItem">客户电话:</div>
@@ -19,6 +24,11 @@
<img @click="copyText" src="@/assets/copy.png" style="width: 35px;height: 15px;margin-left: 10px"/> <img @click="copyText" src="@/assets/copy.png" style="width: 35px;height: 15px;margin-left: 10px"/>
</div> </div>
<div class="rightItem">{{ orderDetailInfo.contractName }}</div> <div class="rightItem">{{ orderDetailInfo.contractName }}</div>
<template v-if="orderDetailInfo.contractParentId == 110">
<div class="rightItem">{{ orderDetailInfo.organizeName }}</div>
<div class="rightItem">{{ orderDetailInfo.saleName }}</div>
<div class="rightItem">{{ orderDetailInfo.driverPhone ? orderDetailInfo.driverPhone : ' '}}</div>
</template>
<div class="rightItem">{{ orderDetailInfo.contractSettleType?.label }}</div> <div class="rightItem">{{ orderDetailInfo.contractSettleType?.label }}</div>
<div class="rightItem">{{ orderDetailInfo.userName }}</div> <div class="rightItem">{{ orderDetailInfo.userName }}</div>
<div class="rightItem">{{ orderDetailInfo.userPhone }}</div> <div class="rightItem">{{ orderDetailInfo.userPhone }}</div>
@@ -36,6 +46,9 @@
<div class="item"> <div class="item">
<span class="leftTitle fontColor">服务类型:</span><span class="rightContent">{{ orderDetailInfo.taskServiceName }}</span> <span class="leftTitle fontColor">服务类型:</span><span class="rightContent">{{ orderDetailInfo.taskServiceName }}</span>
</div> </div>
<div class="item" v-if="orderDetailInfo?.userVehicleTypeString">
<span class="leftTitle fontColor">车辆类型:</span><span class="rightContent">{{ orderDetailInfo.userVehicleTypeString }}<van-icon class="icon" name="question" @click="showCarTypeShow = true" /></span>
</div>
<div class="item"> <div class="item">
<span class="leftTitle fontColor">车辆位于:</span><span class="rightContent">{{ orderDetailInfo.positionEnvironment?.label }}</span> <span class="leftTitle fontColor">车辆位于:</span><span class="rightContent">{{ orderDetailInfo.positionEnvironment?.label }}</span>
</div> </div>
@@ -61,6 +74,7 @@
<div class="item"> <div class="item">
<span class="leftTitle fontColor">服务师傅:</span><span class="rightContent">{{ orderDetailInfo.driverName }} {{orderDetailInfo.drivePhone ? '/' : ''}} {{orderDetailInfo.drivePhone }} <span class="leftTitle fontColor">服务师傅:</span><span class="rightContent">{{ orderDetailInfo.driverName }} {{orderDetailInfo.drivePhone ? '/' : ''}} {{orderDetailInfo.drivePhone }}
<span v-if="queryType == 5" class="driverPoiBtn" @click="noMultipleClicks(showMap)">查看司机位置</span> <span v-if="queryType == 5" class="driverPoiBtn" @click="noMultipleClicks(showMap)">查看司机位置</span>
<span v-if="orderDetailInfo.driverName && orderDetailInfo.proprietary?.code==1" class="driverPoiBtn" @click="noMultipleClicks(createDriverInfo)">生成司机信息</span>
</span> </span>
</div> </div>
<div class="item" v-if="queryType == 9 || queryType ==11 || queryType ==12"> <div class="item" v-if="queryType == 9 || queryType ==11 || queryType ==12">
@@ -85,7 +99,15 @@
</div> </div>
</div> </div>
</div> </div>
<van-popup v-model="showCarTypeShow" round position="center" class="popupCenter">
<table v-for="(item, index) in carTypeList" :key="index">
<tr>
<td width="50">{{item.type}}:</td>
<td>{{item.abbr}}</td>
</tr>
</table>
<!-- <div v-for="(item, index) in carTypeList" :key="index"><span style="margin-right: 5px">{{item.type}}:</span><span>{{item.abbr}}</span></div>-->
</van-popup>
<div class="map" v-show="showPopup" id="container"> <div class="map" v-show="showPopup" id="container">
<img @click="showPopup = false" src="@/assets/delKey.png" class="mapImg"> <img @click="showPopup = false" src="@/assets/delKey.png" class="mapImg">
</div> </div>
@@ -93,7 +115,7 @@
</template> </template>
<script> <script>
import {myMixins} from '@/utils/myMixins' import {myMixins} from '@/utils/myMixins'
import {getOrderDetail,showVehiclePositionInfo} from "@/api/order" import {getOrderDetail,showVehiclePositionInfo, getConfigByCode,getDriverInfo} from "@/api/order"
import minePosition from '@/assets/minePosition.png'; import minePosition from '@/assets/minePosition.png';
import vehiclePosition from '@/assets/vehiclePosition.png'; import vehiclePosition from '@/assets/vehiclePosition.png';
import desitationPosition from '@/assets/desitationPosition.png' import desitationPosition from '@/assets/desitationPosition.png'
@@ -111,6 +133,8 @@ export default {
map: '', map: '',
driverPoiInfo:{}, driverPoiInfo:{},
noClick:true, noClick:true,
showCarTypeShow: false,
carTypeList: []
} }
}, },
async mounted() { async mounted() {
@@ -121,6 +145,7 @@ export default {
this.userOrderId = urlParams.get('userOrderId'); this.userOrderId = urlParams.get('userOrderId');
this.orderCode=urlParams.get('orderCode'); this.orderCode=urlParams.get('orderCode');
this.taskOrderId=urlParams.get('taskOrderId') ? urlParams.get('taskOrderId') : ''; this.taskOrderId=urlParams.get('taskOrderId') ? urlParams.get('taskOrderId') : '';
await this.getConfigByCodeHandler();
await this.getDetail(); await this.getDetail();
if(this.queryType == 5){ if(this.queryType == 5){
await this.getDriverPoi(); await this.getDriverPoi();
@@ -131,6 +156,36 @@ export default {
}, },
methods:{ methods:{
async getConfigByCodeHandler() {
let res = await getConfigByCode({
code: 'userVehicleTypeConfig'
});
this.carTypeList = res?.data?.userVehicleType
},
async getDriverInfo(){
let result=await getDriverInfo({
driverId:this.orderDetailInfo.driverId
})
if(result.data){
// console.log('--result--',result.data)
let params={
'姓名:':this.orderDetailInfo.driverName,
'身份证:':result.data.identityCardNumber,
'车牌:':this.orderDetailInfo.plateNumber,
'手机:':this.orderDetailInfo.driverPhone,
}
let data = {"action":"copyToClipboard","params":JSON.stringify(params)}
var u = navigator.userAgent;
var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if(isiOS){
window.webkit.messageHandlers.nativeObject.postMessage(data);
}else {
window.android.copyToClipboard(JSON.stringify(params));
}
}else {
this.$toast('未获取到司机信息')
}
},
async getDetail(){ async getDetail(){
let result=await getOrderDetail({ let result=await getOrderDetail({
queryType:this.queryType, queryType:this.queryType,
@@ -146,6 +201,9 @@ export default {
this.showPopup = true; this.showPopup = true;
this.mapMarkers(); this.mapMarkers();
}, },
async createDriverInfo(){//生成司机信息
await this.getDriverInfo()
},
checkPhoto(){ checkPhoto(){
let isAllowImage = this.queryType == 9 ? 0 : 1 let isAllowImage = this.queryType == 9 ? 0 : 1
let data = { let data = {
@@ -263,7 +321,8 @@ export default {
line-height: 24px; line-height: 24px;
} }
.baseInfo{ .baseInfo{
@include wh(100%,260px); width: 100%;
//@include wh(100%,260px);
margin-bottom: 12px; margin-bottom: 12px;
.infoWrap{ .infoWrap{
display: flex; display: flex;
@@ -276,6 +335,9 @@ export default {
.rightContent{ .rightContent{
height: 189px; height: 189px;
width: calc(100% - 60px); width: calc(100% - 60px);
.rightItem{
height: 24px;
}
} }
} }
} }
@@ -330,4 +392,8 @@ export default {
margin: 7px 0; margin: 7px 0;
border-image: linear-gradient(270deg, rgba(217, 217, 217, 0.6), rgba(178, 178, 178, 1), rgba(178, 178, 178, 1), rgba(217, 217, 217, 0.6)) 1 1; border-image: linear-gradient(270deg, rgba(217, 217, 217, 0.6), rgba(178, 178, 178, 1), rgba(178, 178, 178, 1), rgba(217, 217, 217, 0.6)) 1 1;
} }
.popupCenter {
padding: 20px 10px;
width: 80%;
}
</style> </style>

View File

@@ -0,0 +1,46 @@
<template>
<div class="wrap">
<el-table :data="tableData"
stripe
border
style="width: 100%"
height="100%"
v-loading="loading"
class="custom-table">
<el-table-column v-for="item in labelList" :key="item.prop" :label="item.label" :prop="item.prop" align="center">
<template slot-scope="scope">{{scope.row[item.prop]}} </template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: "fit-table",
props: ['tableData', 'labelList', 'loading', 'isMobile','active'],
data() {
return {}
},
mounted() {
},
methods: {
}
}
</script>
<style scoped lang="scss">
@import "@/styles/mixin.scss";
::v-deep .el-table{
font-size: 11px;
}
::v-deep .el-table thead{
color: #1D2129;
font-weight: bold;
}
::v-deep .el-table th.el-table__cell.is-leaf {
background-color: #E5E6EB;
}
::v-deep .el-table .el-table__cell{
padding: 4px 0 !important;
}
</style>

1203
src/views/kpi/kpiCaseNew.vue Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -39,14 +39,13 @@
<van-tabs v-model="active" sticky @click="tabClickHandle"> <van-tabs v-model="active" sticky @click="tabClickHandle">
<van-tab v-for="(item,index) in tabArr" :key="index" :title="item.name"></van-tab> <van-tab v-for="(item,index) in tabArr" :key="index" :title="item.name"></van-tab>
<div v-if="isMobile && !([0,1,2,3].includes(active))" class="tipArrow left">{{ leftArr }}</div> <div v-if="isMobile && !([0,1,2,3].includes(active))" class="tipArrow left">{{ leftArr }}</div>
<div v-if="isMobile && !([9,10, 11].includes(active))" class="tipArrow right">>>></div> <div v-if="isMobile && !([7,8, 9].includes(active))" class="tipArrow right">>>></div>
</van-tabs> </van-tabs>
<div v-loading="loadingData" :class="{'contentWrap':true,'webcontentWrap':!isMobile}" v-if="active===0"> <div v-loading="loadingData" :class="{'contentWrap':true,'webcontentWrap':!isMobile}" v-if="active===0">
<div :class="{'reciceOrder':true,'webCom':!isMobile}"> <!--<div :class="{'reciceOrder':true,'webCom':!isMobile}">
<div :class="{'title':true,'webTitle':!isMobile}">接单指标</div> <div :class="{'title':true,'webTitle':!isMobile}">接单指标</div>
<div class="reciceOrderIWrap"> <div class="reciceOrderIWrap">
<div class="left common"> <div class="left common">
<!-- indexData && -->
<div class="num">{{ formatCurrency(indexData?.receiveOrderCount) }}</div> <div class="num">{{ formatCurrency(indexData?.receiveOrderCount) }}</div>
<div class="itemTitle">承接案件量</div> <div class="itemTitle">承接案件量</div>
</div> </div>
@@ -59,13 +58,13 @@
<div class="itemTitle" style="cursor: pointer">超时率 ></div> <div class="itemTitle" style="cursor: pointer">超时率 ></div>
</div> </div>
</div> </div>
</div> </div>-->
<div :class="{'reciceOrder':true,'webCom':!isMobile,'evaluate':isMobile}"> <div :class="{'reciceOrder':true,'webCom':!isMobile,'evaluate':isMobile}">
<div class="title">客户评价</div> <div class="title">客户评价</div>
<div class="reciceOrderIWrap" v-if="indexData"> <div class="reciceOrderIWrap" v-if="indexData">
<circle-char ref="Doughnut1" :data="indexData && indexData.complainOrderRate" :title-text="'投诉率'" :bg-color="Number(indexData?.complainOrderRate || 0) <= 0.1 ? 'green' : 'red'" <circle-char ref="Doughnut1" :data="indexData && indexData.complainOrderRate" :title-text="'投诉率'" :bg-color="Number(indexData?.complainOrderRate || 0) <= 0.1 ? 'green' : 'red'"
:is-store="false" @clickComplain="clickJumpHandle(7)"></circle-char> :is-store="false" @clickComplain="clickJumpHandle(7)"></circle-char>
<circle-char ref="Doughnut2" :data="indexData && indexData.pinganFavorableRate" :title-text="'平安好评率'" :is-store="false" <circle-char v-if="false" ref="Doughnut2" :data="indexData && indexData.pinganFavorableRate" :title-text="'平安好评率'" :is-store="false"
:bg-color="Number(indexData?.pinganFavorableRate || 0) >= 99.4 ? 'green' : 'red'"></circle-char> :bg-color="Number(indexData?.pinganFavorableRate || 0) >= 99.4 ? 'green' : 'red'"></circle-char>
<circle-char ref="Doughnut3" :data="indexData && indexData.urgeRate" :title-text="'催促率'" <circle-char ref="Doughnut3" :data="indexData && indexData.urgeRate" :title-text="'催促率'"
:bg-color="Number(indexData?.urgeRate || 0) >= 3 ? 'red' : 'green'"></circle-char> :bg-color="Number(indexData?.urgeRate || 0) >= 3 ? 'red' : 'green'"></circle-char>
@@ -88,8 +87,8 @@
<div class="num" :class="{'numRed': Number(indexData?.receiving) > 5, 'numGreen': Number(indexData?.receiving) <= 5 }">{{ indexData && indexData.receiving }}</div> <div class="num" :class="{'numRed': Number(indexData?.receiving) > 5, 'numGreen': Number(indexData?.receiving) <= 5 }">{{ indexData && indexData.receiving }}</div>
<div class="itemTitle">接单时效(分)</div> <div class="itemTitle">接单时效(分)</div>
</div> </div>
<div class="line"></div> <div class="line" v-if="false"></div>
<div class="center common"> <div class="center common" v-if="false">
<div class="num" :class="{'numRed': Number(indexData?.pinganJuheSuccessArriving) > 22, 'numGreen': Number(indexData?.pinganJuheSuccessArriving) <= 22 }">{{ indexData && indexData.pinganJuheSuccessArriving }}</div> <div class="num" :class="{'numRed': Number(indexData?.pinganJuheSuccessArriving) > 22, 'numGreen': Number(indexData?.pinganJuheSuccessArriving) <= 22 }">{{ indexData && indexData.pinganJuheSuccessArriving }}</div>
<div class="itemTitle">平安聚合成功到达时效(分)</div> <div class="itemTitle">平安聚合成功到达时效(分)</div>
</div> </div>
@@ -112,38 +111,28 @@
<circle-char v-show="showScoreChart" ref="Doughnut7" :data="indexData && indexData.score" :bg-color="Number(indexData?.score || 0) >= 60 ? 'green' : 'red'" :is-store="true"></circle-char> <circle-char v-show="showScoreChart" ref="Doughnut7" :data="indexData && indexData.score" :bg-color="Number(indexData?.score || 0) >= 60 ? 'green' : 'red'" :is-store="true"></circle-char>
<div v-show="!showScoreChart" class="detailScore"> <div v-show="!showScoreChart" class="detailScore">
<div class="left"> <div class="left">
<div> <!-- <div><span class="defen">接单得分:</span></div>-->
<span class="defen">接单得分:</span> <div><span class="defen">接单时效得分:</span></div>
</div> <div><span class="defen">到达时效得分:</span></div>
<div> <div><span class="defen">聚合成功率得分:</span></div>
<span class="defen">接单时效得分:</span> <div><span class="defen">APP使用率得分:</span></div>
</div> <div><span class="defen">催促率得分:</span></div>
<div> <div><span class="defen">投诉率得分:</span></div>
<span class="defen">接单时效得分:</span> <div><span class="defen">超时率得分:</span></div>
</div> <div><span class="defen">拒单率得分:</span></div>
<div><span class="defen">聚合成功率得分:</span> <div><span class="defen">3'联系率得分:</span></div>
</div>
<div><span class="defen">APP使用率得分:</span>
</div>
<div><span class="defen">催促率得分:</span>
</div>
<div><span class="defen">投诉率得分:</span>
</div>
</div> </div>
<div class="right"> <div class="right">
<div> <!-- <div><span>{{ indexData.orderScore }}</span></div>-->
<span>{{ indexData.orderScore }}</span> <div><span>{{ indexData.orderAgeingScore }}</span></div>
</div> <div><span>{{ indexData.arriveAgeingScore }}</span></div>
<div>
<span>{{ indexData.orderAgeingScore }}</span>
</div>
<div>
<span>{{ indexData.arriveAgeingScore }}</span>
</div>
<div> <span>{{ indexData.polymerizationSuccessScore }}</span></div> <div> <span>{{ indexData.polymerizationSuccessScore }}</span></div>
<div> <span>{{ indexData.appUseScore }}</span></div> <div> <span>{{ indexData.appUseScore }}</span></div>
<div> <span>{{ indexData.urgeScore }}</span></div> <div> <span>{{ indexData.urgeScore }}</span></div>
<div><span>{{ indexData.urgeScore }}</span></div> <div><span>{{ indexData.urgeScore }}</span></div>
<div> <span>{{ indexData.timeOutScore }}</span></div>
<div> <span>{{ indexData.refuseOrderScore }}</span></div>
<div><span>{{ indexData.threeMinutesContactSocre }}</span></div>
</div> </div>
</div> </div>
</div> </div>
@@ -164,7 +153,7 @@
<div v-if="active==1" style="width: 100%"> <div v-if="active==1" style="width: 100%">
<div id="chartWrap" style="width: 100%;height:300px"></div> <div id="chartWrap" style="width: 100%;height:300px"></div>
</div> </div>
<div v-if="activeIndex==3" class="selectWrap"> <div v-if="activeIndex==2" class="selectWrap">
<el-select v-model="value" @change="changeHandle"> <el-select v-model="value" @change="changeHandle">
<el-option <el-option
v-for="item in options" v-for="item in options"
@@ -176,7 +165,7 @@
</div> </div>
</template> </template>
<template v-else> <template v-else>
<div v-if="[0,1,2].includes(activeIndex)"> <div v-if="[0,1].includes(activeIndex)">
<div id="chartWrap" style="width: 100%;height:300px"></div> <div id="chartWrap" style="width: 100%;height:300px"></div>
</div> </div>
<div v-else style="width: 100%;display: flex;justify-content: space-between"> <div v-else style="width: 100%;display: flex;justify-content: space-between">
@@ -200,8 +189,8 @@
<noFit-table v-else :active='active' :is-mobile='isMobile' :table-data="detailList" :label-list="labelList"></noFit-table> <noFit-table v-else :active='active' :is-mobile='isMobile' :table-data="detailList" :label-list="labelList"></noFit-table>
</div> </div>
</div> </div>
<div v-loading="loadingData" class="contentWrap monthTotal" v-if="[2,4,5].includes(active)"> <div v-loading="loadingData" class="contentWrap monthTotal" v-if="[2,3,4].includes(active)">
<div class="searchDriverName" v-if="[5,4].includes(active)"> <div class="searchDriverName" v-if="[3,4].includes(active)">
<el-select <el-select
v-model="driverName" v-model="driverName"
filterable filterable
@@ -223,12 +212,12 @@
</el-select> </el-select>
</div> </div>
<div :class="{'tabWrap':true,'webTabWrap':!isMobile,'mobileTab':isMobile}"> <div :class="{'tabWrap':true,'webTabWrap':!isMobile,'mobileTab':isMobile}">
<div v-for="(item,index) in (active===4 ? driverList : list)" :class="activeIndex===index ? 'active' : ''" <div v-for="(item,index) in (active===3 ? driverList : list)" :class="activeIndex===index ? 'active' : ''"
:key="index" :key="index"
@click="changeTab(index)">{{ item.name }} @click="changeTab(index)">{{ item.name }}
</div> </div>
</div> </div>
<div :class="{'comTab':active !== 4,'comTabActive3':active === 4}"> <div :class="{'comTab':active !== 3,'comTabActive3':active === 3}">
<noFit-table :active='active' :is-mobile='isMobile' :table-data="detailList" :label-list="labelList"></noFit-table> <noFit-table :active='active' :is-mobile='isMobile' :table-data="detailList" :label-list="labelList"></noFit-table>
</div> </div>
<el-pagination <el-pagination
@@ -243,13 +232,13 @@
:total="total"> :total="total">
</el-pagination> </el-pagination>
</div> </div>
<div v-loading="loadingData" class="contentWrap monthTotal" v-if="[3,6,7,8,9,10, 11].includes(active)"> <div v-loading="loadingData" class="contentWrap monthTotal" v-if="[5,6,7,8,9].includes(active)">
<div :class="{'comTab':true,'detailTable':isMobile}"> <div :class="{'comTab':true,'detailTable':isMobile}">
<noFit-table :active='active' :is-mobile='isMobile' :table-data="detailList" :label-list="labelList" <noFit-table :active='active' :is-mobile='isMobile' :table-data="detailList" :label-list="labelList"
></noFit-table> ></noFit-table>
</div> </div>
<el-pagination <el-pagination
v-if="active !== 10" v-if="active !== 8"
small small
:page-sizes="[20, 50, 100]" :page-sizes="[20, 50, 100]"
:current-page.sync="pageNum" :current-page.sync="pageNum"
@@ -272,8 +261,9 @@ import {
getStatisticsKpi, getStatisticsKpi,
getSupplierId, getSupplierId,
getDriverName,getDriverStatisticsKpi, getDriverName,getDriverStatisticsKpi,
getRecentSupplierKpi, querySupplierDriverStatisticsScore getRecentSupplierKpi,
} from "@/api/kpi.js" } from "@/api/kpi.js"
// querySupplierDriverStatisticsScore
import {myMixins} from "@/utils/myMixins" import {myMixins} from "@/utils/myMixins"
import CircleChar from "@/views/kpi/components/circleChar.vue"; import CircleChar from "@/views/kpi/components/circleChar.vue";
import NoFitTable from "@/views/kpi/components/noFit-table.vue"; import NoFitTable from "@/views/kpi/components/noFit-table.vue";
@@ -289,11 +279,14 @@ export default {
activeIndex: 0, activeIndex: 0,
// //
tabArr: [ tabArr: [
{name: '总览'}, {name: '月/总'}, {name: '日/总'},{name: '师傅满意度'},{name: '月/师傅'}, {name: '日/师傅'}, {name: '拒单明细'}, {name: '总览',value:0}, {name: '月/总'}, {name: '日/总'},{name: '月/师傅'}, {name: '日/师傅'}, /*{name: '拒单明细'},*/
{name: '超时明细'}, {name: '投诉明细'}, {name: '不使用APP案件明细'}, {name: '车辆在线情况'} , {name: '聚合失败案件明细'} /*{name: '超时明细'},*/ {name: '催促明细'},{name: '投诉明细'}, {name: '不使用APP案件明细'}, {name: '车辆在线情况'} , {name: '聚合失败案件明细'}
], ],
list: [{name: '接单指标'}, {name: '客户评价'}, {name: 'APP使用'}, {name: ' 时效 '}], list: [ {name: '服务评价'}, {name: 'APP使用情况'}, {name: ' 时效 '}],
driverList: [{name: '得分总览'},{name: '接单情况'}, {name: '服务评价'}, {name: 'APP使用情况'}, {name: '时效 '}], // driverList: [{name: '得分总览'},{name: '接单情况'}, {name: '服务评价'}, {name: 'APP使用情况'}, {name: '时效 '}],
// {name: '接单情况'},
driverList: [{name: '服务评价'}, {name: 'APP使用情况'}, {name: '时效 '}],//story#7149,要求暂时隐藏得分总览
startMonthTime: '', startMonthTime: '',
startTime: '', startTime: '',
endTime: '', endTime: '',
@@ -316,7 +309,6 @@ export default {
isMobile: false, isMobile: false,
isZd: '', isZd: '',
current:'2024-10', current:'2024-10',
// current: dayjs(new Date()).format('M'),
supplierName:'', supplierName:'',
value: '1', value: '1',
options: [ options: [
@@ -370,21 +362,13 @@ export default {
} }
}, },
monthChangeHandle(value){ monthChangeHandle(value){
console.log('valuevaluevalue', dayjs(new Date(value)).format('YYYY-MM-DD'))
if (value) { if (value) {
this.current = dayjs(new Date(value)).format('YYYY-MM') this.current = dayjs(new Date(value)).format('YYYY-MM')
const _tempDate = dayjs(new Date(value)).format('YYYY-MM-DD') const _tempDate = dayjs(new Date(value)).format('YYYY-MM-DD')
const lastDay = dayjs(_tempDate).endOf('month'); const lastDay = dayjs(_tempDate).endOf('month');
/*const year = value.getFullYear();
const month = value.getMonth() + 1; // 月份从 0 开始,需要加 1
const yearAndMonth = year + '-' + (month > 9 ? month : '0' + month);
this.current = dayjs(new Date(yearAndMonth)).format('YYYY-MM')*/
this.startTime = `${this.current}-01 00:00:00`; this.startTime = `${this.current}-01 00:00:00`;
// const lastDay = new Date(year, month, 0).getDate(); // 获取该月的最后一天
this.endTime = `${this.current}-${this.padZero(lastDay.date())} 23:59:59`; this.endTime = `${this.current}-${this.padZero(lastDay.date())} 23:59:59`;
this.startMonthTime=this.getStartTimeFromEndTime(this.endTime) this.startMonthTime=this.getStartTimeFromEndTime(this.endTime)
console.log(" this.startMonthTime", this.startMonthTime)
this.selectSupplierNameHandle(); this.selectSupplierNameHandle();
if(this.active===1){ if(this.active===1){
this.tabClickHandle() this.tabClickHandle()
@@ -400,7 +384,7 @@ export default {
return return
} }
this.$refs.Doughnut1.initCircle() this.$refs.Doughnut1.initCircle()
this.$refs.Doughnut2.initCircle() // this.$refs.Doughnut2.initCircle()
this.$refs.Doughnut3.initCircle() this.$refs.Doughnut3.initCircle()
this.$refs.Doughnut4.initCircle() this.$refs.Doughnut4.initCircle()
this.$refs.Doughnut5.initCircle() this.$refs.Doughnut5.initCircle()
@@ -513,7 +497,7 @@ export default {
let myChart = echarts.init(document.getElementById('chartWrap')) let myChart = echarts.init(document.getElementById('chartWrap'))
let option; let option;
//接单指标 //接单指标
let series1 = [{ /*let series1 = [{
name: '派遣案件量', name: '派遣案件量',
type: 'bar', type: 'bar',
data: this.v1?.map(item => Number(item?.toString()?.replace(/,/g, ''))), data: this.v1?.map(item => Number(item?.toString()?.replace(/,/g, ''))),
@@ -552,19 +536,19 @@ export default {
formatter: '{c}%' formatter: '{c}%'
}, },
}, },
/* { // {
name: '客户取消率', // name: '客户取消率',
type: "line", // type: "line",
data: this.v4, // data: this.v4,
yAxisIndex: 1, // yAxisIndex: 1,
smooth: true, // smooth: true,
label: { // label: {
show: true, // show: true,
position: 'top', // position: 'top',
formatter: '{c}%' // formatter: '{c}%'
}, // },
},*/ // },
] ]*/
let series2 = [ let series2 = [
{ {
name: '投诉率', name: '投诉率',
@@ -740,7 +724,7 @@ export default {
}, },
}, },
] ]
let yAxis1 = [ /*let yAxis1 = [
{type: 'value'}, {type: 'value'},
{ {
type: 'value', type: 'value',
@@ -748,7 +732,7 @@ export default {
formatter: '{value}%' formatter: '{value}%'
} }
}, },
] ]*/
let yAxis2 = [ let yAxis2 = [
{ {
type: 'value', type: 'value',
@@ -779,16 +763,17 @@ export default {
let series = [] let series = []
let yAxis = [] let yAxis = []
if (this.active === 1) { if (this.active === 1) {
if (this.activeIndex === 0) { /* if (this.activeIndex === 0) {
series = series1 series = series1
yAxis = yAxis1 yAxis = yAxis1
} else if (this.activeIndex === 1) { } else*/
if (this.activeIndex === 0) {
series = series2 series = series2
yAxis = yAxis2 yAxis = yAxis2
} else if (this.activeIndex === 2) { } else if (this.activeIndex === 1) {
series = [] series = []
yAxis = [] yAxis = []
} else if (this.activeIndex === 3) { } else if (this.activeIndex === 2) {
if (this.value == 1) { if (this.value == 1) {
series = series4 series = series4
yAxis = yAxis4 yAxis = yAxis4
@@ -800,7 +785,7 @@ export default {
} }
option = { option = {
title: { title: {
text: this.isMobile ? this.getTitle(this.activeIndex) : (this.active === 1 && this.activeIndex === 2) ? '' : '师傅接单时效', text: this.isMobile ? this.getTitle(this.activeIndex) : (this.active === 1 && this.activeIndex === 1) ? '' : '师傅接单时效',
textStyle: { textStyle: {
fontSize: 12 fontSize: 12
}, },
@@ -812,7 +797,7 @@ export default {
right: '1%', right: '1%',
itemWidth: this.isMobile ? 10 : 18, // 设置图例图标的宽度,从而调整图标大小 itemWidth: this.isMobile ? 10 : 18, // 设置图例图标的宽度,从而调整图标大小
itemHeight: this.isMobile ? 6 : 10, itemHeight: this.isMobile ? 6 : 10,
width: (this.active == 1 && this.activeIndex == 2) ? '60%' : '100%', width: (this.active == 1 && this.activeIndex == 1) ? '60%' : '100%',
}, },
xAxis: { xAxis: {
type: 'category', type: 'category',
@@ -985,7 +970,7 @@ export default {
async getKpiData() { async getKpiData() {
try { try {
this.loading = true this.loading = true
if (this.active === 0) { if (this.active === 0) {//总览
await this.allDataChart() await this.allDataChart()
let res = await getStatisticsKpiByMonth({ let res = await getStatisticsKpiByMonth({
startTime: this.startTime, startTime: this.startTime,
@@ -1016,7 +1001,7 @@ export default {
this.indexData[key] = this.processPercentage(this.indexData[key]); this.indexData[key] = this.processPercentage(this.indexData[key]);
} }
} }
} else if ([1, 2].includes(this.active)) { } else if ([1, 2].includes(this.active)) {//月总 日总
let res = await getStatisticsKpi({ let res = await getStatisticsKpi({
startTime: this.active === 1 ? this.startMonthTime : this.startTime, startTime: this.active === 1 ? this.startMonthTime : this.startTime,
endTime: this.endTime, endTime: this.endTime,
@@ -1047,8 +1032,6 @@ export default {
item.minorFortyMinutesArrivalRate=this.formatPercentage(item.minorFortyMinutesArrivalRate) ; item.minorFortyMinutesArrivalRate=this.formatPercentage(item.minorFortyMinutesArrivalRate) ;
let formatVal = dayjs(item.statisticsDate).format('DD'); let formatVal = dayjs(item.statisticsDate).format('DD');
let formatVal1 = dayjs(item.statisticsDate).format('M'); let formatVal1 = dayjs(item.statisticsDate).format('M');
// console.log("formatVal1",formatVal1)
// return {...item, date: formatVal, month: (formatVal1 == this.current) ? '本月' : (formatVal1 + '月')};
return {...item, date: formatVal, month: formatVal1 + '月'}; return {...item, date: formatVal, month: formatVal1 + '月'};
}); });
this.loading = false this.loading = false
@@ -1056,33 +1039,8 @@ export default {
this.xAxisArr.push(item.month) this.xAxisArr.push(item.month)
this.xAxisArr = [...new Set(this.xAxisArr)]; // 去重 this.xAxisArr = [...new Set(this.xAxisArr)]; // 去重
}) })
console.log(" this.xAxisArr", this.xAxisArr)
// this.xAxisArr[this.xAxisArr.length - 1] = '本月'
await this.twoTabHanldeData() await this.twoTabHanldeData()
}else if (this.active === 3) { } else if ([3,4].includes(this.active)) {//月师傅 日师傅
let res = await querySupplierDriverStatisticsScore({
startTime: this.startTime ,
endTime: this.endTime,
statisticsType: 1,
supplierId: this.supplierId,
driverId: this.driverId,
driverName:this.driverName,
pageNum: this.pageNum,
pageSize: this.pageSize
})
this.total = res.total
this.detailList = res.data?.map(item => {
let formatVal = dayjs(item.statisticsDate).format('DD');
return {...item, date: formatVal};
});
this.labelList = [
{label: '师傅姓名', prop: 'driverName'},
{label: '案件总量', prop: 'orderCount'},
{label: '满意度得分 ', prop: 'driverSatisfaction'},
]
this.loading = false;
}
else if ([4,5].includes(this.active)) {
let res = await getDriverStatisticsKpi({ let res = await getDriverStatisticsKpi({
startTime: this.startTime , startTime: this.startTime ,
endTime: this.endTime, endTime: this.endTime,
@@ -1113,13 +1071,32 @@ export default {
return {...item, date: formatVal}; return {...item, date: formatVal};
}); });
this.loading = false; this.loading = false;
if(this.active===5 && !this.driverName){ /* if(this.active===5 && !this.driverName){
this.detailList=[] this.detailList=[]
this.total=0 this.total=0
} }*/
await this.twoTabHanldeData(); await this.twoTabHanldeData();
} }
else if ([ 6, 7, 8,9,10, 11].includes(this.active)) { /* else if (this.active ===7) {
let res = await querySupplierDriverStatisticsScore({
startTime: this.startTime ,
endTime: this.endTime,
statisticsType: 1,
supplierId: this.supplierId,
driverId: this.driverId,
driverName:this.driverName,
pageNum: this.pageNum,
pageSize: this.pageSize
})
this.total = res.total
this.detailList = res.data?.map(item => {
let formatVal = dayjs(item.statisticsDate).format('DD');
return {...item, date: formatVal};
});
this.loading = false;
} */
else if ([ 5,6,7, 8,9].includes(this.active)) {
this.detailList = [] this.detailList = []
this.labelList = [] this.labelList = []
let result = await getKpiDetailsData({ let result = await getKpiDetailsData({
@@ -1136,7 +1113,7 @@ export default {
return {...item, date: formatVal}; return {...item, date: formatVal};
}); });
this.loading = false this.loading = false
if (this.active === 6) {//拒单明细 /*if (this.active === 5) {//拒单明细
this.labelList = [ this.labelList = [
{label: '案件编号', prop: 'orderCode'}, {label: '案件编号', prop: 'orderCode'},
{label: '服务内容', prop: 'serviceName'}, {label: '服务内容', prop: 'serviceName'},
@@ -1146,7 +1123,7 @@ export default {
{label: '拒绝时间', prop: 'time'}, {label: '拒绝时间', prop: 'time'},
{label: '拒单原因', prop: 'reason'}, {label: '拒单原因', prop: 'reason'},
] ]
} else if (this.active === 7) {//超时明细 } else if (this.active === 6) {//超时明细
this.labelList = [ this.labelList = [
{label: '案件编号', prop: 'orderCode'}, {label: '案件编号', prop: 'orderCode'},
{label: '服务内容', prop: 'serviceName'}, {label: '服务内容', prop: 'serviceName'},
@@ -1156,7 +1133,25 @@ export default {
{label: '超时时间', prop: 'time'}, {label: '超时时间', prop: 'time'},
{label: '超时原因', prop: 'reason'}, {label: '超时原因', prop: 'reason'},
] ]
} else if (this.active === 8) {//投诉明细 } else */
if (this.active === 5) {//催促明细
this.labelList = [
{label: '案件编号', prop: 'orderCode'},
{label: '二级合同名称', prop: 'contractName'},
{label: '案件创建时间', prop: 'orderCreateTime'},
{label: '催促创建时间 ', prop: 'urgeTime'},
{label: '服务商接单时间 ', prop: 'taskAcceptTime'},
{label: '备注内容(催促内容) ', prop: 'urgeRemark'},
{label: '催促次数', prop: 'urgeCount'},//无催促次数,催促一次生成一条新的
{label: '服务商名称', prop: 'supplierName'},
{label: '服务车辆', prop: 'vehicleName'},
{label: '服务完成状况', prop: 'orderStatusString'},
{label: '案件完成时间', prop: 'finishTime'},
{label: '省(B)', prop: 'bprovince'},
{label: '市(B)', prop: 'bcity'},
{label: '区(B)', prop: 'area'},
]
} else if (this.active === 6) {//投诉明细
this.labelList = [ this.labelList = [
{label: '案件编号', prop: 'orderCode'}, {label: '案件编号', prop: 'orderCode'},
{label: '服务内容', prop: 'serviceName'}, {label: '服务内容', prop: 'serviceName'},
@@ -1165,7 +1160,7 @@ export default {
{label: '投诉类型', prop: 'complainTypeString'}, {label: '投诉类型', prop: 'complainTypeString'},
{label: '责任供应商扣罚金额', prop: 'compensateFee'}, {label: '责任供应商扣罚金额', prop: 'compensateFee'},
] ]
} else if (this.active === 9) {//不使用App案件明细 } else if (this.active === 7) {//不使用App案件明细
this.labelList = [ this.labelList = [
{label: '案件编号', prop: 'orderCode'}, {label: '案件编号', prop: 'orderCode'},
{label: '服务内容', prop: 'serviceName'}, {label: '服务内容', prop: 'serviceName'},
@@ -1174,17 +1169,16 @@ export default {
{label: '案件创建时间', prop: 'orderCreateTime'}, {label: '案件创建时间', prop: 'orderCreateTime'},
{label: '事发地', prop: 'vehiclePointAddress'}, {label: '事发地', prop: 'vehiclePointAddress'},
] ]
} else if (this.active === 10) {//车辆在线情况 } else if (this.active === 8) {//车辆在线情况
this.labelList = [ this.labelList = [
{label: '日期', prop: 'date'}, // {label: '总车辆数', prop: 'totalCount'},
{label: '0点在线车辆数', prop: 'zeroClockVehicleCount'}, {label: '在线车辆数(取每日的12点)', prop: 'twelveClockVehicleCount'},
{label: '8点在线车辆数量', prop: 'eightClockVehicleCount'}, {label: '在线拖车数(12点)', prop: 'trailCount'},
{label: '12点在线车辆数量', prop: 'twelveClockVehicleCount'}, {label: '在线小修车数(12点)', prop: 'minorCount'},
{label: '16点在线车辆数', prop: 'sixteenClockVehicleCount'}, {label: '在线率(在线车辆数/总车辆数)', prop: 'onlineRate'},
{label: '20点在线车辆数量', prop: 'twentyClockVehicleCount'}, // {label: '车辆平均在线时长', prop: ''},
{label: '22点在线车辆数量', prop: 'twentyTwoClockVehicleCount'},
] ]
} else if (this.active === 11) {//车辆在线情况 } else if (this.active === 9) {//聚合失败案件明细
this.labelList = [ this.labelList = [
{label: '案件编号', prop: 'orderCode'}, {label: '案件编号', prop: 'orderCode'},
{label: '服务内容', prop: 'serviceName'}, {label: '服务内容', prop: 'serviceName'},
@@ -1208,22 +1202,6 @@ export default {
}, },
// 初始化获取当月日期 // 初始化获取当月日期
initDate() { initDate() {
/*let year=''
let month=''
if( this.current ) {
year = new Date(this.current).getFullYear();
month = new Date(this.current).getMonth() + 1;
} else {
year = new Date().getFullYear();
month = new Date().getMonth() + 1;
}
let yearAndMonth = year + '-' + (month > 9 ? month : '0' + month);
this.current = dayjs(new Date(yearAndMonth)).format('YYYY-MM')
this.startTime = dayjs(new Date()).format('YYYY-MM') + '-01 00:00:00'
this.endTime = dayjs(new Date()).format('YYYY-MM') + '-' + this.getDayLen()+' 23:59:59'*/
// test
// let _testDate = new Date('2024-11-01 00:00:01')
const today = dayjs(); // 获取当前日期 const today = dayjs(); // 获取当前日期
const currentDay = today.date(); // 获取今天是几号1-31 const currentDay = today.date(); // 获取今天是几号1-31
let targetMonth = today; // 默认目标月份是当前月 let targetMonth = today; // 默认目标月份是当前月
@@ -1240,7 +1218,6 @@ export default {
} }
this.endTime = endTime.format('YYYY-MM-DD HH:mm:ss'); this.endTime = endTime.format('YYYY-MM-DD HH:mm:ss');
this.startMonthTime=this.getStartTimeFromEndTime(this.endTime) this.startMonthTime=this.getStartTimeFromEndTime(this.endTime)
console.log(" this.startMonthTime", this.startMonthTime,this.startTime)
}, },
// 获取当月天数 // 获取当月天数
getDayLen() { getDayLen() {
@@ -1295,12 +1272,12 @@ export default {
twoTabHanldeData() { twoTabHanldeData() {
this.etlDetailList=[] this.etlDetailList=[]
this.etlLabelList=[] this.etlLabelList=[]
if (this.active === 1) { if (this.active === 1) {//月总
const columnObj = {} //创建标题数组中第一个对象 const columnObj = {} //创建标题数组中第一个对象
columnObj.label = 'KPI' //第一个标题名称 columnObj.label = 'KPI' //第一个标题名称
columnObj.prop = 'month' //第一个标题名称对应的字段 columnObj.prop = 'month' //第一个标题名称对应的字段
this.etlLabelList.push(columnObj) this.etlLabelList.push(columnObj)
if (this.activeIndex === 0) {//接单指标 /*if (this.activeIndex === 0) {//接单指标
this.etlDetailList=[{ 'month': '派遣量' },{ 'month': '承接量' },{ 'month': '完成量' }, this.etlDetailList=[{ 'month': '派遣量' },{ 'month': '承接量' },{ 'month': '完成量' },
{ 'month': '拒单量' },{ 'month': '拒单率(%)' },{ 'month': '超时接单量' },{ 'month': '超时率(%)' },{ 'month': '客户取消率(%)' }] { 'month': '拒单量' },{ 'month': '拒单率(%)' },{ 'month': '超时接单量' },{ 'month': '超时率(%)' },{ 'month': '客户取消率(%)' }]
let props = 'prop' //自定义字段名称 let props = 'prop' //自定义字段名称
@@ -1336,20 +1313,22 @@ export default {
{label: '超时率(%)', prop: 'timeoutOrderRate'}, {label: '超时率(%)', prop: 'timeoutOrderRate'},
{label: '取消率(%)', prop: 'cancelRate'}, {label: '取消率(%)', prop: 'cancelRate'},
] ]
} else if (this.activeIndex === 1) { } else*/
this.etlDetailList=[{ 'month': '投诉量' },{ 'month': '投诉率(%)' },{ 'month': '平安好评量' }, { 'month': '平安好评率' }] if (this.activeIndex === 0) {
console.log('detailList', this.detailList) // ,{ 'month': '平安好评量' }, { 'month': '平安好评率' }
this.etlDetailList=[{ 'month': '投诉量' },{ 'month': '投诉率(%)' }]
let props = 'prop' //自定义字段名称 let props = 'prop' //自定义字段名称
this.detailList?.map((item,index) => { this.detailList?.map((item,index) => {
this.v1.push(item.complainOrderCount) this.v1.push(item.complainOrderCount)
this.v2.push(item.complainOrderRate?.replace('%', '')) this.v2.push(item.complainOrderRate?.replace('%', ''))
this.v3.push(item?.pinganFavorableCount) // this.v3.push(item?.pinganFavorableCount)
this.v4.push(item.pinganFavorableRate?.replace('%', '')) // this.v4.push(item.pinganFavorableRate?.replace('%', ''))
const columnObj = {} const columnObj = {}
columnObj.label = item.month // 每一列的标题的名称 columnObj.label = item.month // 每一列的标题的名称
columnObj.prop = props + index //自定义每一列标题字段名称 columnObj.prop = props + index //自定义每一列标题字段名称
this.etlLabelList.push(columnObj) this.etlLabelList.push(columnObj)
let mappings = [ 'complainOrderCount', 'complainOrderRate', 'pinganFavorableCount','pinganFavorableRate' ]; // 'pinganFavorableCount','pinganFavorableRate'
let mappings = [ 'complainOrderCount', 'complainOrderRate' ];
for (let i = 0; i < mappings.length; i++) { for (let i = 0; i < mappings.length; i++) {
this.$set(this.etlDetailList[i], columnObj.prop, item[mappings[i]]); this.$set(this.etlDetailList[i], columnObj.prop, item[mappings[i]]);
} }
@@ -1358,22 +1337,23 @@ export default {
{label: '月份', prop: 'month'}, {label: '月份', prop: 'month'},
{label: '投诉量', prop: 'complainOrderCount'}, {label: '投诉量', prop: 'complainOrderCount'},
{label: '投诉率', prop: 'complainOrderRate'}, {label: '投诉率', prop: 'complainOrderRate'},
{label: '平安好评量', prop: 'pinganFavorableCount'},
{label: '平安好评率', prop: 'pinganFavorableRate'},
] ]
} else if (this.activeIndex === 2) { /* {label: '平安好评量', prop: 'pinganFavorableCount'},
this.etlDetailList=[{ 'month': 'APP使用量' }, { 'month': 'APP使用率' }, { 'month': '平安聚合成功量' },{ 'month': '平安聚合成功率' }, {label: '平安好评率', prop: 'pinganFavorableRate'},*/
} else if (this.activeIndex === 1) {
// { 'month': '平安聚合成功量' },{ 'month': '平安聚合成功率' },
this.etlDetailList=[{ 'month': 'APP使用量' }, { 'month': 'APP使用率' },
{ 'month': '中华联合聚合成功量' }, { 'month': '中华联合聚合成功率' }, { 'month': '整体聚合成功量' }, { 'month': '整体聚合成功率' }] { 'month': '中华联合聚合成功量' }, { 'month': '中华联合聚合成功率' }, { 'month': '整体聚合成功量' }, { 'month': '整体聚合成功率' }]
let props = 'prop' //自定义字段名称 let props = 'prop' //自定义字段名称
this.detailList?.map((item,index) => { this.detailList?.map((item,index) => {
this.v1.push(item.appUseCount) this.v1.push(item.appUseCount)
this.v2.push(item.appRate.replace('%', '')) this.v2.push(item.appRate.replace('%', ''))
this.v3.push(item.pinganJuheSuccessCount) /*this.v3.push(item.pinganJuheSuccessCount)
this.v4.push(item.pinganPolymerizationSuccessRate.replace('%', '')) this.v4.push(item.pinganPolymerizationSuccessRate.replace('%', ''))*/
this.v5.push(item.zhonghuaPolymerizationSuccessCount) this.v3.push(item.zhonghuaPolymerizationSuccessCount)
this.v6.push(item.zhonghuaPolymerizationSuccessRate.replace('%', '')) this.v4.push(item.zhonghuaPolymerizationSuccessRate.replace('%', ''))
this.v7.push(item.wholeJuheSuccessCount) this.v5.push(item.wholeJuheSuccessCount)
this.v7.push(item.wholeJuheSuccessRate.replace('%', '')) this.v6.push(item.wholeJuheSuccessRate.replace('%', ''))
const columnObj = {} const columnObj = {}
columnObj.label = item.month // 每一列的标题的名称 columnObj.label = item.month // 每一列的标题的名称
columnObj.prop = props + index //自定义每一列标题字段名称 columnObj.prop = props + index //自定义每一列标题字段名称
@@ -1383,19 +1363,20 @@ export default {
this.$set(this.etlDetailList[i], columnObj.prop, item[mappings[i]]); this.$set(this.etlDetailList[i], columnObj.prop, item[mappings[i]]);
} }
}) })
/*{label: '平安聚合成功量', prop: 'pinganJuheSuccessCount'},
{label: '平安聚合成功率', prop: 'pinganPolymerizationSuccessRate'},*/
this.labelList = [ this.labelList = [
{label: '月份', prop: 'month'}, {label: '月份', prop: 'month'},
{label: 'APP使用量', prop: 'appUseCount'}, {label: 'APP使用量', prop: 'appUseCount'},
{label: 'APP使用率', prop: 'appRate'}, {label: 'APP使用率', prop: 'appRate'},
{label: '平安聚合成功量', prop: 'pinganJuheSuccessCount'},
{label: '平安聚合成功率', prop: 'pinganPolymerizationSuccessRate'},
{label: '中华联合聚合成功量', prop: 'zhonghuaPolymerizationSuccessCount'}, {label: '中华联合聚合成功量', prop: 'zhonghuaPolymerizationSuccessCount'},
{label: '中华联合聚合成功率', prop: 'zhonghuaPolymerizationSuccessRate'}, {label: '中华联合聚合成功率', prop: 'zhonghuaPolymerizationSuccessRate'},
{label: '整体聚合成功量', prop: 'wholeJuheSuccessCount'}, {label: '整体聚合成功量', prop: 'wholeJuheSuccessCount'},
{label: '整体聚合成功率', prop: 'wholeJuheSuccessRate'}, {label: '整体聚合成功率', prop: 'wholeJuheSuccessRate'},
] ]
} else if (this.activeIndex === 3) { } else if (this.activeIndex === 2) {
this.etlDetailList=[{ 'month': '接单时效' },{ 'month': '3分钟联系客户率' },{ 'month': '到达时效' },{'month':'平安聚合成功到达时效'}] // ,{'month':'平安聚合成功到达时效'}
this.etlDetailList=[{ 'month': '接单时效' },{ 'month': '3分钟联系客户率' },{ 'month': '到达时效' }]
let props = 'prop' //自定义字段名称 let props = 'prop' //自定义字段名称
if (this.isMobile) { if (this.isMobile) {
if (this.value == 1) { if (this.value == 1) {
@@ -1439,16 +1420,16 @@ export default {
}) })
} }
} }
// {label: '平安聚合成功到达时效', prop: 'pinganJuheSuccessArriving'},
this.labelList = [ this.labelList = [
{label: '月份', prop: 'month'}, {label: '月份', prop: 'month'},
{label: '接单时效', prop: 'receiving'}, {label: '接单时效', prop: 'receiving'},
{label: '3分钟联系客户率', prop: 'threeMinutesContactRate'}, {label: '3分钟联系客户率', prop: 'threeMinutesContactRate'},
{label: '到达时效', prop: 'arriving'}, {label: '到达时效', prop: 'arriving'},
{label: '平安聚合成功到达时效', prop: 'pinganJuheSuccessArriving'},
] ]
} }
} else if (this.active === 2) { } else if (this.active === 2) {//日总
if (this.activeIndex === 0) {//接单指标 /*if (this.activeIndex === 0) {//接单指标
this.labelList = [ this.labelList = [
{label: '日', prop: 'date'}, {label: '日', prop: 'date'},
{label: '派单量', prop: 'dispatchOrderCount'}, {label: '派单量', prop: 'dispatchOrderCount'},
@@ -1460,7 +1441,8 @@ export default {
{label: '超时率', prop: 'timeoutOrderRate'}, {label: '超时率', prop: 'timeoutOrderRate'},
// {label: '客户取消率(%)', prop: 'cancelRate'}, // {label: '客户取消率(%)', prop: 'cancelRate'},
] ]
} else if (this.activeIndex === 1) { } else*/
if (this.activeIndex === 0) {
this.labelList = [ this.labelList = [
{label: '日', prop: 'date'}, {label: '日', prop: 'date'},
{label: '投诉量', prop: 'complainOrderCount'}, {label: '投诉量', prop: 'complainOrderCount'},
@@ -1468,9 +1450,9 @@ export default {
/* {label: '好评量', prop: 'favorableCount'}, /* {label: '好评量', prop: 'favorableCount'},
{label: '好评率', prop: 'favorableRate'},*/ {label: '好评率', prop: 'favorableRate'},*/
{label: '平安评价率', prop: 'pinganEvaluateRate'}, {label: '平安评价率', prop: 'pinganEvaluateRate'},
{label: '平安好评率', prop: 'pinganFavorableRate'}, // {label: '平安好评率', prop: 'pinganFavorableRate'},
] ]
} else if (this.activeIndex === 2) { } else if (this.activeIndex === 1) {
this.labelList = [ this.labelList = [
{label: '日', prop: 'date'}, {label: '日', prop: 'date'},
{label: 'APP使用量', prop: 'appUseCount'}, {label: 'APP使用量', prop: 'appUseCount'},
@@ -1482,21 +1464,17 @@ export default {
{label: '整体聚合成功量', prop: 'wholeJuheSuccessCount'}, {label: '整体聚合成功量', prop: 'wholeJuheSuccessCount'},
{label: '整体聚合成功率', prop: 'wholeJuheSuccessRate'}, {label: '整体聚合成功率', prop: 'wholeJuheSuccessRate'},
] ]
} else if (this.activeIndex === 3) { } else if (this.activeIndex === 2) {
this.labelList = [ this.labelList = [
{label: '日', prop: 'date'}, {label: '日', prop: 'date'},
{label: '接单时效(分)', prop: 'receiving'}, {label: '接单时效(分)', prop: 'receiving'},
{label: '3分钟联系客户率', prop: 'threeMinutesContactRate'}, {label: '3分钟联系客户率', prop: 'threeMinutesContactRate'},
{label: '到达时效(分)', prop: 'arriving'}, {label: '到达时效(分)', prop: 'arriving'},
{label: '平安聚合成功到达时效(分)', prop: 'pinganJuheSuccessArriving'}, // {label: '平安聚合成功到达时效(分)', prop: 'pinganJuheSuccessArriving'},
] ]
} }
} } else if (this.active === 3) {//月师傅
/* else if(this.active === 3){ /* if (this.activeIndex === 0) {
} */
else if (this.active === 4) {
if (this.activeIndex === 0) {
this.labelList = [ this.labelList = [
{label: '师傅姓名', prop: 'driverName'}, {label: '师傅姓名', prop: 'driverName'},
{label: '总分', prop: 'score'}, {label: '总分', prop: 'score'},
@@ -1524,92 +1502,100 @@ export default {
{label: '新手入列得分', prop: 'listedScore'}, {label: '新手入列得分', prop: 'listedScore'},
{label: '星级评分', prop: 'starRank'}, {label: '星级评分', prop: 'starRank'},
] ]
}if (this.activeIndex === 1) { }else*/
/* if (this.activeIndex === 0) {
this.labelList = [ this.labelList = [
{label: '师傅姓名', prop: 'driverName'}, {label: '师傅姓名', prop: 'driverName'},
{label: '承接案件量', prop: 'receiveOrderCount'}, {label: '派单量', prop: 'dispatchOrderCount'},
{label: '接单量', prop: 'receiveOrderCount'},
{label: '拒单量', prop: 'refuseOrderCount'}, {label: '拒单量', prop: 'refuseOrderCount'},
{label: '拒单率(%)', prop: 'refuseOrderRate'}, {label: '拒单率(%)', prop: 'refuseOrderRate'},
{label: '超时接单量', prop: 'timeoutOrderCount'}, {label: '超时量', prop: 'timeoutOrderCount'},
{label: '超时率(%)', prop: 'timeoutOrderRate'}, {label: '超时率(%)', prop: 'timeoutOrderRate'},
] ]
} else */
if (this.activeIndex === 0) {
this.labelList = [
{label: '师傅姓名', prop: 'driverName'},
// {label: '承接案件量', prop: 'receiveOrderCount'},
{label: '投诉量', prop: 'complainOrderCount'},
{label: '投诉率(%)', prop: 'complainOrderRate'},
{label: '平安评价量', prop: 'pinganEvaluateCount'},
{label: '平安评价率(%)', prop: 'pinganEvaluateRate'},
/* {label: '平安好评量', prop: 'pinganFavorableCount'},
{label: '平安好评率(%)', prop: 'pinganFavorableRate'},*/
// {label: '催促率(%)', prop: 'urgeRate'},
]
} else if (this.activeIndex === 1) {
this.labelList = [
{label: '师傅姓名', prop: 'driverName'},
{label: 'App使用量', prop: 'appUseCount'},
{label: 'App使用率(%)', prop: 'appRate'},
// {label: '3联系客户率(%)', prop: 'threeMinutesContactRate'},
{label: '平安聚合成功量', prop: 'pinganPolymerizationSuccessCount'},
{label: '平安聚合成功率(%)', prop: 'pinganPolymerizationSuccessRate'},
{label: '中华联合聚合成功量', prop: 'zhonghuaPolymerizationSuccessCount'},
{label: '中华联合聚合成功率(%)', prop: 'zhonghuaPolymerizationSuccessRate'},
// {label: '中道聚合成功率(%)', prop: 'zdPolymerizationSuccessRate'},
{label: '整体聚合成功量', prop: 'wholeJuheSuccessCount'},
{label: '整体聚合成功率(%)', prop: 'wholeJuheSuccessRate'},
// {label: '日均在线时长(h)', prop: 'onlineDuration'},
]
} else if (this.activeIndex === 2) { } else if (this.activeIndex === 2) {
this.labelList = [
{label: '师傅姓名', prop: 'driverName'},
{label: '承接案件量', prop: 'receiveOrderCount'},
{label: '投诉量', prop: 'complainOrderCount'},
{label: '投诉率(%)', prop: 'complainOrderRate'},
{label: '客户满意度(%)', prop: 'customerSatisfaction'},
{label: '客户评价率(%)', prop: 'customerEvaluateRate'},
{label: '催促率(%)', prop: 'urgeRate'},
]
} else if (this.activeIndex === 3) {
this.labelList = [
{label: '师傅姓名', prop: 'driverName'},
{label: '承接案件量', prop: 'receiveOrderCount'},
{label: 'App使用率(%)', prop: 'appRate'},
{label: '3联系客户率(%)', prop: 'threeMinutesContactRate'},
{label: '平安聚合成功率(%)', prop: 'pinganPolymerizationSuccessRate'},
{label: '中华聚合成功率(%)', prop: 'zhonghuaPolymerizationSuccessRate'},
{label: '中道聚合成功率(%)', prop: 'zdPolymerizationSuccessRate'},
{label: '总聚合成功率(%)', prop: 'polymerizationSuccessRate'},
{label: '日均在线时长(h)', prop: 'onlineDuration'},
]
} else if (this.activeIndex === 4) {
this.labelList = [ this.labelList = [
{label: '师傅姓名', prop: 'driverName'}, {label: '师傅姓名', prop: 'driverName'},
{label: '接单时效(分)', prop: 'receiving'}, {label: '接单时效(分)', prop: 'receiving'},
{label: '3接单率(%)', prop: 'threeMinutesReceivingRate'}, {label: '3联系客户率(%)', prop: 'threeMinutesReceivingRate'},
{label: '到达时效(分)', prop: 'arriving'}, {label: '到达时效(分)', prop: 'arriving'},
{label: '40到达率(%)', prop: 'fortyMinutesArrivalRate'}, // {label: '40到达率(%)', prop: 'fortyMinutesArrivalRate'},
{label: '聚合成功到达时效(分)', prop: 'polymerizationSuccessArriving'}, // {label: '平安聚合成功到达时效(分)', prop: 'pinganJuheSuccessArriving'},
] ]
} }
} else if (this.active === 5) { } else if (this.active === 4) {//日师傅
if (this.activeIndex === 0) {//接单指标 /*if (this.activeIndex === 0) {//接单指标
this.labelList = [ this.labelList = [
{label: '日', prop: 'date'}, {label: '日', prop: 'date'},
{label: '师傅姓名', prop: 'driverName'}, {label: '师傅姓名', prop: 'driverName'},
{label: '派遣案件量', prop: 'dispatchOrderCount'}, {label: '派量', prop: 'dispatchOrderCount'},
{label: '承接案件量', prop: 'receiveOrderCount'}, {label: '接单量', prop: 'receiveOrderCount'},
{label: '完成量', prop: 'finishOrderCount'},
{label: '拒单量', prop: 'refuseOrderCount'}, {label: '拒单量', prop: 'refuseOrderCount'},
{label: '拒单率(%)', prop: 'refuseOrderRate'}, {label: '拒单率(%)', prop: 'refuseOrderRate'},
{label: '超时接单量', prop: 'timeoutOrderCount'}, {label: '超时量', prop: 'timeoutOrderCount'},
{label: '超时率(%)', prop: 'timeoutOrderRate'}, {label: '超时率(%)', prop: 'timeoutOrderRate'},
{label: '客户取消率(%)', prop: 'cancelRate'}, ]
} else */
if (this.activeIndex === 0) {
this.labelList = [
{label: '日', prop: 'date'},
{label: '师傅姓名', prop: 'driverName'},
{label: '投诉量', prop: 'complainOrderCount'},
{label: '投诉率(%)', prop: 'complainOrderRate'},
{label: '平安评价量', prop: 'pinganEvaluateCount'},
{label: '平安评价率(%)', prop: 'pinganEvaluateRate'},
// {label: '平安好评量', prop: 'pinganFavorableCount'},
// {label: '平安好评率(%)', prop: 'pinganFavorableRate'},
] ]
} else if (this.activeIndex === 1) { } else if (this.activeIndex === 1) {
this.labelList = [ this.labelList = [
{label: '日', prop: 'date'}, {label: '日', prop: 'date'},
{label: '师傅姓名', prop: 'driverName'}, {label: '师傅姓名', prop: 'driverName'},
{label: '投诉量', prop: 'complainOrderCount'}, {label: 'App使用量', prop: 'appUseCount'},
{label: '投诉率(%)', prop: 'complainOrderRate'}, {label: 'App使用率(%)', prop: 'appRate'},
{label: '客户满意度(%)', prop: 'customerSatisfaction'}, {label: '平安聚合成功量', prop: 'pinganPolymerizationSuccessCount'},
{label: '客户评价率(%)', prop: 'customerEvaluateRate'}, {label: '平安聚合成功率(%)', prop: 'pinganPolymerizationSuccessRate'},
{label: '催促率(%)', prop: 'urgeRate'}, {label: '中华联合聚合成功量', prop: 'zhonghuaPolymerizationSuccessCount'},
{label: '中华联合聚合成功率(%)', prop: 'zhonghuaPolymerizationSuccessRate'},
{label: '整体聚合成功量', prop: 'wholeJuheSuccessCount'},
{label: '整体聚合成功率(%)', prop: 'wholeJuheSuccessRate'},
] ]
} else if (this.activeIndex === 2) { } else if (this.activeIndex === 2) {
this.labelList = [
{label: '日', prop: 'date'},
{label: '师傅姓名', prop: 'driverName'},
{label: '使用率(%)', prop: 'appRate'},
{label: '3联系客户率(%)', prop: 'threeMinutesContactRate'},
{label: '平安聚合成功率(%)', prop: 'pinganPolymerizationSuccessRate'},
{label: '中华聚合成功率(%)', prop: 'zhonghuaPolymerizationSuccessRate'},
{label: '中道聚合成功率(%)', prop: 'zdPolymerizationSuccessRate'},
{label: '总聚合成功率(%)', prop: 'polymerizationSuccessRate'},
{label: '日均在线时长(h)', prop: 'onlineDuration'},
]
} else if (this.activeIndex === 3) {
this.labelList = [ this.labelList = [
{label: '日', prop: 'date'}, {label: '日', prop: 'date'},
{label: '师傅姓名', prop: 'driverName'}, {label: '师傅姓名', prop: 'driverName'},
{label: '接单时效(分)', prop: 'receiving'}, {label: '接单时效(分)', prop: 'receiving'},
{label: '3接单率(%)', prop: 'threeMinutesReceivingRate'}, {label: '3联系客户率(%)', prop: 'threeMinutesReceivingRate'},
{label: '到达时效(分)', prop: 'arriving'}, {label: '到达时效(分)', prop: 'arriving'},
{label: '40到达率(%)', prop: 'fortyMinutesArrivalRate'}, // {label: '平安聚合成功到达时效(分)', prop: 'pinganJuheSuccessArriving'},
{label: '聚合成功到达时效(分)', prop: 'polymerizationSuccessArriving'},
] ]
} }
} }
@@ -1621,30 +1607,32 @@ export default {
}, },
setType(type) { setType(type) {
switch (type) { switch (type) {
case 6: /*case 5:
return 1; return 1;
case 7: case 6:
return 2; return 2;*/
case 8: case 5:
return 7;
case 6:
return 3; return 3;
case 9: case 7:
return 4; return 4;
case 10: case 8:
return 5; return 5;
case 11: case 9:
return 6; return 6;
} }
}, },
getTitle(type) { getTitle(type) {
switch (type) { switch (type) {
case 0: case 0:
return '接单时效';
case 1:
return '客户评价'; return '客户评价';
case 2: case 1:
return 'APP使用'; return 'APP使用';
case 3: case 2:
return '时效'; return '时效';
/* case 3:
return '时效';*/
} }
}, },
} }

View File

@@ -22,7 +22,7 @@
为此中道救援经过与保司沟通协调特为与中道救援合作紧密的服务商提供救援职业责任险参保渠道提升服务商服务能力降低运营风险实现共同进步 为此中道救援经过与保司沟通协调特为与中道救援合作紧密的服务商提供救援职业责任险参保渠道提升服务商服务能力降低运营风险实现共同进步
</div> </div>
<div>救援职业责任险简介</div> <div>救援职业责任险简介</div>
<div>1综合保额50万元可全方位覆盖我们日常的经营活动</div> <div> 1综合保额100万元其中救援责任50万元物流责任50万元可全方位覆盖我们日常的经营活动</div>
<div> 2保费支付可采用救援服务费抵扣的方式降低资金压力</div> <div> 2保费支付可采用救援服务费抵扣的方式降低资金压力</div>
<div> 3详细保险条款保费和其他问题如需了解请与辖区区域经理联系</div> <div> 3详细保险条款保费和其他问题如需了解请与辖区区域经理联系</div>
<div> 其他意见建议如需交流请与18621558505曲仁杰联系</div> <div> 其他意见建议如需交流请与18621558505曲仁杰联系</div>
@@ -65,6 +65,7 @@ export default {
return { return {
showPoup: false, showPoup: false,
used:false, used:false,
saveLoading: true,
} }
}, },
async mounted() { async mounted() {
@@ -73,12 +74,19 @@ export default {
}, },
methods: { methods: {
async saveHandle() { async saveHandle() {
if( this.saveLoading ) {
try {
this.saveLoading = false;
await sendInsuranceEmail(); await sendInsuranceEmail();
this.$toast('操作成功'); this.$toast('操作成功');
this.showPoup=false this.showPoup = false
setTimeout(()=>{ setTimeout(() => {
this.goBack() this.goBack()
},1500) }, 1500)
} finally {
this.saveLoading = true;
}
}
}, },
} }
} }

View File

@@ -0,0 +1,453 @@
<template>
<div class="wrap">
<div class="navBar">
<van-nav-bar
title="人员信息"
:left-arrow="Boolean(!isWebFunc())"
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="goBack"
/>
</div>
<div :class="{'tipWrap':true,'yelBg':type==3,'greBg':type==4}">
<img v-show="[1,2].includes(type)" src="@/assets/unpass.png" />
<img v-show="[3].includes(type)" src="@/assets/yelTip.png" />
<img v-show="[4].includes(type)" src="@/assets/greTip.png" />
<span v-if="type==1">请立即核对或修改以下信息姓名/身份/电话/微信号/邮箱</span>
<span v-else-if="type==2">角色无法修改如需修改角色请联系区域经理提交审批后请到管理人员模块进行查看</span>
<span v-else-if="type==3">当前信息正在确认中如需调整请联系区域经理</span>
<span v-else-if="type==4">当前信息已确认如需调整请联系区域经理</span>
</div>
<van-loading v-show="personList.length<=0" class="loadingWrap" type="spinner" color="#1989fa" />
<div class="contentWrap" v-show="personList.length>0"
:style="{'height':([1,2].includes(type) && isMaster) ? 'calc(100% - 160px)' : 'calc(100% - 90px)'}">
<div class="itemWrap" v-for="(item,index) in personList" :key="index">
<div class="opaCol">人员{{(index+1)}}:</div>
<div class="line"></div>
<div class="item">
<div class="left" :class="{'opaCol':type!=2}"><span class="star">*</span><span>姓名</span></div>
<div class="right">
<van-field :input-align="type==2 ? 'right' : 'left'" :readonly="type!=2" v-model="item.name" placeholder="请输入" />
</div>
</div>
<div class="item">
<div class="left opaCol"><span class="star" style="opacity: 0">*</span><span>角色</span></div>
<div class="right" :class="{'opaCol':type==2}">
<van-field :input-align="type==2 ? 'right' : 'left'" readonly v-model="item.roleName" placeholder="请输入" />
</div>
</div>
<div class="item">
<div class="left" :class="{'opaCol':type!=2}"><span class="star">*</span><span>电话1</span></div>
<div class="right">
<van-field :input-align="type==2 ? 'right' : 'left'" :readonly="type!=2" v-model.number="item.phone1" placeholder="请输入" @blur="blurHandle" />
</div>
</div>
<div class="item">
<div class="left" :class="{'opaCol':type!=2}"><span class="star" style="opacity: 0">*</span><span>电话2</span></div>
<div class="right">
<van-field :input-align="type==2 ? 'right' : 'left'" :readonly="type!=2" v-model.number="item.phone2" @blur="blurHandle" placeholder="请输入" />
</div>
</div>
<div class="item">
<div class="left" :class="{'opaCol':type!=2}"><span class="star">*</span><span>微信号</span></div>
<div class="right wechatRight">
<span class="reviseBtn" v-show="type==2" @click="wechatRevise(item,index)">修改</span>
<van-field :input-align="type==2 ? 'right' : 'left'" readonly v-model="item.wechatName" />
</div>
</div>
<div class="item">
<div class="left" :class="{'opaCol':type!=2}"><span class="star" style="opacity: 0">*</span><span>邮箱</span></div>
<div class="right">
<van-field :input-align="type==2 ? 'right' : 'left'" :readonly="type!=2" v-model="item.email" placeholder="请输入" />
</div>
</div>
</div>
</div>
<div class="btnWrap" v-if="isMaster && [1,2].includes(type)">
<div v-show="type==2" class="audit common" @click="auditHandle">提交审批</div>
<div v-show="type==1" class="revise common" @click="reviseHandle">立即修改</div>
<div v-show="type==1" class="confirm common" @click="confirmHandle">确认信息无误</div>
</div>
<van-dialog v-model="dialogShow" title="请将此二维码发送至相应人员进行添加,成功添加后将更新微信号。" show-cancel-button
confirmButtonText="确认已添加" confirmButtonColor="#354E93" className="customDialog"
@confirm="wechatConfirm" @cancel="cancelHandle">
<img v-if="wechatInfo?.qrCode" :src="wechatInfo.qrCode" style="width: 83%"/>
</van-dialog>
</div>
</template>
<script>
import {myMixins} from "@/utils/myMixins"
import {getConfirmPerson,getConfirmStatus,getQrCode,confirmAddWechat,confirm,submitConfirm} from "@/api/authentication";
import { Dialog } from 'vant';
export default {
name: "personList",
mixins:[myMixins],
data(){
return{
noClick:true,
id:'',
type:'',//1确认信息 2修改 3审批中 4已确认
personList:[],
dialogShow:false,
reviseIndex:-1,
supplierId:'',
wechatInfo:'',
personInfoId:'',
personInfo:'',
isMaster:false,
}
},
async mounted() {
window.addEventListener('message', (event) => {
if (event.data === 'dialogClosed') {
// console.log('Dialog 已关闭 // 执行关闭后的逻辑');
}
});
// console.log('isWebFunc()',this.isWebFunc())
const urlParams = new URLSearchParams(window.location.search);
this.id=this.$route.query.id || urlParams.get('id');
this.supplierId=this.$route.query.supplierId || urlParams.get('supplierId');
// this.supplierId=1128
console.log('1111',this.supplierId)
await this.getPersonList()
},
methods:{
blurHandle(e){
let val= e.target.value || ''
let flag=this.validatePhone(val)
// console.log('flag',flag)
if(!flag){
this.$toast('电话号码格式不正确')
}
},
validatePhone(val) {
console.log('val',val)
if(!val){
return true
}
const purePhone = String(val).trim()
const mobileReg = /^1[3-9]\d{9}$/ // 大陆手机号正则表达式
const hkMobileReg = /^[569]\d{3}[\s-]?\d{4}$/ // 香港手机号正则表达式,允许使用空格或 "-" 分隔
const macauMobileReg = /^6\d{3}[\s-]?\d{4}$/ // 澳门手机号正则表达式,允许使用空格或 "-" 分隔
const telReg = /^(0\d{2,3})([\s-])?\d{7,8}$/ // 大陆座机号正则表达式,允许区号和座机号用空格或 "-" 分开
const hkTelReg = /^\(?\d{2,4}\)?[\s-]?\d{4}[\s-]?\d{4}$/ // 香港座机号正则表达式,允许使用空格或 "-" 分隔
const macauTelReg = /^\(?\d{2,4}\)?[\s-]?\d{4}[\s-]?\d{4}$/ // 澳门座机号正则表达式,允许使用空格或 "-" 分隔
const phone400Reg = /^400[\s-]?\d{3}[\s-]?\d{4}$/ // 以 "400" 开头的号码正则表达式,允许使用空格或 "-" 分隔
// 情况112位且首位是0、第二位是1 → 去0后按大陆手机号校验
if (/^01[0-9]{10}$/.test(purePhone)) {
return true
}
// 匹配任意一种格式即为合法
if (mobileReg.test(purePhone) || hkMobileReg.test(purePhone) || macauMobileReg.test(purePhone) ||
telReg.test(purePhone) || hkTelReg.test(purePhone) || macauTelReg.test(purePhone) ||
phone400Reg.test(purePhone)) {
return true
}
// 其他情况 → 不合法
return false
},
async getPersonList(){
let result=await getConfirmStatus({supplierId:this.supplierId})
if(result.data?.wechatConfirmStatus==2){
this.type=3
}else if(result.data?.wechatConfirmStatus==3){
this.type=4
}else if(!result.data?.wechatConfirmStatus || result.data?.wechatConfirmStatus==1){
this.type=1
}
this.isMaster=result.data.isMaster
// this.type=2
let res=await getConfirmPerson({supplierId:this.supplierId})
if(res.data && res.data.length>0){
this.personList=res.data
}else{
this.personList=[]
}
},
async wechatConfirm(){//确认已添加微信按钮
Dialog.confirm({
message:'请确认相关人员是否已添加该二维码。',
confirmButtonText:'确认',
cancelButtonText:'取消',
confirmButtonColor:'#354E93',
}).then(async() => {
let res=await confirmAddWechat({supplierId:this.supplierId,supplierPersonInfoId:this.personInfoId})
console.log('res',this.personInfo,res.data?.name,this.personInfo.wechatName)
if((res.data?.name == this.personInfo.wechatName) || (!res.data && this.personInfo.wechatName)){
console.log('11111111')
this.$set(this.personList[this.reviseIndex],'isChange',false)
}else {
console.log('2222222')
this.$set(this.personList[this.reviseIndex],'isChange',true)
}
console.log('this.personList',this.personList)
let flagRevise=this.personList.some(item => 'isChange' in item && !item.isChange)
console.log('存在未修改',flagRevise)
if(res.data){
this.personList[this.reviseIndex].wechatId=res.data?.externalUserId
this.personList[this.reviseIndex].wechatName=res.data?.name
}
await this.cancelHandle()
}).catch(async () => {
await this.cancelHandle()
});
},
cancelHandle(){
this.dialogShow=false
this.wechatInfo=''
this.reviseIndex=-1
this.personInfoId=''
},
async wechatRevise(item,index){
console.log('item,index',item,index)
// console.log('item',item)
this.personInfoId=item.id
this.reviseIndex=index
this.personInfo=item
await this.getCode()
this.dialogShow=true
},
async getCode(){//获取二维码
let res = await getQrCode({supplierId:this.supplierId,supplierPersonInfoId:this.personInfoId})
// console.log('res--getCode',res)
this.wechatInfo=res.data || ''
},
async auditHandle(){//提交审批
let flag=this.personList.every(item => item.name && item.phone1 && item.wechatId && item.wechatName)
if(!flag){
this.$toast('必填项不可为空')
return
}
console.log('----',this.personList)
let flagRevise=this.personList.some(item => 'isChange' in item && !item.isChange)
console.log('存在未修改',flagRevise)
if(flagRevise){
this.$toast('您仍未修改微信号,请先修改再提交审批。')
return
}
let phone1Flag= this.personList.every(item => this.validatePhone(item.phone1))
let phone2Flag= this.personList.every(item => (item.phone2 && this.validatePhone(item.phone2) || !item.phone2))
console.log('phone1Flag',phone1Flag)
console.log('phone2Flag',phone2Flag)
if(!phone1Flag || !phone2Flag){
this.$toast('电话号码格式不正确')
return
}
await submitConfirm({supplierId:this.supplierId,infos:this.personList})
this.$toast('操作成功')
if(this.isWebFunc()){
setTimeout(()=>{
this.closeParentDialog()
},1500)
}else{
setTimeout(()=>{
this.goBack()
},1500)
}
},
async reviseHandle(){//修改
this.type=2
},
async confirmHandle(){//确认信息无误
let flag=this.personList.every(item => item.name && item.phone1 && item.wechatId && item.wechatName)
if(!flag){
this.$toast('必填项不可为空,请点击“立即修改”将信息补充完整')
return
}
Dialog.confirm({
message:'请务必仔细确认信息是否无误。',
confirmButtonText:'确认无误',
cancelButtonText:'返回',
confirmButtonColor:'#354E93',
}).then(async() => {
// console.log('确认无误')
await confirm({supplierId:this.supplierId})
this.$toast('操作成功')
if(this.isWebFunc()){
setTimeout(()=>{
this.closeParentDialog()
},1500)
}else{
setTimeout(()=>{
this.goBack()
},1500)
}
}).catch(() => {
});
},
}
}
</script>
<style lang="scss">
.customDialog {
.van-dialog__content{
text-align: center !important;
}
.van-dialog__header {
box-sizing: border-box;
padding: 12px;
}
}
</style>
<style scoped lang="scss">
@import "@/styles/common.scss";
@import '@/styles/mixin.scss';
.wrap {
@include wh(100%, 100%);
position: relative;
background-color: #F6F6F6;
}
.navBar{
margin-bottom: 46px;
}
.tipWrap{
width: 100%;
box-sizing: border-box;
padding: 8px 8px 8px 18px;
margin-bottom: 10px;
display: flex;
background-color: #FFF6F2;
img{
width: 14px;
height: 14px;
//vertical-align: middle;
margin-right: 5px;
margin-top: 2px;
}
span{
color: #FC3C06;
}
}
.yelBg{
background-color: #FFFFED ;
span{
color: #F36708;
}
}
.greBg{
background-color: #E8FFF3;
span{
color: #19AC43;
}
}
/*.headerWrap{
width: 100%;
box-sizing: border-box;
padding: 15px 16px;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
.back{
@include wh(15px,15px);
}
span{
font-weight: bold;
font-size: 16px;
color: #203152;
}
}*/
.loadingWrap{
width: 100%;
height: calc(100% - 90px);
text-align: center;
line-height: 200px;
}
.contentWrap{
//height: calc(100% - 160px);
//height: calc(100% - 90px);//没有按钮时
overflow-y: auto;
.itemWrap{
font-size: 14px;
width: 100%;
margin-bottom: 10px;
background-color: #FFFFFF;
box-sizing: border-box;
padding:10px 15px 10px 20px;
.line{
width: 100%;
text-align: center;
border-bottom: 2px solid;
opacity: 0.16;
margin-top: 10px;
border-image: linear-gradient(270deg, rgba(217, 217, 217, 0.6), rgba(178, 178, 178, 1), rgba(178, 178, 178, 1), rgba(217, 217, 217, 0.6)) 1 1;
}
.item{
//line-height: 36px;
display: flex;
align-items: center;
.left{
width: 66px;
}
.right{
flex: 1;
}
.wechatRight{
display: flex;
align-items: center;
justify-content: space-between;
.reviseBtn{
display: inline-block;
width: 60px;
text-align: center;
border-radius: 4px;
background-color: #354D93;
color: #FFFFFF;
box-sizing: border-box;
padding: 2px 0;
}
}
}
.opaCol{
color: #323643;
opacity: .65;
}
.star{
font-weight: bold;
font-size: 13px;
color: #FF0808;
}
}
}
.btnWrap{
width: 100%;
position: fixed;
bottom: 0;
left: 0;
box-sizing: border-box;
padding: 10px 19px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: #F6F6F6;
.common{
background: #354D93;
height: 48px;
line-height: 48px;
text-align: center;
border-radius: 5px;
font-weight: 500;
font-size: 14px;
color: #FFFFFF;
cursor: pointer;
}
.audit{
width: 100%;
}
.revise{
width: 30%;
background-color: #FFFFFF;
color: #354D93;
box-sizing: border-box;
border: 1px solid #354D93;
}
.confirm{
width: 67%;
}
}
</style>

View File

@@ -78,9 +78,11 @@ export default {
isLoading:false, isLoading:false,
showPoup:true,//进入弹框 showPoup:true,//进入弹框
isFinished:false, isFinished:false,
type: '',
} }
}, },
mounted() { mounted() {
this.type = this.$route.query?.type;
// this.onRefresh(); // this.onRefresh();
this.getList(); this.getList();
@@ -120,6 +122,7 @@ export default {
pageSize:this.pageSize, pageSize:this.pageSize,
docType:1, docType:1,
trainingType:4, trainingType:4,
type: this.type,
}) })
this.pageList=res.data?.list || []; this.pageList=res.data?.list || [];
if(res.data.assessState == 0){ if(res.data.assessState == 0){

View File

@@ -2,7 +2,7 @@
<div class="bottom_wrap"> <div class="bottom_wrap">
<div class="report_item" v-for="(item, index) in reportList" @click="goReportHandler(item)" :key="index"> <div class="report_item" v-for="(item, index) in reportList" @click="goReportHandler(item)" :key="index">
<img class="report_icon" :src="item?.iconUrl" alt=""> <img class="report_icon" :src="item?.iconUrl" alt="">
<div class="report_title">{{item.name}}</div> <!-- <div class="report_title">{{item.name}}</div>-->
</div> </div>
</div> </div>
</template> </template>
@@ -43,8 +43,8 @@ export default {
margin-top: 20px; margin-top: 20px;
text-align: center; text-align: center;
.report_icon { .report_icon {
width: 45px; width: 60px;
height: 45px; height: 60px;
} }
.report_title { .report_title {
color: rgba(53, 53, 53, 0.67); color: rgba(53, 53, 53, 0.67);

View File

@@ -0,0 +1,581 @@
<template>
<!-- <van-pull-refresh v-model="isLoading" class="custom-pull-refresh safe-pull-refresh" @refresh="onRefresh">-->
<div class="main_wrap">
<div class="top_bg" :class="{'dispatch' : type == 1 , 'driver' : type != 1}">
<!-- <div class="title">报备中心</div>-->
</div>
<div class="service_wrap">
<service-item :order-info="orderInfo" @refresh="onRefreshHandler"></service-item>
</div>
<div class="chat_list" ref="chatList" >
<!--ai对话框 s -->
<div v-for="(item, index) in recordList" :key="index">
<template v-if="item.messageType == 4">
<div class="top_tip_wrap">为了快速解决问题请选择下方咨询类型</div>
<div class="ai_chat" >
<div class="ai_left">
<img class="report_ai" src="@/assets/report/report_ai.png" alt="">
</div>
<div class="ai_right">
<div class="ai_title">{{ orderInfo?.driverName }}你好请选择报备内容</div>
<ul>
<li v-for="_item in item.content" :key="_item.id" @click="addReportHandler(_item)">{{_item.name}}</li>
</ul>
</div>
</div>
</template>
<template v-if="[2, 3].includes(Number(item.messageType))">
<!--ai对话框 e -->
<div class="tip_wrap">{{item.createTime}}</div>
<!--客服对话框 s -->
<div class="customer_item mb20">
<div class="customer_left">
<img class="profile_photo mr" src="@/assets/report/report_customer.png" alt="">
</div>
<div class="common_right customer_cls">
<div class="customer_status">{{item.reportConfigName}}</div>
<div class="response_con">{{item.remark}}</div>
</div>
</div>
</template>
<template v-if="item.messageType == 1">
<!--服务人员对话框 e -->
<div class="tip_wrap">{{item.createTime}}</div>
<!--服务人员对话框 s -->
<div class="server_item mb20">
<div class="common_right service_cls">
<div class="service_status">{{item.reportConfigName}}</div>
<div class="response_con">{{item.remark}}</div>
</div>
<div class="customer_left">
<img class="profile_photo ml" v-if="type == 1" src="@/assets/report/report_dispatch.png" alt="">
<img class="profile_photo ml" v-else src="@/assets/report/report_driver.png" alt="">
</div>
</div>
<!--服务人员对话框 e -->
</template>
</div>
</div>
<report-list-item :report-list.sync="reportList" @getReport="getReportHandler" />
<van-popup ref="addReportModal" v-model="addReportShow" :close-on-click-overlay="false" closeable duration="0" round position="bottom">
<div class="dialog_wrap">
<img class="add_report_bg" src="@/assets/report/add_report_bg.png" alt="">
<div class="report_content">
<template v-if="currentInfo.component == 'time'">
<!--预约时间报备 s -->
<div class="report_title">
<img class="dot" src="@/assets/report/add_report_dot.png" alt="">
<span>预约时间</span>
</div>
<div class="report_time_content" @click="showDatetime = true">
<div class="report_time_left">
<img class="add_report_time" src="@/assets/report/add_report_time.png" alt="">
<span>{{appointTime || '请选择时间'}}</span>
</div>
<img class="report_arrow" src="@/assets/report/add_report_arrow.png" alt="">
</div>
<!--预约时间报备 e -->
</template>
<template v-if="currentInfo.component == 'address'">
<!--修改地址报备 s -->
<div class="report_title">
<img class="dot" src="@/assets/report/add_report_dot.png" alt="">
<span>修改地址</span>
</div>
<div class="report_time_content" @click="goPage('addressMap')">
<div class="report_time_left">
<img class="add_report_time" src="@/assets/report/add_report_address.png" alt="">
<span>{{address || '请选择地址'}}</span>
</div>
<img class="report_arrow" src="@/assets/report/add_report_arrow.png" alt="">
</div>
<!--修改地址报备 e -->
</template>
<div class="report_title">
<img class="dot" src="@/assets/report/add_report_dot.png" alt="">
<span>补充报备内容</span>
</div>
<div class="report_common_content">
<textarea class="report_textarea" id="text-input" rows="4" placeholder="点击这里输入补充报备内容" v-model.trim="remark"></textarea>
<!-- <van-field-->
<!-- v-model="remark"-->
<!-- class="report_textarea"-->
<!-- placeholder="点击这里输入补充报备内容" />-->
</div>
</div>
<div class="report_btn" @click="saveHandler">
提交报备
</div>
</div>
</van-popup>
<van-popup v-model="showDatetime" round position="bottom">
<van-datetime-picker
class="dataTime"
v-if="showDatetime"
v-model="appointTime"
type="datetime"
:min-date="minDate"
:filter="filter"
@confirm="onConfirm"
@cancel="showDatetime = false"
/>
</van-popup>
</div>
<!-- </van-pull-refresh>-->
</template>
<script>
import { getReportListByOrder, reportHistory, newOrderReporting, getOrderInfo } from "@/api/report"
import { myMixins} from "@/utils/myMixins";
import {timeFormat} from "@/utils/common";
import reportListItem from '@/views/report/components/report-list-item'
import serviceItem from "@/views/report/components/service-item"
import {Dialog, Toast} from "vant";
export default {
name: "reportIndex",
components: { serviceItem, reportListItem },
mixins: [myMixins],
data() {
return {
addReportShow: false,
remark: '',
showDatetime: false,
appointTime: '',
minDate: new Date(),
address: '',
lat: '',
lng: '',
reportList: [],
recordList: [],
orderInfo: {},
type: '', // 1 调度 2 司机
currentInfo: '',
userOrderId: '',
userOrderCode: '',
driverId: '',
clickFlag: true,
isLoading: false,
}
},
async mounted() {
const urlParams = new URLSearchParams(window.location.search);
this.userOrderId = this.$route.query.userOrderId || urlParams.get('userOrderId');
this.userOrderCode = this.$route.query.userOrderCode || urlParams.get('userOrderCode');
this.type = this.$route.query.type || urlParams.get('type');
this.driverId = this.$route.query.driverId || urlParams.get('driverId');
await this.getReportList();
await this.getDetail();
await this.getRecordList();
await this.scrollToBottom();
},
activated() {
let addressSession = sessionStorage.getItem('reportAddress');
if(addressSession) {
let _obj = JSON.parse(addressSession)
this.address = _obj.startPoiAddress;
this.lat = _obj.startLat;
this.lng = _obj.startLng;
this.adCode = _obj.adCode;
}
},
methods: {
filter(type, options) {
if (type === 'minute') {
return options.filter((option) => option % 5 === 0);
}
return options;
},
onRefreshHandler() {
setTimeout(async () => {
try {
this.recordList = [];
await this.getReportList();
await this.getDetail();
await this.getRecordList();
await this.scrollToBottom();
} finally {
this.isLoading = false; // 结束加载状态
}
}, 100)
},
// 添加滚动方法
scrollToBottom() {
this.$nextTick(() => {
const container = this.$refs.chatList
container.scrollTop = container.scrollHeight
})
},
async getRecordList() {
let recordList = await reportHistory({
userOrderId: this.userOrderId,
userOrderCode: this.userOrderCode,
driverId: this.driverId,
source: Number(this.type),
})
this.recordList = recordList.data;
},
async saveHandler() {
if( this.clickFlag ) {
let data = {
source: Number(this.type),
reportContent: this.remark,
userOrderId: Number(this.userOrderId),
reportConfigId: this.currentInfo.id,
userOrderCode: this.userOrderCode,
driverId: this.driverId,
}
if(this.currentInfo.component == 'time') {
if( !this.appointTime ) {
Toast('预约时间不能为空')
return
}
if( new Date(this.appointTime).getTime() <= new Date().getTime() ) {
Toast('预约时间不能小于当前时间')
return
}
data.time = this.appointTime
}
if(this.currentInfo.component == 'address') {
if( !this.address ) {
Toast('地址不能为空')
return
}
data.address = this.address
data.lat = this.lat;
data.lng = this.lng;
}
if( !this.remark ) {
Toast('备注内容不能为空')
return
}
this.clickFlag = false;
try {
await newOrderReporting(data)
Dialog.alert({
title: '提示',
message: "报备添加成功"
}).then(async () => {
await this.getRecordList()
this.addReportShow = false
this.scrollToBottom();
this.initDialogData();
this.clickFlag = true
});
} finally {
this.clickFlag = true
}
}
},
initDialogData() {
this.appointTime = '';
this.address = '';
this.lat = '';
this.lng = '';
this.remark = '';
},
addReportHandler(data) { // 点击添加报备弹框
console.log('currentInfocurrentInfo', data)
this.currentInfo = data;
this.remark = '';
this.addReportShow = true
},
getReportHandler(data) { // 点击获取当前报备信息
console.log('dadadada', data.child)
this.recordList.push({
messageType: 4,
content: data.child
})
this.scrollToBottom();
if( data.child?.length == 1 ) {
this.addReportHandler(data.child[0])
}
},
async getDetail(){ // 订单详情
if(this.userOrderId) {
let result = await getOrderInfo({
userOrderId: this.userOrderId,
userOrderCode: this.userOrderCode
})
this.orderInfo = result.data
} else {
this.orderInfo = {}
}
},
async getReportList() { // 报备大类
let res = await getReportListByOrder({
orderId: this.userOrderId
});
this.reportList = res.data
},
onConfirm(data) {
this.appointTime = timeFormat(new Date(data))
this.showDatetime = false;
}
}
}
</script>
<style lang="scss">
.custom-pull-refresh {
height: 100% !important;
}
</style>
<style lang="scss" scoped>
#app {
background: #F9FCFF !important;
height: 100%;
}
.main_wrap {
width: 100%;
height: 100%;
background: #F9FCFF !important;
display: flex;
flex-direction: column;
// 添加以下样式确保正确的高度计算
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.top_bg {
width: 100%;
height: 87px;
/*.title {
color: #fff;
text-align: center;
padding-top: 52px;
font-size: 17px;
line-height: 24px;
}*/
}
.dispatch { // 调度app头部背景色
background: #354683;
}
.driver { // 司机app头部背景色
background: #334885;
}
.service_wrap {
margin-top: -75px;
/*margin-bottom: 20px;*/
}
.chat_list {
flex: 1;
/*overflow: auto;*/
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch; // 为了iOS平滑滚动
padding-top: 10px;
/* 修复 iOS 滚动问题 */
transform: translateZ(0);
.top_tip_wrap {
color: #7C8698;
text-align: center;
font-size: 13px;
}
.tip_wrap {
color: #7C8698;
text-align: center;
font-size: 13px;
margin-bottom: 10px;
}
.ai_chat {
padding: 25px 10px 20px;
display: flex;
.ai_left {
.report_ai {
width: 44px;
height: 44px;
margin-right: 12px;
}
}
.ai_right {
.ai_title {
color: #203152;
font-size: 15px;
font-weight: 600;
margin-bottom: 15px;
}
li {
font-size: 13px;
color: #267EF0;
line-height: 18px;
margin-bottom: 15px;
font-weight: bold;
}
li::before {
content: "";
display: inline-block;
width: 8px;
height: 8px;
background-color: #5680FA;
border-radius: 50%; /* 圆形 */
margin-right: 10px;
}
}
}
}
/*客服人员,服务人员对话弹框样式 s*/
.profile_photo {
width: 44px;
height: 44px;
}
.mr {
margin-right: 10px;
}
.ml {
margin-left: 10px;
}
.mb20 {
margin-bottom: 20px;
}
.customer_item {
display: flex;
padding-left: 10px;
padding-right: 64px;
.customer_left {
}
}
.common_right {
padding: 11px 13px;
flex: 1;
.customer_status::before {
content: "";
display: inline-block;
width: 8px;
height: 8px;
background-color: #5680FA;
border-radius: 50%; /* 圆形 */
margin-right: 10px;
}
.customer_status {
font-size: 14px;
color: #267EF0;
line-height: 20px;
font-weight: bold;
}
.service_status {
font-size: 14px;
color: #F07926;
line-height: 20px;
font-weight: bold;
}
.service_status::before {
content: "";
display: inline-block;
width: 8px;
height: 8px;
background-color: #F07926;
border-radius: 50%; /* 圆形 */
margin-right: 10px;
}
}
.customer_cls {
border-radius: 0px 6px 6px 6px;
background: #E3F0FF;
}
.service_cls {
background: #FAEBD8;
border-radius: 0px 6px 6px 6px;
}
.server_item {
display: flex;
padding-right: 10px;
padding-left: 64px;
}
.response_con {
font-size: 13px;
color: #242A37;
line-height: 18px;
font-weight: bold;
margin-top: 5px;
}
/*客服人员,服务人员对话弹框样式 e*/
.dialog_wrap {
.add_report_bg {
width: 100%;
height: 76px;
}
.report_content {
width: calc(100% - 12px);
margin: -30px auto 0;
padding-right: 14px;
padding-left: 20px;
box-sizing: border-box;
background: #fff;
position: relative;
padding-top: 25px;
border-radius: 10px;
.report_title {
font-size: 16px;
font-weight: 600;
color: #267EF0;
line-height: 22px;
margin-bottom: 10px;
.dot {
width: 7px;
height: 6px;
margin-right: 12px;
}
}
.report_time_content {
padding: 13px;
background: #F2F7FF;
border-radius: 6px;
border: 1px solid #E2EAF6;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
.report_time_left {
font-size: 14px;
font-weight: bold;
color: rgba(0, 0, 0, 0.9);
display: flex;
align-items: flex-start;
}
.add_report_time {
width: 18px;
height: 18px;
margin-right: 8px;
}
.report_arrow {
width: 8px;
height: 12px;
margin-left: 5px;
}
}
.report_common_content {
margin-bottom: 27px;
.report_textarea {
width: 100%;
box-sizing: border-box;
background: #F8FAFC;
border-radius: 6px;
min-height: 95px;
border: 1px solid #E2EAF6;
padding: 10px;
font-size: 13px;
}
}
}
.report_btn {
width: calc(100% - 80px);
height: 46px;
line-height: 46px;
background: #005DD5;
border-radius: 23px;
color: #FFFFFF;
font-size: 15px;
font-weight: bold;
text-align: center;
margin: 0 auto 40px;
}
}
::v-deep .van-popup__close-icon {
color: #0F458E;
}
</style>

View File

@@ -57,16 +57,30 @@
</div> </div>
</div> </div>
<report-list-item :report-list.sync="reportList" @getReport="getReportHandler" /> <report-list-item :report-list.sync="reportList" @getReport="getReportHandler" />
<van-popup ref="addReportModal" v-model="addReportShow" :close-on-click-overlay="false" closeable duration="0" round position="bottom"> <van-popup ref="addReportModal" v-model="addReportShow" :close-on-click-overlay="false" z-index="500" closeable duration="0" round position="bottom">
<div class="dialog_wrap"> <div class="dialog_wrap">
<img class="add_report_bg" src="@/assets/report/add_report_bg.png" alt=""> <img class="add_report_bg" src="@/assets/report/add_report_bg.png" alt="">
<div class="report_content"> <div class="report_content">
<div class="report_title" style="margin-bottom: 10px;"><span>{{currentInfo.name}}</span></div>
<template v-if="currentInfo.component == 'time'"> <template v-if="currentInfo.component == 'time'">
<!--预约时间报备 s --> <!--预约时间报备 s -->
<div class="report_title"> <div class="report_title">
<img class="dot" src="@/assets/report/add_report_dot.png" alt=""> <img class="dot" src="@/assets/report/add_report_dot.png" alt="">
<span>预约时间</span> <span>预约时间</span>
</div> </div>
<!--<el-date-picker class="report_time_content owner_time high-zindex-picker"
v-model="appointTime"
type="datetime"
:picker-options="pickerOptions"
:minutes-step="5"
format="yyyy-MM-dd HH:mm:00"
placeholder="选择日期时间">
</el-date-picker>-->
<!--<el-date-picker
v-model="appointTime"
type="datetime"
placeholder="选择日期时间">
</el-date-picker>-->
<div class="report_time_content" @click="showDatetime = true"> <div class="report_time_content" @click="showDatetime = true">
<div class="report_time_left"> <div class="report_time_left">
<img class="add_report_time" src="@/assets/report/add_report_time.png" alt=""> <img class="add_report_time" src="@/assets/report/add_report_time.png" alt="">
@@ -91,17 +105,15 @@
</div> </div>
<!--修改地址报备 e --> <!--修改地址报备 e -->
</template> </template>
<template v-if="currentInfo.component != 'time'">
<div class="report_title"> <div class="report_title">
<img class="dot" src="@/assets/report/add_report_dot.png" alt=""> <img class="dot" src="@/assets/report/add_report_dot.png" alt="">
<span>补充报备内容</span> <span>补充反馈内容</span>
</div> </div>
<div class="report_common_content"> <div class="report_common_content">
<textarea class="report_textarea" id="text-input" rows="4" placeholder="点击这里输入补充报备内容" v-model.trim="remark"></textarea> <textarea class="report_textarea" id="text-input" rows="4" placeholder="点击这里输入补充反馈内容" v-model.trim="remark"></textarea>
<!-- <van-field-->
<!-- v-model="remark"-->
<!-- class="report_textarea"-->
<!-- placeholder="点击这里输入补充报备内容" />-->
</div> </div>
</template>
</div> </div>
<div class="report_btn" @click="saveHandler"> <div class="report_btn" @click="saveHandler">
提交报备 提交报备
@@ -109,15 +121,16 @@
</div> </div>
</van-popup> </van-popup>
<van-popup v-model="showDatetime" round position="bottom"> <van-popup v-model="showDatetime" round position="bottom" :close-on-click-overlay="false">
<van-datetime-picker <van-datetime-picker
class="dataTime" class="dataTime"
v-if="showDatetime" v-if="showDatetime"
v-model="appointTime" v-model="appointTime"
type="datetime" type="datetime"
:min-date="minDate" :min-date="minDate"
:filter="filter"
@confirm="onConfirm" @confirm="onConfirm"
@cancel="showDatetime = false" @cancel="cancelHandler"
/> />
</van-popup> </van-popup>
</div> </div>
@@ -155,6 +168,12 @@
driverId: '', driverId: '',
clickFlag: true, clickFlag: true,
isLoading: false, isLoading: false,
pickerOptions: {
// 可选:限制预约时间不能小于当前时间(复用你原有逻辑)
disabledDate: (time) => {
return time.getTime() <= new Date().getTime();
}
}
} }
}, },
async mounted() { async mounted() {
@@ -179,6 +198,12 @@
} }
}, },
methods: { methods: {
filter(type, options) {
if (type === 'minute') {
return options.filter((option) => option % 5 === 0);
}
return options;
},
onRefreshHandler() { onRefreshHandler() {
setTimeout(async () => { setTimeout(async () => {
try { try {
@@ -238,10 +263,10 @@
data.lat = this.lat; data.lat = this.lat;
data.lng = this.lng; data.lng = this.lng;
} }
if( !this.remark ) { /*if( !this.remark ) {
Toast('备注内容不能为空') Toast('备注内容不能为空')
return return
} }*/
this.clickFlag = false; this.clickFlag = false;
try { try {
await newOrderReporting(data) await newOrderReporting(data)
@@ -268,15 +293,21 @@
this.remark = ''; this.remark = '';
}, },
addReportHandler(data) { // 点击添加报备弹框 addReportHandler(data) { // 点击添加报备弹框
console.log('currentInfocurrentInfo', data)
this.currentInfo = data; this.currentInfo = data;
this.remark = '';
this.addReportShow = true this.addReportShow = true
}, },
getReportHandler(data) { // 点击获取当前报备信息 getReportHandler(data) { // 点击获取当前报备信息
console.log('dadadada', data.child)
this.recordList.push({ this.recordList.push({
messageType: 4, messageType: 4,
content: data.child content: data.child
}) })
this.scrollToBottom(); this.scrollToBottom();
if( data.child?.length == 1 ) {
this.addReportHandler(data.child[0])
}
}, },
async getDetail(){ // 订单详情 async getDetail(){ // 订单详情
if(this.userOrderId) { if(this.userOrderId) {
@@ -299,6 +330,10 @@
onConfirm(data) { onConfirm(data) {
this.appointTime = timeFormat(new Date(data)) this.appointTime = timeFormat(new Date(data))
this.showDatetime = false; this.showDatetime = false;
},
cancelHandler() {
this.appointTime = ''
this.showDatetime = false
} }
} }
} }
@@ -535,6 +570,9 @@
margin-left: 5px; margin-left: 5px;
} }
} }
.owner_time {
padding: 0 !important;
}
.report_common_content { .report_common_content {
margin-bottom: 27px; margin-bottom: 27px;
.report_textarea { .report_textarea {
@@ -565,4 +603,22 @@
::v-deep .van-popup__close-icon { ::v-deep .van-popup__close-icon {
color: #0F458E; color: #0F458E;
} }
::v-deep .el-date-editor.el-input,::v-deep .el-date-editor.el-input__inner {
width: 100%;
}
::v-deep .el-input__inner {
background: none !important;
}
::v-deep .el-picker-panel {
z-index: 100000000 !important;
}
.el-picker-panel{
z-index: 100000000 !important;
}
::v-deep .high-zindex-picker {
z-index: 9999 !important; // 高于 van-popup 默认层级(通常 1000-2000
}
::v-deep .el-date-editor {
overflow: visible !important;
}
</style> </style>

View File

@@ -0,0 +1,164 @@
<template>
<div class="content">
<div class="navBar">
<van-nav-bar
title="小板运输司机认证"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="h5GoBack"
/>
</div>
<img class="icon_register" mode="widthFix" src="@/assets/authentication/icon_register.png" />
<tip-bar :title="'应国家政策要求:从事货运行业的司机用户,身份证照片、驾驶证信息、行驶证信息、人车合影及承运资质信息必须进行实名认证。'"></tip-bar>
<div class="audit_list">
<audit-item title="个人信息" tip="上传本人头像和身份证"
:url="currentFlag(1) ? personActiveUrl : personUrl"
:pass="currentFlag(1)" :current-class="currentStep == 1"
@detail="showDetail('personAudit')" @upload="showDetail('personAudit')"></audit-item>
<audit-item title="驾照信息" tip="上传驾驶证" :url="currentFlag(2) ? driverActiveUrl : driverUrl" v-if="type != 'simple'" :pass="currentFlag(2)" :current-class="currentStep == 2"
@detail="showDetail('carAudit')" @upload="showDetail('carAudit')"></audit-item>
<audit-item title="车辆信息" tip="上传行驶证与车辆照片" :url="currentFlag(3) ? carActiveUrl : carUrl" :pass="currentFlag(3)" :current-class="currentStep == 3"
@detail="showDetail('carInfoAudit')" @upload="showDetail('carInfoAudit')"></audit-item>
<audit-item title="银行卡信息" tip="上传本人银行卡信息" :url="currentFlag(4) ? bankActiveUrl :bankUrl" :pass="currentFlag(4)" :current-class="currentStep == 4"
@detail="showDetail('bankInfo')" @upload="showDetail('bankInfo')"></audit-item>
<audit-item title="审核信息" :tip="auditTip" :status="statusStr" :url="currentFlag(5) ? bankActiveUrl :bankUrl" :pass="currentFlag(5)" :current-class="currentStep == 5" :button-hide="false"
></audit-item>
</div>
<fixed-button v-if="verifyStatus == 11" @myClick="showDetail('personAudit')" title="重新认证"></fixed-button>
<success-dialog ref="successDialog"></success-dialog>s
</div>
</template>
<script>
import successDialog from "./component/successDialog.vue";
import auditItem from "./component/auditItem";
import tipBar from "./component/tipBar";
import { verifyStatus, verifyStatusSimple ,tipString} from '@/utils/common';
import { myMixins } from '@/utils/myMixins.js';
import fixedButton from "./component/fixedButton";
import {infoVerifyProgress} from "@/api/authentication"
export default {
name:"auditList",
data() {
return {
personUrl: require('@/assets/authentication/audit_icon4_gray.png'),
personActiveUrl: require('@/assets/authentication/audit_icon4.png'),
driverUrl: require('@/assets/authentication/audit_icon1_gray.png'),
driverActiveUrl: require('@/assets/authentication/aduit_icon1.png'),
carUrl: require('@/assets/authentication/audit_icon2_gray.png'),
carActiveUrl: require('@/assets/authentication/audit_icon2.png'),
bankUrl: require('@/assets/authentication/audit_icon3_gray.png'),
bankActiveUrl: require('@/assets/authentication/audit_icon3.png'),
currentStep: undefined,
auditTip: '',
statusStr: '',
verifyStatus: '',
type: 'full',
}
},
mixins: [ myMixins ],
components: {
tipBar,
auditItem,
fixedButton,
successDialog
},
// onLoad() {
// },
// async onPullDownRefresh() {
// await this.refresh()
// uni.stopPullDownRefresh()
// },
async mounted() {
// await this.$onLaunched;
// 禁止双击放大
let lastTouchEnd = 0;
document.addEventListener('touchend', (event) => {
const now = Date.now();
if (now - lastTouchEnd <= 300) {
event.preventDefault(); // 阻止双击放大
}
lastTouchEnd = now;
}, { passive: false });
await this.refresh()
},
methods: {
async getRegisterInfo(data) {
let res = await infoVerifyProgress( data)
// console.log("res",res)
localStorage.setItem('infoVerify', res?.data?.infoVerify?.code)
localStorage.setItem('failReason', res?.data?.verifyRemark)
localStorage.setItem('authIsSuccess', res?.data?.authIsSuccess)
localStorage.setItem('name', res?.data?.name)
},
async refresh() {
await this.getRegisterInfo()
await this.getVerifyStatus()
let obj = await tipString(localStorage.getItem('infoVerify'))
this.verifyStatus = localStorage.getItem('infoVerify')
if( this.verifyStatus == 11 ) {
this.auditTip = localStorage.getItem('failReason')
localStorage.setItem('authIsSuccess', 0)
} else {
this.auditTip = obj.tip
}
if( this.verifyStatus == 12 && parseInt(localStorage.getItem('authIsSuccess')) != 1) { // 审核通过
this.$refs.successDialog.openHandler()
}
this.statusStr = obj.button
},
currentFlag(status) {
return this.currentStep > status
},
showDetail(path) {
this.goPage(path,{
token:localStorage.getItem('token')
})
},
getVerifyStatus() {
if( this.type == 'simple' ) {
this.currentStep = verifyStatusSimple(localStorage.getItem('infoVerify'))
} else {
this.currentStep = verifyStatus(localStorage.getItem('infoVerify'))
}
},
}
}
</script>
<style lang="scss">
@import "@/styles/common.scss";
.navBar{
margin-bottom: 46px;
}
.content {
font-size: 0;
padding-bottom: 80px;
height: 100%;
overflow-y: auto;
-webkit-overflow-scrolling: touch; /* 启用iOS惯性滚动 */
scroll-behavior: smooth; /* 平滑滚动(部分浏览器支持) */
}
.audit_list {
padding: 20px 30px;
.audit_item:after{
left: 18px;
position: absolute;
content: '';
display: block;
width: 2px;
top: 56px;
height: 48px;
background: rgba($color: #B2C2E4, $alpha: 0.59);
}
.audit_item:last-child {
&::after{
display: none !important;
}
}
}
</style>

View File

@@ -0,0 +1,164 @@
<template>
<div class="content">
<div class="navBar">
<van-nav-bar
title="银行卡信息认证"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="goListPage"
/>
</div>
<tip-bar :title="'温馨提示:服务完成后,平台代收的运费需要提现到您的银行卡账户中,请确保您上传的银行卡信息真实可用。'"></tip-bar>
<photo-item title="银行卡正面照片" :left-url="form.bankCardFront || bank" :show="show" @leftImg="bankHandler"></photo-item>
<div class="carInfo">
<div class="left_wrap title">
<span class="mar_left">姓名</span>
<div>
<span class="star">*</span>
<span>账户号</span>
</div>
<div>
<span class="star">*</span>
<span>开户行</span>
</div>
</div>
<div class="right_wrap">
<input type="text" disabled placeholder="请输入持卡人姓名" v-model="form.name">
<input type="text" placeholder="请输入银行卡号" v-model="form.cardNumber">
<input type="text" placeholder="请输入开户行" v-model="form.bankName">
</div>
</div>
<fixed-button @myClick="clickHandler" v-if="showFun()"></fixed-button>
<!-- <protocol-dialog></protocol-dialog>-->
</div>
</template>
<script>
// import protocolDialog from "./component/protocolDialog";
import fixedButton from "./component/fixedButton";
import photoItem from "./component/photoItem";
import tipBar from "./component/tipBar";
import {ocrRecognize, driverInfoVerify, driverInfoVerifyDetail, infoVerifyProgress} from '@/api/authentication.js'
import { leftCopy } from '@/utils/common.js'
import { myMixins } from '@/utils/myMixins.js'
export default {
name: "bankInfo",
components: {
tipBar,
photoItem,
fixedButton,
// protocolDialog
},
mixins: [myMixins],
data() {
return {
bank: require('@/assets/authentication/bank_icon1.png'),
show: undefined,
form: {
bankCardFront: '',
bankName: '',
cardNumber: '',
name: '',
},
type:localStorage.getItem('type')
}
},
async mounted() {
// 禁止双击放大
let lastTouchEnd = 0;
document.addEventListener('touchend', (event) => {
const now = Date.now();
if (now - lastTouchEnd <= 300) {
event.preventDefault(); // 阻止双击放大
}
lastTouchEnd = now;
}, { passive: false });
// if(options?.show) {
this.show = true
// }
if( this.show ) {
await this.getDetail()
}
},
methods: {
async clickHandler() {
if(!this.form.bankCardFront) {
this.$toast('银行卡照片未上传');
return
}
if( this.form.name && this.form.cardNumber && this.form.bankName ) {
let res = await driverInfoVerify( {
verifyType: 4,
...this.form,
type: this.type || 'full',
})
this.$toast('操作成功')
await this.getRegisterInfo({
verifyType: 4
})
setTimeout(() => {
this.goListPage()
}, 100)
console.log('注册', res)
} else {
this.$toast('银行卡信息识别错误')
}
},
async getRegisterInfo(data) {
let res = await infoVerifyProgress( data)
localStorage.setItem('infoVerify', res?.data?.infoVerify?.code)
localStorage.setItem('failReason', res?.data?.verifyRemark)
localStorage.setItem('authIsSuccess', res?.data?.authIsSuccess)
localStorage.setItem('name', res?.data?.name)
},
goListPage(){
this.goPage('auditList',{
token:localStorage.getItem('token')
})
},
async bankHandler(data) {
this.form.bankName = ''
this.form.cardNumber = ''
this.form.name = ''
this.form.bankCardFront = data
let res = await this.orcHandler(this.form.bankCardFront, 5)
leftCopy(this.form, {...res?.data?.data})
},
async getDetail() { // 认证详情
let res = await driverInfoVerifyDetail( {
verifyType: 4
})
leftCopy(this.form, {...res?.data?.bankCardInfoData})
console.log('bank', res)
},
async orcHandler(url, type) { // ocr 识别
let res = await ocrRecognize( {
ocrType: type,
imageUrl: url
});
return res;
},
}
}
</script>
<style lang="scss">
@import "@/styles/common.scss";
@import "@/styles/infoShow.scss";
page {
background: #F4F5F7;
}
.content{
height: 100%;
overflow-y: auto;
-webkit-overflow-scrolling: touch; /* 启用iOS惯性滚动 */
scroll-behavior: smooth; /* 平滑滚动(部分浏览器支持) */
}
.navBar{
margin-bottom: 46px;
}
</style>

View File

@@ -0,0 +1,237 @@
<template>
<div class="content">
<div class="navBar">
<van-nav-bar
title="驾驶证认证"
left-arrow
left-arrow-color="#FFFFFF"
:border="false"
:fixed="true"
:safe-area-inset-top="true"
@click-left="goListPage"
/>
</div>
<tip-bar :title="'应国家政策要求:从事货运行业的司机用户,身份证照片、驾驶证信息、行驶证信息、人车合影及承运资质信息必须进行实名认证。'"></tip-bar>
<photo-item title="上传驾驶证" :left-url="form.drivingLicenceFront || carFront" :right-url="form.drivingLicenceContrary || carBack"
:show="show" @leftImg="carFrontHandler" @rightImg="carBackHandler"></photo-item>
<div class="carInfo">
<div class="left_wrap title">
<div class="form_item">
<div>
<span class="star">*</span>
<span>姓名</span>
</div>
<span class="phone">{{form.name}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>身份证号</span>
</div>
<input class="phone" type="text" placeholder="请输入持卡人身份证号" v-model="form.licenseNumber">
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>准驾类型</span>
</div>
<span class="phone">{{form.approvedType}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>初次领证日期</span>
</div>
<span class="phone">{{form.initialIssueDate}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>有效期限</span>
</div>
<span class="phone">{{form.validPeriod}}</span>
</div>
<div class="form_item">
<div>
<span class="star">*</span>
<span>档案编号</span>
</div>
<span class="phone">{{form.recordNumber}}</span>
</div>
</div>
</div>
<fixed-button @myClick="clickHandler" v-if="showFun()"></fixed-button>
<!-- <protocol-dialog></protocol-dialog>-->
</div>
</template>
<script>
// import protocolDialog from "./component/protocolDialog";
import fixedButton from "./component/fixedButton";
import photoItem from "./component/photoItem";
import tipBar from "./component/tipBar";
import {ocrRecognize, driverInfoVerify, driverInfoVerifyDetail, infoVerifyProgress} from '@/api/authentication.js'
import { leftCopy } from '@/utils/common.js'
import { myMixins } from '@/utils/myMixins.js'
export default {
name: "carAudit",
components: {
tipBar,
photoItem,
fixedButton,
// protocolDialog
},
mixins: [ myMixins ],
data() {
return {
carFront: require('@/assets/authentication/car_icon1.png'),
carBack: require('@/assets/authentication/car_icon2.png'),
form: {
name: '',
drivingLicenceFront: '',
drivingLicenceContrary: '',
licenseNumber: '',
approvedType: '', // 准驾车型
initialIssueDate: '', // 初次领证日期
validPeriod: '', // 有效期
recordNumber: '', // 档案编号
},
show: undefined,
type: 'full',
}
},
async mounted() {
// 禁止双击放大
let lastTouchEnd = 0;
document.addEventListener('touchend', (event) => {
const now = Date.now();
if (now - lastTouchEnd <= 300) {
event.preventDefault(); // 阻止双击放大
}
lastTouchEnd = now;
}, { passive: false });
// if(options?.show) {
this.show = true
// }
if( this.show ) {
await this.getDetail()
}
},
methods: {
backInit() {
this.form.recordNumber = ''
},
frontInit() {
this.form.licenseNumber = ''
this.form.approvedType = ''
this.form.initialIssueDate = ''
this.form.validPeriod = ''
},
async carFrontHandler(data) {
await this.frontInit();
this.form.drivingLicenceFront = data
await this.idOrcHandler(this.form.drivingLicenceFront)
},
async carBackHandler(data) {
await this.backInit();
this.form.drivingLicenceContrary = data
await this.idOrcHandler(this.form.drivingLicenceContrary, 'back')
},
async idOrcHandler(url, type = 'front') { // ocr 识别
let res = await ocrRecognize({
ocrType: 2,
imageUrl: url
});
let carInfo
if(type == 'back') {
carInfo = res?.data?.data?.back?.data
this.form.recordNumber = carInfo?.recordNumber || ''
} else {
carInfo = res?.data?.data?.face?.data
leftCopy(this.form, {...carInfo})
}
},
async getDetail() { // 认证详情
let res = await driverInfoVerifyDetail( {
verifyType: 2
})
leftCopy(this.form, {...res?.data?.drivingLicenseInfoData})
console.log('carAudit', res)
},
async clickHandler() { // 点击去认证
if( !this.form.drivingLicenceFront ) {
this.$toast('驾驶证正面照片未上传')
return
}
if( !this.form.drivingLicenceContrary ) {
this.$toast('驾驶证反面照片未上传')
return
}
if(!this.form.licenseNumber || !this.form.initialIssueDate || !this.form.validPeriod) {
this.$toast('驾驶证正面识别错误,请重新上传')
return
}
if(!this.form.recordNumber) {
this.$toast('驾驶证反面识别错误,请重新上传')
return
}
await driverInfoVerify({
verifyType: 2,
type: this.type || 'full',
...this.form,
})
this.$toast('操作成功')
await this.getRegisterInfo({
verifyType: 2
})
setTimeout(() => {
this.goListPage()
}, 100)
}, async getRegisterInfo(data) {
let res = await infoVerifyProgress( data)
localStorage.setItem('infoVerify', res?.data?.infoVerify?.code)
localStorage.setItem('failReason', res?.data?.verifyRemark)
localStorage.setItem('authIsSuccess', res?.data?.authIsSuccess)
localStorage.setItem('name', res?.data?.name)
},
goListPage(){
this.goPage('auditList',{
token:localStorage.getItem('token')
})
},
}
}
</script>
<style lang="scss">
@import "@/styles/common.scss";
@import "@/styles/infoShow.scss";
page {
background: #F4F5F7;
}
.content{
height: 100%;
overflow-y: auto;
-webkit-overflow-scrolling: touch; /* 启用iOS惯性滚动 */
scroll-behavior: smooth; /* 平滑滚动(部分浏览器支持) */
}
.navBar{
margin-bottom: 46px;
}
.carInfo .title {
width: 100% !important;
}
.form_item {
line-height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
}
.phone {
flex: 1;
text-align: right;
}
</style>

Some files were not shown because too many files have changed in this diff Show More