Compare commits

...

574 Commits

Author SHA1 Message Date
cb d957a0c2a3 no message 2025-12-22 18:05:22 +08:00
cb dd51d48a45 no message 2025-12-22 17:42:16 +08:00
cb 5a172360bc no message 2025-12-04 17:15:28 +08:00
cb 28c5d34acf no message 2025-12-04 14:46:35 +08:00
cb e66d6b56e9 no message 2025-12-03 17:21:39 +08:00
cb 232509dc14 no message 2025-12-02 16:52:34 +08:00
cb 477f252fd1 no message 2025-11-26 08:58:22 +08:00
cb 4c801f007a no message 2025-11-24 17:13:17 +08:00
cb 5d5f67ef07 no message 2025-11-21 17:41:04 +08:00
cb 027e23e538 no message 2025-11-14 16:34:00 +08:00
cb f88d3a1673 no message 2025-11-13 10:46:50 +08:00
cb 5c17e811a9 处理分页问题 以及完单报错问题处理 2025-11-11 15:22:01 +08:00
cb ae843ab767 取消分页限制以及修改24小时定时后期处理 2025-11-10 15:33:50 +08:00
cb d2db2a5547 删除售后单增加对纠纷单的处理,增加通知设置 2025-11-08 16:47:47 +08:00
cb f1df93ec25 no message 2025-11-07 09:28:08 +08:00
cb 34d71c1fd0 增加新字段代表退款时的支付状态 2025-11-06 12:15:56 +08:00
cb bc9d50bf0c no message 2025-11-06 11:01:46 +08:00
cb e1e41d98bc no message 2025-11-04 08:57:27 +08:00
cb a36d9374dd no message 2025-11-01 11:15:02 +08:00
cb 174f6b4a82 增加商品售后的不同显示 以及后台重复处理的超时设置 2025-10-30 11:35:05 +08:00
cb aa7b8c7a5d no message 2025-10-30 09:35:05 +08:00
cb 77008d11da no message 2025-10-29 11:17:34 +08:00
cb f66ee72314 no message 2025-10-28 15:03:59 +08:00
cb 40ba4652be 修改售后类型,以及平台操作类型,平台退款金额处理 2025-10-25 16:35:48 +08:00
cb 1485037c82 no message 2025-10-24 17:49:51 +08:00
cb cb78526d0e 完善后台售后纠纷处理吗,完善数量以及数据获取, 2025-10-24 15:15:32 +08:00
cb bc96277f86 修改售后处理 以及主单售后纠纷查询 2025-10-23 17:33:12 +08:00
cb c733349a9e 售后超时,恢复财务金额 2025-10-23 10:38:59 +08:00
cb e7bb47f023 no message 2025-10-21 18:07:34 +08:00
cb a805c562c9 no message 2025-10-17 16:53:54 +08:00
cb 8bbacc653f 增加售后记录是否显示, 2025-10-17 14:54:02 +08:00
cb e0060c0432 超市排序处理,售后更新处理,售后记录显示 2025-10-17 11:49:29 +08:00
cb 72748b7113 no message 2025-10-17 08:52:16 +08:00
cb fe13c91ab2 no message 2025-10-16 14:28:11 +08:00
cb 16891e331d no message 2025-10-16 08:42:48 +08:00
cb 9ebbc056f3 no message 2025-10-14 16:43:01 +08:00
cb 43e51e7557 no message 2025-10-14 14:50:09 +08:00
cb 642038eef5 no message 2025-10-11 16:18:34 +08:00
cb 5489aaa620 no message 2025-10-11 10:12:59 +08:00
cb 9bb52b5ffb no message 2025-10-10 16:42:53 +08:00
cb bba67251af 支付后更新生成服务主单财务状态,修改监控单的查询条件,增加商品主单 全单退款 2025-10-10 16:13:24 +08:00
cb 4388cbb3f6 no message 2025-10-10 09:58:55 +08:00
cb e0226437ad no message 2025-09-30 17:52:47 +08:00
cb c57c585b37 no message 2025-09-29 15:35:25 +08:00
cb eced56a427 no message 2025-09-26 18:06:05 +08:00
cb 8148a59e83 no message 2025-09-26 11:02:57 +08:00
cb c84c39a28f 增加售后倒计时 以及 师傅状态查询 2025-09-25 15:53:14 +08:00
cb 47f717fcb2 no message 2025-09-25 11:38:11 +08:00
cb 5c2049c3ea no message 2025-09-15 18:08:27 +08:00
cb 82ecd1a144 no message 2025-09-15 16:51:52 +08:00
cb 9acd98d9b5 no message 2025-09-15 15:43:51 +08:00
cb 9db20efd88 no message 2025-09-13 17:30:50 +08:00
cb 61dcb7b25c no message 2025-09-12 17:14:20 +08:00
cb c8825f1c16 增加子单立即发货 2025-09-12 11:30:28 +08:00
cb c3f89a3a4f 修改距离计算 2025-09-12 10:18:55 +08:00
cb e9771921db 增加交货图片备注以及店铺和店铺距离 2025-09-11 17:57:16 +08:00
cb 9ebbcfacf7 修改不同的 类型调入大厅时间 增加详情返回对应的店铺信息 快递信息 2025-09-11 16:49:10 +08:00
cb 4783b4b077 增加类目设置倒计时 以及实付备注字段显示 2025-09-11 15:37:03 +08:00
cb 5cc6d5736d 增加类目倒计时小时数 增加新字段来表示分账结束时间 2025-09-11 11:47:57 +08:00
cb 87bcdda6f8 增加字段 2025-09-11 11:01:42 +08:00
cb 624921d776 增加返回的地址详情 2025-09-10 17:22:01 +08:00
cb 75ffa0f6ee no message 2025-09-10 16:49:28 +08:00
cb 1a8283e441 修改图片返回地址为https 增加商品店铺以及对应的距离显示 2025-09-10 12:13:28 +08:00
cb cb3e5d98a8 增加商品售后一些未修改的字段 2025-09-08 17:23:02 +08:00
cb 731d340abf 增加字段 2025-09-08 14:30:10 +08:00
cb e9ab52cb7e 增加子单的售后纠纷处理 2025-09-06 17:44:40 +08:00
cb 7878cc61c1 增加子单售后纠纷处理 2025-09-05 15:15:49 +08:00
cb c55ac047c0 增加pc端显示售后纠纷处理 2025-09-05 14:45:02 +08:00
cb a64f1728ac 优化商品售后的退款流程 2025-09-05 10:28:28 +08:00
cb a75d05bc9a no message 2025-09-05 09:29:24 +08:00
cb 6532c9d460 师傅立即重发补发方案 以及定时处理 2025-09-04 17:42:21 +08:00
cb 3eb0bd846f no message 2025-09-04 17:21:18 +08:00
cb 7d2b4f7fdb 增加商品售后大类 2025-09-04 17:12:02 +08:00
cb 7a2f71624b no message 2025-09-04 16:47:11 +08:00
cb 190d2a2bed 增加确认中倒计时的暂停以及开始 2025-09-04 16:25:46 +08:00
cb f12121c457 增加单独的售后纠纷查询 2025-09-04 15:27:43 +08:00
cb c7953da901 增加客户不同意的图片以及原因上传 2025-09-04 15:13:42 +08:00
cb 464fab9fa1 增加 重发补发 以及退货的接口 2025-09-03 16:30:42 +08:00
cb ef8fc2c492 no message 2025-09-03 15:10:18 +08:00
cb 9090b61095 增加定时处理 2025-09-03 15:04:37 +08:00
cb 08e5353b4e 处理商品类目没有的问题,增加客户是否同意上门重做方案,以及师傅重做/补做完成接口 2025-09-03 10:38:31 +08:00
cb a2a009a1e2 no message 2025-09-01 17:23:26 +08:00
cb 49394a5172 增加省市显示 2025-09-01 16:22:58 +08:00
cb 57d5161b2c 增加类目 类型区分 2025-08-30 16:08:35 +08:00
cb 270ad85a10 增加区域 类型划分 2025-08-30 12:28:04 +08:00
cb 65ca7bf9aa 增加主单和子单的师傅备注 2025-08-30 08:54:52 +08:00
cb 356d2beaa5 增加退单 后台主单显示 2025-08-28 11:45:31 +08:00
cb d2260ade7b 增加主单退单原因 2025-08-28 11:33:01 +08:00
cb 9c519ce980 no message 2025-08-26 15:40:58 +08:00
cb 620af65906 no message 2025-08-25 08:44:15 +08:00
cb 353e302df9 增加详细地址计算与店铺的距离 2025-08-23 16:45:00 +08:00
cb 0a37c352fb 增加通过店铺id 以及 经纬计算与店铺的距离 返回店铺详情 2025-08-23 16:04:57 +08:00
cb 1a5b094388 no message 2025-08-22 16:31:54 +08:00
cb c8811b0e60 增加地址经纬度以及逆解析地址到经纬度 2025-08-22 16:31:17 +08:00
cb 510e696030 no message 2025-08-22 11:35:33 +08:00
cb 8c859e1866 增加通过商品id 去获取对应的服务店铺列表 2025-08-21 17:17:30 +08:00
cb 91cb050b47 no message 2025-08-01 15:40:43 +08:00
cb 1fe53780b9 no message 2025-07-31 16:34:53 +08:00
cb 671a9f225e no message 2025-07-31 10:39:56 +08:00
cb ae2f59d183 no message 2025-07-29 17:39:22 +08:00
cb d59b15c569 no message 2025-07-29 08:34:57 +08:00
cb fa7ff1971f no message 2025-07-18 17:43:55 +08:00
cb 08c7cb32a9 no message 2025-07-14 17:33:50 +08:00
cb f1d55564c3 修改交货图片 备注字段名 2025-07-13 09:09:27 +08:00
cb 3cf9951bb3 no message 2025-07-11 20:53:39 +08:00
cb ce8015b836 no message 2025-07-11 18:55:44 +08:00
cb 9a3245380b 增加定时器来处理 发货中的状态转为确认中 2025-07-10 17:12:48 +08:00
cb 02528c930f no message 2025-07-10 15:13:57 +08:00
cb 3dc68ceaf8 no message 2025-07-09 17:41:24 +08:00
cb ad6473f446 no message 2025-07-08 10:36:12 +08:00
cb 61e9859181 no message 2025-07-08 09:47:25 +08:00
cb 3fbd432b9c 按照商品规格进行模糊查询 2025-07-07 15:12:25 +08:00
cb 7643b5d6d8 no message 2025-07-03 15:06:41 +08:00
cb 4ef6b6de2c no message 2025-07-03 14:55:42 +08:00
cb 7a73c9b099 no message 2025-07-03 11:00:34 +08:00
cb 40f5c1472e no message 2025-07-02 18:05:58 +08:00
cb 8870875647 no message 2025-07-02 16:17:24 +08:00
cb 5fe9d79a94 no message 2025-07-02 10:41:39 +08:00
cb ee36d363a7 no message 2025-06-30 18:07:40 +08:00
cb f9f36c16d9 no message 2025-06-25 11:46:55 +08:00
cb 7f959107da no message 2025-06-24 17:52:14 +08:00
cb 47f5c7b039 no message 2025-06-24 16:19:24 +08:00
cb 704454a759 no message 2025-06-20 17:08:54 +08:00
cb a82b513755 no message 2025-06-20 16:14:10 +08:00
cb c726bf91d4 给配件主单增加是否派发服务主单字段 2025-06-20 11:33:53 +08:00
cb ea0233425e no message 2025-06-20 11:20:31 +08:00
cb 708d2f12f5 增加配件主单下的服务主单退单逻辑 增加商品列表按距离排序 2025-06-20 11:20:03 +08:00
cb 037b1b5b5e no message 2025-06-20 10:09:03 +08:00
cb b2ddfb1502 no message 2025-06-19 18:10:43 +08:00
cb bd78980529 no message 2025-06-19 14:49:23 +08:00
cb fa616c8de6 no message 2025-06-18 15:46:13 +08:00
cb 7afe847942 后台增加商品类目可以配置服务类目 2025-06-18 15:33:49 +08:00
cb d3dcb97911 no message 2025-06-18 14:36:35 +08:00
cb 10835cd1a7 no message 2025-06-17 17:38:41 +08:00
cb e2ec85c7ae 增加根据用户id获取对应的商铺id 的方法 2025-06-16 17:29:13 +08:00
cb 7a2a155938 no message 2025-06-16 16:43:07 +08:00
cb dfcf26d976 no message 2025-06-16 15:37:36 +08:00
cb cedc78e76e no message 2025-06-14 21:37:33 +08:00
cb e38126d341 待完善 2025-06-14 12:50:26 +08:00
cb 547fcfc37b 增加新订单状态 来表示提现未到账 2025-06-14 12:46:35 +08:00
cb e8af400536 no message 2025-06-14 12:39:03 +08:00
cb 3524b20075 no message 2025-06-13 17:54:49 +08:00
cb affce5e1b4 no message 2025-06-12 19:00:48 +08:00
cb f1328d4db8 no message 2025-06-11 19:02:44 +08:00
cb 75c06e6457 增加加价的截留扣点设置 2025-06-10 18:01:10 +08:00
cb 448b134f11 主单状态修改 不在分账的时候就进入已完成的状态 2025-06-10 16:59:19 +08:00
cb 5b8fe3cd58 修改类目中的设置的时候显示全部的类目 2025-06-10 16:55:31 +08:00
cb f68eb53363 no message 2025-06-09 17:53:46 +08:00
cb 9a722c8da2 增加子单金额的分账 2025-06-08 18:13:17 +08:00
cb 18b6d5325d no message 2025-06-05 17:29:37 +08:00
cb 8766726189 no message 2025-06-05 14:43:49 +08:00
cb dfc1aaca91 no message 2025-06-04 18:01:21 +08:00
cb ca4530ce84 no message 2025-06-04 15:44:49 +08:00
cb 6c500a0349 no message 2025-05-30 17:35:08 +08:00
cb d7f8ffa20d no message 2025-05-30 16:15:04 +08:00
cb 8e09f2aaf6 no message 2025-05-29 18:13:16 +08:00
cb 36767a00bf no message 2025-05-28 16:43:40 +08:00
cb ecd9a76eeb no message 2025-05-27 17:32:29 +08:00
cb 4f984ab2e7 no message 2025-05-26 18:10:41 +08:00
cb 1d91eb9976 暂时只显示正选类目 2025-05-26 17:16:13 +08:00
cb c747158393 修改类目设置 2025-05-26 16:17:34 +08:00
cb cb16333e61 修改子单的服务金额 2025-05-26 14:35:26 +08:00
cb 964d1cb519 no message 2025-05-26 11:55:12 +08:00
cb cc032f44c0 11 2025-05-23 18:06:54 +08:00
cb 71bb414f23 1 2025-05-22 20:53:55 +08:00
cb ef23b61265 no message 2025-05-22 18:06:12 +08:00
cb 6dd60354a6 删除配件费用,增加加价凭证 2025-05-21 17:50:04 +08:00
cb 582d478186 no message 2025-05-20 09:25:52 +08:00
cb a14f69f77c 修改一小时上门的判断条件 2025-05-15 11:47:05 +08:00
cb 5a4945955d no message 2025-05-14 10:34:16 +08:00
cb 99be99391f no message 2025-05-13 15:19:41 +08:00
cb 60952f6b47 no message 2025-05-13 09:58:36 +08:00
cb 60c02a28ed no message 2025-05-13 09:51:25 +08:00
cb 05ac0b5acb no message 2025-05-13 09:18:38 +08:00
cb 087ea91ecf no message 2025-05-12 16:12:51 +08:00
cb 54a7b65f8f no message 2025-05-10 16:59:45 +08:00
cb 687f691ff9 no message 2025-05-10 09:33:36 +08:00
cb 78f43c0c16 no message 2025-05-09 15:30:39 +08:00
cb 880866b1b6 no message 2025-05-09 15:21:52 +08:00
cb c07f80e18f no message 2025-05-09 15:02:21 +08:00
cb 1abb02f464 1 2025-05-09 14:45:47 +08:00
cb fc38c49162 no message 2025-05-09 11:36:51 +08:00
cb c857e551fb no message 2025-05-09 09:49:20 +08:00
cb a22d60f23a no message 2025-05-09 09:03:24 +08:00
cb 806e5e700e no message 2025-05-08 18:05:13 +08:00
cb f8a987a0f6 no message 2025-05-08 18:03:29 +08:00
cb be3311daee 修改子单撤单后的 判断是否有子单还在派单 如果没有再修改为null 2025-05-08 17:39:37 +08:00
cb 0ff2a6b703 no message 2025-05-08 16:51:09 +08:00
cb dbeace3191 no message 2025-05-08 16:33:18 +08:00
cb 96cbd47cb0 no message 2025-05-08 16:08:19 +08:00
cb bcffad126c no message 2025-05-08 15:52:48 +08:00
cb 6dbdb33a2b no message 2025-05-08 15:24:49 +08:00
cb fecb22b5ad no message 2025-05-08 15:14:43 +08:00
cb e661871090 no message 2025-05-08 15:03:17 +08:00
cb 38c26e399f no message 2025-05-08 14:53:22 +08:00
cb e1696d937b no message 2025-05-08 14:31:14 +08:00
cb 2099610e59 no message 2025-05-08 14:24:53 +08:00
cb 2e2494c9bb no message 2025-05-08 12:22:55 +08:00
cb ed034cb2c7 no message 2025-05-08 12:05:23 +08:00
cb d40822487f no message 2025-05-07 16:40:55 +08:00
cb 3cd9560732 no message 2025-05-07 15:34:10 +08:00
cb 479e619d39 增加子单超时未接单 2025-05-07 14:35:05 +08:00
cb bd9883c0d0 no message 2025-05-07 11:42:09 +08:00
cb 6aec17ed20 no message 2025-05-07 11:41:17 +08:00
cb 5aea1c4731 no message 2025-05-07 11:31:53 +08:00
cb f385aaabf3 no message 2025-05-07 11:24:39 +08:00
cb 0a86d01406 no message 2025-05-07 11:13:32 +08:00
cb ccb7cc34b5 no message 2025-05-07 11:06:06 +08:00
cb 37722ef2fa no message 2025-05-07 10:57:38 +08:00
cb d1ce4b76a2 no message 2025-05-07 10:04:24 +08:00
cb 95952ea425 no message 2025-05-07 08:51:01 +08:00
cb 1a2f919f79 no message 2025-05-06 17:50:01 +08:00
cb 3c958a2923 no message 2025-05-06 15:06:10 +08:00
cb ec4fdda392 no message 2025-05-06 09:56:16 +08:00
cb 73710b0a4c no message 2025-05-06 09:37:45 +08:00
cb e6a3d6fc2d no message 2025-05-06 09:24:25 +08:00
cb e7e8583806 Merge branch 'master' of https://git.opsoul.com/clunt/ghy-all 2025-05-06 09:21:08 +08:00
cb 259b99c3f0 no message 2025-05-06 09:20:27 +08:00
cb 9df61f6a85 修改列表查询 2025-04-30 21:57:34 +08:00
cb 21c4d8e7dc Merge remote-tracking branch 'origin/master' 2025-04-30 19:47:44 +08:00
cb 174b6031e9 no message 2025-04-30 18:11:14 +08:00
cb 37471713b7 Merge remote-tracking branch 'origin/master' 2025-04-30 18:01:22 +08:00
cb 4c8a00d081 no message 2025-04-30 18:01:06 +08:00
cb f9080bb812 Merge remote-tracking branch 'origin/master' 2025-04-30 17:38:30 +08:00
cb cf10288761 no message 2025-04-30 17:37:56 +08:00
cb 1be8d59c6f Merge remote-tracking branch 'origin/master' 2025-04-30 17:36:37 +08:00
cb 930a9e3de8 no message 2025-04-30 17:36:19 +08:00
cb 2e7bcaba70 Merge remote-tracking branch 'origin/master' 2025-04-30 17:14:35 +08:00
cb d6028c3e1e no message 2025-04-30 17:14:23 +08:00
cb ff67462b73 Merge remote-tracking branch 'origin/master' 2025-04-30 16:53:49 +08:00
cb fab703b7af no message 2025-04-30 16:53:31 +08:00
cb 2655d8ffdb Merge remote-tracking branch 'origin/master' 2025-04-30 14:50:13 +08:00
cb ab7e7eaca7 no message 2025-04-30 14:48:40 +08:00
cb c92ea38c60 Merge remote-tracking branch 'origin/master' 2025-04-30 09:55:26 +08:00
cb fabfbad8e3 Reapply "no message"
This reverts commit 63f85c996f.
2025-04-30 09:38:05 +08:00
cb 63f85c996f Revert "no message"
This reverts commit 45ee79cc6d.
2025-04-30 09:37:36 +08:00
cb 45ee79cc6d no message 2025-04-30 09:35:46 +08:00
cb 977994aeee no message 2025-04-30 09:31:13 +08:00
cb a04f2ac07c no message 2025-04-29 17:40:27 +08:00
cb c421a6a9b5 no message 2025-04-29 15:39:57 +08:00
cb 9ce50574d0 no message 2025-04-28 22:24:44 +08:00
cb 1bf22bad69 no message 2025-04-28 15:51:08 +08:00
cb 55b1e1a16d no message 2025-04-28 09:07:04 +08:00
cb a4aaf529dd no message 2025-04-28 08:51:43 +08:00
cb 6f4cd2d217 no message 2025-04-28 08:46:00 +08:00
cb 3ff590511d no message 2025-04-27 22:02:09 +08:00
cb c832f2632e no message 2025-04-27 21:26:20 +08:00
cb 33e278b904 no message 2025-04-27 20:57:05 +08:00
cb 6a191fe575 no message 2025-04-27 20:32:43 +08:00
cb 7726728114 增加手续费财务子单 2025-04-27 16:47:10 +08:00
cb 021ab31732 no message 2025-04-27 15:18:10 +08:00
cb ccbbbe7ec5 no message 2025-04-27 11:43:04 +08:00
cb 487c912351 处理承担手续费的问题 2025-04-27 11:40:42 +08:00
cb a22fb81326 no message 2025-04-25 17:02:02 +08:00
cb 62c0baa1db no message 2025-04-25 16:40:51 +08:00
cb 7460a01b22 no message 2025-04-25 14:58:09 +08:00
cb c99975c300 no message 2025-04-25 14:48:44 +08:00
cb 9fad62d168 no message 2025-04-24 16:50:32 +08:00
cb d132a9f68f no message 2025-04-24 16:08:19 +08:00
cb 7bbefd0d60 no message 2025-04-24 15:56:55 +08:00
cb 1fdb099591 no message 2025-04-24 15:36:25 +08:00
cb 700b261e36 no message 2025-04-24 11:46:06 +08:00
cb 368f943211 no message 2025-04-24 11:33:58 +08:00
cb 38b6211531 no message 2025-04-24 11:16:09 +08:00
cb b4cb0f6a65 no message 2025-04-24 11:01:40 +08:00
cb 2c3328b320 no message 2025-04-24 09:59:15 +08:00
cb 3ef7b08c95 no message 2025-04-24 09:55:58 +08:00
cb a1d6f90837 no message 2025-04-23 18:10:14 +08:00
cb ed1790a79a no message 2025-04-22 20:58:01 +08:00
cb 7844f470fa no message 2025-04-22 19:58:01 +08:00
cb b572d35b88 no message 2025-04-22 19:51:37 +08:00
cb 0c6ced5f64 no message 2025-04-22 17:58:54 +08:00
cb 37b2158fe0 no message 2025-04-22 14:53:55 +08:00
cb 269c023cfb no message 2025-04-22 14:43:53 +08:00
cb 2b8747b6f7 no message 2025-04-22 11:44:51 +08:00
cb 66eabfee3f no message 2025-04-22 10:18:03 +08:00
cb 2379de2ca8 no message 2025-04-21 19:38:53 +08:00
cb 365bb601dc no message 2025-04-20 12:57:32 +08:00
cb 41a79155e8 客户操作后的日志 2025-04-20 09:34:14 +08:00
cb dde04d33d7 增加未约未排验证 2025-04-20 09:29:23 +08:00
cb ebed7ed88a no message 2025-04-20 08:48:38 +08:00
cb 6e9f52b0f1 no message 2025-04-19 14:58:05 +08:00
cb a44ffd15cd Merge branch 'master' of https://git.opsoul.com/clunt/ghy-all 2025-04-19 14:42:26 +08:00
cb 7440a5d166 修改待上门的订单不受时间影响 2025-04-19 14:42:14 +08:00
cb 3fd8968a1a no message 2025-04-19 14:39:25 +08:00
cb 19940c64ae no message 2025-04-19 09:55:06 +08:00
cb c471f79d34 超时4小时时间处理 2025-04-19 09:33:09 +08:00
cb 6f357a3bcb no message 2025-04-18 17:14:05 +08:00
cb 077fe631a3 明日单通知文案修改 2025-04-18 15:45:18 +08:00
cb 6fee96a602 no message 2025-04-18 15:08:22 +08:00
cb 73bba5dc9d no message 2025-04-18 11:39:46 +08:00
cb f04fa50549 增加定点巡查 2025-04-18 10:54:05 +08:00
cb 21bfff0400 no message 2025-04-17 18:09:10 +08:00
cb 0ca42dc14b no message 2025-04-17 17:49:25 +08:00
cb 435f63560f no message 2025-04-17 14:49:30 +08:00
cb 7c07a7951c no message 2025-04-17 12:26:22 +08:00
cb 6920d3d554 no message 2025-04-17 12:23:02 +08:00
cb 3f726ca439 no message 2025-04-17 11:31:39 +08:00
cb 1254dd9e79 增加一小时订单通知提醒 2025-04-17 11:12:01 +08:00
cb 44eab29981 Merge branch 'master' of https://git.opsoul.com/clunt/ghy-all 2025-04-17 10:47:01 +08:00
cb 70b31a6a8e no message 2025-04-17 10:46:33 +08:00
cb cd0fb4c6ce 修改师傅的实名缺少姓的问题 2025-04-16 21:23:46 +08:00
cb f0cd7c5172 no message 2025-04-16 18:02:38 +08:00
cb 76323f4bbc no message 2025-04-16 12:27:51 +08:00
cb 0433165ae2 no message 2025-04-15 18:02:16 +08:00
cb db05137f27 no message 2025-04-15 17:48:09 +08:00
cb 31670d8962 售后订单超时判断修改 2025-04-15 11:00:52 +08:00
cb 20ce2319e7 no message 2025-04-14 18:31:02 +08:00
cb 0c015748fc 主单未约未排 2025-04-14 12:01:36 +08:00
YiFei Kuang 89a9c13822 子单未约未排问题 2025-04-14 10:55:00 +08:00
cb ccc6b3cb99 no message 2025-04-11 17:12:50 +08:00
cb 41a9c93f62 no message 2025-04-11 15:07:47 +08:00
cb 35b0b86c60 no message 2025-04-11 11:49:26 +08:00
cb bfcbaa9cae 拒单key修改 2025-04-11 09:11:08 +08:00
cb 67b4f95237 no message 2025-04-11 09:07:49 +08:00
cb980602 ce70f4f954 no message 2025-04-10 17:45:25 +08:00
YiFei Kuang 152c2c5caa fix_1 2025-04-10 16:31:09 +08:00
YiFei Kuang fb57b9e9f9 fix bug-1 2025-03-24 13:25:38 +08:00
YiFei Kuang b4617d3135 fix bug 2025-03-10 21:07:02 +08:00
YiFei Kuang ffb560da51 fix bug 2025-03-03 11:47:33 +08:00
YiFei Kuang c58346349c fix bug 2025-02-20 23:04:12 +08:00
YiFei Kuang 109cc4ccca fix bug 2025-02-20 17:03:53 +08:00
YiFei Kuang e8fd8d49d2 fix bug 2025-02-16 19:20:51 +08:00
YiFei Kuang 68023b8cc0 fix: 商品编辑金额不生效问题 2025-02-06 11:32:07 +08:00
YiFei Kuang 2549dcd977 fix: 师傅二级技能类目筛选,待上门超时问题 2025-01-21 18:06:10 +08:00
YiFei Kuang 934afa402a fix: 子单待上门超时 2025-01-21 16:50:00 +08:00
YiFei Kuang 0975f12e39 fix: 计算超时时,不能一味的按照+13h来算,而是应该按照从早上8点开始计算 2025-01-20 14:12:01 +08:00
YiFei Kuang 5c54c87ea3 完成超时问题解决,类目三级筛选,修改扣点和金额无效问题 2025-01-19 21:15:01 +08:00
Yifei Kuang 67f8738c5e 师傅列表支持区域和类目筛选 2025-01-12 23:35:57 +08:00
Yifei Kuang 8a8cd9353b fix bug 2025-01-12 22:11:57 +08:00
Yifei Kuang 88db2391d2 修改保险文字提示 2025-01-10 17:11:30 +08:00
Yifei Kuang 4f55e0e9f8 fix bug 2025-01-10 13:56:00 +08:00
Yifei Kuang ec5fcacf64 feat: 保险增员问题 2024-12-12 15:13:31 +08:00
Yifei Kuang d798bf8f26 1.后台下单备注问题 2024-12-09 16:49:23 +08:00
Yifei Kuang a0aefb4850 1.发单管理页面支持选择保险
2.发单管理页面支持批量发单
3.主单管理页面支持批量发单
4.商城-消费者管理页面,支持修改用户分销
5.商城-消费者管理页面,支持通过用户手机号模糊查询用户
6.保险增员时,身份二要素校验
7.发单账号可见的订单是他自己所发订单。发单账号主单上的订单也是见自己所发订单。(13386441744查一下)
2024-12-09 00:37:48 +08:00
Yifei Kuang e24cbde6f0 feat: 后台增加保险 2024-12-04 10:06:21 +08:00
Yifei Kuang a13ac431dc feat: 在线支付订单提交后,不支付的,师傅端点接单键提示(待支付后再接单) 2024-12-01 16:37:47 +08:00
Yifei Kuang ff366f9ec5 保险异步进行,失败了也不用管 2024-12-01 16:06:10 +08:00
Yifei Kuang 482e2225f1 身份证二要素 2024-11-18 13:41:57 +08:00
Yifei Kuang 94277bce22 保险金额归属给平台,不应展示给客户 2024-11-03 21:24:55 +08:00
kuang.yife 1a18fbb03b fix bug 2024-10-28 16:45:10 +08:00
kuang.yife b57f751831 fix bug 2024-10-23 17:00:48 +08:00
kuang.yife 9d78fcef91 fix bug 2024-10-21 15:35:55 +08:00
kuang.yife 87e049618e 商城内,保险相关页面 2024-10-21 14:03:49 +08:00
kuang.yife 3e96984d64 下单获取保险信息 2024-10-12 10:42:07 +08:00
kuang.yife 1b712a705d Merge remote-tracking branch 'origin/master' 2024-10-01 12:18:29 +08:00
kuang.yife 6357dc58d2 保险管理、总平台保险、保险关系 2024-10-01 12:17:15 +08:00
但星霖 f09fa1e8b6 订单声音配置后台代码 2024-09-29 07:47:53 +08:00
kuang.yife 02683fcfeb 保险管理、总平台保险、保险关系 2024-09-27 17:15:34 +08:00
但星霖 014e591916 订单声音配置后台代码 2024-09-27 12:14:59 +08:00
kuang.yife aac5ba8b20 保险管理、总平台保险、保险关系 2024-09-25 18:16:49 +08:00
kuang.yife e398ad7e25 保险业务 2024-09-11 15:54:25 +08:00
kuang.yife d5c1dda703 保险下单 2024-09-09 15:37:45 +08:00
kuang.yife d44591330a 正选问题 2024-08-29 17:26:21 +08:00
kuang.yife d8b6c15034 正选问题 2024-08-26 10:43:34 +08:00
kuang.yife cf7c708f3a 默认地址问题 2024-08-23 09:23:55 +08:00
kuang.yife 6d72575c0b 修复未入驻师傅不展示的bug 2024-08-06 14:14:07 +08:00
kuang.yife 3bf3f56587 入驻信息展示、师傅信息 2024-08-05 18:06:38 +08:00
kuang.yife 228e8d3a70 修复后台合并支付时,前端的分帐bug 2024-06-11 13:09:24 +08:00
kuang.yife 96891f811c 1,主单派单加上姓名(不是分派那里)
2,派单搜索姓名,未能搜索(注意派主单处搜索和分派处搜索)
3,搜索地址搜索不了。
4,品牌和规格搜索不了。
5,下单模式未展示,且上面筛选处未能筛选下单模式。
6,原来第5点下单的备注提到后台。未见
2024-06-05 23:26:10 +08:00
kuang.yife a329df620d 1.主订单规格展示
3.电话姓名查找订单筛选
4.主单派单时,弹框通过手机号搜索子师傅
2024-05-27 11:19:50 +08:00
kuang.yife bc960bbb2b 优化展示。修复bug 2024-05-20 09:19:08 +08:00
kuang.yife 739976b1f9 需求开发 2024-03-18 18:17:49 +08:00
kuang.yife 0fcc7efb8e 规格问题 2024-03-04 09:51:09 +08:00
kuang.yife 660acc64ee 名字不显示问题 2024-03-02 20:54:15 +08:00
kuang.yife a8452e1f52 合约订单标签,四级地址 2024-03-02 20:47:11 +08:00
kuang.yife 199fc1c619 合约订单,以及合约订单权限 2024-03-02 18:25:30 +08:00
kuang.yife 0c82e06c91 发单管理师傅号码不显示、派单自己的时候不通知 2024-02-19 17:14:58 +08:00
kuang.yife d266225943 催单/约单,以及公众号通知 2024-02-18 17:59:52 +08:00
kuang.yife 7cdbfe8e9d 催单/约单 2024-02-18 15:33:21 +08:00
kuang.yife 2f488a71e1 订单完单图片 2024-02-18 09:38:44 +08:00
kuang.yife 8c805e710a 主单/子单流程轨迹 2024-02-17 13:50:22 +08:00
kuang.yife cc5f528bf7 代码迁移 2024-01-31 23:34:31 +08:00
kuang.yife 0a4264c9ac 导入问题,子单号问题 2024-01-31 23:32:54 +08:00
kuang.yife 6f2c5f534d 导入问题,外加派单可以二次派新订单 2024-01-30 17:23:44 +08:00
kuang.yife d7053a4d9c 导入问题,外加派单可以二次派新订单 2024-01-30 17:08:51 +08:00
kuang.yife 3271cf06f3 审核倒序+40分钟自动拒单 2024-01-29 17:57:24 +08:00
kuang.yife 43df3100ed 导入 2024-01-29 17:26:04 +08:00
kuang.yife c6b3fdaf03 派单时间问题/子师傅+师傅新订单列表 2024-01-24 15:08:26 +08:00
kuang.yife 5136738411 附件费用加价 2024-01-02 22:29:52 +08:00
kuang.yife 443a61e2ec 附件费用加价 2024-01-02 22:26:46 +08:00
kuang.yife e79e530bcd 指定唯一键 2024-01-02 18:13:22 +08:00
kuang.yife ddaf344907 定时任务 2023-12-26 10:14:37 +08:00
kuang.yife a56511b4f2 修改数据库 2023-12-16 13:32:27 +08:00
kuang.yife 54b214c4b4 修改数据库 2023-12-05 17:33:02 +08:00
kuang.yife 32119e1348 各列表超时状态、序列、扣点随动、状态名称 2023-11-13 00:11:49 +08:00
kuang.yife c97d064aca Merge remote-tracking branch 'origin/master' 2023-11-09 10:00:06 +08:00
kuang.yife d1cac03848 小程序后台各种取值 2023-11-09 09:59:34 +08:00
donqi 7e48da6fb3 主单列表页面修改按钮及弹窗 2023-11-04 02:28:15 +08:00
kuang.yife e32a57baf7 第三点,A,订单编号那4个字不要,编号后面是品牌、规格这两个信息;
订单信息里的预约时间:表示方式2013-10-31   08:-10:00
第4订单状态未对,子师傅订单状态未约未排,未拆。师傅排单时间未提后台。
第5接单信息,师傅是实名(这里看回那个取认证名字的步骤是否影响了),拔打次数和详情展示(拔打详情有),接单信息未展示。子师傅的也未展示,子师傅的分做单与接单师傅展示。看整个第5条
2023-11-04 01:16:30 +08:00
kuang.yife cc2abf126a 发单管理页面 2023-10-30 22:11:32 +08:00
kuang.yife 9a2524bbde 识别每小时新订单收取 + 推送微信公众号通知 2023-10-29 23:53:07 +08:00
杨丹琪 2d1c925e47 师傅实名认证报错修复 2023-10-29 22:57:56 +08:00
kuang.yife 3bd058f650 修改下备案号 2023-10-25 22:32:10 +08:00
kuang.yife 7b1ed37c50 优化代码 2023-10-24 00:39:12 +08:00
杨丹琪 3eb06f5951 主单查询增加区域条件的筛选 2023-10-21 03:04:05 +08:00
kuang.yife c328e4f4c4 修改文档内容3和5两点,其中3主要缺少地址修改。省市区列表慢的问题 2023-10-18 23:23:53 +08:00
kuang.yife 4fcdc5a1dc 主订单,订单详情修改 2023-10-16 18:18:20 +08:00
kuang.yife 572bfcbc05 主单退单/商家退单 2023-10-15 00:45:44 +08:00
kuang.yife 1264052f30 主单派单位置迁移 2023-10-11 09:37:32 +08:00
kuang.yife facc4199f6 pc派单 2023-10-10 23:09:29 +08:00
kuang.yife 3a5cd3b210 小程序openid转公众号openid逻辑 2023-10-09 00:03:50 +08:00
kuang.yife 1dd6bc0065 公众号获取用户信息接口 2023-10-08 23:08:27 +08:00
kuang.yife 8e661f0211 需求大厅问题 2023-10-08 22:23:21 +08:00
kuang.yife 57a211bbce 公众号通知问题 2023-10-06 00:33:50 +08:00
kuang.yife 37b3d0a716 Merge remote-tracking branch 'origin/master' 2023-10-05 23:00:59 +08:00
kuang.yife 1cebda3074 下单备注问题/后台发单不允许小数点存在 2023-10-05 23:00:32 +08:00
但星霖 ee243b5d61 微信消息通知更新。 2023-10-05 21:42:10 +08:00
kuang.yife f3c0419987 后台发单扣点不对问题解决 2023-10-05 02:23:47 +08:00
kuang.yife 6b6886f3f3 加价拆分逻辑/下单到付逻辑 2023-10-05 01:24:05 +08:00
kuang.yife 73f9cd14e6 后台下单整体流程修复,各类统计问题修复 2023-10-01 01:37:28 +08:00
kuang.yife 1df8410b99 注册默认为101工圈子 2023-09-30 23:54:42 +08:00
kuang.yife bc8a43ce2f 权限问题 2023-09-28 16:25:22 +08:00
kuang.yife 134da09966 fix bug 2023-09-28 16:01:07 +08:00
但星霖 8625d959da 微信消息通知更新。 2023-09-28 09:56:09 +08:00
但星霖 b5a09dfd71 微信消息通知更新。 2023-09-28 09:55:21 +08:00
kuang.yife 5e0d35a989 fix bug 2023-09-06 09:10:18 +08:00
kuang.yife 0ee5ababdc 暂时注释抵扣 2023-09-01 15:56:28 +08:00
donqi 28c6ccd65b 优化统计接口速度 2023-08-30 23:20:19 +08:00
HH a5ad79dc0e 更新主单支付状态的时候,顺便把子单的也一起更新咯 2023-08-29 20:15:58 +08:00
donqi 7733e4f755 app单量统计接口修改 2023-08-22 23:01:00 +08:00
donqi 555fd91a56 派单接口中判断为未派完的单,必定指派给了其他师傅,设置是否自己承接的标识为否 2023-08-22 22:42:43 +08:00
kuang.yife a0ab257b18 提交代码 2023-08-19 00:04:41 +08:00
kuang.yife 294123359f Merge remote-tracking branch 'origin/master' 2023-08-15 22:59:14 +08:00
kuang.yife c64902e206 1.子单加价金额合并展示 2023-08-15 22:57:06 +08:00
donqi f13e74aff7 主单子单混合查询接口增加返回isCall 2023-08-13 22:35:45 +08:00
kuang.yife 8edb26d46f 1,关键词搜索。
2,未约点了拨打,不用再形成超时了;未牌的超时标签不对(现在是超时未约单)
3,主单接单超时退到大厅的,和主单拒绝接单退到大厅的,大厅里面的单没见到。不知道去哪了。
2023-08-13 22:21:05 +08:00
kuang.yife b6d6dafe8d 子单超时包含新订单状态 2023-08-10 17:23:50 +08:00
kuang.yife 68661072ce 子单超时状态变更 2023-08-09 23:06:35 +08:00
kuang.yife 7062b7dd52 超时状态变更 + 退款未退加价 2023-08-09 22:38:34 +08:00
kuang.yife 2ebe61813d 热门类目排序问题 2023-08-08 17:08:14 +08:00
kuang.yife 22f73e9a06 大师傅提成合并问题 2023-08-01 20:07:05 +08:00
kuang.yife 14d3a48dda 修改扣点为三级目录+增加分销扣点 2023-07-30 19:54:22 +08:00
kuang.yife 77e7ae8227 修改扣点为三级目录+增加分销扣点 2023-07-30 19:48:00 +08:00
Hawking bd6dee6d8c 分账后自动提现 2023-07-23 22:43:18 +08:00
donqi b95dcce2b4 混合单列表查询排序 2023-07-23 00:08:18 +08:00
kuang.yife 81ccbc40bc fix 2023-07-10 22:39:21 +08:00
Hawking bc64e4a10c 支付成功回调时更新OrderMaster的支付状态 2023-07-10 16:35:27 +08:00
donqi 062164f90d Merge branch 'old-version' 2023-07-09 16:57:30 +08:00
donqi 227c7f6896 更新状态或更新预约时间清除超时标识 2023-07-09 16:39:49 +08:00
Hawking 95c9bfcfcf 订单加价扣除平台抽成和团队抽成 2023-07-08 17:34:18 +08:00
Hawking 44f780f15b 订单加价扣除平台抽成和团队抽成 2023-07-07 22:51:51 +08:00
donqi 49ca78bdf3 注册功能及页面,将配置是否注册部分注释放开 2023-07-01 19:36:34 +08:00
donqi 9cd69109f9 注册功能及页面 2023-07-01 19:34:25 +08:00
donqi bb5f136025 主单列表页面查询修改 2023-06-26 00:31:20 +08:00
donqi d6bd909075 主单列表页面查询调整 2023-06-26 00:02:43 +08:00
Hawking 9109c692a1 Merge remote-tracking branch 'origin/old-version' 2023-06-22 19:24:57 +08:00
donqi 6d4cf3ed78 后台整单派单派到新订单 2023-06-21 18:16:16 +08:00
donqi 59a662d56a 发单页面的校验完善 2023-06-19 00:03:09 +08:00
donqi 82f8a40f87 没有大师傅的主单指派时只允许整单指派 2023-06-18 21:46:10 +08:00
donqi 0de3aa5058 没有大师傅的主单指派时只允许整单指派 2023-06-18 20:57:39 +08:00
donqi 118107cc15 发单表单修改 2023-06-17 01:40:40 +08:00
donqi 638c3bd518 派单页面 2023-06-17 01:28:14 +08:00
kuang.yife d1634edfcb 主单+主单指派 2023-06-16 21:23:11 +08:00
kuang.yife 316de8d63e 指派500修复 2023-06-15 00:34:18 +08:00
donqi bd7bc74bdb Merge remote-tracking branch 'origin/old-version' into old-version 2023-06-15 00:17:37 +08:00
donqi 043d8cf9f9 服务订单管理查询接口对接 2023-06-15 00:17:23 +08:00
kuang.yife d11dfdc04d 指派初版... 2023-06-14 23:16:28 +08:00
kuang.yife 19161fda7f 师傅列表账号展示 2023-06-14 23:04:51 +08:00
kuang.yife 232eed7361 师傅列表账号展示 2023-06-14 22:13:04 +08:00
kuang.yife f42f56c48e 师傅姓名/电话 2023-06-14 22:02:30 +08:00
kuang.yife f7017a21c1 订单列表 接单 + 商家信息 2023-06-14 21:53:33 +08:00
kuang.yife 9a193669b8 修复师傅查询分页bug + 待付款状态查询 2023-06-14 21:34:00 +08:00
kuang.yife 77a45f2c52 fix 2023-06-14 21:23:11 +08:00
kuang.yife 5d99c998fe fix 2023-06-14 21:22:44 +08:00
kuang.yife a82fa6f21f Merge remote-tracking branch 'origin/old-version' into old-version 2023-06-14 21:07:36 +08:00
kuang.yife ebef42aba7 fix 2023-06-14 21:07:26 +08:00
donqi d65dedb62d feat 2023-06-07 23:24:58 +08:00
Hawking ce77b24b47 子订单finish判断调整日志调整 2023-06-05 12:27:53 +08:00
donqi 009c391e44 fix 2023-06-05 00:56:03 +08:00
donqi 0d6a963959 发单管理未约未排按钮合并为已接单 2023-06-04 23:40:38 +08:00
donqi de669894fc feat 2023-06-04 01:57:37 +08:00
kuang.yife 5b54770a40 未约未排 2023-06-04 01:40:36 +08:00
Hawking 49f52d0845 支付宝支付调整 2023-06-02 16:51:14 +08:00
kuang.yife 8ad615c8b7 缺少待付款/已发布 2023-06-01 23:40:19 +08:00
donqi 7b0169e4bc 发单管理待付款及已发布查询 2023-06-01 23:18:06 +08:00
kuang.yife 3a829cae26 缺少待付款/已发布 2023-06-01 21:41:59 +08:00
donqi d5847db0b9 发单页面修改 2023-06-01 21:35:06 +08:00
Hawking 84bbf53ea4 微信支付调整 2023-06-01 15:50:31 +08:00
kuang.yife ffcf62c5f3 更新 2023-06-01 14:55:59 +08:00
Hawking 8df08d1ff1 支付回调调整:
原逻辑: 单直接关联payment_id,当一个单发起了多次支付时,会造成混乱.
现更改为: 由支付成功的payment在回调时通过payment_relation表找到对应的单并关联.
1. FinancialMaster: 保存paymentId,更新支付状态;
2. FinancialChange: 保存paymentId,更新支付状态,并把金额加到FinancialDetail与FinancialMaster里;
3. OrderAddSubtract: 保存paymentId,更新支付状态,并把金额加到FinancialDetail与FinancialMaster里;
2023-05-31 23:13:21 +08:00
Hawking 210ade5f47 Adapay_payment 支付表 2023-05-31 18:50:46 +08:00
Hawking 05265ac17e PaymentRelationMapper 支付关系表 2023-05-31 15:32:07 +08:00
kuang.yife d28e6a1b90 重构支付流水逻辑 2023-05-31 09:38:56 +08:00
Hawking 82a9d1cdbc 补充Adapay相关内容 2023-05-29 23:26:27 +08:00
Hawking 842793a74e 付款二维码接口参数改为String,以便后续支持多个订单ID传参 2023-05-29 15:44:40 +08:00
kuang.yife 36aa346c2a Merge remote-tracking branch 'origin/master' 2023-05-28 23:56:37 +08:00
kuang.yife b57a8383d2 pc发单流程 2023-05-28 23:56:29 +08:00
donqi 3ec22e2a8e 修改派单逻辑 2023-05-28 22:46:43 +08:00
kuang.yife cea7d3301a pc发单扣点 2023-05-28 22:43:18 +08:00
kuang.yife a3168fdb6d Merge remote-tracking branch 'origin/master' 2023-05-28 22:16:02 +08:00
kuang.yife 9f6a22a065 数据更改,PC发单扣点编辑 2023-05-28 22:15:53 +08:00
donqi 7d22d8bd86 二维码问题修复 2023-05-28 21:51:31 +08:00
donqi b71f6d5570 付款二维码 2023-05-28 21:23:46 +08:00
donqi 27a8302c7f 生成二维码 2023-05-27 23:46:07 +08:00
donqi 6fc928fa34 订单管理的条件项 2023-05-25 02:06:13 +08:00
Hawking 09a0b0696c 子订单追加分账 2023-05-24 11:27:49 +08:00
Hawking 352a4323d0 保存子订单的追加扣减记录 2023-05-23 14:45:22 +08:00
kuang.yife 32a7dc96ea PC下单默认付款方式在线支付 2023-05-22 14:43:23 +08:00
kuang.yife eb8a213cc4 PC下单接口 2023-05-21 22:14:44 +08:00
donqi d78b636d6b 订单状态 2023-05-21 22:14:17 +08:00
Hawking ea674336ff 保存子订单的追加扣减记录 2023-05-21 16:02:47 +08:00
donqi 4929fc8d3a 模版发单页面样式修改 2023-05-21 03:07:18 +08:00
kuang.yife db11b450a3 PC下单接口 2023-05-21 02:49:21 +08:00
kuang.yife 7caf7eae18 PC下单接口 2023-05-21 02:30:53 +08:00
donqi f574bfed24 修改服务上架页面 2023-05-21 01:45:09 +08:00
kuang.yife 7d7d7ee584 PC下单接口 2023-05-21 00:29:24 +08:00
kuang.yife f7cca0de02 Merge remote-tracking branch 'origin/master' 2023-05-20 23:49:02 +08:00
kuang.yife 8b7ab3c6fe 临时区域接口 2023-05-20 23:48:51 +08:00
Hawking db206b6577 补充大师傅的子订单的提现时间 2023-05-18 23:45:34 +08:00
Hawking 12438386bd 补充大师傅的子订单的提现时间 2023-05-18 21:18:43 +08:00
Hawking 08b50407dd 订单列表“查看” 2023-05-18 16:33:33 +08:00
donqi 6d431cf991 订单统计问题修复 2023-05-17 21:50:03 +08:00
Hawking f401676e02 后台下单时创建Customer和CustomerAddress 2023-05-17 21:31:48 +08:00
kuang.yife 444c532f9a Merge remote-tracking branch 'origin/master' 2023-05-17 20:38:16 +08:00
kuang.yife 4a094c256e 默认101 2023-05-17 20:38:08 +08:00
donqi 92bf1bb533 修改订单统计及订单列表查询 2023-05-17 20:35:21 +08:00
kuang.yife ea2d9d683b Merge remote-tracking branch 'origin/master' 2023-05-17 20:33:09 +08:00
kuang.yife 74a72688db 数据隔离 2023-05-17 20:32:58 +08:00
Hawking d00aaea21c 查询师傅银行卡信息时要带上deptId 2023-05-17 15:18:56 +08:00
Hawking 40e5098a7e Merge remote-tracking branch 'origin/master' 2023-05-16 22:49:20 +08:00
Hawking 063717b4ca 师傅退单/商家退单 2023-05-16 22:48:43 +08:00
kuang.yife f9b9653cc6 数据隔离 2023-05-16 14:44:59 +08:00
kuang.yife daa1555f62 文案修复 2023-05-16 11:43:51 +08:00
kuang.yife feb2bee79e PC 师傅列表分公司数据权限隔离 2023-05-16 11:25:14 +08:00
donqi 9ad2b8cb3b 修改订单列表及详情查询是否超时单判断逻辑 2023-05-12 22:24:28 +08:00
kuang.yife c3540575ab 子单订单详情 2023-05-11 14:45:35 +08:00
kuang.yife ba8a37c77d Merge remote-tracking branch 'origin/master'
# Conflicts:
#	ghy-payment/src/main/resources/mapper/financial/OrderFineRecordMapper.xml
2023-05-11 10:58:37 +08:00
donqi 5b1f10fadd 超时记录同状态同子单有两条?默认先取时间较晚单那条记录 2023-05-10 22:03:29 +08:00
Hawking e7cdfe188d 主订单分账时扣除罚金 2023-05-10 21:02:04 +08:00
Hawking 6436dffee0 主订单超时罚金 2023-05-10 20:47:05 +08:00
Hawking f64296dec7 主订单未派单超时 2023-05-10 20:14:07 +08:00
Hawking 6013517d26 OrderDetail.deptId 为null,改用 OrderMaster.deptId 2023-05-10 14:11:54 +08:00
Hawking dd43a90d15 主单的update_time为null,改为用create_time判断超时 2023-05-10 14:01:36 +08:00
Hawking a500a5581d 主单超时逻辑 2023-05-09 19:53:44 +08:00
Hawking 5337178504 自动完单时主单状态错误 2023-05-09 11:05:27 +08:00
Hawking 24a5b2d44f 扣款罚金区分公司 2023-05-05 22:43:33 +08:00
Hawking 9982b95211 Customer自动提现 2023-05-05 18:04:58 +08:00
Hawking acf7a47be6 子单分账时抵扣超时罚金 2023-05-05 17:20:40 +08:00
kuang.yife 48986fd44a 旧超时状态暂时用limit 1限制,避免报错 2023-05-05 11:01:01 +08:00
kuang.yife ccf9a8bb61 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	ghy-payment/src/main/resources/mapper/financial/OrderFineRecordMapper.xml
2023-05-05 11:00:42 +08:00
kuang.yife 29588e68d2 旧超时状态暂时用limit 1限制,避免报错 2023-05-05 10:59:44 +08:00
Hawking 6b064b7fe1 Merge remote-tracking branch 'origin/master' 2023-05-05 10:12:34 +08:00
Hawking 2aaab088a6 订单超时与扣款记录 2023-05-05 10:12:23 +08:00
kuang.yife c25587ffb6 分界线退款文案修复 2023-05-05 00:42:18 +08:00
kuang.yife e5a7c1bb99 解决微信订阅号授权的问题 2023-05-04 23:20:47 +08:00
kuang.yife cd21ae9d17 时间判断。 2023-05-04 11:02:49 +08:00
kuang.yife 83754b9d2c 流程e+确认发起判断 2023-04-26 22:52:03 +08:00
kuang.yife bc24d8d243 修复支付切换微信的问题 2023-04-25 23:18:10 +08:00
Hawking 47533e40e0 主单分账时金额<=0判断 2023-04-25 01:00:39 +08:00
Hawking 132047104b 调整一下日志 2023-04-25 00:43:13 +08:00
Hawking 5976ab5c54 主单分账时金额<=0判断 2023-04-25 00:33:21 +08:00
Hawking d12f2f7eae Merge remote-tracking branch 'origin/master'
# Conflicts:
#	ghy-order/src/main/java/com/ghy/order/service/impl/OrderDetailServiceImpl.java
2023-04-25 00:25:14 +08:00
Hawking 7528ee8d28 分账失败不回滚主订单了 2023-04-25 00:24:45 +08:00
kuang.yife 8034d35fff 避免提现造成数据回滚 2023-04-25 00:14:34 +08:00
Hawking af4d4321fe 售后日志 2023-04-24 23:46:49 +08:00
Hawking d9e2a782ac 补偿提现定时器 2023-04-22 22:45:28 +08:00
Hawking 2e5ff5096c 分账总金额计算错误 2023-04-22 20:59:00 +08:00
Hawking c1b93ee051 主单无法自动完单分账的问题 2023-04-22 20:33:58 +08:00
Hawking 43aaede0b6 子单售后退错钱了 2023-04-20 23:05:22 +08:00
Hawking 5bd28dc039 分帐后也能同意退款,修改提示语 2023-04-20 22:44:10 +08:00
Hawking 777178cc45 分帐后也能同意退款,但是退款0元 2023-04-20 22:33:06 +08:00
Hawking 0a82851e2c 改支付状态 如果是已支付改退款中 如果是未支付改为取消 2023-04-20 21:50:41 +08:00
Hawking e2dfdd057e 未支付的订单可以取消,跳过退款 2023-04-20 21:40:22 +08:00
Hawking 2077230be3 未支付的订单可以取消,跳过退款 2023-04-20 21:04:53 +08:00
HH 67aaad5519 判断是否全部派单的逻辑改回 2023-04-20 11:58:33 +08:00
kuang.yife a72d302696 退款要判断是否是已付款的单 2023-04-20 10:40:12 +08:00
Hawking fb30737591 当客户申请退款大师傅手中所有金额时:
如果派了单给子师傅,就不全退。
如果没有派单给子师傅,就全退。
2023-04-20 00:49:09 +08:00
Hawking 8d3a159405 手机号去除空格 2023-04-19 22:53:53 +08:00
Hawking ceafb5526c Merge remote-tracking branch 'origin/master' 2023-04-19 22:37:32 +08:00
Hawking 439fecbff2 售后记录SQL错误 2023-04-19 22:37:25 +08:00
donqi 94852f198a Merge branch 'master' of https://gitee.com/op-souls/ghy-all 2023-04-19 22:35:16 +08:00
donqi 2aca501eaf 问题修复 2023-04-19 22:34:50 +08:00
Hawking 103b864df2 派单金额问题 2023-04-19 22:07:51 +08:00
365 changed files with 36269 additions and 2450 deletions

3
.gitignore vendored
View File

@ -33,4 +33,5 @@ build/
### VS Code ### ### VS Code ###
.vscode/ .vscode/
/logs/ /logs/
/ghy-admin/src/test/ /ghy-admin/src/test/
ghy-shop/ADDRESS_QUERY_EXAMPLE.md

View File

@ -0,0 +1,214 @@
<!-- @author Yifei.Kuang -->
# 房间 / 群 / 群员业务需求说明文档
## 一、项目背景与目标
- **背景**
在现有「师傅 / 商城 / 分销」体系上,引入「房间(圈子)+ 群 + 分销」的新结构,实现多房间、多群、多身份的精细化运营与监管。
- **目标**
- 建立清晰的层级结构:**平台 → 房间 → 群 → 群员/分销**。
- 统一分销身份规则,保证订单与佣金归属准确。
- 支持群主、房间主、下级分销、运营商等多角色协同。
- 为后续房间收费、群收费、群员收费等模式预留空间。
---
## 二、核心概念定义
### 2.1 平台
- 系统最上层运营主体,负责全局参数(平台扣点、结算规则等)。
### 2.2 房间(圈子)
- **定义**:平台下的独立运营空间,一个平台可创建多个房间。
- **特点**
- 房间名称:限制在 46 个字。
- 房间标识图片、品牌注解由房间主配置。
- 顶部功能栏:默认为「师傅库 / 商城 / 会话厅」,文字可改,总长度有限制但功能不变。
- 房间可配置自身的功能权限(是否开放商城、是否允许群选品等)以及扣点、收费策略。
- **关系**
- 「微社圈」是整体产品名,“切换圈子”即切换不同房间。
### 2.3 群(分销群)
- **定义**:隶属于某房间的运营群,每个房间下可以创建多个群。
- **建群要求**
- 填写城市、区域、主营品类、预期群规模等信息。
- 建群申请需由房间主及后台审核(形式类似现有分销申请)。
- **职责**
- 每个群经营自己的商品与客户。
- 群商城中仅群主有选品权限,下级分销不能选品。
### 2.4 群主
- 该群的最高级分销者。
- 新建群后自动成为本群顶级分销(无上级分销)。
- 负责本群的选品、群成员管理、群内规则等。
### 2.5 群员 / 分销人员
- 所有群员可根据既有三级分销规则绑定上级关系。
- **分销身份规则**
- 每个群员在「平台 + 房间 + 群」这一组合下有一个独立分销身份。
- 同一微信号在不同房间、不同群中,对系统而言是多个独立身份。
- **影响**
- 每个身份对应一条独立的分销线。
- 订单结算与分账都按所在群对应的分销线进行。
### 2.6 系统机器人 / 监管号
- 平台可在任意群中驻入一个“系统机器人”账号:
- 拥有类似群主的管理能力及后台监管能力。
- 用于监管群运营是否健康、是否违规。
### 2.7 运营商(按微信号)
- 以微信号为主体的运营视角。
- 同一微信号在多个房间、多个群中有多条分销线,但在运营统计中可统一聚合。
---
## 三、分销身份与订单归属规则
### 3.1 唯一身份线
- 每条分销身份线由四段组合定义:
**平台ID + 房间ID + 群ID + 用户ID**
- 每一条组合都被视为“系统中的一个人、一条分销线”。
### 3.2 多群多房间身份
- 同一微信号在不同房间/群中创建或加入时:
- 系统会为其生成新的分销身份线。
- 不同房间、群的身份互不影响。
### 3.3 分销绑定
- 在某群中被拉入的新成员:
- 按现有三级分销规则建立上下级关系。
- 上下级关系限定在本群对应的分销线中。
### 3.4 订单与分销归属
- 用户从某个群入口进入商城并下单:
- 所有分销与分账都按该群的分销线计算。
- 即使服务商在其他群也有身份,本订单仍只归属于当前群对应的身份线。
---
## 四、房间与群的前台结构
### 4.1 房间首页结构
- 房间头部展示:
- 房间头像/标识图;
- 品牌名称46 字);
- 简短品牌注解。
- 顶部功能栏:
- 默认入口为:「师傅库 / 商城 / 会话厅」。
- 房间主可修改这三个名称(总长度有限制),但功能含义不变。
- 顶部入口与底部导航对应,为功能快捷入口。
### 4.2 师傅库
- 展示本房间下已入驻的师傅与服务店铺。
- 支持按街道、服务品类筛选。
- 师傅资料在现有认证信息基础上增加头像和定位信息。
- 用户可在师傅详情中:
- 直接发起“发布订单”给该师傅;
- 或将已有未接订单指派给该师傅。
### 4.3 商城
- 房间/群共用一个商城体系:
- 房间级定义基础类目与商品池。
- 群主在此基础上为本群做选品配置。
- 首页默认展示热门服务类目,可左划展示其他商品类目。
- 列表支持按价格、评分、销量筛选。
- 商品销量按整条上架商品做统一统计。
### 4.4 会话厅
- 作为房间的首页使用:
- 展示全部群、自建群、已加入群、单聊会话等。
- 顶部菜单包含:申请房间、申请建群、搜索群、房间名称设置等入口。
- 与群聊页面不同,主要承载群列表与会话入口。
---
## 五、订单与发布相关需求(概要)
### 5.1 师傅端状态汇总
- 师傅端首页顶部使用黄条展示:
- 新订单数量;
- 未约订单数量;
- 待上门/待发货数量。
- 点击不同统计可跳转到对应订单列表。
### 5.2 发单入口
- 页面底部设置蓝色「+」按钮作为发布主单入口。
- 支持:
- 服务类/商品类发单;
- 选择到第 4 级类目,可多选;
- 将常用配置保存为模板。
- 支持代填发布,由专业师傅代填问题内容,客户补充地址、电话后提交。
### 5.3 保险规则(概念级)
- 发单时默认勾选“启用保险核查服务费”。
- 发单方需选择保险费用由谁承担:
- 服务费由发单方支付;
- 服务费在订单中扣除。
- 到付场景下,已产生的保险费用仍需保留,并可在后续订单中抵扣。
### 5.4 报价/加价模式(概念级)
- 在满足一定条件(报价模式或允许商家报价)时,显示“加价/报价”入口。
- 支持大厅主单、未约/未排/监控单、已接单主单进行报价。
- 客户最多可选择 3 家(特例 4 家)报价,确认后进入支付流程。
---
## 六、「我的」与运营统计(概念级)
- “我的”页面延用现有结构:
- 展示分销中心、订单、选品等信息。
- 运营统计以微信号为主体:
- 汇总展示多房间、多群的运营数据;
- 可按房间、群维度下钻查看。
---
## 七、商品与服务上架(概念级)
- 服务上架沿用当前规则。
- 商品上架需区分于服务:
- 针对库存、规格、展示方式做单独设计;
- 与服务上架在前台展示上明显区分。
---
## 八、后台与安全监管(概念级)
- 房间级管理:
- 房间创建与审核;
- 房间启用/禁用;
- 房间收费与扣点配置。
- 群级管理:
- 建群审核;
- 群启用/禁用;
- 群主调整;
- 系统机器人驻入/移除。
- 操作审计:
- 记录房间、群创建和重要参数修改,便于运营追溯。
---
**文档定位**:业务需求说明(偏产品视角)
**用途**:为后续详细设计与开发提供业务背景和规则依据

View File

@ -0,0 +1,285 @@
<!-- @author Yifei.Kuang -->
# 房间 / 群 / 分销功能说明文档(开发视角)
## 一、整体架构
- 层级结构:
- 平台 → 房间Room→ 群Group→ 群员 / 分销身份Distributor
- 身份核心:
- 每条分销身份由「平台 + 房间 + 群 + 用户」组合唯一确定,用于分销归属和订单结算。
---
## 二、房间模块Room
### 2.1 房间功能点
- 创建房间申请:
- 用户提交房间名称、头像、品牌注解等信息。
- 后台审核通过后,生成房间,并指定房间主。
- 房间信息维护:
- 房间主可编辑名称、头像、品牌注解。
- 房间顶部功能栏配置:
- 默认显示「师傅库 / 商城 / 会话厅」三项。
- 房间主可以修改显示文案(总字数受限),功能类型不变。
- 房间权限与扣点设置(后台):
- 是否开启本房间商城。
- 是否允许本房间下的群进行选品。
- 房间级扣点与收费策略配置。
- 房间切换:
- 同一微信可加入多个房间,通过「切换圈子」在不同房间间切换。
---
## 三、群模块Group
### 3.1 建群与审核
- 在某房间内,用户可发起建群申请。
- 填写群基础信息(城市、区域、主营类目、群规模等)。
- 审核流程:
- 房间主初审;
- 后台终审;
- 通过后创建群,申请人自动成为群主。
### 3.2 群基本操作
- 群信息维护:
- 群主可编辑群名、介绍、主营描述等。
- 群状态控制(后台):
- 支持群的启用/禁用;
- 禁用后,群内发单、接单、分销等操作关闭或受限。
- 群主变更:
- 后台可在必要时调整群主(例如违规处理)。
### 3.3 群监管
- 支持在任意群中驻入“系统机器人/系统监管号”:
- 具备基本群管理与后台数据采集、监控能力。
- 用于运营与风险控制。
---
## 四、群员 / 分销身份模块
### 4.1 分销身份规则
- 每个用户在某「平台 + 房间 + 群」组合下对应一个分销身份。
- 同一微信在不同房间/群中拥有多个独立身份:
- 每个身份有独立的分销链;
- 后台视为多个“人”。
### 4.2 加入群与分销绑定
- 成员加入群时:
- 若在该群下不存在分销身份,则系统为其创建一条新身份线。
- 按既有三级分销规则绑定上级分销。
- 上下级分销关系:
- 限定在当前群对应的分销线中,不跨群共享。
### 4.3 角色与权限(概念层)
- 群主:
- 本群最高级分销;
- 拥有选品、群配置、成员管理等高权限。
- 管理员:
- 由群主任命,可拥有部分管理能力(禁言、审核、公告等)。
- 普通分销/群员:
- 不能在群内进行选品;
- 可以拉人建立下级分销关系。
---
## 五、会话厅与群聊相关功能
### 5.1 订单页面导航(左侧)
- 导航栏包含 4 项:
- 资源库;
- 商品城;
- 会话厅;
- 附近圈动态。
- 群主可以:
- 修改导航名称(总字数有限制);
- 单独开放/禁用任一入口;
- 与外层房间首页的导航机制保持一致。
- 右下角「会话大厅」按钮:
- 进入群聊页面(中间页);
- 文案可改,群主/平台可控制是否可用。
### 5.2 资源库A
- 展示服务师傅资料与店铺:
- 格式类似现有“师傅圈”,但样式可定制。
- 群主可设置仅群内成员可见,或继承房间级展示。
- 提供发布入口,支持基于群选品的类目发单。
### 5.3 商品城B
- 群级商城展示逻辑:
- 与整体商城逻辑一致;
- 差异在于:群商城的选品由群主独立配置。
- 所有人看到的商品、类目等均来源于群主选品结果。
- 首页热门类目默认服务类,可左滑出商品类目列表。
- 列表筛选按价格、评分、销量进行。
- 销量统计按整条商品聚合,不再按规格拆分。
### 5.4 会话厅C
- 会话厅为“会话/订单流”页面,不是群聊页面。
- 默认进入订单页时落在该列:
- 支持上拉刷新;
- 承载订单、系统相关信息的流式展示。
### 5.5 附近圈动态D
- 展示商家图文动态的“公共圈子”区域:
- 默认名称为“附近圈动态”;
- 群主可以改名,但含义不变(商家圈/动态圈)。
### 5.6 会话大厅图与编辑订单E
- 页面中部展示“会话大厅相关图”:
- 使用会话大厅图的一部分放大,作为视觉入口。
- 支持进入“编辑订单/发单页”:
- 编辑后的订单可发至全群;
- 管理员可选择仅发送至单个客户。
---
## 六、群聊在线控制与刷新机制
### 6.1 在线人数限制
- 当群聊在线人数超过上限(群主/后台可配置):
- 群主与管理员不受上线限制,始终在线。
- 系统自动将部分成员标记为离线:
- 优先踢出近期未发言的成员;
- 该过程对成员前端为“默默离线”,不会强制踢出页面。
### 6.2 重新上线与刷新
- 被标记为离线的成员:
- 在输入框输入内容时,自动重新上线。
- 新进群但未发言的成员:
- 一段时间后,输入框变为“消息刷新”按钮;
- 点击后重新加载消息,并作为新上线行为。
- 在已超上线限制的状态下:
- 新进入成员默认离线;
- 需主动刷新或发言才开始拉取实时消息。
### 6.3 页面跳转与上线状态
- 在群聊中点击任何产品、品类跳转其他页面:
- 无论是否超限,都视为离线(停止实时连接)。
- 从商品/其他页面返回群聊页:
- 自动恢复为在线状态。
- 在商品页面点击“聊天”:
- 跳回群聊,并恢复在线。
---
## 七、会话厅顶部类目与选品关系
### 7.1 顶部类目区
- 顶部显示:
- 「全部」入口;
- 若干热门类目。
- 热门类目:
- 群主从本群的主营/重点品类中选定;
- 可对特别重要的类目打红点标记。
- 展示方式:
- 左右滑动;
- 每行最多 8 个类目,最多展示两行。
### 7.2 选品关系
- 群主 = 分销顶层:
- 群主在本群选品的结果,体现在“全部”和热门类目展示中。
- 群员:
- 无法直接在群内进行选品;
- 仅能浏览、转发商品并参与分销。
---
## 八、群内订单与全域订单
### 8.1 群内订单发起
- 在群聊页面可以通过以下方式生成群内订单:
- 使用专门的“群内订单发单入口”;
- 将当前输入框的文字通过快捷键转换为订单(跳转到发单确认页)。
- 生成的群内订单:
- 在群聊中以订单卡片形式展示;
- 提供“接单”按钮。
### 8.2 与专业版(师傅端)的联动
- 若群内发单时勾选“保险”等高级字段:
- 该订单将按专业版(师傅端)逻辑处理;
- 接单、保险、结算等均走专业端流程。
- 群主可配置:
- 群内订单是否仅允许本群服务人员接单;
- 或是否允许进入大厅,被所有专业师傅接单。
### 8.3 全域订单
- 群主可将部分群内订单开放到“全域订单池”:
- 其他群的服务商也能在“全域订单”中看到这些订单并接单。
- 展示限制:
- 在群页面或全域订单列表中:
- 只有服务商能看到具体金额;
- 普通消费者看不到金额。
### 8.4 订单生命周期(概念)
- 典型状态流:
- 已发单 → 待服务(需要填写上门时间)→ 已提交 → 已付款 → 已完成。
- 客户侧操作:
- 在“已提交”中查看支付方式并确认;
- 确认支付后进入“已付款”。
- 服务侧操作:
- 服务方确认“已收款,结单”,进入“已完成”。
### 8.5 纯发单群模式
- 对于“只发单、不聊天”的群:
- 群聊可以不保持实时连接;
- 用户仅在手动刷新时看到新订单;
- 群形态接近“单纯接单页面”,以降低系统实时成本。
---
## 九、「我的」与运营视角
- “我的”页面沿用现有商城结构:
- 包含分销中心、订单、选品等模块。
- 统计以微信号为主视角:
- 汇总展示该用户在不同房间、群中的运营情况;
- 可按房间、群进行明细下钻。
---
## 十、后台与审计(功能级)
- 房间管理:
- 房间申请审批;
- 房间启用/禁用;
- 房间级扣点/收费配置。
- 群管理:
- 建群申请审核;
- 群启用/禁用;
- 群主调整;
- 系统机器人驻入/移除。
- 审计日志:
- 创建/修改房间、群;
- 修改扣点与重要配置;
- 关键权限调整(如群主、管理员变更)等操作均需记录。
---
**文档定位**:开发可读的功能说明(不含字段/接口细节)
**用途**:指导后续接口设计、表结构设计与前后端实现拆分

View File

@ -0,0 +1,299 @@
# 群成员身份标签与权限管理功能文档
## 文档说明
本文档描述群聊中**群成员身份标签、分类管理、权限控制、消息通知**相关的功能逻辑,不涉及字段/表结构设计,仅面向功能实现。
---
## 一、群成员身份标签系统
### 1.1 身份标签类型
系统支持以下身份标签:
- **创建者**:群创建者(通常也是群主)
- **管理员**:被群主任命的管理员
- **服务商家**:提供服务的商家/师傅
- **商品商家**:提供商品的商家
- **消费者**:普通消费者
- **发单人**:经常发单的用户
- **接单人**:经常接单的用户
- **群成员**:普通群成员
- **VIP客户**VIP客户
### 1.2 标签分配流程
- **入群时自选标签**
- 用户加入群时,系统提供两个初始选项:
- **非商家**
- **商家**
- 用户选择一个作为初始身份标识。
- **群主/管理员最终确认**
- 群主或管理员可以在群成员资料中:
- 查看用户自选的标签。
- 从系统标签库中选择一个标签,覆盖或确认用户的标签。
- 后续可以随时修改成员的标签。
- **标签对外展示**
- 标签会显示在群成员资料、群成员列表等位置,作为该成员在群内的“对外身份”。
### 1.3 群成员资料栏位
- **群成员资料页包含7个栏位**
- 每个栏位可以放置一个名称/备注。
- 这些栏位对所有身份/标签的群员都开放使用。
- 用途:方便所有群员查看和识别成员信息。
---
## 二、群成员分类/分组系统
### 2.1 分类概念
- **分类定义**
- 群内成员可以按照“分类”进行组织,每个分类可以理解为“分组”或“分仓”。
- 系统支持创建 **1~7个分类**
- 每个分类可以自定义命名例如“1类”、“2类”或自定义别名如“核心商家组”、“普通客户组”等
- **分类与标签的关系**
- 分类与身份标签是**独立的两套体系**
- 一个成员可以拥有一个身份标签(如“服务商家”)。
- 同时该成员可以被放入任意一个分类中如“1类”
- 标签不影响分类归属,分类也不影响标签展示。
### 2.2 分类操作
- **成员分类归属**
- 任何成员可以被放入任意一个分类中。
- 例如可以将某个“服务商家”放入“1类”也可以将某个“消费者”放入“1类”。
- 成员可以只属于一个分类,也可以不属于任何分类(显示在“未分类”或“全部”中)。
- **按分类查看成员**
- 群主与管理员可以:
- 按分类查看成员列表。
- 按标签查看成员列表。
- 按“分类+标签”组合筛选查看。
- **普通群成员查看**
- 普通群成员在群名单中:
- 可以按“全部”及“标签身份”查看成员信息。
- 不能按分类查看(分类信息对普通成员不展示)。
### 2.3 分类消息发送
- **管理员按分类发消息**
- 管理员可以:
- 选择向某个分类的所有成员发送消息(其他分类看不到)。
- 选择向某个分类中的单个成员发送消息。
- 用途:主要用于群管理员进行精细化运营和定向通知。
---
## 三、管理员任命与权限体系
### 3.1 管理员任命
- **任命流程**
- 群主可以任命任意群成员为管理员。
- 任命时可以:
- 标注该管理员的“岗位名称”(例如“客服主管”、“运营专员”等)。
- 有岗位名称的管理员会在“服务团队消息专列”中显示。
- **订单交付权限(独立于管理员)**
- 订单交付栏的权限与管理员身份独立:
- 群主可以勾选某些成员(不一定是管理员)拥有“订单交付权限”。
- 拥有交付权限的人可以在订单交付栏中发布交付信息。
### 3.2 管理员权限列表
群主在任命管理员时,可以勾选该管理员拥有的权限项。管理员在哪个分类中不影响其权限范围。
#### 权限1按类发群信息
- 管理员可以向指定分类的所有成员发送群消息(其他分类看不到)。
#### 权限2禁言与消息可见性控制
- **禁言功能(实际为“审核可见”)**
- 管理员可以按分类或单个成员设置“禁言”。
- 被禁言的成员:
- 仍然可以发送消息,但消息默认**仅管理员可见 + 自己可见**。
- 管理员可以在后台审核这些消息,勾选后才会展示到群聊页面。
- 严格来说这不是传统“禁言”,而是“审核可见”机制。
- **消息可见性设置**
- 管理员可以:
- 按分类设置:该类群员发的消息仅该类成员可见,或仅管理员可见。
- 按单个成员设置:该成员发的消息仅管理员可见(在群内形成独立通道,对其他人无感)。
- **特殊规则**
- 被禁言的成员仍然可以发送商品链接到群(商品链接不受禁言限制)。
- 管理员查看消息的规则:
- 如果管理员属于某个分类,只能看到该类群员发的信息。
- 如果管理员在“全部”分类中,可以看到所有分类群员发的信息。
- **管理员@解禁**
- 管理员可以@被禁言的成员临时解禁3小时。
#### 权限3禁止接单
- 管理员可以按分类或单个成员设置“禁止点击接单键”。
- 被禁止的成员无法接取群消息中的订单。
#### 权限4禁止发单
- 管理员可以按分类或单个成员设置“禁止点击发单键”。
- 被禁止的成员无法使用发单功能(包括类目发单)。
#### 权限5禁止互加好友
- 管理员可以按分类或单个成员设置“禁止互加好友”。
- 被禁止的成员:
- 别人无法添加他为好友。
- 他也无法添加别人为好友。
- **特殊规则**
- 即使被禁止加好友,双方仍然可以:
- 在服务团队聊天中直接对话(通过服务团队入口)。
#### 权限6屏蔽群内信息
- 管理员可以按分类或单个成员设置“屏蔽群内信息”。
- 被屏蔽的成员:
- 看不到群内在发的消息。
- **但订单仍然可见可接**(屏蔽消息,不屏蔽订单展示)。
#### 权限7禁止发圈信息
- 管理员可以按分类或单个成员设置“禁止发圈信息”。
- 被禁止的成员无法在商家圈/动态圈中发布内容。
#### 权限8审核成员入群
- 管理员可以审核新成员的入群申请。
#### 权限9删除成员与撤回消息
- 管理员可以:
- 删除群成员(将成员移出群)。
- 撤回群成员的消息:
- 可以撤回任意成员的一条消息。
- 可以彻底删除消息(删除后不可见,不可恢复)。
#### 权限10分类分标签发公告
- 管理员可以:
- 按分类发送公告。
- 按标签发送公告。
- 按“分类+标签”组合发送公告。
---
## 四、群主专属权限
### 4.1 群名设置
- 群主可以修改群名称。
### 4.2 群转让
- 群主可以将群主身份转让给其他成员。
### 4.3 开通入群申请
- 群主可以开启/关闭“入群申请”功能。
- 开启后,新成员需要申请才能加入群。
### 4.4 待接单显示规则(待定)
- 群主可以设置“待接单是否仅显示本群的订单”(此功能待定,可能不实现)。
---
## 五、群消息通知机制
### 5.1 消息通知基础规则
#### 未打开登录页面的通知策略
- 用户未打开登录页面APP未打开
- 系统每 **5分钟** 聚合一次新消息,发送一条通知。
- 通知内容显示所有群的新消息汇总例如“您有X条新消息”
- 用户打开APP后不再发送聚合通知。
#### 群外消息计数
- 在群列表页面(群外):
- 每个群名旁边显示该群的消息数量角标。
- APP端统一使用角标显示。
### 5.2 群消息免打扰设置
#### 免打扰选项
每个群成员可以为自己设置该群的“免打扰”策略,选项包括:
- **仅1小时1条**1小时内只通知一次。
- **仅1天1条**1天内只通知一次。
- **仅3天1条**3天内只通知一次。
- **仅10天1条**10天内只通知一次。
#### 免打扰与通知队列的关系
- 系统维护多个通知队列:
- **5分钟通知队列**默认队列每5分钟通知一次。
- **1小时通知队列**设置了“1小时1条”的用户进入此队列。
- **1天通知队列**设置了“1天1条”的用户进入此队列。
- **3天通知队列**设置了“3天1条”的用户进入此队列。
- **10天通知队列**设置了“10天1条”的用户进入此队列。
- 用户设置免打扰后:
- 从“5分钟队列”中剔除进入对应的免打扰队列。
- 例如设置“1小时1条”后每1小时聚合通知一次而不是每5分钟
#### 通知时间窗口
- **5分钟队列与1小时队列**
- 晚上7点后不通知。
- 早上8点后才开始通知。
- **1天队列、3天队列、10天队列**
- 通知时间点可以设定在12点或错开时间点例如1天队列12点3天队列14点10天队列16点以减少大量通知同时推送。
#### 用户类型与免打扰选择
- **经营者(商家/师傅)**
- 更多选择“5分钟通知”或“1小时通知”需要及时响应
- **客户(消费者)**
- 更多选择“3天通知”或“10天通知”降低打扰频率
### 5.3 @通知机制
#### @通知规则
- **无论用户是否设置免打扰**,被@时:
- 使用**手机上方消息栏**直接通知(不进入队列等待)。
- 通知带有声音提醒(用户可以自定义声音)。
- 不等待5分钟/1小时等时间窗口立即推送。
#### @通知展示位置
- @通知显示在手机顶部通知栏(系统级通知)。
---
## 六、消息通知总结
### 6.1 通知队列体系
系统维护以下通知队列:
1. **5分钟通知队列**(默认)
- 时间窗口早上8点 ~ 晚上7点。
- 每5分钟聚合通知一次。
2. **1小时通知队列**
- 时间窗口早上8点 ~ 晚上7点。
- 每1小时聚合通知一次。
3. **1天通知队列**
- 在指定时间点例如12点通知一次。
4. **3天通知队列**
- 在指定时间点例如14点通知一次。
5. **10天通知队列**
- 在指定时间点例如16点通知一次。
### 6.2 特殊通知(不受队列限制)
- **@通知**
- 立即推送,使用手机顶部通知栏。
- 带声音提醒。
- 不受免打扰设置影响。
### 6.3 通知聚合规则
- **未打开APP时**
- 所有群的新消息统一聚合为一条通知例如“您有X条新消息”
- 按用户所属队列的时间窗口进行通知。
- **打开APP后**
- 不再发送聚合通知。
- 用户可以在APP内查看各群的具体消息。
---
## 七、功能总结
### 7.1 身份标签与分类
- 9种身份标签入群时自选群主/管理员可最终确认和修改。
- 支持1~7个分类分类与标签独立成员可被放入任意分类。
### 7.2 管理员权限
- 10个权限点群主可灵活配置每个管理员的权限。
- 订单交付权限独立于管理员身份。
### 7.3 消息通知
- 5个通知队列5分钟/1小时/1天/3天/10天用户可自由选择。
- @通知立即推送,不受免打扰影响。
- 时间窗口控制,避免夜间打扰。
---
## 八、待定事项
- 待接单是否仅显示本群的订单(功能待定)。
---
**文档版本**v1.0
**最后更新**2024年

View File

@ -17,6 +17,38 @@
<dependencies> <dependencies>
<dependency>
<groupId>com.tencentcloudapi.cls</groupId>
<artifactId>tencentcloud-cls-logback-appender</artifactId>
<version>1.0.3</version>
</dependency>
<!-- 阿里云api-SDK -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dytnsapi20200217</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-openapi</artifactId>
<version>0.3.6</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-console</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>tea-util</artifactId>
<version>0.2.23</version>
</dependency>
<!-- SpringBoot集成thymeleaf模板 --> <!-- SpringBoot集成thymeleaf模板 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -111,6 +143,10 @@
<artifactId>spring-test</artifactId> <artifactId>spring-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.ghy</groupId>
<artifactId>ghy-shop</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@ -4,13 +4,18 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/** /**
* 启动程序 * 启动程序
* *
* @author clunt * @author clunt
*/ */
@EnableScheduling
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
public class GhyApplication public class GhyApplication
{ {
@ -34,4 +39,25 @@ public class GhyApplication
public RestTemplate restTemplate(){ public RestTemplate restTemplate(){
return new RestTemplate(); return new RestTemplate();
} }
private CorsConfiguration corsConfig() {
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 请求常用的三种配置*代表允许所有当时你也可以自定义属性比如header只能带什么只能是post方式等等
// corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOriginPattern("*");
corsConfiguration.setMaxAge(3600L);
return corsConfiguration;
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig());
return new CorsFilter(source);
}
} }

View File

@ -7,21 +7,27 @@ import com.ghy.common.adapay.model.Event;
import com.ghy.common.adapay.model.PayCallback; import com.ghy.common.adapay.model.PayCallback;
import com.ghy.common.adapay.model.PaymentDTO; import com.ghy.common.adapay.model.PaymentDTO;
import com.ghy.common.enums.PayStatus; import com.ghy.common.enums.PayStatus;
import com.ghy.order.domain.OrderAddSubtract;
import com.ghy.order.domain.OrderMaster;
import com.ghy.order.mapper.OrderMasterMapper;
import com.ghy.order.service.IOrderAddSubtractService;
import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialChangeRecord; import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialDetail; import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster; import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.domain.PaymentRelation;
import com.ghy.payment.mapper.PaymentRelationMapper;
import com.ghy.payment.service.CallBackService; import com.ghy.payment.service.CallBackService;
import com.ghy.payment.service.FinancialChangeRecordService; import com.ghy.payment.service.FinancialChangeRecordService;
import com.ghy.payment.service.FinancialDetailService; import com.ghy.payment.service.FinancialDetailService;
import com.ghy.payment.service.FinancialMasterService; import com.ghy.payment.service.FinancialMasterService;
import org.slf4j.Logger; import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
/** /**
@ -29,98 +35,160 @@ import java.util.concurrent.CompletableFuture;
* *
* @author HH 2022/5/31 * @author HH 2022/5/31
*/ */
@Slf4j
@Service("payCallbackService") @Service("payCallbackService")
public class PayCallbackService implements CallBackService { public class PayCallbackService implements CallBackService {
private static final Logger logger = LoggerFactory.getLogger(PayCallbackService.class); @Resource
OrderMasterService orderMasterService;
@Resource @Resource
FinancialMasterService financialMasterService; FinancialMasterService financialMasterService;
@Resource
PaymentRelationMapper paymentRelationMapper;
@Resource @Resource
FinancialDetailService financialDetailService; FinancialDetailService financialDetailService;
@Resource
IOrderAddSubtractService orderAddSubtractService;
@Resource @Resource
FinancialChangeRecordService financialChangeRecordService; FinancialChangeRecordService financialChangeRecordService;
@Override @Override
@Transactional(rollbackFor = Exception.class)
public void onCallback(Event event) { public void onCallback(Event event) {
logger.info("支付回调: {}", event); log.info("支付回调: {}", event);
String data = event.getData(); String data = event.getData();
PayCallback payment = JSON.parseObject(data, PayCallback.class); PayCallback payment = JSON.parseObject(data, PayCallback.class);
PaymentDTO dto = financialMasterService.selectPaymentById(payment.getId()); PaymentDTO dto = financialMasterService.selectPaymentById(payment.getId());
// 校验是否是本系统发出去的支付请求 // 支付ID
if (dto != null) { final String paymentId = dto.getId();
CompletableFuture.runAsync(() -> { // 是否支付成功
// 异步更新交易记录 避免被回滚 final boolean succeeded = AdapayStatusEnum.succeeded.code.equals(payment.getStatus());
PaymentDTO param = new PaymentDTO();
param.setId(payment.getId()); // 异步更新交易记录 避免被其它业务异常回滚
CompletableFuture.runAsync(() -> {
PaymentDTO param = new PaymentDTO();
param.setId(payment.getId());
param.setStatus(payment.getStatus());
if (succeeded) {
// 如果支付成功 更新支付渠道支付时间手续费
param.setPayChannel(payment.getPayChannel());
param.setFeeAmt(payment.getFeeAmt()); param.setFeeAmt(payment.getFeeAmt());
param.setStatus(payment.getStatus());
param.setPayTime(LocalDateTime.now()); param.setPayTime(LocalDateTime.now());
financialMasterService.updatePayment(param); if ("delay".equals(dto.getPayMode())) {
}); // 如果支付成功 且是延迟分账模式 更新可用金额=交易金额
if (AdapayStatusEnum.succeeded.code.equals(payment.getStatus())) { param.setAvailableAmt(dto.getPayAmt());
if (payment.getOrderNo().split("_").length > 2) { }
// 支付回调中的加价记录ID }
String fcrIdStr = payment.getOrderNo().split("_")[1]; financialMasterService.updatePayment(param);
String[] fcrIds = fcrIdStr.split(","); });
BigDecimal totalChangeMoney = BigDecimal.ZERO; if (succeeded) {
Long financialMasterId = null; // 支付成功 查询支付关联的订单
for (String fcrId : fcrIds) { List<PaymentRelation> paymentRelations = paymentRelationMapper.selectByPaymentId(paymentId);
FinancialChangeRecord financialChangeRecord = new FinancialChangeRecord(); if (CollectionUtils.isEmpty(paymentRelations)) {
financialChangeRecord.setId(Long.valueOf(fcrId)); log.error("未关联订单的支付回调: {}", data);
financialChangeRecord.setPayStatus(1); return;
// 加价的支付paymentId回填到remark }
financialChangeRecord.setRemark(payment.getId());
financialChangeRecord.setRemark(payment.getId());
financialChangeRecord.setPaymentId(payment.getId());
financialChangeRecordService.update(financialChangeRecord);
// 修改子订单的payMoney for (PaymentRelation relation : paymentRelations) {
FinancialChangeRecord fc = financialChangeRecordService.selectFinancialChangeRecordById(financialChangeRecord.getId()); Long relationId = relation.getRelationId();
FinancialDetail financialDetail = financialDetailService.selectByOrderDetailId(fc.getOrderDetailId()); if (PaymentRelation.FINANCIAL_MASTER.equals(relation.getRelationIdType())) {
FinancialDetail financialDetail2Update = new FinancialDetail(); FinancialMaster financialMaster = financialMasterService.selectById(relationId);
financialDetail2Update.setId(financialDetail.getId()); // 更新主订单的支付信息
financialDetail2Update.setPayMoney(financialDetail.getPayMoney().add(fc.getChangeMoney())); orderMasterService.updatePayStatus(financialMaster.getOrderMasterId(), PayStatus.PAID.getCode());
financialDetail2Update.setPayStatus(PayStatus.PAID.getCode()); // 更新主财务单的支付信息
financialDetailService.updateFinancialDetail(financialDetail2Update); financialMasterService.updatePay(relationId, paymentId, PayStatus.PAID.getCode());
totalChangeMoney = totalChangeMoney.add(fc.getChangeMoney()); log.info("主财务单[{}]支付成功", relationId);
if (financialMasterId == null) {
financialMasterId = financialDetail.getFinancialMasterId(); // 检查是否为商品订单且有关联的服务订单需要同步更新服务订单财务主单支付状态
try {
OrderMaster orderMaster = orderMasterService.selectById(financialMaster.getOrderMasterId());
if (orderMaster != null && orderMaster.getOrderType() == 1 && orderMaster.getHasServiceOrder() == 1) {
// 查询关联的服务订单
OrderMaster serviceOrder = orderMasterService.selectByGoodsOrderMasterId(orderMaster.getId());
if (serviceOrder != null) {
// 查询服务订单对应的财务主单
FinancialMaster serviceFinancialMaster = financialMasterService.selectByOrderMasterId(serviceOrder.getId());
if (serviceFinancialMaster != null && !PayStatus.PAID.getCode().equals(serviceFinancialMaster.getPayStatus())) {
// 更新服务订单财务主单支付状态
financialMasterService.updatePay(serviceFinancialMaster.getId(), paymentId, PayStatus.PAID.getCode());
// 更新服务订单支付状态
orderMasterService.updatePayStatus(serviceOrder.getId(), PayStatus.PAID.getCode());
log.info("商品订单[{}]关联的服务订单[{}]财务主单[{}]支付状态已同步更新为已支付",
orderMaster.getId(), serviceOrder.getId(), serviceFinancialMaster.getId());
}
}
} }
} catch (Exception e) {
log.error("同步更新商品订单关联服务订单支付状态时发生异常商品订单ID: {}, 异常信息: {}",
financialMaster.getOrderMasterId(), e.getMessage(), e);
} }
} else if (PaymentRelation.FINANCIAL_CHANGE.equals(relation.getRelationIdType())) {
// 更新加价单的支付信息
financialChangeRecordService.updatePay(relationId, paymentId, PayStatus.PAID.getCode());
FinancialChangeRecord fc = financialChangeRecordService.selectFinancialChangeRecordById(relationId);
// 修改子订单的payMoney
FinancialDetail fd = financialDetailService.selectByOrderDetailId(fc.getOrderDetailId());
FinancialDetail fd2Update = new FinancialDetail();
fd2Update.setId(fd.getId());
fd2Update.setPayMoney(fd.getPayMoney());
fd2Update.setPayStatus(PayStatus.PAID.getCode());
financialDetailService.updateFinancialDetail(fd2Update);
// 修改主单的payMoney // 修改主单的payMoney
FinancialMaster financialMaster = financialMasterService.selectById(financialMasterId); FinancialMaster financialMaster = financialMasterService.selectById(fd.getFinancialMasterId());
FinancialMaster financialMaster2Update = new FinancialMaster(); FinancialMaster financialMaster2Update = new FinancialMaster();
financialMaster2Update.setId(financialMaster.getId()); financialMaster2Update.setId(financialMaster.getId());
financialMaster2Update.setPayMoney(financialMaster.getPayMoney().add(totalChangeMoney)); financialMaster2Update.setPayMoney(financialMaster.getPayMoney());
financialMaster2Update.setPayStatus(PayStatus.PAID.getCode()); financialMaster2Update.setPayStatus(PayStatus.PAID.getCode());
financialMasterService.updateFinancialMaster(financialMaster2Update); financialMasterService.updateFinancialMaster(financialMaster2Update);
// TODO 拆分对应的分账流水 // 更新主订单的支付信息
orderMasterService.updatePayStatus(financialMaster.getOrderMasterId(), PayStatus.PAID.getCode());
log.info("FinancialChange[{}]支付成功", relationId);
} else if (PaymentRelation.ORDER_ADD.equals(relation.getRelationIdType())) {
// 更新订单追加单的支付信息
orderAddSubtractService.updatePay(relationId, paymentId, PayStatus.PAID.getCode());
OrderAddSubtract orderAdd = orderAddSubtractService.selectById(relationId);
// 修改子订单的payMoney
FinancialDetail fd = financialDetailService.selectByOrderDetailId(orderAdd.getOrderDetailId());
FinancialDetail fd2Update = new FinancialDetail();
fd2Update.setId(fd.getId());
fd2Update.setPayMoney(fd.getPayMoney());
fd2Update.setPayStatus(PayStatus.PAID.getCode());
financialDetailService.updateFinancialDetail(fd2Update);
// 修改主单的payMoney
FinancialMaster financialMaster = financialMasterService.selectById(fd.getFinancialMasterId());
FinancialMaster financialMaster2Update = new FinancialMaster();
financialMaster2Update.setId(financialMaster.getId());
financialMaster2Update.setPayMoney(financialMaster.getPayMoney());
financialMaster2Update.setPayStatus(PayStatus.PAID.getCode());
financialMasterService.updateFinancialMaster(financialMaster2Update);
log.info("订单追加[{}]支付成功", relationId);
} else if (PaymentRelation.CONSULT_ADD.equals(relation.getRelationIdType())) {
// 更新加价单的支付信息
financialChangeRecordService.updatePay(relationId, paymentId, PayStatus.PAID.getCode());
} else {
log.error("未知的订单类型: relationIdType={}, relationId={}", relation.getRelationIdType(), relationId);
} }
// 更新主财务单状态
financialMasterService.paySucceeded(payment.getId(), payment.getPayChannel());
} else {
logger.warn("支付失败 : {}", data);
} }
} else {
logger.warn("系统中不存在这条交易记录: {}", event);
} }
} }
@Override @Override
public void onResponse(JSONObject response) { public void onResponse(JSONObject response) {
logger.info("发起支付 Response: {}", response.toJSONString()); log.info("发起支付 Response: {}", response.toJSONString());
// 保存一条支付记录 // 保存一条支付记录
PaymentDTO payment = response.toJavaObject(PaymentDTO.class); PaymentDTO payment = response.toJavaObject(PaymentDTO.class);
String status = payment.getStatus(); String status = payment.getStatus();
payment.setStatus(AdapayStatusEnum.pending.code);
financialMasterService.insertPayment(payment); financialMasterService.insertPayment(payment);
if (!AdapayStatusEnum.succeeded.code.equals(status)) { if (!AdapayStatusEnum.succeeded.code.equals(status)) {
logger.warn("发起支付失败 : {}", response.toJSONString()); log.warn("发起支付失败 : {}", response.toJSONString());
} }
} }

View File

@ -0,0 +1,66 @@
package com.ghy.callback;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.adapay.model.Event;
import com.ghy.common.adapay.model.PaymentDTO;
import com.ghy.common.utils.MoneyUtil;
import com.ghy.payment.domain.PaymentConfirm;
import com.ghy.payment.mapper.PaymentConfirmMapper;
import com.ghy.payment.mapper.PaymentMapper;
import com.ghy.payment.service.CallBackService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
@Service("paymentConfirmCallbackService")
public class PaymentConfirmCallbackService implements CallBackService {
@Resource
private PaymentMapper paymentMapper;
@Resource
private PaymentConfirmMapper paymentConfirmMapper;
@Override
public void onCallback(Event event) {
// 支付确认没有callback
}
@Override
public void onResponse(JSONObject response) {
if (AdapayStatusEnum.succeeded.code.equals(response.getString("status")) ||
AdapayStatusEnum.pending.code.equals(response.getString("status"))) {
// 支付确认 操作成功
PaymentConfirm paymentConfirm = response.toJavaObject(PaymentConfirm.class);
// 保存支付确认记录
paymentConfirmMapper.insert(paymentConfirm);
// 更新支付单信息
updatePayment(paymentConfirm);
}
}
private synchronized void updatePayment(PaymentConfirm paymentConfirm) {
String paymentId = paymentConfirm.getPaymentId();
PaymentDTO payment = paymentMapper.selectById(paymentId);
// 支付金额
BigDecimal payAmt = new BigDecimal(payment.getPayAmt());
// 已确认金额
BigDecimal confirmedAmt = new BigDecimal(paymentConfirm.getConfirmedAmt());
// 已退款金额
BigDecimal refundedAmt = new BigDecimal(paymentConfirm.getRefundedAmt());
// 已撤销金额
BigDecimal reservedAmt = new BigDecimal(paymentConfirm.getReservedAmt());
// 可支配金额 = 支付金额 - 已确认金额 - 已退款金额 - 已撤销金额
BigDecimal availableAmt = payAmt.subtract(confirmedAmt).subtract(refundedAmt).subtract(reservedAmt);
// 更新支付单信息
PaymentDTO payment2up = new PaymentDTO();
payment2up.setId(paymentId);
payment2up.setConfirmedAmt(paymentConfirm.getConfirmedAmt());
payment2up.setRefundedAmt(paymentConfirm.getRefundedAmt());
payment2up.setReservedAmt(paymentConfirm.getReservedAmt());
payment2up.setAvailableAmt(MoneyUtil.toS(availableAmt));
paymentMapper.updatePayment(payment2up);
}
}

View File

@ -0,0 +1,44 @@
package com.ghy.web.controller;
import com.ghy.common.dto.DataEntityDTO;
import com.ghy.common.enums.WxMsgEnum;
import com.ghy.common.utils.WechatMsgUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author 但星霖
* @Date 2023-09-28 104256
* 说明
*/
@RestController
@RequestMapping("/mesg/test")
public class MesgTestController {
@GetMapping("/{openId}")
public void edit(@PathVariable("openId") String openId){
try {
// 消息组装
Map<String, Object> paramsNew = new HashMap<>();
// 订单编号
paramsNew.put("character_string1", new DataEntityDTO("12312"));
// 名称
paramsNew.put("thing2", new DataEntityDTO("订单被拒通知"));
// 预约时间
paramsNew.put("data8", new DataEntityDTO(com.ghy.common.utils.DateUtils.parseDateToStr("yyyy年MM月dd日 HH:mm", new Date())));
// 师傅姓名
paramsNew.put("name3", new DataEntityDTO("测试"));
// 服务区域
paramsNew.put("thing4", new DataEntityDTO("成都市"));
// 消息推送
WechatMsgUtils.sendWeChatMsg(WechatMsgUtils.getToken(), openId, WxMsgEnum.TEXT, paramsNew);
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,576 @@
package com.ghy.web.controller;
import com.ghy.common.core.controller.BaseController;
import com.ghy.shop.domain.Shop;
import com.ghy.shop.domain.ShopDistanceQuery;
import com.ghy.shop.service.ShopService;
import com.ghy.common.core.domain.AjaxResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.client.RestTemplate;
import com.ghy.common.utils.LocationUtils;
import java.util.stream.Collectors;
import java.util.Comparator;
/**
* 店铺管理接口
*/
@RestController
@RequestMapping("/shop")
public class ShopController extends BaseController {
@Autowired
private ShopService shopService;
@Autowired
private RestTemplate restTemplate;
@PostMapping("/add")
public AjaxResult addShop(@RequestBody Shop shop) {
// 如果没有经纬度尝试通过地址解析获取
if ((shop.getLatitude() == null || shop.getLongitude() == null) &&
shop.getAddress() != null && !shop.getAddress().trim().isEmpty()) {
try {
Map<String, Double> coordinates = getCoordinatesByAddress(shop);
if (coordinates != null) {
shop.setLatitude(coordinates.get("latitude"));
shop.setLongitude(coordinates.get("longitude"));
logger.info("为店铺[{}]自动获取到坐标: 经度={}, 纬度={}",
shop.getShopName(), shop.getLongitude(), shop.getLatitude());
}
} catch (Exception e) {
logger.warn("获取地址经纬度失败: {}", e.getMessage());
}
}
int result = shopService.addShop(shop);
if (result > 0) {
Map<String, Object> response = new HashMap<>();
response.put("shopId", shop.getShopId());
response.put("shopName", shop.getShopName());
response.put("latitude", shop.getLatitude());
response.put("longitude", shop.getLongitude());
response.put("address", shop.getAddress());
return AjaxResult.success("店铺创建成功", response);
} else {
return AjaxResult.error("店铺创建失败");
}
}
@GetMapping("/list")
public AjaxResult listShops() {
List<Shop> list = shopService.listShops();
return AjaxResult.success(list);
}
@GetMapping("/{id}")
public AjaxResult getShop(@PathVariable Long id) {
Shop shop = shopService.getShop(id);
return shop != null ? AjaxResult.success(shop) : AjaxResult.error("未找到店铺");
}
@PostMapping("/update")
public AjaxResult updateShop(@RequestBody Shop shop) {
// 如果没有经纬度但有地址尝试通过地址解析获取经纬度
if ((shop.getLatitude() == null || shop.getLongitude() == null) &&
shop.getAddress() != null && !shop.getAddress().trim().isEmpty()) {
try {
Map<String, Double> coordinates = getCoordinatesByAddress(shop);
if (coordinates != null) {
shop.setLatitude(coordinates.get("latitude"));
shop.setLongitude(coordinates.get("longitude"));
}
} catch (Exception e) {
logger.warn("更新店铺时获取地址经纬度失败: {}", e.getMessage());
}
}
return toAjax(shopService.updateShop(shop));
}
@PostMapping("/delete/{id}")
public AjaxResult deleteShop(@PathVariable Long id) {
return toAjax(shopService.deleteShop(id));
}
@GetMapping("/{id}/location")
public AjaxResult getShopLocation(@PathVariable Long id) {
Shop shop = shopService.getShop(id);
if (shop == null) {
return AjaxResult.error("未找到店铺");
}
Map<String, Object> location = new HashMap<>();
location.put("address", shop.getAddress());
location.put("latitude", shop.getLatitude());
location.put("longitude", shop.getLongitude());
location.put("provinceName", shop.getProvinceName());
location.put("cityName", shop.getCityName());
location.put("countryName", shop.getCountryName());
location.put("streetName", shop.getStreetName());
return AjaxResult.success(location);
}
// @GetMapping("/getCurrentLocation")
// public AjaxResult getCurrentLocation() {
// try {
// // 直接调用百度地图API获取当前位置信息
// String url = "/tool/baidu/getLocation";
// return restTemplate.getForObject(url, AjaxResult.class);
// } catch (Exception e) {
// return AjaxResult.error("获取当前位置失败:" + e.getMessage());
// }
// }
@GetMapping("/worker/{workerId}")
public AjaxResult getShopsByWorkerId(@PathVariable Long workerId) {
List<Shop> shops = shopService.getShopsByWorkerId(workerId);
return AjaxResult.success(shops);
}
// /**
// * 通过地址获取经纬度坐标
// */
// @PostMapping("/getCoordinates")
// public AjaxResult getCoordinatesByAddress(@RequestBody Shop shop) {
// try {
// Map<String, Double> coordinates = getCoordinatesByAddress(shop);
// if (coordinates != null) {
// return AjaxResult.success("获取坐标成功", coordinates);
// } else {
// return AjaxResult.error("无法获取该地址的坐标信息");
// }
// } catch (Exception e) {
// logger.error("获取坐标失败: {}", e.getMessage(), e);
// return AjaxResult.error("获取坐标失败: " + e.getMessage());
// }
// }
/**
* 通过经纬度逆解析获取地址信息并保存到店铺
*/
@PostMapping("/saveShopByLocation")
public AjaxResult saveShopByLocation(@RequestBody Map<String, Object> params) {
try {
String location = params.get("location").toString(); // 格式: "经度,纬度"
// 调用百度地图逆解析API
String url = "/tool/baidu/getLocation";
Map<String, String> requestBody = new HashMap<>();
requestBody.put("location", location);
// 这里应该调用百度接口获取地址信息
// AjaxResult locationResult = restTemplate.postForObject(url, requestBody, AjaxResult.class);
// 解析经纬度
String[] coordinates = location.split(",");
if (coordinates.length != 2) {
return AjaxResult.error("location格式错误应为经度,纬度");
}
Double longitude = Double.parseDouble(coordinates[0]);
Double latitude = Double.parseDouble(coordinates[1]);
// 创建店铺对象
Shop shop = new Shop();
shop.setLongitude(longitude);
shop.setLatitude(latitude);
// 设置其他信息
if (params.containsKey("shopName")) {
shop.setShopName(params.get("shopName").toString());
}
if (params.containsKey("workerId")) {
shop.setWorkerId(Long.valueOf(params.get("workerId").toString()));
}
if (params.containsKey("phone")) {
shop.setPhone(params.get("phone").toString());
}
// 保存店铺
int result = shopService.addShop(shop);
if (result > 0) {
Map<String, Object> response = new HashMap<>();
response.put("shopId", shop.getShopId());
response.put("longitude", longitude);
response.put("latitude", latitude);
response.put("location", location);
return AjaxResult.success("店铺创建成功", response);
} else {
return AjaxResult.error("店铺创建失败");
}
} catch (Exception e) {
logger.error("通过位置创建店铺失败: {}", e.getMessage(), e);
return AjaxResult.error("创建失败: " + e.getMessage());
}
}
/**
* 内部方法通过地址解析获取经纬度
*/
private Map<String, Double> getCoordinatesByAddress(Shop shop) {
try {
// 构建完整地址
StringBuilder fullAddress = new StringBuilder();
if (shop.getProvinceName() != null) fullAddress.append(shop.getProvinceName());
if (shop.getCityName() != null) fullAddress.append(shop.getCityName());
if (shop.getCountryName() != null) fullAddress.append(shop.getCountryName());
if (shop.getStreetName() != null) fullAddress.append(shop.getStreetName());
if (shop.getAddress() != null) fullAddress.append(shop.getAddress());
String address = fullAddress.toString();
if (address.isEmpty()) {
return null;
}
logger.info("开始解析地址获取坐标: {}", address);
// TODO: 这里应该调用真实的地图API
// 示例百度地图正向地理编码API
// String url = "https://api.map.baidu.com/geocoding/v3/?address=" +
// java.net.URLEncoder.encode(address, "UTF-8") +
// "&output=json&ak=YOUR_BAIDU_API_KEY";
//
// String result = restTemplate.getForObject(url, String.class);
// JSONObject jsonResult = JSONObject.parseObject(result);
//
// if ("0".equals(jsonResult.getString("status"))) {
// JSONObject location = jsonResult.getJSONObject("result").getJSONObject("location");
// Double lng = location.getDouble("lng");
// Double lat = location.getDouble("lat");
//
// Map<String, Double> coordinates = new HashMap<>();
// coordinates.put("longitude", lng);
// coordinates.put("latitude", lat);
// return coordinates;
// }
// 临时返回示例坐标实际使用时请替换为真实的API调用
Map<String, Double> coordinates = new HashMap<>();
coordinates.put("latitude", 39.915 + Math.random() * 0.1); // 示例纬度
coordinates.put("longitude", 116.404 + Math.random() * 0.1); // 示例经度
logger.info("地址解析成功: {} -> 经度={}, 纬度={}",
address, coordinates.get("longitude"), coordinates.get("latitude"));
return coordinates;
} catch (Exception e) {
logger.error("地址解析失败: {}", e.getMessage(), e);
return null;
}
}
/**
* 手动设置店铺经纬度
*/
@PostMapping("/setCoordinates")
public AjaxResult setCoordinates(@RequestBody Map<String, Object> params) {
try {
Long shopId = Long.valueOf(params.get("shopId").toString());
Double latitude = Double.valueOf(params.get("latitude").toString());
Double longitude = Double.valueOf(params.get("longitude").toString());
Shop shop = new Shop();
shop.setShopId(shopId);
shop.setLatitude(latitude);
shop.setLongitude(longitude);
int result = shopService.updateShop(shop);
if (result > 0) {
Map<String, Object> response = new HashMap<>();
response.put("shopId", shopId);
response.put("latitude", latitude);
response.put("longitude", longitude);
return AjaxResult.success("坐标设置成功", response);
} else {
return AjaxResult.error("坐标设置失败");
}
} catch (Exception e) {
logger.error("设置坐标失败: {}", e.getMessage(), e);
return AjaxResult.error("设置坐标失败: " + e.getMessage());
}
}
/**
* 批量查询店铺包含经纬度信息
*/
@PostMapping("/listWithLocation")
public AjaxResult listShopsWithLocation(@RequestBody(required = false) Map<String, Object> params) {
try {
List<Shop> shops = shopService.listShops();
// 可以根据参数进行筛选
if (params != null) {
// 按城市筛选
if (params.containsKey("cityId")) {
Long cityId = Long.valueOf(params.get("cityId").toString());
shops = shops.stream()
.filter(shop -> shop.getCityId() != null && shop.getCityId().equals(cityId))
.collect(java.util.stream.Collectors.toList());
}
// 按师傅筛选
if (params.containsKey("workerId")) {
Long workerId = Long.valueOf(params.get("workerId").toString());
shops = shops.stream()
.filter(shop -> shop.getWorkerId() != null && shop.getWorkerId().equals(workerId))
.collect(java.util.stream.Collectors.toList());
}
// 只返回有坐标的店铺
if (params.containsKey("hasLocation") && Boolean.valueOf(params.get("hasLocation").toString())) {
shops = shops.stream()
.filter(shop -> shop.getLatitude() != null && shop.getLongitude() != null)
.collect(java.util.stream.Collectors.toList());
}
}
return AjaxResult.success(shops);
} catch (Exception e) {
logger.error("查询店铺列表失败: {}", e.getMessage(), e);
return AjaxResult.error("查询失败: " + e.getMessage());
}
}
/**
* 查询附近的店铺
*/
@PostMapping("/nearby")
public AjaxResult getNearbyShops(@RequestBody Map<String, Object> params) {
try {
Double latitude = Double.valueOf(params.get("latitude").toString());
Double longitude = Double.valueOf(params.get("longitude").toString());
Double radiusKm = params.containsKey("radiusKm") ?
Double.valueOf(params.get("radiusKm").toString()) : 5.0; // 默认5公里
// 验证坐标有效性
if (!LocationUtils.isValidCoordinate(latitude, longitude)) {
return AjaxResult.error("无效的坐标参数");
}
// 获取所有店铺
List<Shop> allShops = shopService.listShops();
// 筛选出有坐标的店铺并计算距离
List<Map<String, Object>> nearbyShops = allShops.stream()
.filter(shop -> LocationUtils.isValidCoordinate(shop.getLatitude(), shop.getLongitude()))
.map(shop -> {
double distance = LocationUtils.getDistanceInKilometers(
latitude, longitude, shop.getLatitude(), shop.getLongitude());
Map<String, Object> shopWithDistance = new HashMap<>();
shopWithDistance.put("shop", shop);
shopWithDistance.put("distance", distance);
shopWithDistance.put("distanceText", LocationUtils.formatDistance(distance * 1000));
// 计算方向
double bearing = LocationUtils.getBearing(latitude, longitude,
shop.getLatitude(), shop.getLongitude());
shopWithDistance.put("direction", LocationUtils.getDirectionDescription(bearing));
shopWithDistance.put("bearing", bearing);
return shopWithDistance;
})
.filter(shopMap -> (Double) shopMap.get("distance") <= radiusKm)
.sorted(Comparator.comparingDouble(shopMap -> (Double) shopMap.get("distance")))
.collect(Collectors.toList());
Map<String, Object> result = new HashMap<>();
result.put("centerLatitude", latitude);
result.put("centerLongitude", longitude);
result.put("radiusKm", radiusKm);
result.put("totalCount", nearbyShops.size());
result.put("shops", nearbyShops);
return AjaxResult.success("查询成功", result);
} catch (Exception e) {
logger.error("查询附近店铺失败: {}", e.getMessage(), e);
return AjaxResult.error("查询失败: " + e.getMessage());
}
}
/**
* 计算两个店铺之间的距离
*/
@PostMapping("/distance")
public AjaxResult getShopsDistance(@RequestBody Map<String, Object> params) {
try {
Long shopId1 = Long.valueOf(params.get("shopId1").toString());
Long shopId2 = Long.valueOf(params.get("shopId2").toString());
Shop shop1 = shopService.getShop(shopId1);
Shop shop2 = shopService.getShop(shopId2);
if (shop1 == null || shop2 == null) {
return AjaxResult.error("店铺不存在");
}
if (!LocationUtils.isValidCoordinate(shop1.getLatitude(), shop1.getLongitude()) ||
!LocationUtils.isValidCoordinate(shop2.getLatitude(), shop2.getLongitude())) {
return AjaxResult.error("店铺坐标信息不完整");
}
double distanceKm = LocationUtils.getDistanceInKilometers(
shop1.getLatitude(), shop1.getLongitude(),
shop2.getLatitude(), shop2.getLongitude());
double bearing = LocationUtils.getBearing(
shop1.getLatitude(), shop1.getLongitude(),
shop2.getLatitude(), shop2.getLongitude());
Map<String, Object> result = new HashMap<>();
result.put("shop1", shop1);
result.put("shop2", shop2);
result.put("distanceKm", distanceKm);
result.put("distanceText", LocationUtils.formatDistance(distanceKm * 1000));
result.put("direction", LocationUtils.getDirectionDescription(bearing));
result.put("bearing", bearing);
return AjaxResult.success("计算成功", result);
} catch (Exception e) {
logger.error("计算店铺距离失败: {}", e.getMessage(), e);
return AjaxResult.error("计算失败: " + e.getMessage());
}
}
/**
* 通过店铺ID查询详细信息并计算距离
* 最终效果
* 1. 传入的详细地址 转换为经纬度
* 2. 店铺有经纬度 直接使用
* 3. 店铺没有经纬度 通过详细地址生成经纬度
* 4. 最终通过经纬度计算距离 放在店铺的距离字段上
*
* @param query 距离查询请求实体
* @return 包含距离信息的完整店铺详情
*/
@PostMapping("/getShopDetailWithDistance")
public AjaxResult getShopDetailWithDistance(@RequestBody ShopDistanceQuery query) {
try {
// 验证参数
if (query.getShopId() == null) {
return AjaxResult.error("店铺ID不能为空");
}
// 验证是否有足够的信息来计算距离或获取位置
if (!query.hasEnoughInfo()) {
return AjaxResult.error("请提供经纬度或地址信息");
}
// 如果提供了经纬度验证其有效性
if (query.hasCoordinateInfo() && !LocationUtils.isValidCoordinate(query.getLatitude(), query.getLongitude())) {
return AjaxResult.error("无效的坐标参数");
}
// 验证地址参数如果提供了地址信息则验证其完整性
if (query.hasAddressInfo()) {
String fullAddress = query.getFullAddress();
if (fullAddress.trim().length() < 5) {
return AjaxResult.error("地址信息不完整,请提供更详细的地址");
}
logger.info("使用传入的地址信息: {}", fullAddress);
}
// 调用服务层方法获取店铺详情和距离
Shop shop = shopService.getShopWithDistance(query);
if (shop == null) {
return AjaxResult.error("未找到店铺");
}
// 检查距离是否有效
if (shop.getDistance() == null || shop.getDistance().equals("无法计算距离")) {
if (query.hasCoordinateInfo()) {
return AjaxResult.error("无法计算店铺距离,请检查店铺地址信息或提供更详细的地址参数");
} else {
// 如果没有经纬度只获取位置信息
logger.info("仅获取店铺位置信息,无法计算距离");
}
}
// 构建返回结果
Map<String, Object> result = new HashMap<>();
result.put("shopId", shop.getShopId());
result.put("shopName", shop.getShopName());
result.put("imageUrl", shop.getImageUrl());
result.put("workerId", shop.getWorkerId());
result.put("provinceId", shop.getProvinceId());
result.put("provinceName", shop.getProvinceName());
result.put("cityId", shop.getCityId());
result.put("cityName", shop.getCityName());
result.put("countryId", shop.getCountryId());
result.put("countryName", shop.getCountryName());
result.put("streetId", shop.getStreetId());
result.put("streetName", shop.getStreetName());
result.put("address", shop.getAddress());
result.put("phone", shop.getPhone());
result.put("latitude", shop.getLatitude());
result.put("longitude", shop.getLongitude());
result.put("distance", shop.getDistance());
return AjaxResult.success("查询成功", result);
} catch (Exception e) {
logger.error("查询店铺详情失败: {}", e.getMessage(), e);
return AjaxResult.error("查询失败: " + e.getMessage());
}
}
// /**
// * 获取店铺覆盖范围内的其他店铺
// */
// @PostMapping("/coverage")
// public AjaxResult getShopsCoverage(@RequestBody Map<String, Object> params) {
// try {
// Long shopId = Long.valueOf(params.get("shopId").toString());
// Double radiusKm = params.containsKey("radiusKm") ?
// Double.valueOf(params.get("radiusKm").toString()) : 10.0; // 默认10公里
//
// Shop centerShop = shopService.getShop(shopId);
// if (centerShop == null) {
// return AjaxResult.error("店铺不存在");
// }
//
// if (!LocationUtils.isValidCoordinate(centerShop.getLatitude(), centerShop.getLongitude())) {
// return AjaxResult.error("中心店铺坐标信息不完整");
// }
//
// // 获取附近的店铺
// Map<String, Object> nearbyParams = new HashMap<>();
// nearbyParams.put("latitude", centerShop.getLatitude());
// nearbyParams.put("longitude", centerShop.getLongitude());
// radiusKm);
//
// AjaxResult nearbyResult = getNearbyShops(nearbyParams);
// if (nearbyResult.isSuccess()) {
// Map<String, Object> data = (Map<String, Object>) nearbyResult.get("data");
// List<Map<String, Object>> shops = (List<Map<String, Object>>) data.get("shops");
//
// // 排除自己
// shops = shops.stream()
// .filter(shopMap -> {
// Shop shop = (Shop) shopMap.get("shop");
// return !shop.getShopId().equals(shopId);
// })
// .collect(Collectors.toList());
//
// data.put("centerShop", centerShop);
// data.put("shops", shops);
// data.put("totalCount", shops.size());
//
// return AjaxResult.success("查询成功", data);
// } else {
// return nearbyResult;
// }
//
// } catch (Exception e) {
// logger.error("查询店铺覆盖范围失败: {}", e.getMessage(), e);
// return AjaxResult.error("查询失败: " + e.getMessage());
// }
// }
}

View File

@ -0,0 +1,60 @@
package com.ghy.web.controller.config;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.system.service.ISysGlobalConfigService;
import com.ghy.web.pojo.vo.SysGlobalConfigRequestVO;
import com.ghy.web.pojo.vo.SysGlobalConfigResponseVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
/**
* @Author: 但星霖
* @Date: 2023-11-09 14:42
* @Version: 1.0
* @Description: web-系统配置控制层
*/
@Controller
@RequestMapping("/config/globalConfig")
@Tag(name = "web-系统配置控制层")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SysGlobalConfigController {
private String prefix = "config/globalConfig";
@RequiresPermissions("sys:order:audio:config")
@GetMapping()
public String place() {
return prefix + "/edit";
}
private final ISysGlobalConfigService service;
@ResponseBody
@Operation(summary = "系统配置查询接口(根据类型查询)", method = "GET")
@Parameters({
@Parameter(name = "typeId", description = "配置类型Code", required = true, in = ParameterIn.PATH)
})
@GetMapping(path = "/search/type/{typeId}", produces = MediaType.APPLICATION_JSON_VALUE)
public AjaxResult searchByType(@PathVariable("typeId") Integer typeId) {
return AjaxResult.success(SysGlobalConfigResponseVO.toVo(service.loadByConfigType(typeId)));
}
@ResponseBody
@RequiresPermissions("sys:order:audio:config:update")
@Operation(summary = "系统配置修改", method = "PUT")
@PutMapping(path = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
public AjaxResult update(@RequestBody SysGlobalConfigRequestVO sysConfigRequestVO) {
return AjaxResult.success(service.update(SysGlobalConfigRequestVO.toModel(sysConfigRequestVO)));
}
}

View File

@ -1,5 +1,6 @@
package com.ghy.web.controller.customer; package com.ghy.web.controller.customer;
import cn.hutool.core.util.ObjectUtil;
import com.ghy.common.core.controller.BaseController; import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.ExceptionUtil; import com.ghy.common.utils.ExceptionUtil;
@ -12,6 +13,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
@Controller @Controller
@RequestMapping("/customer/address") @RequestMapping("/customer/address")
@ -100,6 +103,20 @@ public class CustomerAddressController extends BaseController {
@ResponseBody @ResponseBody
AjaxResult insertCustomerAddress(@RequestBody CustomerAddress customerAddress){ AjaxResult insertCustomerAddress(@RequestBody CustomerAddress customerAddress){
try { try {
// 判断下当前是否是默认地址
if(ObjectUtil.equals(customerAddress.getIsDefault(), 1)){
CustomerAddress param = new CustomerAddress();
param.setNeedNameFlag(false);
param.setCustomerId(customerAddress.getCustomerId());
param.setIsDefault(1);
List<CustomerAddress> sourceDefaultAddress = customerAddressService.getCustomerAddressList(param);
for (CustomerAddress defaultAddress : sourceDefaultAddress) {
CustomerAddress defaultParam = new CustomerAddress();
defaultParam.setCustomerAddressId(defaultAddress.getCustomerAddressId());
defaultParam.setIsDefault(0);
customerAddressService.updateCustomerAddress(defaultParam);
}
}
customerAddressService.insertCustomerAddress(customerAddress); customerAddressService.insertCustomerAddress(customerAddress);
return AjaxResult.success("操作成功"); return AjaxResult.success("操作成功");
}catch (Exception e){ }catch (Exception e){
@ -114,7 +131,24 @@ public class CustomerAddressController extends BaseController {
@PostMapping("/update") @PostMapping("/update")
@ResponseBody @ResponseBody
AjaxResult updateCustomerAddress(@RequestBody CustomerAddress customerAddress){ AjaxResult updateCustomerAddress(@RequestBody CustomerAddress customerAddress){
logger.info("地址库的订单修改方法{}",customerAddress);
try { try {
// 判断下当前是否是默认地址
if(ObjectUtil.equals(customerAddress.getIsDefault(), 1)){
CustomerAddress param = new CustomerAddress();
param.setNeedNameFlag(false);
param.setCustomerId(customerAddress.getCustomerId());
param.setIsDefault(1);
List<CustomerAddress> sourceDefaultAddress = customerAddressService.getCustomerAddressList(param);
for (CustomerAddress defaultAddress : sourceDefaultAddress) {
if(!Objects.equals(defaultAddress.getCustomerAddressId(), customerAddress.getCustomerAddressId())){
CustomerAddress defaultParam = new CustomerAddress();
defaultParam.setCustomerAddressId(defaultAddress.getCustomerAddressId());
defaultParam.setIsDefault(0);
customerAddressService.updateCustomerAddress(defaultParam);
}
}
}
customerAddressService.updateCustomerAddress(customerAddress); customerAddressService.updateCustomerAddress(customerAddress);
return AjaxResult.success("操作成功"); return AjaxResult.success("操作成功");
}catch (Exception e){ }catch (Exception e){

View File

@ -18,6 +18,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -45,6 +46,8 @@ public class CustomerBankController {
@ResponseBody @ResponseBody
private AjaxResult bindBankCard(@RequestBody @Valid BindBankCardRequest request) throws BaseAdaPayException { private AjaxResult bindBankCard(@RequestBody @Valid BindBankCardRequest request) throws BaseAdaPayException {
Set<Merchant> merchants = AdapayConfig.getMerchants(); Set<Merchant> merchants = AdapayConfig.getMerchants();
String phone = request.getPhone();
phone = StringUtils.trimAllWhitespace(phone);
for (Merchant merchant : merchants) { for (Merchant merchant : merchants) {
String memberId = AdapayUtils.getCustomerMemberId(request.getCustomerId(), merchant.getDeptId()); String memberId = AdapayUtils.getCustomerMemberId(request.getCustomerId(), merchant.getDeptId());
@ -60,7 +63,7 @@ public class CustomerBankController {
log.info("用户[memberId={}]已存在 跳过实名直接绑卡", memberId); log.info("用户[memberId={}]已存在 跳过实名直接绑卡", memberId);
} else { } else {
// 先在Adapay创建实名用户 // 先在Adapay创建实名用户
Map<String, Object> result1 = adapayService.createMember(merchant.getDeptId(), memberId, request.getPhone(), Map<String, Object> result1 = adapayService.createMember(merchant.getDeptId(), memberId, phone,
request.getName(), request.getCertId()); request.getName(), request.getCertId());
if (!AdapayStatusEnum.succeeded.code.equals(result1.get("status"))) { if (!AdapayStatusEnum.succeeded.code.equals(result1.get("status"))) {
log.error("实名认证失败[{}]", JSON.toJSONString(result1)); log.error("实名认证失败[{}]", JSON.toJSONString(result1));
@ -70,7 +73,7 @@ public class CustomerBankController {
// 开始创建结算账户 // 开始创建结算账户
JSONObject result2 = adapayService.createSettleAccount(merchant.getDeptId(), memberId, request.getBankNum(), request.getName(), JSONObject result2 = adapayService.createSettleAccount(merchant.getDeptId(), memberId, request.getBankNum(), request.getName(),
"2", request.getCertId(), request.getPhone(), null, null, null); "2", request.getCertId(), phone, null, null, null);
if (!AdapayStatusEnum.succeeded.code.equals(result2.get("status"))) { if (!AdapayStatusEnum.succeeded.code.equals(result2.get("status"))) {
if ("account_exists".equals(result2.get("error_code"))) { if ("account_exists".equals(result2.get("error_code"))) {
log.info("用户[memberId={}]结算账户已存在 跳过", memberId); log.info("用户[memberId={}]结算账户已存在 跳过", memberId);
@ -85,7 +88,7 @@ public class CustomerBankController {
customerBank.setName(request.getName()); customerBank.setName(request.getName());
customerBank.setCertId(request.getCertId()); customerBank.setCertId(request.getCertId());
customerBank.setBankNum(request.getBankNum()); customerBank.setBankNum(request.getBankNum());
customerBank.setPhone(request.getPhone()); customerBank.setPhone(phone);
customerBank.setDeptId(merchant.getDeptId()); customerBank.setDeptId(merchant.getDeptId());
customerBank.setAdapayMemberId(memberId); customerBank.setAdapayMemberId(memberId);
customerBank.setSettleAccount(1); customerBank.setSettleAccount(1);

View File

@ -4,13 +4,16 @@ import com.ghy.common.adapay.model.AnalyseItemEnum;
import com.ghy.common.core.controller.BaseController; import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.core.page.TableDataInfo; import com.ghy.common.core.page.TableDataInfo;
import com.ghy.common.enums.FinancialDetailType;
import com.ghy.common.enums.PlaceStatus; import com.ghy.common.enums.PlaceStatus;
import com.ghy.common.enums.UserStatus; import com.ghy.common.enums.UserStatus;
import com.ghy.common.utils.ExceptionUtil; import com.ghy.common.utils.ExceptionUtil;
import com.ghy.customer.domain.Customer; import com.ghy.customer.domain.Customer;
import com.ghy.customer.service.CustomerService; import com.ghy.customer.service.CustomerService;
import com.ghy.goods.domain.InsuranceManager;
import com.ghy.order.domain.OrderMaster; import com.ghy.order.domain.OrderMaster;
import com.ghy.order.service.OrderMasterService; import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster; import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.service.FinancialMasterService; import com.ghy.payment.service.FinancialMasterService;
import com.ghy.web.pojo.vo.AnalyseItem; import com.ghy.web.pojo.vo.AnalyseItem;
@ -19,6 +22,7 @@ import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -72,17 +76,19 @@ public class CustomerController extends BaseController {
startPage(); startPage();
List<Customer> list = customerService.getCustomerList(customer); List<Customer> list = customerService.getCustomerList(customer);
for (Customer curCustomer: list) { for (Customer curCustomer: list) {
Long teamNum = 0L;
List<Long> customerIds = new ArrayList<Long>(){{ List<Long> customerIds = new ArrayList<Long>(){{
add(curCustomer.getCustomerId()); add(curCustomer.getCustomerId());
}}; }};
List<Long> nextLevelCustomerIds = new ArrayList<>();
if (customer.getIsDistributor()) { if (customer.getIsDistributor()) {
// 分销商需要查询所有下一级分销用户作为统计条件 // 分销商需要查询所有下一级分销用户作为统计条件
Customer customerQry = new Customer(); Customer customerQry = new Customer();
customerQry.setCustomerPlace(curCustomer.getCustomerId()); customerQry.setCustomerPlace(curCustomer.getCustomerId());
customerQry.setStatus(Integer.valueOf(UserStatus.OK.getCode())); customerQry.setStatus(Integer.valueOf(UserStatus.OK.getCode()));
List<Customer> nextLevelCustomers = customerService.getCustomerList(customerQry); List<Customer> nextLevelCustomers = customerService.getCustomerList(customerQry);
List<Long> nextLevelCustomerIds = nextLevelCustomers.stream().map(Customer::getCustomerId).collect(Collectors.toList()); teamNum = teamNum + nextLevelCustomers.stream().filter(x->PlaceStatus.CAN_PLACE.getCode().equals(x.getPlaceStatus())).count();
customerIds.addAll(nextLevelCustomerIds); nextLevelCustomerIds = nextLevelCustomers.stream().map(Customer::getCustomerId).collect(Collectors.toList());
} }
// 本月第一天 // 本月第一天
@ -103,30 +109,36 @@ public class CustomerController extends BaseController {
.setValue(customerService.countCustomer(customerParams)); .setValue(customerService.countCustomer(customerParams));
analyseItems.add(aItem1); analyseItems.add(aItem1);
// 本月绑定客户数 // 本月绑定客户数
customerParams.setPlaceStatus(null);
customerParams.setUpdateTimeStart(firstDayCurMonth.atStartOfDay()); customerParams.setUpdateTimeStart(firstDayCurMonth.atStartOfDay());
AnalyseItem aItem2 = new AnalyseItem() AnalyseItem aItem2 = new AnalyseItem()
.setType(AnalyseItemEnum.CUSTOMER_NUM_ADDED_CUR_MONTH.getType()) .setType(AnalyseItemEnum.CUSTOMER_NUM_ADDED_CUR_MONTH.getType())
.setTitle(AnalyseItemEnum.CUSTOMER_NUM_ADDED_CUR_MONTH.getTitle()) .setTitle(AnalyseItemEnum.CUSTOMER_NUM_ADDED_CUR_MONTH.getTitle())
.setUnit(AnalyseItemEnum.CUSTOMER_NUM_ADDED_CUR_MONTH.getUnit()) .setUnit(AnalyseItemEnum.CUSTOMER_NUM_ADDED_CUR_MONTH.getUnit())
.setValue(customerService.countCustomer(customerParams)); .setValue(customerService.countCustomer(customerParams));
analyseItems.add(aItem2); analyseItems.add(aItem2);
// 团队 // 团队
customerParams.setUpdateTimeStart(null);
customerParams.setPlaceStatus(PlaceStatus.CAN_PLACE.getCode());
AnalyseItem aItem11 = new AnalyseItem() AnalyseItem aItem11 = new AnalyseItem()
.setType(AnalyseItemEnum.TEAM_MEMBER_NUM.getType()) .setType(AnalyseItemEnum.TEAM_MEMBER_NUM.getType())
.setTitle(AnalyseItemEnum.TEAM_MEMBER_NUM.getTitle()) .setTitle(AnalyseItemEnum.TEAM_MEMBER_NUM.getTitle())
.setUnit(AnalyseItemEnum.TEAM_MEMBER_NUM.getUnit()) .setUnit(AnalyseItemEnum.TEAM_MEMBER_NUM.getUnit())
.setValue(aItem1.getValue()); .setValue(customerService.countCustomer(customerParams));
analyseItems.add(aItem11); analyseItems.add(aItem11);
// 本月绑定客户数 // 本月绑定客户数
customerParams.setUpdateTimeStart(firstDayCurMonth.atStartOfDay());
customerParams.setPlaceStatus(PlaceStatus.CAN_PLACE.getCode());
AnalyseItem aItem12 = new AnalyseItem() AnalyseItem aItem12 = new AnalyseItem()
.setType(AnalyseItemEnum.TEAM_MEMBER_ADDED_CUR_MONTH.getType()) .setType(AnalyseItemEnum.TEAM_MEMBER_ADDED_CUR_MONTH.getType())
.setTitle(AnalyseItemEnum.TEAM_MEMBER_ADDED_CUR_MONTH.getTitle()) .setTitle(AnalyseItemEnum.TEAM_MEMBER_ADDED_CUR_MONTH.getTitle())
.setUnit(AnalyseItemEnum.TEAM_MEMBER_ADDED_CUR_MONTH.getUnit()) .setUnit(AnalyseItemEnum.TEAM_MEMBER_ADDED_CUR_MONTH.getUnit())
.setValue(aItem2.getValue()); .setValue(customerService.countCustomer(customerParams));
analyseItems.add(aItem12); analyseItems.add(aItem12);
// 本月订单数及本月订单额 // 本月订单数及本月订单额
OrderMaster orderParams1 = new OrderMaster(); OrderMaster orderParams1 = new OrderMaster();
customerIds.addAll(nextLevelCustomerIds);
orderParams1.setCustomerIds(customerIds); orderParams1.setCustomerIds(customerIds);
orderParams1.setCreateTimeStart(firstDayCurMonth.atStartOfDay()); orderParams1.setCreateTimeStart(firstDayCurMonth.atStartOfDay());
List<OrderMaster> ordersCurMonth1 = orderMasterService.selectOrderMasterList(orderParams1); List<OrderMaster> ordersCurMonth1 = orderMasterService.selectOrderMasterList(orderParams1);
@ -208,7 +220,7 @@ public class CustomerController extends BaseController {
OrderMaster orderParams4 = new OrderMaster(); OrderMaster orderParams4 = new OrderMaster();
orderParams4.setCustomerIds(customerIds); orderParams4.setCustomerIds(customerIds);
orderParams4.setCreateTimeStart(firstDayCurWeek.atStartOfDay()); orderParams4.setCreateTimeStart(firstDayCurWeek.atStartOfDay());
List<OrderMaster> ordersCurWeek = orderMasterService.selectOrderMasterList(orderParams3); List<OrderMaster> ordersCurWeek = orderMasterService.selectOrderMasterList(orderParams4);
List<Long> orderIdsCurWeek = ordersCurWeek.stream().map(OrderMaster::getId).collect(Collectors.toList()); List<Long> orderIdsCurWeek = ordersCurWeek.stream().map(OrderMaster::getId).collect(Collectors.toList());
BigDecimal totalMoneyCurWeek = new BigDecimal(0); BigDecimal totalMoneyCurWeek = new BigDecimal(0);
if (CollectionUtils.isNotEmpty(orderIdsCurWeek)) { if (CollectionUtils.isNotEmpty(orderIdsCurWeek)) {
@ -242,6 +254,25 @@ public class CustomerController extends BaseController {
return getDataTable(response); return getDataTable(response);
} }
@GetMapping("/changePlace/{customerId}")
public String changePlace(@PathVariable("customerId") Long customerId, ModelMap mmap)
{
mmap.put("customerId", customerId);
mmap.put("customerPlaces", customerService.getPlaceCustomerList());
return prefix + "/changePlace";
}
@PostMapping("/changePlace")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult changePlace(Customer customer) {
Customer place = customerService.selectByCustomerId(customer.getCustomerPlace());
customer.setParentCustomerPlace(place.getCustomerPlace());
customerService.updateCustomer(customer);
return AjaxResult.success();
}
@RequiresPermissions("customer:customer:resetPwd") @RequiresPermissions("customer:customer:resetPwd")
@GetMapping("/resetPwd/{customerId}") @GetMapping("/resetPwd/{customerId}")
public String resetPwd(@PathVariable("customerId") Long customerId, ModelMap mmap) public String resetPwd(@PathVariable("customerId") Long customerId, ModelMap mmap)

View File

@ -1,6 +1,8 @@
package com.ghy.web.controller.customer; package com.ghy.web.controller.customer;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import com.ghy.common.exception.base.BaseException; import com.ghy.common.exception.base.BaseException;
import com.ghy.customer.domain.Customer; import com.ghy.customer.domain.Customer;
@ -62,6 +64,22 @@ public class CustomerSelectionController extends BaseController
return getDataTable(list); return getDataTable(list);
} }
/**
* 查询消费者选品列表
*/
@PostMapping("/listNoPage")
@ResponseBody
public AjaxResult listNoPage(@RequestBody CustomerSelection customerSelection)
{
// 判断是否有上级有上级则取上级的 -- 没有则就是自身
Customer customer = customerService.selectByCustomerId(customerSelection.getCustomerId());
if(customer.getPlaceStatus() != 2 && customer.getCustomerPlace() != null){
customerSelection.setCustomerId(customer.getCustomerPlace());
}
List<CustomerSelection> list = customerSelectionService.selectCustomerSelectionList(customerSelection);
return AjaxResult.success(list.stream().map(CustomerSelection::getDeptCategoryId).collect(Collectors.toList()));
}
/** /**
* App查询消费者选品列表 * App查询消费者选品列表
*/ */
@ -129,18 +147,28 @@ public class CustomerSelectionController extends BaseController
}else { }else {
workId = workList.get(0).getWorkerId(); workId = workList.get(0).getWorkerId();
} }
// 删除历史的
CustomerSelection hisParam = new CustomerSelection();
hisParam.setCustomerId(customerSelection.getCustomerId());
hisParam.setSelectionType(customerSelection.getSelectionType());
List<CustomerSelection> hisList = customerSelectionService.selectCustomerSelectionList(hisParam);
if(!CollectionUtils.isEmpty(hisList)){
List<String> hisIds = hisList.stream()
.filter(customerSelection1 -> Objects.equals(customerSelection1.getType(), customerSelection.getType())).map(CustomerSelection::getId).collect(Collectors.toList());
StringBuilder ids = new StringBuilder();
hisIds.forEach(model->{
ids.append(model.trim()).append(",");
});
if(!StringUtil.isEmpty(ids)&&ids.length()>0){
String idString = ids.substring(0, ids.length()-1);
customerSelectionService.deleteCustomerSelectionByIds(idString);
}
}
// 判断是否有历史数据 - 有则删除 // 判断是否有历史数据 - 有则删除
customerSelection.getDeptCategoryIds().forEach(selection->{ customerSelection.getDeptCategoryIds().forEach(selection->{
customerSelection.setWorkId(workId); customerSelection.setWorkId(workId);
customerSelection.setDeptCategoryId(selection); customerSelection.setDeptCategoryId(selection);
CustomerSelection param = new CustomerSelection(); customerSelectionService.insertCustomerSelection(customerSelection);
param.setDeptCategoryId(selection);
param.setSelectionType(customerSelection.getSelectionType());
param.setCustomerId(customerSelection.getCustomerId());
List<CustomerSelection> customerSelections = customerSelectionService.selectCustomerSelectionList(param);
if(CollectionUtils.isEmpty(customerSelections)){
customerSelectionService.insertCustomerSelection(customerSelection);
}
}); });
return AjaxResult.success("新增成功"); return AjaxResult.success("新增成功");
}catch (Exception e){ }catch (Exception e){

View File

@ -1,5 +1,6 @@
package com.ghy.web.controller.goods; package com.ghy.web.controller.goods;
import cn.hutool.core.collection.CollectionUtil;
import com.ghy.common.annotation.Log; import com.ghy.common.annotation.Log;
import com.ghy.common.constant.UserConstants; import com.ghy.common.constant.UserConstants;
import com.ghy.common.core.controller.BaseController; import com.ghy.common.core.controller.BaseController;
@ -7,16 +8,24 @@ import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.core.domain.Ztree; import com.ghy.common.core.domain.Ztree;
import com.ghy.common.enums.BusinessType; import com.ghy.common.enums.BusinessType;
import com.ghy.common.utils.ShiroUtils; import com.ghy.common.utils.ShiroUtils;
import com.ghy.common.utils.StringUtils;
import com.ghy.goods.domain.CategoryInsuranceRelation;
import com.ghy.goods.domain.GoodsCategory; import com.ghy.goods.domain.GoodsCategory;
import com.ghy.goods.domain.InsuranceManager;
import com.ghy.goods.service.GoodsCategoryService; import com.ghy.goods.service.GoodsCategoryService;
import com.ghy.goods.service.ICategoryInsuranceRelationService;
import com.ghy.goods.service.IInsuranceManagerService;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/** /**
* @author HH 2022/3/19 * @author HH 2022/3/19
@ -30,6 +39,12 @@ public class GoodsCategoryController extends BaseController {
@Resource @Resource
private GoodsCategoryService goodsCategoryService; private GoodsCategoryService goodsCategoryService;
@Resource
private IInsuranceManagerService insuranceManagerService;
@Resource
private ICategoryInsuranceRelationService categoryInsuranceRelationService;
@RequiresPermissions("goods:category:view") @RequiresPermissions("goods:category:view")
@GetMapping() @GetMapping()
public String goodsCategory() { public String goodsCategory() {
@ -43,6 +58,7 @@ public class GoodsCategoryController extends BaseController {
@GetMapping("/add/{parentCategoryId}") @GetMapping("/add/{parentCategoryId}")
public String add(@PathVariable("parentCategoryId") Long parentCategoryId, ModelMap mmap) { public String add(@PathVariable("parentCategoryId") Long parentCategoryId, ModelMap mmap) {
mmap.put("goodsCategory", goodsCategoryService.selectById(parentCategoryId)); mmap.put("goodsCategory", goodsCategoryService.selectById(parentCategoryId));
mmap.put("insurances", insuranceManagerService.selectInsuranceManagerList(new InsuranceManager()));
return PREFIX + "/add"; return PREFIX + "/add";
} }
@ -50,7 +66,8 @@ public class GoodsCategoryController extends BaseController {
* 新增商品类别页面 * 新增商品类别页面
*/ */
@GetMapping("/add") @GetMapping("/add")
public String add() { public String add(ModelMap mmap) {
mmap.put("insurances", insuranceManagerService.selectInsuranceManagerList(new InsuranceManager()));
return PREFIX + "/add"; return PREFIX + "/add";
} }
@ -60,7 +77,21 @@ public class GoodsCategoryController extends BaseController {
@RequiresPermissions("goods:category:edit") @RequiresPermissions("goods:category:edit")
@GetMapping("/edit/{goodsId}") @GetMapping("/edit/{goodsId}")
public String edit(@PathVariable("goodsId") Long goodsId, ModelMap mmap) { public String edit(@PathVariable("goodsId") Long goodsId, ModelMap mmap) {
mmap.put("goodsCategory", goodsCategoryService.selectById(goodsId)); GoodsCategory goodsCategory = goodsCategoryService.selectById(goodsId);
mmap.put("goodsCategory", goodsCategory);
List<InsuranceManager> list = insuranceManagerService.selectInsuranceManagerList(new InsuranceManager());
CategoryInsuranceRelation param = new CategoryInsuranceRelation();
param.setGoodsCategoryId(goodsCategory.getGoodsCategoryId());
List<CategoryInsuranceRelation> relations = categoryInsuranceRelationService.selectCategoryInsuranceRelationList(param);
if(CollectionUtil.isNotEmpty(relations)){
Map<Long, List<CategoryInsuranceRelation>> map = relations.stream().collect(Collectors.groupingBy(CategoryInsuranceRelation::getInsuranceId));
list.forEach(model->{
if(map.containsKey(model.getId())){
model.setFlag(true);
}
});
}
mmap.put("insurances", list);
return PREFIX + "/edit"; return PREFIX + "/edit";
} }
@ -103,12 +134,10 @@ public class GoodsCategoryController extends BaseController {
@Log(title = "商品类别管理", businessType = BusinessType.UPDATE) @Log(title = "商品类别管理", businessType = BusinessType.UPDATE)
@PostMapping("/edit") @PostMapping("/edit")
@ResponseBody @ResponseBody
@Transactional
public AjaxResult editSave(@Validated GoodsCategory category) { public AjaxResult editSave(@Validated GoodsCategory category) {
// if (goodsCategoryService.checkGoodsCategoryNameUnique(category)) { // 更新保险设置
// return error("新增商品类别'" + category.getGoodsCategoryName() + "'失败,商品类别名称已存在"); categoryInsuranceRelationService.updateCategoryInsuranceRelation(category.getInsuranceIds(), category.getGoodsCategoryId());
// } else if (goodsCategoryService.checkGoodsCategoryCodeUnique(category)) {
// return error("新增商品类别'" + category.getGoodsCategoryCode() + "'失败,商品类别编码已存在");
// }
category.setUpdateBy(getLoginName()); category.setUpdateBy(getLoginName());
return toAjax(goodsCategoryService.updateGoodsCategory(category)); return toAjax(goodsCategoryService.updateGoodsCategory(category));
} }
@ -152,6 +181,25 @@ public class GoodsCategoryController extends BaseController {
return goodsCategoryService.selectCategoryTree(new GoodsCategory()); return goodsCategoryService.selectCategoryTree(new GoodsCategory());
} }
/**
* 选择服务类目树
*/
@GetMapping("/selectServiceCategoryTree")
public String selectServiceCategoryTree(ModelMap mmap) {
return PREFIX + "/serviceTree";
}
/**
* 获取服务类目树数据
*/
@GetMapping("/serviceTreeData")
@ResponseBody
public List<Ztree> serviceTreeData() {
GoodsCategory category = new GoodsCategory();
category.setType(1); // 1表示服务类
return goodsCategoryService.selectCategoryTree(category);
}
/** /**
* 商品类别表 * 商品类别表
*/ */

View File

@ -10,8 +10,13 @@ import com.ghy.common.utils.ShiroUtils;
import com.ghy.common.utils.StringUtils; import com.ghy.common.utils.StringUtils;
import com.ghy.common.utils.bean.BeanUtils; import com.ghy.common.utils.bean.BeanUtils;
import com.ghy.common.utils.poi.ExcelUtil; import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.common.utils.LocationUtils;
import com.ghy.common.utils.http.HttpUtils;
import com.alibaba.fastjson.JSONObject;
import com.ghy.goods.domain.*; import com.ghy.goods.domain.*;
import com.ghy.goods.service.*; import com.ghy.goods.service.*;
import com.ghy.shop.domain.Shop;
import com.ghy.shop.service.ShopService;
import com.ghy.system.domain.SysArea; import com.ghy.system.domain.SysArea;
import com.ghy.system.service.ISysAreaService; import com.ghy.system.service.ISysAreaService;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
@ -26,6 +31,7 @@ import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.ghy.common.utils.BaiduMapUtils;
@Controller @Controller
@RequestMapping("/goods/goods") @RequestMapping("/goods/goods")
@ -47,6 +53,14 @@ public class GoodsController extends BaseController {
private GoodsStandardService goodsStandardService; private GoodsStandardService goodsStandardService;
@Resource @Resource
private ISysAreaService sysAreaService; private ISysAreaService sysAreaService;
@Resource
private IInsuranceManagerService insuranceManagerService;
@Resource
private IDeptCategoryInsuranceRelationService deptCategoryInsuranceRelationService;
@Resource
private ShopService shopService;
@Resource
private BaiduMapUtils baiduMapUtils;
@RequiresPermissions("goods:goods:view") @RequiresPermissions("goods:goods:view")
@GetMapping() @GetMapping()
@ -160,6 +174,15 @@ public class GoodsController extends BaseController {
@PostMapping("/app/list") @PostMapping("/app/list")
@ResponseBody @ResponseBody
public TableDataInfo appList(@RequestBody Goods goods) { public TableDataInfo appList(@RequestBody Goods goods) {
Integer type=goods.getType();
if (type==null){
goods.setType(1);
}
// 获取用户当前位置
Double userLatitude = goods.getLatitude();
Double userLongitude = goods.getLongitude();
// 判断类目id是否为第三级不是的话需要找到所有符合条件的第三级类目id作为新的条件 // 判断类目id是否为第三级不是的话需要找到所有符合条件的第三级类目id作为新的条件
if (goods.getDeptGoodsCategoryId() != null) { if (goods.getDeptGoodsCategoryId() != null) {
logger.info("入参:" + goods.getDeptGoodsCategoryId()); logger.info("入参:" + goods.getDeptGoodsCategoryId());
@ -198,9 +221,40 @@ public class GoodsController extends BaseController {
} }
} }
// 通过商品规格名称模糊查询
if (StringUtils.isNotEmpty(goods.getGoodsStandard())) {
logger.info("通过商品规格查询:{}", goods.getGoodsStandard());
List<GoodsStandard> matchedStandards = goodsStandardService.selectByStandardNameLike(goods.getGoodsStandard());
if (CollectionUtils.isNotEmpty(matchedStandards)) {
// 获取所有符合规格条件的商品ID
List<Long> goodsIds = matchedStandards.stream()
.map(GoodsStandard::getGoodsId)
.distinct()
.collect(Collectors.toList());
logger.info("通过规格查询到的商品ID列表{}", goodsIds);
// 设置商品ID筛选条件与现有的类目筛选条件组合使用
if (goods.getGoodsIds() == null) {
goods.setGoodsIds(goodsIds);
} else {
// 如果已有商品ID筛选条件取交集
goods.getGoodsIds().retainAll(goodsIds);
}
} else {
logger.info("未找到符合规格条件的商品,设置空结果");
// 如果没找到符合条件的规格设置一个不存在的商品ID
goods.setGoodsIds(Arrays.asList(-1L));
}
}
startPage(); startPage();
List<Goods> list = goodsService.selectGoodsList(goods); List<Goods> list = goodsService.selectGoodsList(goods);
logger.info("传入的类目id汇总{},传入的goods信息为{},获取到的所有商品{}",goods.getDeptGoodsCategoryIds(),goods,list);
// 用于缓存店铺信息避免重复查询
Map<Long, Shop> shopCache = new HashMap<>();
list.forEach(one -> { list.forEach(one -> {
// 补全商品服务区域 // 补全商品服务区域
List<GoodsArea> goodsAreas = goodsAreaService.selectByGoodsId(one.getGoodsId()); List<GoodsArea> goodsAreas = goodsAreaService.selectByGoodsId(one.getGoodsId());
@ -218,9 +272,88 @@ public class GoodsController extends BaseController {
one.setParGoodsCategoryId(parGoodsCategory.getGoodsCategoryId()); one.setParGoodsCategoryId(parGoodsCategory.getGoodsCategoryId());
one.setParGoodsCategoryName(parGoodsCategory.getGoodsCategoryName()); one.setParGoodsCategoryName(parGoodsCategory.getGoodsCategoryName());
} }
logger.debug("验证坐标是否合理: {}", LocationUtils.isValidCoordinate(userLatitude, userLongitude));
// 计算距离逻辑
if (LocationUtils.isValidCoordinate(userLatitude, userLongitude) && one.getShopId() != null) {
try {
// 从缓存获取店铺信息避免重复查询
Shop shop = shopCache.computeIfAbsent(one.getShopId(),
shopId -> shopService.getShop(shopId));
if (shop != null && LocationUtils.isValidCoordinate(shop.getLatitude(), shop.getLongitude())) {
// 计算距离
double distanceInMeters = LocationUtils.getDistanceInMeters(
userLatitude, userLongitude,
shop.getLatitude(), shop.getLongitude()
);
// 格式化距离并设置到商品对象
one.setDistance(LocationUtils.formatDistance(distanceInMeters));
logger.debug("商品[{}]距离用户: {}", one.getGoodsName(), one.getDistance());
} else {
// 店铺坐标不完整
one.setDistance(null);
}
} catch (Exception e) {
logger.warn("计算商品[{}]距离失败: {}", one.getGoodsName(), e.getMessage());
// 计算异常时设为null
one.setDistance(null);
}
} else {
// 用户未提供位置或商品无店铺信息
one.setDistance(null);
}
}); });
// 如果用户提供了位置信息按距离排序距离为null的排在最后
if (LocationUtils.isValidCoordinate(userLatitude, userLongitude)) {
list.sort((goods1, goods2) -> {
String distance1 = goods1.getDistance();
String distance2 = goods2.getDistance();
// 距离为null的排在最后
if (distance1 == null && distance2 == null) return 0;
if (distance1 == null) return 1;
if (distance2 == null) return -1;
// 解析距离数值进行比较
try {
double dist1 = parseDistanceToMeters(distance1);
double dist2 = parseDistanceToMeters(distance2);
return Double.compare(dist1, dist2);
} catch (Exception e) {
// 解析失败时保持原顺序
return 0;
}
});
logger.info("已按距离排序,用户位置: 纬度={}, 经度={}", userLatitude, userLongitude);
}
return getDataTable(list); return getDataTable(list);
} }
/**
* 解析距离字符串为米数用于排序
*/
private double parseDistanceToMeters(String distanceText) {
if (distanceText == null || distanceText.trim().isEmpty()) {
return Double.MAX_VALUE;
}
try {
if (distanceText.endsWith("")) {
return Double.parseDouble(distanceText.replace("", ""));
} else if (distanceText.endsWith("公里")) {
return Double.parseDouble(distanceText.replace("公里", "")) * 1000;
}
} catch (NumberFormatException e) {
logger.warn("无法解析距离字符串: {}", distanceText);
}
return Double.MAX_VALUE;
}
@PostMapping("/hot/list") @PostMapping("/hot/list")
@ResponseBody @ResponseBody
@ -271,11 +404,225 @@ public class GoodsController extends BaseController {
} }
} }
/**
* 获取商品详情
*
* @param requestBody 请求参数
* @return 商品详情信息
*/
@PostMapping("/getDetail") @PostMapping("/getDetail")
@ResponseBody @ResponseBody
public AjaxResult getDetail(@RequestBody Goods goods) { public AjaxResult getDetail(@RequestBody JSONObject requestBody) {
try { try {
Goods result = goodsService.selectById(goods.getGoodsId()); // 从请求体中提取参数
Long goodsId = requestBody.getLong("goodsId");
Double userLatitude = requestBody.getDouble("latitude");
Double userLongitude = requestBody.getDouble("longitude");
String provinceName = requestBody.getString("provinceName");
String cityName = requestBody.getString("cityName");
String countryName = requestBody.getString("countryName");
String streetName = requestBody.getString("streetName");
String address = requestBody.getString("address");
if (goodsId == null) {
return AjaxResult.error("商品ID不能为空");
}
Goods result = goodsService.selectById(goodsId);
if (result == null) {
return AjaxResult.error("商品不存在");
}
// 如果用户没有提供经纬度但有详细地址则通过地址获取经纬度
if ((userLatitude == null || userLongitude == null) &&
(provinceName != null || cityName != null ||
countryName != null || streetName != null ||
address != null)) {
try {
// 使用BaiduMapUtils工具类获取经纬度
Map<String, Double> coordinates = baiduMapUtils.getCoordinatesByAddress(
provinceName, cityName, countryName, streetName, address
);
if (coordinates != null) {
userLongitude = coordinates.get("longitude");
userLatitude = coordinates.get("latitude");
logger.info("通过地址获取到用户经纬度: 经度={}, 纬度={}", userLongitude, userLatitude);
} else {
logger.warn("通过地址获取用户经纬度失败");
}
} catch (Exception e) {
logger.error("调用百度地图API异常: {}", e.getMessage(), e);
}
}
// 获取商品店铺信息
Shop goodsShop = null;
if (result.getShopId() != null) {
try {
goodsShop = shopService.getShop(result.getShopId());
} catch (Exception e) {
logger.warn("获取商品店铺信息失败: {}", e.getMessage());
}
}
// 获取服务店铺信息
Shop serviceShop = null;
if (result.getDeptGoodsCategoryId() != null) {
try {
// 1. 通过商品的类目ID获取类目信息
DeptGoodsCategory deptGoodsCategory = deptGoodsCategoryService.selectOneByGoodsCategoryId(result.getDeptGoodsCategoryId());
Long serviceCategoryId = null;
if (deptGoodsCategory != null) {
// 先检查当前类目是否有服务类目ID
if (deptGoodsCategory.getServiceCategoryId() != null) {
serviceCategoryId = deptGoodsCategory.getServiceCategoryId();
logger.debug("当前类目[{}]的服务类目ID: {}", deptGoodsCategory.getGoodsCategoryName(), serviceCategoryId);
} else {
// 如果当前类目没有服务类目ID查找上一级类目
logger.debug("当前类目[{}]未配置服务类目ID查找上一级类目", deptGoodsCategory.getGoodsCategoryName());
if (deptGoodsCategory.getParentCategoryId() != null) {
DeptGoodsCategory parentCategory = deptGoodsCategoryService.selectOneByGoodsCategoryId(deptGoodsCategory.getParentCategoryId());
if (parentCategory != null && parentCategory.getServiceCategoryId() != null) {
serviceCategoryId = parentCategory.getServiceCategoryId();
logger.debug("上一级类目[{}]的服务类目ID: {}", parentCategory.getGoodsCategoryName(), serviceCategoryId);
} else {
logger.debug("上一级类目[{}]也未配置服务类目ID", parentCategory != null ? parentCategory.getGoodsCategoryName() : "null");
}
} else {
logger.debug("当前类目没有父级类目");
}
}
}
if (serviceCategoryId != null) {
// 2. 通过服务类目ID查询所有使用该服务类目的商品
Goods queryGoods = new Goods();
queryGoods.setDeptGoodsCategoryId(serviceCategoryId);
queryGoods.setStatus(0); // 只查询上架的商品
List<Goods> goodsList = goodsService.selectGoodsList(queryGoods);
if (goodsList.size()==0){
DeptGoodsCategory deptGoodsCategory1=deptGoodsCategoryService.selectOneByGoodsCategoryId(serviceCategoryId);
serviceCategoryId=deptGoodsCategory1.getDeptGoodsCategoryId();
// 直接使用新方法获取商品列表
goodsList = goodsStandardService.selectGoodsByDeptGoodsCategoryId(serviceCategoryId);
// 过滤只保留上架的商品
goodsList = goodsList.stream()
.filter(goods -> goods.getStatus() != null && goods.getStatus() == 0)
.collect(Collectors.toList());
}
logger.info("获取到的服务类目id{} 取到的商品列表:{}", serviceCategoryId,goodsList);
// 3. 提取所有店铺ID去重
Set<Long> shopIds = goodsList.stream()
.filter(g -> g.getShopId() != null)
.map(Goods::getShopId)
.collect(Collectors.toSet());
logger.info("取到的店铺列表:{}", shopIds);
if (!shopIds.isEmpty()) {
// 找到最近的店铺
Shop nearestShop = null;
double minDistance = Double.MAX_VALUE;
for (Long shopId : shopIds) {
Shop shop = shopService.getShop(shopId);
if (shop != null && LocationUtils.isValidCoordinate(shop.getLatitude(), shop.getLongitude())) {
if (LocationUtils.isValidCoordinate(userLatitude, userLongitude)) {
try {
double distanceInMeters = LocationUtils.getDistanceInMeters(
userLatitude, userLongitude,
shop.getLatitude(), shop.getLongitude()
);
if (distanceInMeters < minDistance) {
minDistance = distanceInMeters;
nearestShop = shop;
}
} catch (Exception e) {
logger.warn("计算店铺[{}]距离失败: {}", shop.getShopName(), e.getMessage());
}
} else {
// 如果用户没有提供位置选择第一个有效店铺
if (nearestShop == null) {
nearestShop = shop;
}
}
}
}
serviceShop = nearestShop;
} else {
logger.debug("服务类目[{}]下没有找到商品", serviceCategoryId);
}
} else {
logger.debug("未找到有效的服务类目ID");
}
} catch (Exception e) {
logger.warn("获取服务店铺信息失败: {}", e.getMessage());
}
}
// 设置商品店铺和服务店铺信息
if(result.getType()==1){
serviceShop=goodsShop;
result.setServiceShop(serviceShop);
}else {
result.setShop(goodsShop);
}
// 计算距离逻辑
if (LocationUtils.isValidCoordinate(userLatitude, userLongitude)) {
// 计算服务店铺距离
if (serviceShop != null) {
try {
if (LocationUtils.isValidCoordinate(serviceShop.getLatitude(), serviceShop.getLongitude())) {
// 计算距离
double distanceInMeters = LocationUtils.getDistanceInMeters(
userLatitude, userLongitude,
serviceShop.getLatitude(), serviceShop.getLongitude()
);
// 格式化距离并设置到服务店铺对象
serviceShop.setDistance(LocationUtils.formatDistance(distanceInMeters));
logger.debug("商品[{}]服务店铺距离用户: {}", result.getGoodsName(), serviceShop.getDistance());
} else {
// 店铺坐标不完整
serviceShop.setDistance(null);
}
} catch (Exception e) {
logger.warn("计算商品[{}]服务店铺距离失败: {}", result.getGoodsName(), e.getMessage());
// 计算异常时设为null
serviceShop.setDistance(null);
}
}
// 计算商品店铺距离
if (goodsShop != null) {
try {
if (LocationUtils.isValidCoordinate(goodsShop.getLatitude(), goodsShop.getLongitude())) {
// 计算距离
double distanceInMeters = LocationUtils.getDistanceInMeters(
userLatitude, userLongitude,
goodsShop.getLatitude(), goodsShop.getLongitude()
);
// 格式化距离并设置到商品店铺对象
goodsShop.setDistance(LocationUtils.formatDistance(distanceInMeters));
logger.debug("商品[{}]商品店铺距离用户: {}", result.getGoodsName(), goodsShop.getDistance());
} else {
// 店铺坐标不完整
goodsShop.setDistance(null);
}
} catch (Exception e) {
logger.warn("计算商品[{}]商品店铺距离失败: {}", result.getGoodsName(), e.getMessage());
// 计算异常时设为null
goodsShop.setDistance(null);
}
}
}
result.setServiceShop(serviceShop);
// 补全商品类目及父级类目信息 // 补全商品类目及父级类目信息
GoodsCategory goodsCategory = goodsCategoryService.selectById(result.getDeptGoodsCategoryId()); GoodsCategory goodsCategory = goodsCategoryService.selectById(result.getDeptGoodsCategoryId());
@ -322,7 +669,24 @@ public class GoodsController extends BaseController {
goodsStandard.setFinalPrice(finalPrice); goodsStandard.setFinalPrice(finalPrice);
}); });
result.setGoodsStandardList(goodsStandards); result.setGoodsStandardList(goodsStandards);
// 所有保险信息
List<InsuranceManager> insuranceManagers = insuranceManagerService.selectInsuranceManagerList(new InsuranceManager());
// 查询本类目保险信息
DeptCategoryInsuranceRelation param = new DeptCategoryInsuranceRelation();
param.setType("01");
param.setDeptCategoryId(goodsStandards.get(0).getDeptGoodsCategoryId());
List<DeptCategoryInsuranceRelation> deptCategoryInsuranceRelations = deptCategoryInsuranceRelationService.selectDeptCategoryInsuranceRelationList(param);
if(CollectionUtils.isNotEmpty(deptCategoryInsuranceRelations)){
Map<Long, List<DeptCategoryInsuranceRelation>> insuranceMap = deptCategoryInsuranceRelations.stream().collect(Collectors.groupingBy(DeptCategoryInsuranceRelation::getInsuranceId));
// 目标保险
List<InsuranceManager> goal = new ArrayList<>();
insuranceManagers.forEach(model->{
if(insuranceMap.containsKey(model.getId())){
goal.add(model);
}
});
result.setInsuranceManagers(goal);
}
return AjaxResult.success(result); return AjaxResult.success(result);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -331,6 +695,186 @@ public class GoodsController extends BaseController {
} }
} }
/**
* 根据商品ID和用户位置获取服务店铺列表
* @return 服务店铺列表按距离排序
*/
@PostMapping("/getShopsByGoodsId")
@ResponseBody
public AjaxResult getShopsByGoodsId(@RequestBody JSONObject requestBody) {
try {
Long goodsId = requestBody.getLong("goodsId");
Double latitude = requestBody.getDouble("latitude");
Double longitude = requestBody.getDouble("longitude");
String provinceName = requestBody.getString("provinceName");
String cityName = requestBody.getString("cityName");
String countryName = requestBody.getString("countryName");
String streetName = requestBody.getString("streetName");
String address = requestBody.getString("address");
if (goodsId == null) {
return AjaxResult.error("商品ID不能为空");
}
// 如果用户没有提供经纬度但有详细地址则通过地址获取经纬度
if ((latitude == null || longitude == null) &&
(provinceName != null || cityName != null || countryName != null ||
streetName != null || address != null)) {
try {
// 使用BaiduMapUtils工具类获取经纬度
Map<String, Double> coordinates = baiduMapUtils.getCoordinatesByAddress(
provinceName, cityName, countryName, streetName, address
);
if (coordinates != null) {
longitude = coordinates.get("longitude");
latitude = coordinates.get("latitude");
logger.info("通过地址获取到用户经纬度: 经度={}, 纬度={}", longitude, latitude);
} else {
logger.warn("通过地址获取用户经纬度失败");
}
} catch (Exception e) {
logger.error("调用百度地图API异常: {}", e.getMessage(), e);
}
}
// 获取商品信息
Goods goods = goodsService.selectById(goodsId);
if (goods == null) {
return AjaxResult.error("商品不存在");
}
List<Shop> serviceShops = new ArrayList<>();
// 通过商品的服务类目获取服务店铺
if (goods.getDeptGoodsCategoryId() != null) {
try {
// 1. 通过商品的类目ID获取类目信息
DeptGoodsCategory deptGoodsCategory = deptGoodsCategoryService.selectOneByGoodsCategoryId(goods.getDeptGoodsCategoryId());
Long serviceCategoryId = null;
if (deptGoodsCategory != null) {
// 先检查当前类目是否有服务类目ID
if (deptGoodsCategory.getServiceCategoryId() != null) {
serviceCategoryId = deptGoodsCategory.getServiceCategoryId();
logger.debug("当前类目[{}]的服务类目ID: {}", deptGoodsCategory.getGoodsCategoryName(), serviceCategoryId);
} else {
// 如果当前类目没有服务类目ID查找上一级类目
logger.debug("当前类目[{}]未配置服务类目ID查找上一级类目", deptGoodsCategory.getGoodsCategoryName());
if (deptGoodsCategory.getParentCategoryId() != null) {
DeptGoodsCategory parentCategory = deptGoodsCategoryService.selectOneByGoodsCategoryId(deptGoodsCategory.getParentCategoryId());
if (parentCategory != null && parentCategory.getServiceCategoryId() != null) {
serviceCategoryId = parentCategory.getServiceCategoryId();
logger.debug("上一级类目[{}]的服务类目ID: {}", parentCategory.getGoodsCategoryName(), serviceCategoryId);
} else {
logger.debug("上一级类目[{}]也未配置服务类目ID", parentCategory != null ? parentCategory.getGoodsCategoryName() : "null");
}
} else {
logger.debug("当前类目没有父级类目");
}
}
}
List<Goods> goodsList = new ArrayList<>();
if (serviceCategoryId != null) {
// 2. 通过服务类目ID查询所有使用该服务类目的商品
Goods queryGoods = new Goods();
queryGoods.setDeptGoodsCategoryId(serviceCategoryId);
queryGoods.setStatus(0); // 只查询上架的商品
goodsList = goodsService.selectGoodsList(queryGoods);
if (goodsList.size() == 0) {
DeptGoodsCategory deptGoodsCategory1 = deptGoodsCategoryService.selectOneByGoodsCategoryId(serviceCategoryId);
serviceCategoryId = deptGoodsCategory1.getDeptGoodsCategoryId();
// 直接使用新方法获取商品列表
goodsList = goodsStandardService.selectGoodsByDeptGoodsCategoryId(serviceCategoryId);
// 过滤只保留上架的商品
goodsList = goodsList.stream()
.filter(g -> g.getStatus() != null && g.getStatus() == 0)
.collect(Collectors.toList());
}
logger.info("获取到的服务类目id{} 取到的商品列表:{}", serviceCategoryId, goodsList);
}
if (!goodsList.isEmpty()) {
logger.debug("通过商品ID[{}]找到{}个相关服务商品", goodsId, goodsList.size());
// 提取所有店铺ID去重
Set<Long> shopIds = goodsList.stream()
.filter(g -> g.getShopId() != null)
.map(Goods::getShopId)
.collect(Collectors.toSet());
if (!shopIds.isEmpty()) {
// 获取所有店铺信息并计算距离
for (Long shopId : shopIds) {
Shop shop = shopService.getShop(shopId);
if (shop != null) {
// 计算距离
if (LocationUtils.isValidCoordinate(latitude, longitude) &&
LocationUtils.isValidCoordinate(shop.getLatitude(), shop.getLongitude())) {
try {
double distanceInMeters = LocationUtils.getDistanceInMeters(
latitude, longitude,
shop.getLatitude(), shop.getLongitude()
);
shop.setDistance(LocationUtils.formatDistance(distanceInMeters));
} catch (Exception e) {
logger.warn("计算店铺[{}]距离失败: {}", shop.getShopName(), e.getMessage());
shop.setDistance(null);
}
} else {
shop.setDistance(null);
}
serviceShops.add(shop);
}
}
// 按距离排序有距离的排在前面然后按距离升序
serviceShops.sort((s1, s2) -> {
if (s1.getDistance() == null && s2.getDistance() == null) {
return 0;
}
if (s1.getDistance() == null) {
return 1;
}
if (s2.getDistance() == null) {
return -1;
}
// 提取距离数值进行比较
try {
double d1 = Double.parseDouble(s1.getDistance().replaceAll("[^0-9.]", ""));
double d2 = Double.parseDouble(s2.getDistance().replaceAll("[^0-9.]", ""));
return Double.compare(d1, d2);
} catch (Exception e) {
return 0;
}
});
}
} else {
logger.debug("未找到商品ID[{}]的相关服务商品", goodsId);
}
} catch (Exception e) {
logger.warn("获取服务店铺信息失败: {}", e.getMessage());
}
}
JSONObject result = new JSONObject();
result.put("goodsId", goodsId);
result.put("goodsName", goods.getGoodsName());
result.put("userLatitude", latitude);
result.put("userLongitude", longitude);
result.put("serviceShops", serviceShops);
result.put("totalCount", serviceShops.size());
return AjaxResult.success(result);
} catch (Exception e) {
logger.error("获取服务店铺列表失败: {}", e.getMessage(), e);
return AjaxResult.error("获取服务店铺列表失败: " + ExceptionUtil.getExceptionMessage(e));
}
}
@Log(title = "商品管理", businessType = BusinessType.EXPORT) @Log(title = "商品管理", businessType = BusinessType.EXPORT)
@RequiresPermissions("goods:goods:export") @RequiresPermissions("goods:goods:export")
@PostMapping("/export") @PostMapping("/export")
@ -401,13 +945,26 @@ public class GoodsController extends BaseController {
@ResponseBody @ResponseBody
public AjaxResult editSave(@Validated Goods goods) { public AjaxResult editSave(@Validated Goods goods) {
goods.setUpdateBy(getLoginName()); goods.setUpdateBy(getLoginName());
// 处理Long类型字段的空值情况
// 当前端传入0或空字符串时将shopId设置为null以便清空
if (goods.getShopId() != null && goods.getShopId().equals(0L)) {
goods.setShopId(null);
}
return toAjax(goodsService.updateGoods(goods)); return toAjax(goodsService.updateGoods(goods));
} }
@PostMapping("/app/edit") @PostMapping("/app/edit")
@ResponseBody @ResponseBody
public AjaxResult appEditSave(@RequestBody @Validated Goods goods) { public AjaxResult appEditSave(@RequestBody @Validated Goods goods) {
// 处理Long类型字段的空值情况
// 当前端传入0或空字符串时将shopId设置为null以便清空
if (goods.getShopId() != null && goods.getShopId().equals(0L)) {
goods.setShopId(null);
}
goodsService.edit(goods); goodsService.edit(goods);
return AjaxResult.success(); return AjaxResult.success();
} }
@ -467,4 +1024,6 @@ public class GoodsController extends BaseController {
return AjaxResult.error(ExceptionUtil.getExceptionMessage(e)); return AjaxResult.error(ExceptionUtil.getExceptionMessage(e));
} }
} }
} }

View File

@ -1,5 +1,7 @@
package com.ghy.web.controller.goods; package com.ghy.web.controller.goods;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.ghy.common.annotation.Log; import com.ghy.common.annotation.Log;
import com.ghy.common.core.controller.BaseController; import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
@ -10,10 +12,8 @@ import com.ghy.common.enums.ImgType;
import com.ghy.common.utils.ExceptionUtil; import com.ghy.common.utils.ExceptionUtil;
import com.ghy.common.utils.ShiroUtils; import com.ghy.common.utils.ShiroUtils;
import com.ghy.common.utils.StringUtils; import com.ghy.common.utils.StringUtils;
import com.ghy.goods.domain.DeptGoodsCategory; import com.ghy.goods.domain.*;
import com.ghy.goods.domain.GoodsImgs; import com.ghy.goods.service.*;
import com.ghy.goods.service.DeptGoodsCategoryService;
import com.ghy.goods.service.GoodsImgsService;
import com.ghy.web.pojo.vo.AppCategoryRequest; import com.ghy.web.pojo.vo.AppCategoryRequest;
import com.ghy.web.pojo.vo.HotCategoryResponse; import com.ghy.web.pojo.vo.HotCategoryResponse;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -30,6 +30,7 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Controller @Controller
@CrossOrigin(origins = "*")
@RequestMapping("goods/deptcategory") @RequestMapping("goods/deptcategory")
public class GoodsDeptCategoryController extends BaseController { public class GoodsDeptCategoryController extends BaseController {
@ -38,6 +39,18 @@ public class GoodsDeptCategoryController extends BaseController {
@Resource @Resource
DeptGoodsCategoryService deptGoodsCategoryService; DeptGoodsCategoryService deptGoodsCategoryService;
@Resource
private GoodsCategoryService goodsCategoryService;
@Resource
ICategoryInsuranceRelationService categoryInsuranceRelationService;
@Resource
IDeptCategoryInsuranceRelationService deptCategoryInsuranceRelationService;
@Resource
IInsuranceManagerService insuranceManagerService;
@Autowired @Autowired
private GoodsImgsService goodsImgsService; private GoodsImgsService goodsImgsService;
@ -145,6 +158,57 @@ public class GoodsDeptCategoryController extends BaseController {
@GetMapping("/edit/{id}") @GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap) { public String edit(@PathVariable("id") Long id, ModelMap mmap) {
DeptGoodsCategory deptGoodsCategory = deptGoodsCategoryService.get(id); DeptGoodsCategory deptGoodsCategory = deptGoodsCategoryService.get(id);
CategoryInsuranceRelation relation = new CategoryInsuranceRelation();
relation.setGoodsCategoryId(deptGoodsCategory.getGoodsCategoryId());
List<CategoryInsuranceRelation> relations = categoryInsuranceRelationService.selectCategoryInsuranceRelationList(relation);
// 当第四级没有的时候往上找三级
if(CollectionUtil.isEmpty(relations)){
GoodsCategory model = goodsCategoryService.selectById(deptGoodsCategory.getGoodsCategoryId());
CategoryInsuranceRelation parentRelation = new CategoryInsuranceRelation();
parentRelation.setGoodsCategoryId(model.getParentCategoryId());
relations = categoryInsuranceRelationService.selectCategoryInsuranceRelationList(parentRelation);
// 当第三级没有的时候往上找二级
if(CollectionUtil.isEmpty(relations)){
GoodsCategory parentModel = goodsCategoryService.selectById(model.getParentCategoryId());
CategoryInsuranceRelation topRelation = new CategoryInsuranceRelation();
topRelation.setGoodsCategoryId(parentModel.getParentCategoryId());
relations = categoryInsuranceRelationService.selectCategoryInsuranceRelationList(topRelation);
}
}
// pc保险设置
List<InsuranceManager> pcInsuranceList = new ArrayList<>();
// 商城保险设置
List<InsuranceManager> shopInsuranceList = new ArrayList<>();
if(CollectionUtil.isNotEmpty(relations)){
List<InsuranceManager> list = insuranceManagerService.selectByIds(relations.stream().map(CategoryInsuranceRelation::getInsuranceId).collect(Collectors.toList()));
list.forEach(model->{
model.setInsuranceName(model.getCompanyName() + "||" + model.getInsuranceName() + "||" + model.getInsuranceAmount() + "");
// 查看pc勾选状态
DeptCategoryInsuranceRelation pcParam = new DeptCategoryInsuranceRelation();
pcParam.setType("02");
pcParam.setInsuranceId(model.getId());
pcParam.setDeptCategoryId(deptGoodsCategory.getDeptGoodsCategoryId());
InsuranceManager pcModel = new InsuranceManager();
BeanUtil.copyProperties(model, pcModel);
if(CollectionUtil.isNotEmpty(deptCategoryInsuranceRelationService.selectDeptCategoryInsuranceRelationList(pcParam))){
pcModel.setFlag(true);
}
pcInsuranceList.add(pcModel);
DeptCategoryInsuranceRelation shopParam = new DeptCategoryInsuranceRelation();
shopParam.setType("01");
shopParam.setInsuranceId(model.getId());
shopParam.setDeptCategoryId(deptGoodsCategory.getDeptGoodsCategoryId());
InsuranceManager shopModel = new InsuranceManager();
BeanUtil.copyProperties(model, shopModel);
if(CollectionUtil.isNotEmpty(deptCategoryInsuranceRelationService.selectDeptCategoryInsuranceRelationList(shopParam))){
shopModel.setFlag(true);
}
shopInsuranceList.add(shopModel);
});
}
mmap.put("pcInsurances", pcInsuranceList);
mmap.put("shopInsurances", shopInsuranceList);
mmap.put("deptGoodsCategory", deptGoodsCategory); mmap.put("deptGoodsCategory", deptGoodsCategory);
return PREFIX + "/edit"; return PREFIX + "/edit";
} }
@ -153,6 +217,8 @@ public class GoodsDeptCategoryController extends BaseController {
@PostMapping("/edit") @PostMapping("/edit")
@ResponseBody @ResponseBody
public AjaxResult edit(DeptGoodsCategory category) { public AjaxResult edit(DeptGoodsCategory category) {
// 更新保险设置
deptCategoryInsuranceRelationService.updateDeptCategoryInsuranceRelation(category.getPcInsuranceIds(), category.getShopInsuranceIds(), category.getDeptGoodsCategoryId());
category.setUpdateBy(getLoginName()); category.setUpdateBy(getLoginName());
deptGoodsCategoryService.edit(category); deptGoodsCategoryService.edit(category);
return AjaxResult.success(); return AjaxResult.success();

View File

@ -3,6 +3,7 @@ package com.ghy.web.controller.goods;
import com.ghy.common.core.controller.BaseController; import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.core.page.TableDataInfo; import com.ghy.common.core.page.TableDataInfo;
import com.ghy.goods.domain.Goods;
import com.ghy.goods.domain.GoodsStandard; import com.ghy.goods.domain.GoodsStandard;
import com.ghy.goods.service.GoodsStandardService; import com.ghy.goods.service.GoodsStandardService;
import com.ghy.order.domain.OrderTemplate; import com.ghy.order.domain.OrderTemplate;
@ -64,4 +65,14 @@ public class GoodsStandardController extends BaseController {
return toAjax(goodsStandardService.save(goodsStandardList)); return toAjax(goodsStandardService.save(goodsStandardList));
} }
/**
* 根据部门商品分类ID获取商品列表
*/
@ResponseBody
@GetMapping("/goods/by-dept-category/{deptGoodsCategoryId}")
public AjaxResult getGoodsByDeptCategoryId(@PathVariable("deptGoodsCategoryId") Long deptGoodsCategoryId) {
List<Goods> goodsList = goodsStandardService.selectGoodsByDeptGoodsCategoryId(deptGoodsCategoryId);
return AjaxResult.success(goodsList);
}
} }

View File

@ -0,0 +1,135 @@
package com.ghy.web.controller.goods;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ghy.common.annotation.Log;
import com.ghy.common.enums.BusinessType;
import com.ghy.goods.domain.InsuranceManager;
import com.ghy.goods.service.IInsuranceManagerService;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.common.core.page.TableDataInfo;
/**
* 保险管理Controller
*
* @author clunt
* @date 2024-09-25
*/
@Controller
@RequestMapping("/goods/manager")
public class InsuranceManagerController extends BaseController
{
private String prefix = "goods/manager";
@Autowired
private IInsuranceManagerService insuranceManagerService;
@RequiresPermissions("goods:manager:view")
@GetMapping()
public String manager()
{
return prefix + "/manager";
}
/**
* 查询保险管理列表
*/
@RequiresPermissions("goods:manager:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(InsuranceManager insuranceManager)
{
startPage();
List<InsuranceManager> list = insuranceManagerService.selectInsuranceManagerList(insuranceManager);
return getDataTable(list);
}
/**
* App查询保险管理列表
*/
@PostMapping("/app/list")
@ResponseBody
public TableDataInfo appList(@RequestBody InsuranceManager insuranceManager)
{
startPage();
List<InsuranceManager> list = insuranceManagerService.selectInsuranceManagerList(insuranceManager);
return getDataTable(list);
}
/**
* 导出保险管理列表
*/
@RequiresPermissions("goods:manager:export")
@Log(title = "保险管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(InsuranceManager insuranceManager)
{
List<InsuranceManager> list = insuranceManagerService.selectInsuranceManagerList(insuranceManager);
ExcelUtil<InsuranceManager> util = new ExcelUtil<InsuranceManager>(InsuranceManager.class);
return util.exportExcel(list, "保险管理数据");
}
/**
* 新增保险管理
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存保险管理
*/
@RequiresPermissions("goods:manager:add")
@Log(title = "保险管理", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(InsuranceManager insuranceManager)
{
return toAjax(insuranceManagerService.insertInsuranceManager(insuranceManager));
}
/**
* 修改保险管理
*/
@RequiresPermissions("goods:manager:edit")
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
InsuranceManager insuranceManager = insuranceManagerService.selectInsuranceManagerById(id);
mmap.put("insuranceManager", insuranceManager);
return prefix + "/edit";
}
/**
* 修改保存保险管理
*/
@RequiresPermissions("goods:manager:edit")
@Log(title = "保险管理", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(InsuranceManager insuranceManager)
{
return toAjax(insuranceManagerService.updateInsuranceManager(insuranceManager));
}
/**
* 删除保险管理
*/
@RequiresPermissions("goods:manager:remove")
@Log(title = "保险管理", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(insuranceManagerService.deleteInsuranceManagerByIds(ids));
}
}

View File

@ -0,0 +1,88 @@
package com.ghy.web.controller.order;
import java.math.BigDecimal;
/**
* 售后纠纷处理请求
*
* @author system
* @date 2024-12-19
*/
public class AfterServiceDisputeRequest {
/**
* 售后记录ID
*/
private String recordId;
/**
* 主单ID
*/
private Long orderMasterId;
/**
* 子单ID
*/
private Long orderDetailId;
/**
* 退款金额
*/
private BigDecimal refundAmount;
/**
* 售后纠纷平台处理原因
*/
private String platformHandleReason;
public String getRecordId() {
return recordId;
}
public void setRecordId(String recordId) {
this.recordId = recordId;
}
public Long getOrderMasterId() {
return orderMasterId;
}
public void setOrderMasterId(Long orderMasterId) {
this.orderMasterId = orderMasterId;
}
public Long getOrderDetailId() {
return orderDetailId;
}
public void setOrderDetailId(Long orderDetailId) {
this.orderDetailId = orderDetailId;
}
public BigDecimal getRefundAmount() {
return refundAmount;
}
public void setRefundAmount(BigDecimal refundAmount) {
this.refundAmount = refundAmount;
}
public String getPlatformHandleReason() {
return platformHandleReason;
}
public void setPlatformHandleReason(String platformHandleReason) {
this.platformHandleReason = platformHandleReason;
}
@Override
public String toString() {
return "AfterServiceDisputeRequest{" +
"recordId='" + recordId + '\'' +
", orderMasterId=" + orderMasterId +
", orderDetailId=" + orderDetailId +
", refundAmount=" + refundAmount +
", platformHandleReason='" + platformHandleReason + '\'' +
'}';
}
}

View File

@ -108,7 +108,7 @@ public class AfterServiceRecordController extends BaseController {
public AjaxResult addSave(@RequestBody AfterServiceRecord afterServiceRecord) { public AjaxResult addSave(@RequestBody AfterServiceRecord afterServiceRecord) {
logger.info("新增售后记录:{}", afterServiceRecord); logger.info("新增售后记录:{}", afterServiceRecord);
OrderDetail orderDetail = orderDetailService.selectById(afterServiceRecord.getOrderDetailId()); OrderDetail orderDetail = orderDetailService.selectById(afterServiceRecord.getOrderDetailId());
if(orderDetail.getDrawCashTime() != null){ if (orderDetail.getDrawCashTime() != null) {
return AjaxResult.error("已发起分账子单,请联系师傅处理线下售后!"); return AjaxResult.error("已发起分账子单,请联系师傅处理线下售后!");
} }
return toAjax(afterServiceRecordService.insertAfterServiceRecord(afterServiceRecord)); return toAjax(afterServiceRecordService.insertAfterServiceRecord(afterServiceRecord));
@ -134,11 +134,22 @@ public class AfterServiceRecordController extends BaseController {
public AjaxResult editSave(@RequestBody AfterServiceRecord afterServiceRecord) { public AjaxResult editSave(@RequestBody AfterServiceRecord afterServiceRecord) {
logger.info("修改售后记录:{}", afterServiceRecord); logger.info("修改售后记录:{}", afterServiceRecord);
try { try {
OrderDetail orderDetail = orderDetailService.selectById(afterServiceRecord.getOrderDetailId()); return afterServiceRecordService.updateAfterServiceRecord(afterServiceRecord);
if(orderDetail.getDrawCashTime() != null){ } catch (Exception exception) {
return AjaxResult.error("已发起分账子单,请联系师傅处理线下售后!"); logger.error(ExceptionUtils.getStackTrace(exception));
} return AjaxResult.error(exception.getMessage());
return toAjax(afterServiceRecordService.updateAfterServiceRecord(afterServiceRecord)); }
}
/**
* 修改商品售后记录
*/
@PostMapping("/editGoods")
@ResponseBody
public AjaxResult editGoodsSave(@RequestBody AfterServiceRecord afterServiceRecord) {
logger.info("修改商品售后记录:{}", afterServiceRecord);
try {
return afterServiceRecordService.updateGoodsAfterServiceRecord(afterServiceRecord);
} catch (Exception exception) { } catch (Exception exception) {
logger.error(ExceptionUtils.getStackTrace(exception)); logger.error(ExceptionUtils.getStackTrace(exception));
return AjaxResult.error(exception.getMessage()); return AjaxResult.error(exception.getMessage());
@ -155,4 +166,34 @@ public class AfterServiceRecordController extends BaseController {
public AjaxResult remove(String ids) { public AjaxResult remove(String ids) {
return toAjax(afterServiceRecordService.deleteAfterServiceRecordByIds(ids)); return toAjax(afterServiceRecordService.deleteAfterServiceRecordByIds(ids));
} }
/**
* 师傅重发/补发操作
* 师傅端点击重发补发按钮保存重发/补发方案
*/
@PostMapping("/workerResendPlan")
@ResponseBody
public AjaxResult workerResendPlan(@RequestBody AfterServiceRecord afterServiceRecord) {
return afterServiceRecordService.workerResendPlan(afterServiceRecord);
}
/**
* 退货操作
* 客户或师傅端进行退货操作保存退货信息
*/
@PostMapping("/returnGoods")
@ResponseBody
public AjaxResult returnGoods(@RequestBody AfterServiceRecord afterServiceRecord) {
return afterServiceRecordService.returnGoods(afterServiceRecord);
}
/**
* 师傅确认收货
* 师傅确认收到货物后根据同意处理方式决定是否执行退款
*/
@PostMapping("/workerConfirmReceive")
@ResponseBody
public AjaxResult workerConfirmReceive(@RequestBody AfterServiceRecord afterServiceRecord) {
return afterServiceRecordService.workerConfirmReceive(afterServiceRecord);
}
} }

View File

@ -0,0 +1,143 @@
package com.ghy.web.controller.order;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ghy.common.annotation.Log;
import com.ghy.common.enums.BusinessType;
import com.ghy.order.domain.OrderAddRecord;
import com.ghy.order.service.IOrderAddRecordService;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.common.core.page.TableDataInfo;
/**
* 发单加价记录Controller
*
* @author clunt
* @date 2023-11-03
*/
@Controller
@RequestMapping("/add/record")
public class OrderAddRecordController extends BaseController
{
private String prefix = "add/record";
@Autowired
private IOrderAddRecordService orderAddRecordService;
@RequiresPermissions("worker:record:view")
@GetMapping()
public String record()
{
return prefix + "/record";
}
/**
* 查询发单加价记录列表
*/
@RequiresPermissions("worker:record:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(OrderAddRecord orderAddRecord)
{
startPage();
List<OrderAddRecord> list = orderAddRecordService.selectOrderAddRecordList(orderAddRecord);
return getDataTable(list);
}
/**
* App查询发单加价记录列表
*/
@PostMapping("/app/list")
@ResponseBody
public TableDataInfo appList(@RequestBody OrderAddRecord orderAddRecord)
{
startPage();
List<OrderAddRecord> list = orderAddRecordService.selectOrderAddRecordList(orderAddRecord);
return getDataTable(list);
}
@PostMapping("/app/add")
@ResponseBody
public AjaxResult appAddSave(@RequestBody OrderAddRecord orderAddRecord)
{
return toAjax(orderAddRecordService.insertOrderAddRecord(orderAddRecord));
}
/**
* 导出发单加价记录列表
*/
@RequiresPermissions("worker:record:export")
@Log(title = "发单加价记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(OrderAddRecord orderAddRecord)
{
List<OrderAddRecord> list = orderAddRecordService.selectOrderAddRecordList(orderAddRecord);
ExcelUtil<OrderAddRecord> util = new ExcelUtil<OrderAddRecord>(OrderAddRecord.class);
return util.exportExcel(list, "发单加价记录数据");
}
/**
* 新增发单加价记录
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存发单加价记录
*/
@RequiresPermissions("worker:record:add")
@Log(title = "发单加价记录", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(OrderAddRecord orderAddRecord)
{
return toAjax(orderAddRecordService.insertOrderAddRecord(orderAddRecord));
}
/**
* 修改发单加价记录
*/
@RequiresPermissions("worker:record:edit")
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
OrderAddRecord orderAddRecord = orderAddRecordService.selectOrderAddRecordById(id);
mmap.put("orderAddRecord", orderAddRecord);
return prefix + "/edit";
}
/**
* 修改保存发单加价记录
*/
@RequiresPermissions("worker:record:edit")
@Log(title = "发单加价记录", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(OrderAddRecord orderAddRecord)
{
return toAjax(orderAddRecordService.updateOrderAddRecord(orderAddRecord));
}
/**
* 删除发单加价记录
*/
@RequiresPermissions("worker:record:remove")
@Log(title = "发单加价记录", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(orderAddRecordService.deleteOrderAddRecordByIds(ids));
}
}

View File

@ -0,0 +1,157 @@
package com.ghy.web.controller.order;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ghy.common.annotation.Log;
import com.ghy.common.enums.BusinessType;
import com.ghy.order.domain.OrderAttachmentRecord;
import com.ghy.order.service.IOrderAttachmentRecordService;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.common.core.page.TableDataInfo;
/**
* 附件费Controller
*
* @author clunt
* @date 2024-01-02
*/
@Controller
@RequestMapping("/order/attach")
public class OrderAttachmentRecordController extends BaseController
{
private String prefix = "order/attach";
@Autowired
private IOrderAttachmentRecordService orderAttachmentRecordService;
@RequiresPermissions("attach:record:view")
@GetMapping()
public String record()
{
return prefix + "/record";
}
/**
* 查询附件费列表
*/
@RequiresPermissions("attach:record:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(OrderAttachmentRecord orderAttachmentRecord)
{
startPage();
List<OrderAttachmentRecord> list = orderAttachmentRecordService.selectOrderAttachmentRecordList(orderAttachmentRecord);
return getDataTable(list);
}
/**
* App查询附件费列表
*/
@PostMapping("/app/list")
@ResponseBody
public TableDataInfo appList(@RequestBody OrderAttachmentRecord orderAttachmentRecord)
{
startPage();
List<OrderAttachmentRecord> list = orderAttachmentRecordService.selectOrderAttachmentRecordList(orderAttachmentRecord);
return getDataTable(list);
}
/**
* 导出附件费列表
*/
@RequiresPermissions("attach:record:export")
@Log(title = "附件费", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(OrderAttachmentRecord orderAttachmentRecord)
{
List<OrderAttachmentRecord> list = orderAttachmentRecordService.selectOrderAttachmentRecordList(orderAttachmentRecord);
ExcelUtil<OrderAttachmentRecord> util = new ExcelUtil<OrderAttachmentRecord>(OrderAttachmentRecord.class);
return util.exportExcel(list, "附件费数据");
}
/**
* 新增附件费
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存附件费
*/
@RequiresPermissions("attach:record:add")
@Log(title = "附件费", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(OrderAttachmentRecord orderAttachmentRecord)
{
return toAjax(orderAttachmentRecordService.insertOrderAttachmentRecord(orderAttachmentRecord));
}
@PostMapping("/appAdd")
@ResponseBody
public AjaxResult appAdd(OrderAttachmentRecord orderAttachmentRecord)
{
return toAjax(orderAttachmentRecordService.insertOrderAttachmentRecord(orderAttachmentRecord));
}
/**
* 修改附件费
*/
@RequiresPermissions("attach:record:edit")
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
OrderAttachmentRecord orderAttachmentRecord = orderAttachmentRecordService.selectOrderAttachmentRecordById(id);
mmap.put("orderAttachmentRecord", orderAttachmentRecord);
return prefix + "/edit";
}
/**
* 修改保存附件费
*/
@RequiresPermissions("attach:record:edit")
@Log(title = "附件费", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(OrderAttachmentRecord orderAttachmentRecord)
{
return toAjax(orderAttachmentRecordService.updateOrderAttachmentRecord(orderAttachmentRecord));
}
/**
* 删除附件费
*/
@RequiresPermissions("attach:record:remove")
@Log(title = "附件费", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(orderAttachmentRecordService.deleteOrderAttachmentRecordByIds(ids));
}
/**
* 删除附件费 根据子单id
*/
@PostMapping( "/deleteByDetailId")
@ResponseBody
public AjaxResult deleteByDetailId(@RequestParam Long orderDetailId)
{
return toAjax(orderAttachmentRecordService.deleteOrderAttachmentRecordByOrderDetailId(orderDetailId));
}
}

View File

@ -0,0 +1,137 @@
package com.ghy.web.controller.order;
import java.util.List;
import com.ghy.order.domain.OrderCallRecord;
import com.ghy.order.service.IOrderCallRecordService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ghy.common.annotation.Log;
import com.ghy.common.enums.BusinessType;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.common.core.page.TableDataInfo;
/**
* 订单约单记录Controller
*
* @author clunt
* @date 2023-06-04
*/
@Controller
@RequestMapping("/order/record")
public class OrderCallRecordController extends BaseController
{
private String prefix = "order/record";
@Autowired
private IOrderCallRecordService orderCallRecordService;
// @RequiresPermissions("worker:record:view")
@GetMapping()
public String record(Long orderId, ModelMap mmap)
{
mmap.put("orderId", orderId);
return prefix;
}
/**
* 查询订单约单记录列表
*/
@RequiresPermissions("worker:record:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(OrderCallRecord orderCallRecord)
{
startPage();
List<OrderCallRecord> list = orderCallRecordService.selectOrderCallRecordList(orderCallRecord);
return getDataTable(list);
}
/**
* App查询订单约单记录列表
*/
@PostMapping("/app/list")
@ResponseBody
public TableDataInfo appList(@RequestBody OrderCallRecord orderCallRecord)
{
startPage();
List<OrderCallRecord> list = orderCallRecordService.selectOrderCallRecordList(orderCallRecord);
return getDataTable(list);
}
/**
* 导出订单约单记录列表
*/
@RequiresPermissions("worker:record:export")
@Log(title = "订单约单记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(OrderCallRecord orderCallRecord)
{
List<OrderCallRecord> list = orderCallRecordService.selectOrderCallRecordList(orderCallRecord);
ExcelUtil<OrderCallRecord> util = new ExcelUtil<OrderCallRecord>(OrderCallRecord.class);
return util.exportExcel(list, "订单约单记录数据");
}
/**
* 新增订单约单记录
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存订单约单记录
*/
@RequiresPermissions("worker:record:add")
@Log(title = "订单约单记录", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(OrderCallRecord orderCallRecord)
{
return toAjax(orderCallRecordService.insertOrderCallRecord(orderCallRecord));
}
/**
* 修改订单约单记录
*/
@RequiresPermissions("worker:record:edit")
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
OrderCallRecord orderCallRecord = orderCallRecordService.selectOrderCallRecordById(id);
mmap.put("orderCallRecord", orderCallRecord);
return prefix + "/edit";
}
/**
* 修改保存订单约单记录
*/
@RequiresPermissions("worker:record:edit")
@Log(title = "订单约单记录", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(OrderCallRecord orderCallRecord)
{
return toAjax(orderCallRecordService.updateOrderCallRecord(orderCallRecord));
}
/**
* 删除订单约单记录
*/
@RequiresPermissions("worker:record:remove")
@Log(title = "订单约单记录", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(orderCallRecordService.deleteOrderCallRecordByIds(ids));
}
}

View File

@ -0,0 +1,159 @@
package com.ghy.web.controller.order;
import java.util.List;
import com.ghy.web.pojo.vo.CertNoTwoElementReq;
import com.ghy.web.service.AliCloudService;
import com.ghy.web.service.InsuranceService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ghy.common.annotation.Log;
import com.ghy.common.enums.BusinessType;
import com.ghy.order.domain.OrderDetailInsuranceUser;
import com.ghy.order.service.IOrderDetailInsuranceUserService;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.common.core.page.TableDataInfo;
/**
* 订单保险人员Controller
*
* @author clunt
* @date 2024-10-21
*/
@Slf4j
@Controller
@RequestMapping("/insurance/user")
public class OrderDetailInsuranceUserController extends BaseController
{
private String prefix = "insurance/user";
@Autowired
private IOrderDetailInsuranceUserService orderDetailInsuranceUserService;
@Autowired
private AliCloudService aliCloudService;
@Autowired
private InsuranceService insuranceService;
@RequiresPermissions("worker:user:view")
@GetMapping()
public String user()
{
return prefix + "/user";
}
/**
* 查询订单保险人员列表
*/
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(OrderDetailInsuranceUser orderDetailInsuranceUser)
{
startPage();
List<OrderDetailInsuranceUser> list = orderDetailInsuranceUserService.selectOrderDetailInsuranceUserList(orderDetailInsuranceUser);
return getDataTable(list);
}
/**
* App查询订单保险人员列表
*/
@PostMapping("/app/list")
@ResponseBody
public TableDataInfo appList(@RequestBody OrderDetailInsuranceUser orderDetailInsuranceUser)
{
startPage();
List<OrderDetailInsuranceUser> list = orderDetailInsuranceUserService.selectOrderDetailInsuranceUserList(orderDetailInsuranceUser);
return getDataTable(list);
}
/**
* 导出订单保险人员列表
*/
@PostMapping("/export")
@ResponseBody
public AjaxResult export(OrderDetailInsuranceUser orderDetailInsuranceUser)
{
List<OrderDetailInsuranceUser> list = orderDetailInsuranceUserService.selectOrderDetailInsuranceUserList(orderDetailInsuranceUser);
ExcelUtil<OrderDetailInsuranceUser> util = new ExcelUtil<OrderDetailInsuranceUser>(OrderDetailInsuranceUser.class);
return util.exportExcel(list, "订单保险人员数据");
}
/**
* 新增订单保险人员
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存订单保险人员
*/
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(@RequestBody OrderDetailInsuranceUser orderDetailInsuranceUser)
{
// 先校验身份证信息是否ok
CertNoTwoElementReq req = new CertNoTwoElementReq();
req.setCertName(orderDetailInsuranceUser.getName());
req.setCertNo(orderDetailInsuranceUser.getIdCardNum());
try {
aliCloudService.certNoTwoElementVerification(req);
} catch (Exception e) {
log.error("身份证二要素校验失败:{}", e.getMessage(), e);
return AjaxResult.error("请核对姓名与身份证号!");
}
// 将保险人员增员到原保险订单上去
try {
insuranceService.editInsurance(orderDetailInsuranceUser);
orderDetailInsuranceUserService.insertOrderDetailInsuranceUser(orderDetailInsuranceUser);
return AjaxResult.success("增员完毕,保险已生效。");
}catch (Exception e){
log.error("保险增员失败:{}", e.getMessage(), e);
return AjaxResult.error("保险正生成中,可能需几秒或几分钟,请稍等即可!若超半小时可联系发单方或平台。");
}
}
/**
* 修改订单保险人员
*/
@RequiresPermissions("worker:user:edit")
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
OrderDetailInsuranceUser orderDetailInsuranceUser = orderDetailInsuranceUserService.selectOrderDetailInsuranceUserById(id);
mmap.put("orderDetailInsuranceUser", orderDetailInsuranceUser);
return prefix + "/edit";
}
/**
* 修改保存订单保险人员
*/
@RequiresPermissions("worker:user:edit")
@Log(title = "订单保险人员", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(OrderDetailInsuranceUser orderDetailInsuranceUser)
{
return toAjax(orderDetailInsuranceUserService.updateOrderDetailInsuranceUser(orderDetailInsuranceUser));
}
/**
* 删除订单保险人员
*/
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(orderDetailInsuranceUserService.deleteOrderDetailInsuranceUserByIds(ids));
}
}

View File

@ -35,14 +35,23 @@ public class OrderGoodsController extends BaseController {
@Resource @Resource
private OrderMasterService orderMasterService; private OrderMasterService orderMasterService;
@RequiresPermissions("order:goods:view") // @RequiresPermissions("order:goods:view")
@GetMapping() @GetMapping()
public String orderGoods(Long orderId, ModelMap mmap) { public String orderGoods(Long orderId, ModelMap mmap) {
OrderMaster orderMaster = orderMasterService.selectById(orderId); OrderMaster orderMaster = orderMasterService.selectById(orderId);
mmap.put("orderId", orderId);
mmap.put("orderMaster", orderMaster); mmap.put("orderMaster", orderMaster);
return prefix; return prefix;
} }
@GetMapping(value = "/master")
public String orderMasterGoods(Long orderId, ModelMap mmap) {
OrderMaster orderMaster = orderMasterService.selectById(orderId);
mmap.put("orderId", orderId);
mmap.put("orderMaster", orderMaster);
return "order/masterGoods";
}
// @RequiresPermissions("order:goods:list") // @RequiresPermissions("order:goods:list")
@PostMapping("/list") @PostMapping("/list")
@ResponseBody @ResponseBody
@ -53,7 +62,7 @@ public class OrderGoodsController extends BaseController {
} }
@Log(title = "主订单管理", businessType = BusinessType.EXPORT) @Log(title = "主订单管理", businessType = BusinessType.EXPORT)
@RequiresPermissions("order:goods:export") // @RequiresPermissions("order:goods:export")
@PostMapping("/export") @PostMapping("/export")
@ResponseBody @ResponseBody
public AjaxResult export(OrderGoods orderGoods) { public AjaxResult export(OrderGoods orderGoods) {
@ -62,7 +71,7 @@ public class OrderGoodsController extends BaseController {
return util.exportExcel(list, "主订单数据"); return util.exportExcel(list, "主订单数据");
} }
@RequiresPermissions("order:goods:remove") // @RequiresPermissions("order:goods:remove")
@Log(title = "主订单管理", businessType = BusinessType.DELETE) @Log(title = "主订单管理", businessType = BusinessType.DELETE)
@PostMapping("/remove") @PostMapping("/remove")
@ResponseBody @ResponseBody
@ -78,7 +87,7 @@ public class OrderGoodsController extends BaseController {
/** /**
* 修改主订单 * 修改主订单
*/ */
@RequiresPermissions("order:goods:edit") // @RequiresPermissions("order:goods:edit")
@GetMapping("/edit/{orderGoodsId}") @GetMapping("/edit/{orderGoodsId}")
public String edit(@PathVariable("orderGoodsId") Long orderGoodsId, ModelMap mmap) { public String edit(@PathVariable("orderGoodsId") Long orderGoodsId, ModelMap mmap) {
mmap.put("orderGoods", orderGoodsService.selectById(orderGoodsId)); mmap.put("orderGoods", orderGoodsService.selectById(orderGoodsId));

View File

@ -0,0 +1,152 @@
package com.ghy.web.controller.order;
import java.util.List;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ghy.common.annotation.Log;
import com.ghy.common.enums.BusinessType;
import com.ghy.order.domain.OrderOperationRecord;
import com.ghy.order.service.IOrderOperationRecordService;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.common.core.page.TableDataInfo;
/**
* 订单操作记录Controller
*
* @author clunt
* @date 2024-02-17
*/
@Api
@Controller
@RequestMapping("/order/operate")
public class OrderOperationRecordController extends BaseController
{
private String prefix = "order/operate";
@Autowired
private IOrderOperationRecordService orderOperationRecordService;
@RequiresPermissions("order:operate:view")
@GetMapping()
public String record()
{
return prefix + "/operate";
}
/**
* 查询订单操作记录列表
*/
@RequiresPermissions("order:operate:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(OrderOperationRecord orderOperationRecord)
{
startPage();
List<OrderOperationRecord> list = orderOperationRecordService.selectOrderOperationRecordList(orderOperationRecord);
return getDataTable(list);
}
/**
* App查询订单操作记录列表
*/
@ApiOperation("订单操作记录列表")
@PostMapping("/app/list")
@ResponseBody
public TableDataInfo appList(@RequestBody OrderOperationRecord orderOperationRecord)
{
startPage();
List<OrderOperationRecord> list = orderOperationRecordService.selectOrderOperationRecordList(orderOperationRecord);
return getDataTable(list);
}
/**
* 新增保存订单操作记录
*/
@ApiOperation("新增订单操作记录")
@PostMapping("/app/add")
@ResponseBody
public AjaxResult appAdd(@RequestBody OrderOperationRecord orderOperationRecord)
{
return toAjax(orderOperationRecordService.insertOrderOperationRecord(orderOperationRecord));
}
/**
* 导出订单操作记录列表
*/
@RequiresPermissions("order:operate:export")
@Log(title = "订单操作记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(OrderOperationRecord orderOperationRecord)
{
List<OrderOperationRecord> list = orderOperationRecordService.selectOrderOperationRecordList(orderOperationRecord);
ExcelUtil<OrderOperationRecord> util = new ExcelUtil<OrderOperationRecord>(OrderOperationRecord.class);
return util.exportExcel(list, "订单操作记录数据");
}
/**
* 新增订单操作记录
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存订单操作记录
*/
@RequiresPermissions("order:operate:add")
@Log(title = "订单操作记录", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(OrderOperationRecord orderOperationRecord)
{
return toAjax(orderOperationRecordService.insertOrderOperationRecord(orderOperationRecord));
}
/**
* 修改订单操作记录
*/
@RequiresPermissions("order:operate:edit")
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
OrderOperationRecord orderOperationRecord = orderOperationRecordService.selectOrderOperationRecordById(id);
mmap.put("orderOperationRecord", orderOperationRecord);
return prefix + "/edit";
}
/**
* 修改保存订单操作记录
*/
@RequiresPermissions("order:operate:edit")
@Log(title = "订单操作记录", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(OrderOperationRecord orderOperationRecord)
{
return toAjax(orderOperationRecordService.updateOrderOperationRecord(orderOperationRecord));
}
/**
* 删除订单操作记录
*/
@RequiresPermissions("order:operate:remove")
@Log(title = "订单操作记录", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(orderOperationRecordService.deleteOrderOperationRecordByIds(ids));
}
}

View File

@ -0,0 +1,202 @@
package com.ghy.web.controller.order;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.ghy.common.enums.WxMsgEnum;
import com.ghy.common.utils.WechatMsgUtils;
import com.ghy.customer.domain.Customer;
import com.ghy.customer.service.CustomerService;
import com.ghy.order.domain.OrderDetail;
import com.ghy.order.domain.OrderMaster;
import com.ghy.order.service.OrderDetailService;
import com.ghy.order.service.OrderMasterService;
import com.ghy.worker.domain.Worker;
import com.ghy.worker.service.WorkerService;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import com.ghy.common.annotation.Log;
import com.ghy.common.enums.BusinessType;
import com.ghy.order.domain.OrderWarnRecord;
import com.ghy.order.service.IOrderWarnRecordService;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.common.core.page.TableDataInfo;
import javax.annotation.Resource;
/**
* 订单急报记录Controller
*
* @author clunt
* @date 2024-02-18
*/
@Controller
@RequestMapping("/warn/record")
public class OrderWarnRecordController extends BaseController
{
private String prefix = "warn/record";
@Autowired
private IOrderWarnRecordService orderWarnRecordService;
@Resource
private OrderMasterService orderMasterService;
@Resource
private OrderDetailService orderDetailService;
@Resource
private WorkerService workerService;
@Resource
private CustomerService customerService;
@RequiresPermissions("warn:record:view")
@GetMapping()
public String record()
{
return prefix + "/record";
}
/**
* 查询订单急报记录列表
*/
@RequiresPermissions("warn:record:list")
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(OrderWarnRecord orderWarnRecord)
{
startPage();
List<OrderWarnRecord> list = orderWarnRecordService.selectOrderWarnRecordList(orderWarnRecord);
return getDataTable(list);
}
/**
* App查询订单急报记录列表
*/
@ApiOperation("急报操作记录列表")
@PostMapping("/app/list")
@ResponseBody
public TableDataInfo appList(@RequestBody OrderWarnRecord orderWarnRecord)
{
startPage();
List<OrderWarnRecord> list = orderWarnRecordService.selectOrderWarnRecordList(orderWarnRecord);
return getDataTable(list);
}
@ApiOperation("新增急报记录(约单/催单)")
@PostMapping("/app/add")
@ResponseBody
public AjaxResult appAdd(@RequestBody OrderWarnRecord orderWarnRecord)
{
Worker worker;
Customer customer;
if("01".equals(orderWarnRecord.getOrderType())){
OrderMaster orderMaster = orderMasterService.selectById(orderWarnRecord.getOrderId());
worker = workerService.selectById(orderMaster.getWorkerId());
customer = customerService.selectByCustomerId(orderMaster.getCustomerId());
}else {
OrderDetail orderDetail = orderDetailService.selectById(orderWarnRecord.getOrderId());
worker = workerService.selectById(orderDetail.getWorkerId());
customer = customerService.selectByCustomerId(orderDetail.getCustomerId());
}
// 发送急报
// 推送公众号通知数据
try {
// 消息组装
Map<String, Object> params = new HashMap<>();
// 订单编号
params.put("thing3", customer.getName());
// 名称
params.put("thing2", orderWarnRecord.getContent());
// 反馈时间
params.put("time6", com.ghy.common.utils.DateUtils.parseDateToStr("yyyy年MM月dd日 HH:mm", new Date()));
// 消息推送
WechatMsgUtils.sendWeChatMsg(WechatMsgUtils.getToken(), worker.getWxOpenId(), WxMsgEnum.WARN_ORDER, params);
} catch (Exception e) {
// 暂时不做任何操作
logger.error(e.getMessage(), e);
}
return toAjax(orderWarnRecordService.insertOrderWarnRecord(orderWarnRecord));
}
/**
* 导出订单急报记录列表
*/
@RequiresPermissions("warn:record:export")
@Log(title = "订单急报记录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
@ResponseBody
public AjaxResult export(OrderWarnRecord orderWarnRecord)
{
List<OrderWarnRecord> list = orderWarnRecordService.selectOrderWarnRecordList(orderWarnRecord);
ExcelUtil<OrderWarnRecord> util = new ExcelUtil<OrderWarnRecord>(OrderWarnRecord.class);
return util.exportExcel(list, "订单急报记录数据");
}
/**
* 新增订单急报记录
*/
@GetMapping("/add")
public String add()
{
return prefix + "/add";
}
/**
* 新增保存订单急报记录
*/
@RequiresPermissions("warn:record:add")
@Log(title = "订单急报记录", businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(OrderWarnRecord orderWarnRecord)
{
return toAjax(orderWarnRecordService.insertOrderWarnRecord(orderWarnRecord));
}
/**
* 修改订单急报记录
*/
@RequiresPermissions("warn:record:edit")
@GetMapping("/edit/{id}")
public String edit(@PathVariable("id") Long id, ModelMap mmap)
{
OrderWarnRecord orderWarnRecord = orderWarnRecordService.selectOrderWarnRecordById(id);
mmap.put("orderWarnRecord", orderWarnRecord);
return prefix + "/edit";
}
/**
* 修改保存订单急报记录
*/
@RequiresPermissions("warn:record:edit")
@Log(title = "订单急报记录", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
@ResponseBody
public AjaxResult editSave(OrderWarnRecord orderWarnRecord)
{
return toAjax(orderWarnRecordService.updateOrderWarnRecord(orderWarnRecord));
}
/**
* 删除订单急报记录
*/
@RequiresPermissions("warn:record:remove")
@Log(title = "订单急报记录", businessType = BusinessType.DELETE)
@PostMapping( "/remove")
@ResponseBody
public AjaxResult remove(String ids)
{
return toAjax(orderWarnRecordService.deleteOrderWarnRecordByIds(ids));
}
}

View File

@ -8,7 +8,9 @@ import com.huifu.adapay.core.AdapayCore;
import com.huifu.adapay.core.util.AdapaySign; import com.huifu.adapay.core.util.AdapaySign;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
/** /**
@ -72,6 +74,12 @@ public class AdapayCallbackController extends BaseController {
return "NG"; return "NG";
} }
@GetMapping("/adapay/callback")
@ResponseBody
public String test() {
return "NG";
}
/** /**
* 校验签名 * 校验签名
* *

View File

@ -1,5 +1,6 @@
package com.ghy.web.controller.pay; package com.ghy.web.controller.pay;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.AdapayStatusEnum; import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.adapay.model.PayParam; import com.ghy.common.adapay.model.PayParam;
@ -7,15 +8,20 @@ import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.enums.PayStatus; import com.ghy.common.enums.PayStatus;
import com.ghy.common.enums.PayTypeEnum; import com.ghy.common.enums.PayTypeEnum;
import com.ghy.common.utils.MoneyUtil;
import com.ghy.order.domain.OrderAttachmentRecord;
import com.ghy.order.domain.OrderDetail; import com.ghy.order.domain.OrderDetail;
import com.ghy.order.domain.OrderMaster; import com.ghy.order.domain.OrderMaster;
import com.ghy.order.service.IOrderAttachmentRecordService;
import com.ghy.order.service.OrderDetailService; import com.ghy.order.service.OrderDetailService;
import com.ghy.order.service.OrderMasterService; import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialChangeRecord; import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialMaster; import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.domain.PaymentRelation;
import com.ghy.payment.service.AdapayService; import com.ghy.payment.service.AdapayService;
import com.ghy.payment.service.FinancialChangeRecordService; import com.ghy.payment.service.FinancialChangeRecordService;
import com.ghy.payment.service.FinancialMasterService; import com.ghy.payment.service.FinancialMasterService;
import com.ghy.payment.service.IPaymentRelationService;
import com.huifu.adapay.core.exception.BaseAdaPayException; import com.huifu.adapay.core.exception.BaseAdaPayException;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
@ -24,7 +30,9 @@ import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Map; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects; import java.util.Objects;
/** /**
@ -40,14 +48,17 @@ public class AlipayController extends BaseController {
private AdapayService adapayService; private AdapayService adapayService;
@Resource @Resource
private OrderMasterService orderMasterService; private OrderMasterService orderMasterService;
@Resource
private FinancialMasterService financialMasterService;
@Resource @Resource
private OrderDetailService orderDetailService; private OrderDetailService orderDetailService;
@Resource
private FinancialMasterService financialMasterService;
@Resource
private IPaymentRelationService paymentRelationService;
@Resource @Resource
private FinancialChangeRecordService financialChangeRecordService; private FinancialChangeRecordService financialChangeRecordService;
@Resource
private IOrderAttachmentRecordService orderAttachmentRecordService;
/** /**
* 支付宝正扫支付 * 支付宝正扫支付
@ -62,17 +73,104 @@ public class AlipayController extends BaseController {
if (om.getPayStatus() == 1 || fm.getPayStatus() == 1) { if (om.getPayStatus() == 1 || fm.getPayStatus() == 1) {
return AjaxResult.error("订单已支付,不要重复付款!"); return AjaxResult.error("订单已支付,不要重复付款!");
} }
Map<String, Object> map; String payMoney = MoneyUtil.toS(fm.getPayMoney());
String payMoney = fm.getPayMoney().setScale(2, BigDecimal.ROUND_UNNECESSARY).toString();
// TODO 这里需要补充商品标题和商品描述信息 // TODO 这里需要补充商品标题和商品描述信息
PayParam payParam = PayParam.delayPayParam(om.getCode() + "_" + System.currentTimeMillis(), payMoney, "商品标题", "商品描述信息"); PayParam payParam = PayParam.delayPayParam(om.getCode() + "_" + System.currentTimeMillis(), payMoney, "商品标题", "商品描述信息");
try { try {
map = adapayService.alipayQrPay(om.getDeptId(), payParam, null, null, null); JSONObject response = adapayService.alipayQrPay(om.getDeptId(), payParam, null, null, null);
boolean status = AdapayStatusEnum.succeeded.code.equals(response.getString("status"));
if (!status) {
logger.error("创建支付失败: {}", response.toJSONString());
return AjaxResult.error("网络不佳 请稍后再试");
}
// 支付二维码创建成功 保存一下paymentId
String paymentId = response.getString("id");
// 更新财务主单的paymentId
FinancialMaster fm2update = new FinancialMaster();
fm2update.setId(fm.getId());
fm2update.setPaymentId(paymentId);
fm2update.setPayType(PayTypeEnum.ALIPAY_QR.getCode());
financialMasterService.updateFinancialMaster(fm2update);
// 保存支付ID与主财务单ID到关系表
PaymentRelation relation = new PaymentRelation(null, fm.getId(), PaymentRelation.FINANCIAL_MASTER, fm.getPayMoney());
relation.setPaymentId(paymentId);
paymentRelationService.insert(relation);
return AjaxResult.success(response);
} catch (BaseAdaPayException e) { } catch (BaseAdaPayException e) {
logger.error("创建支付失败", e); logger.error("创建支付失败", e);
return AjaxResult.error("网络不佳 请稍后再试"); return AjaxResult.error("网络不佳 请稍后再试");
} }
return AjaxResult.success(map); }
@PostMapping("/addMasterQr")
public AjaxResult addMasterQrPay(@RequestBody String orderId) {
orderId = orderId.replace("\"", "");
String [] orderIds = orderId.split(",");
List<String> orderIdList = Arrays.asList(orderIds);
ArrayList<PaymentRelation> relations = new ArrayList<>();
List<Long> fmList = new ArrayList<>();
BigDecimal payMoney = BigDecimal.ZERO;
for (String id : orderIdList){
// 不知道为啥参数可能会带上双引号 这里去掉再转Long
Long orderMasterId = Long.valueOf(id);
OrderMaster orderMaster = orderMasterService.selectById(orderMasterId);
if (orderMaster == null) {
return AjaxResult.error("主订单不存在!");
}
// 查询主单是否有未支付的付款单
FinancialMaster fm = financialMasterService.selectByOrderMasterId(orderMaster.getId());
if (fm == null) {
return AjaxResult.error("财务单不存在!");
}
// 主单是否付款 没付款的话一起付
boolean fmPaid = Objects.equals(PayStatus.WAIT_PAY.getCode(), fm.getPayStatus());
if (fmPaid) {
fmList.add(fm.getId());
payMoney = payMoney.add(fm.getPayMoney());
relations.add(new PaymentRelation(null, fm.getId(), PaymentRelation.FINANCIAL_MASTER, fm.getPayMoney()));
}else {
return AjaxResult.error("选择了不需要付款的订单!");
}
if (MoneyUtil.lte0(payMoney)) {
return AjaxResult.error("不需要支付");
}
}
// 以第一单为第三放的付款单号
OrderMaster orderMaster = orderMasterService.selectById(Long.valueOf(orderIdList.get(0)));
// 付款
PayParam payParam = PayParam.delayPayParam(orderMaster.getCode() + "_" + System.currentTimeMillis(),
MoneyUtil.toS(payMoney), "订单支付", "叮咚到家服务");
JSONObject response;
try {
response = adapayService.alipayQrPay(orderMaster.getDeptId(), payParam, null, null, null);
} catch (BaseAdaPayException e) {
logger.error("创建支付失败: " + e.getMessage(), e);
return AjaxResult.error("网络不佳 请稍后再试");
}
boolean status = AdapayStatusEnum.succeeded.code.equals(response.getString("status"));
if (!status) {
logger.error("创建支付失败: {}", response.toJSONString());
return AjaxResult.error("网络不佳 请稍后再试");
}
// 支付二维码创建成功 保存一下paymentId
String paymentId = response.getString("id");
for (Long id : fmList){
FinancialMaster fm2update = new FinancialMaster();
fm2update.setId(id);
fm2update.setPaymentId(paymentId);
fm2update.setPayType(PayTypeEnum.ALIPAY_QR.getCode());
financialMasterService.updateFinancialMaster(fm2update);
}
// 保存支付ID与订单ID到关系表
for (PaymentRelation relation : relations) {
relation.setPaymentId(paymentId);
paymentRelationService.insert(relation);
}
return AjaxResult.success(response);
} }
@PostMapping("/addQr") @PostMapping("/addQr")
@ -92,29 +190,41 @@ public class AlipayController extends BaseController {
if (fm == null) { if (fm == null) {
return AjaxResult.error("财务单不存在!"); return AjaxResult.error("财务单不存在!");
} }
ArrayList<PaymentRelation> relations = new ArrayList<>();
// 主单是否付款 没付款的话一起付 // 主单是否付款 没付款的话一起付
boolean fmPaid = Objects.equals(PayStatus.WAIT_PAY.getCode(), fm.getPayStatus()); boolean fmPaid = Objects.equals(PayStatus.WAIT_PAY.getCode(), fm.getPayStatus());
if (fmPaid) { if (fmPaid && !"01".equals(orderMaster.getConsultMode())) {
payMoney = payMoney.add(fm.getPayMoney()); payMoney = payMoney.add(fm.getPayMoney());
relations.add(new PaymentRelation(null, fm.getId(), PaymentRelation.FINANCIAL_MASTER, fm.getPayMoney()));
} }
// 查询关联的加价单 // 查询关联的加价单
FinancialChangeRecord financialChangeRecord = financialChangeRecordService.selectNotPayRecordByDetailId(orderDetailId); FinancialChangeRecord fcr = financialChangeRecordService.selectNotPayRecordByDetailId(orderDetailId);
if (financialChangeRecord != null) { if (fcr != null && !"01".equals(orderMaster.getConsultMode())) {
payMoney = payMoney.add(financialChangeRecord.getChangeMoney()); payMoney = payMoney.add(fcr.getChangeMoney());
relations.add(new PaymentRelation(null, fcr.getId(), PaymentRelation.FINANCIAL_CHANGE, fcr.getChangeMoney()));
}else if(fcr != null){
payMoney = payMoney.add(fcr.getChangeMoney());
relations.add(new PaymentRelation(null, fcr.getId(), PaymentRelation.CONSULT_ADD, fcr.getChangeMoney()));
} }
OrderAttachmentRecord param = new OrderAttachmentRecord();
if (BigDecimal.ZERO.compareTo(payMoney) > -1) { param.setOrderDetailId(orderDetailId);
List<OrderAttachmentRecord> orderAttachmentRecordList = orderAttachmentRecordService.selectOrderAttachmentRecordList(param);
if(CollectionUtil.isNotEmpty(orderAttachmentRecordList)){
payMoney = payMoney.add(orderAttachmentRecordList.get(0).getAttachMoney());
relations.add(new PaymentRelation(null, orderAttachmentRecordList.get(0).getId(), PaymentRelation.ORDER_ATTACHMENT, orderAttachmentRecordList.get(0).getAttachMoney()));
}
if (MoneyUtil.lte0(payMoney)) {
return AjaxResult.error("不需要支付"); return AjaxResult.error("不需要支付");
} }
// 付款 // 付款
PayParam payParam; PayParam payParam;
if (financialChangeRecord == null) { if (fcr == null) {
payParam = PayParam.delayPayParam(orderMaster.getCode() + "_" + System.currentTimeMillis(), payParam = PayParam.delayPayParam(orderMaster.getCode() + "_" + System.currentTimeMillis(),
payMoney.setScale(2, BigDecimal.ROUND_UNNECESSARY).toString(), payMoney.setScale(2, BigDecimal.ROUND_UNNECESSARY).toString(),
"订单支付", "叮咚到家服务"); "订单支付", "叮咚到家服务");
} else { } else {
payParam = PayParam.delayPayParam(orderMaster.getCode() + "_" + financialChangeRecord.getId() + "_" + System.currentTimeMillis(), payParam = PayParam.delayPayParam(orderMaster.getCode() + "_" + fcr.getId() + "_" + System.currentTimeMillis(),
payMoney.setScale(2, BigDecimal.ROUND_UNNECESSARY).toString(), payMoney.setScale(2, BigDecimal.ROUND_UNNECESSARY).toString(),
"加价付款", "叮咚到家服务"); "加价付款", "叮咚到家服务");
} }
@ -140,12 +250,23 @@ public class AlipayController extends BaseController {
fm2update.setPayType(PayTypeEnum.ALIPAY_QR.getCode()); fm2update.setPayType(PayTypeEnum.ALIPAY_QR.getCode());
financialMasterService.updateFinancialMaster(fm2update); financialMasterService.updateFinancialMaster(fm2update);
} }
if (financialChangeRecord != null) { if (fcr != null) {
FinancialChangeRecord fcr2update = new FinancialChangeRecord(); FinancialChangeRecord fcr2update = new FinancialChangeRecord();
fcr2update.setId(financialChangeRecord.getId()); fcr2update.setId(fcr.getId());
fcr2update.setPaymentId(paymentId); fcr2update.setPaymentId(paymentId);
financialChangeRecordService.update(fcr2update); financialChangeRecordService.update(fcr2update);
} }
if(CollectionUtil.isNotEmpty(orderAttachmentRecordList)){
OrderAttachmentRecord oarUpdate = new OrderAttachmentRecord();
oarUpdate.setId(orderAttachmentRecordList.get(0).getId());
oarUpdate.setPaymentId(paymentId);
orderAttachmentRecordService.updateOrderAttachmentRecord(oarUpdate);
}
// 保存支付ID与订单ID到关系表
for (PaymentRelation relation : relations) {
relation.setPaymentId(paymentId);
paymentRelationService.insert(relation);
}
return AjaxResult.success(response); return AjaxResult.success(response);
} }
} }

View File

@ -1,12 +1,12 @@
package com.ghy.web.controller.pay; package com.ghy.web.controller.pay;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.PayParam; import com.ghy.common.adapay.model.PayParam;
import com.ghy.common.adapay.model.WxpayExpend; import com.ghy.common.adapay.model.WxpayExpend;
import com.ghy.common.config.WxConfig; import com.ghy.common.config.WxConfig;
import com.ghy.common.core.controller.BaseController; import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.enums.PayStatus; import com.ghy.common.enums.PayStatus;
import com.ghy.common.json.JSONObject;
import com.ghy.common.utils.StringUtils; import com.ghy.common.utils.StringUtils;
import com.ghy.order.domain.OrderDetail; import com.ghy.order.domain.OrderDetail;
import com.ghy.order.domain.OrderMaster; import com.ghy.order.domain.OrderMaster;
@ -14,9 +14,11 @@ import com.ghy.order.service.OrderDetailService;
import com.ghy.order.service.OrderMasterService; import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialChangeRecord; import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialMaster; import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.domain.PaymentRelation;
import com.ghy.payment.service.AdapayService; import com.ghy.payment.service.AdapayService;
import com.ghy.payment.service.FinancialChangeRecordService; import com.ghy.payment.service.FinancialChangeRecordService;
import com.ghy.payment.service.FinancialMasterService; import com.ghy.payment.service.FinancialMasterService;
import com.ghy.payment.service.IPaymentRelationService;
import com.huifu.adapay.core.exception.BaseAdaPayException; import com.huifu.adapay.core.exception.BaseAdaPayException;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -30,7 +32,6 @@ import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Controller @Controller
@ -47,7 +48,8 @@ public class WxPayController extends BaseController {
private FinancialMasterService financialMasterService; private FinancialMasterService financialMasterService;
@Resource @Resource
private OrderDetailService orderDetailService; private OrderDetailService orderDetailService;
@Resource
private IPaymentRelationService paymentRelationService;
@Resource @Resource
private FinancialChangeRecordService financialChangeRecordService; private FinancialChangeRecordService financialChangeRecordService;
@ -56,11 +58,11 @@ public class WxPayController extends BaseController {
public AjaxResult drawCash(@RequestBody JSONObject object) { public AjaxResult drawCash(@RequestBody JSONObject object) {
try { try {
Long deptId = object.getLong("deptId"); Long deptId = object.getLong("deptId");
String orderNo = object.getStr("orderNo"); String orderNo = object.getString("orderNo");
String cashType = object.getStr("cashType"); String cashType = object.getString("cashType");
String cashAmt = object.getStr("cashAmt"); String cashAmt = object.getString("cashAmt");
String memberId = object.getStr("memberId"); String memberId = object.getString("memberId");
String remark = object.getStr("remark"); String remark = object.getString("remark");
adapayService.drawCash(deptId, orderNo, cashType, cashAmt, memberId, remark, null); adapayService.drawCash(deptId, orderNo, cashType, cashAmt, memberId, remark, null);
return AjaxResult.success("操作成功"); return AjaxResult.success("操作成功");
} catch (Exception e) { } catch (Exception e) {
@ -80,33 +82,60 @@ public class WxPayController extends BaseController {
Assert.notNull(orderMaster, "找不到对应的订单"); Assert.notNull(orderMaster, "找不到对应的订单");
FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderMaster.getId()); FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderMaster.getId());
BigDecimal payMoney = BigDecimal.ZERO; BigDecimal payMoney = BigDecimal.ZERO;
if(PayStatus.WAIT_PAY.getCode().equals(financialMaster.getPayStatus())){ ArrayList<PaymentRelation> relations = new ArrayList<>();
if (PayStatus.WAIT_PAY.getCode().equals(financialMaster.getPayStatus())) {
payMoney = financialMaster.getPayMoney(); payMoney = financialMaster.getPayMoney();
relations.add(new PaymentRelation(null, financialMaster.getId(), PaymentRelation.FINANCIAL_MASTER, financialMaster.getPayMoney()));
} }
List<Long> idList = orderDetailService.selectByOrderMasterId(orderMaster.getId()).stream().map(OrderDetail::getId).collect(Collectors.toList()); List<Long> idList = orderDetailService.selectByOrderMasterId(orderMaster.getId()).stream().map(OrderDetail::getId).collect(Collectors.toList());
List<FinancialChangeRecord> financialChangeRecords = financialChangeRecordService.selectByDetailIds(StringUtils.join(idList, ",")); List<FinancialChangeRecord> financialChangeRecords = financialChangeRecordService.selectByDetailIds(StringUtils.join(idList, ","));
List<Long> financialChangeRecordIds = new ArrayList<>(); List<Long> financialChangeRecordIds = new ArrayList<>();
for (FinancialChangeRecord financialChangeRecord : financialChangeRecords) { for (FinancialChangeRecord fcr : financialChangeRecords) {
if (PayStatus.WAIT_PAY.getCode().equals(financialChangeRecord.getPayStatus())) { if (PayStatus.WAIT_PAY.getCode().equals(fcr.getPayStatus())) {
payMoney = payMoney.add(financialChangeRecord.getChangeMoney()); payMoney = payMoney.add(fcr.getChangeMoney());
financialChangeRecordIds.add(financialChangeRecord.getId()); financialChangeRecordIds.add(fcr.getId());
relations.add(new PaymentRelation(null, fcr.getId(), PaymentRelation.FINANCIAL_CHANGE, fcr.getChangeMoney()));
} }
} }
//调用adapay微信公众号支付. //调用adapay微信公众号支付.
WxpayExpend expend = new WxpayExpend(); WxpayExpend expend = new WxpayExpend();
expend.setOpenId(openId); expend.setOpenId(openId);
Map<String, Object> map;
try { try {
// TODO 订单里需要补充支付金额tittle简要描述分账信息description // TODO 订单里需要补充支付金额tittle简要描述分账信息description
String changeRecordIdStr = financialChangeRecordIds.size() > 0 ? StringUtils.join(financialChangeRecordIds, ",") + "_" : ""; String changeRecordIdStr = financialChangeRecordIds.size() > 0 ? StringUtils.join(financialChangeRecordIds, ",") + "_" : "";
PayParam payParam = PayParam.delayPayParam(orderMaster.getCode() + "_" + changeRecordIdStr + System.currentTimeMillis(), PayParam payParam = PayParam.delayPayParam(orderMaster.getCode() + "_" + changeRecordIdStr + System.currentTimeMillis(),
String.valueOf(payMoney), "工圈子居家设备", "工圈子居家设备购买付费"); String.valueOf(payMoney), "工圈子居家设备", "工圈子居家设备购买付费");
map = adapayService.wxLitePay(orderMaster.getDeptId(), payParam, expend, null, null); JSONObject response = adapayService.wxLitePay(orderMaster.getDeptId(), payParam, expend, null, null);
String paymentId = response.getString("id");
// 更新财务主单的paymentId
if (PayStatus.WAIT_PAY.getCode().equals(financialMaster.getPayStatus())) {
FinancialMaster fm2update = new FinancialMaster();
fm2update.setId(financialMaster.getId());
fm2update.setPaymentId(paymentId);
financialMasterService.updateFinancialMaster(fm2update);
}
// 更新财务变更记录的paymentId
for (FinancialChangeRecord fcr : financialChangeRecords) {
if (PayStatus.WAIT_PAY.getCode().equals(fcr.getPayStatus())) {
FinancialChangeRecord fcr2update = new FinancialChangeRecord();
fcr2update.setId(fcr.getId());
fcr2update.setPaymentId(paymentId);
financialChangeRecordService.update(fcr2update);
}
}
// 保存支付ID与订单ID到关系表
for (PaymentRelation relation : relations) {
relation.setPaymentId(paymentId);
paymentRelationService.insert(relation);
}
return AjaxResult.success(response);
} catch (BaseAdaPayException e) { } catch (BaseAdaPayException e) {
logger.error("获取微信用户信息失败", e); logger.error("获取微信用户信息失败", e);
return AjaxResult.error(); return AjaxResult.error();
} }
return AjaxResult.success(map);
} }
// /** // /**

View File

@ -9,6 +9,8 @@ import com.ghy.common.enums.BusinessType;
import com.ghy.common.utils.ExceptionUtil; import com.ghy.common.utils.ExceptionUtil;
import com.ghy.common.utils.poi.ExcelUtil; import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.payment.domain.FinancialDetail; import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.request.FinancialAccountBillReq;
import com.ghy.payment.response.FinancialAccountBillResp;
import com.ghy.payment.service.FinancialDetailService; import com.ghy.payment.service.FinancialDetailService;
import com.ghy.web.pojo.vo.FinancialCountRequest; import com.ghy.web.pojo.vo.FinancialCountRequest;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -68,6 +70,14 @@ public class FinancialDetailController extends BaseController {
return getDataTable(list); return getDataTable(list);
} }
@PostMapping("/app/listV2")
@ResponseBody
public TableDataInfo appListV2(@RequestBody FinancialAccountBillReq financialAccountBillReq) {
startPage();
List<FinancialAccountBillResp> list = financialDetailService.selectFinancialDetailListV2(financialAccountBillReq);
return getDataTable(list);
}
@Log(title = "财务细单管理", businessType = BusinessType.EXPORT) @Log(title = "财务细单管理", businessType = BusinessType.EXPORT)
@RequiresPermissions("financial:detail:export") @RequiresPermissions("financial:detail:export")
@PostMapping("/export") @PostMapping("/export")

View File

@ -5,6 +5,7 @@ import com.ghy.common.constant.UserConstants;
import com.ghy.common.core.controller.BaseController; import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.enums.BusinessType; import com.ghy.common.enums.BusinessType;
import com.ghy.common.json.JSONObject;
import com.ghy.common.utils.ExceptionUtil; import com.ghy.common.utils.ExceptionUtil;
import com.ghy.system.domain.SysArea; import com.ghy.system.domain.SysArea;
import com.ghy.system.service.ISysAreaService; import com.ghy.system.service.ISysAreaService;
@ -15,6 +16,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@ -45,6 +47,43 @@ public class SysAreaController extends BaseController {
} }
@PostMapping("/app/all")
@ResponseBody
public Object appAll(@RequestBody SysArea sysArea)
{
try {
// 第一层
List<SysArea> provinceAreas = sysAreaService.selectSysAreaList(sysArea);
for (SysArea provinceArea : provinceAreas) {
logger.info("进行中的省 : " + provinceArea.getAreaName());
SysArea param1 = new SysArea();
param1.setParentCode(provinceArea.getAreaCode());
// 第二层
List<SysArea> cityAreas = sysAreaService.selectSysAreaList(param1);
for (SysArea cityArea : cityAreas){
SysArea param2 = new SysArea();
param2.setParentCode(cityArea.getAreaCode());
// 第三层
List<SysArea> countryAreas = sysAreaService.selectSysAreaList(param2);
for (SysArea countryArea : countryAreas){
SysArea param3 = new SysArea();
param3.setParentCode(countryArea.getAreaCode());
// 第三层 街道
List<SysArea> streetAreas = sysAreaService.selectSysAreaList(param3);
countryArea.setChild(streetAreas);
}
cityArea.setChild(countryAreas);
}
provinceArea.setChild(cityAreas);
}
return provinceAreas;
}catch (Exception e){
logger.error(ExceptionUtil.getExceptionMessage(e));
return AjaxResult.error(e.getMessage());
}
}
@PostMapping("/app/list") @PostMapping("/app/list")
@ResponseBody @ResponseBody
public AjaxResult appList(@RequestBody SysArea sysArea) public AjaxResult appList(@RequestBody SysArea sysArea)

View File

@ -26,7 +26,7 @@ import com.ghy.system.service.ISysDeptService;
/** /**
* 部门信息 * 部门信息
* *
* @author clunt * @author clunt
*/ */
@Controller @Controller
@ -45,7 +45,7 @@ public class SysDeptController extends BaseController
return prefix + "/dept"; return prefix + "/dept";
} }
@RequiresPermissions("system:dept:list") // @RequiresPermissions("system:dept:list")
@PostMapping("/list") @PostMapping("/list")
@ResponseBody @ResponseBody
public List<SysDept> list(SysDept dept) public List<SysDept> list(SysDept dept)
@ -160,7 +160,7 @@ public class SysDeptController extends BaseController
/** /**
* 选择部门树 * 选择部门树
* *
* @param deptId 部门ID * @param deptId 部门ID
* @param excludeId 排除ID * @param excludeId 排除ID
*/ */

View File

@ -1,5 +1,6 @@
package com.ghy.web.controller.system; package com.ghy.web.controller.system;
import com.ghy.common.core.domain.dto.SysUserAddDTO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@ -12,9 +13,11 @@ import com.ghy.common.utils.StringUtils;
import com.ghy.framework.shiro.service.SysRegisterService; import com.ghy.framework.shiro.service.SysRegisterService;
import com.ghy.system.service.ISysConfigService; import com.ghy.system.service.ISysConfigService;
import javax.validation.Valid;
/** /**
* 注册验证 * 注册验证
* *
* @author clunt * @author clunt
*/ */
@Controller @Controller
@ -34,13 +37,13 @@ public class SysRegisterController extends BaseController
@PostMapping("/register") @PostMapping("/register")
@ResponseBody @ResponseBody
public AjaxResult ajaxRegister(SysUser user) public AjaxResult ajaxRegister(@Valid SysUserAddDTO userAddDTO)
{ {
if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
{ {
return error("当前系统没有开启注册功能!"); return error("当前系统没有开启注册功能!");
} }
String msg = registerService.register(user); String msg = registerService.register(userAddDTO);
return StringUtils.isEmpty(msg) ? success() : error(msg); return StringUtils.isEmpty(msg) ? success() : error(msg);
} }
} }

View File

@ -0,0 +1,52 @@
package com.ghy.web.controller.tool;
import cn.hutool.json.JSONUtil;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.utils.StringUtils;
import com.ghy.web.pojo.vo.CertNoTwoElementReq;
import com.ghy.web.service.AliCloudService;
import com.ghy.worker.domain.Worker;
import com.ghy.worker.service.WorkerService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Slf4j
@Tag(name = "阿里云Api接口")
@Controller
@RequestMapping("/tool/ali")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AliCloudController {
private final AliCloudService aliCloudService;
private final WorkerService workerService;
@Operation(summary = "身份证二要素校验")
@PostMapping("/certNoTwoElementVerification")
@ResponseBody
public AjaxResult certNoTwoElementVerification(@RequestBody CertNoTwoElementReq certNoTwoElementReq){
try {
Worker worker = workerService.selectById(certNoTwoElementReq.getWorkerId());
if(StringUtils.isNotEmpty(worker.getRemark())){
return AjaxResult.success("操作成功!");
}else {
aliCloudService.certNoTwoElementVerification(certNoTwoElementReq);
worker.setRemark(JSONUtil.toJsonStr(certNoTwoElementReq));
workerService.updateWorker(worker);
return AjaxResult.success();
}
}catch (Exception e){
log.error("身份证二要素校验失败:{}", e.getMessage(), e);
return AjaxResult.success(e.getMessage(), "身份证二要素校验失败!");
}
}
}

View File

@ -17,6 +17,9 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/** /**
* 百度地图逆解析 * 百度地图逆解析
* @author clunt * @author clunt
@ -38,12 +41,34 @@ public class BaiduController extends BaseController {
JSONObject json = new JSONObject(); JSONObject json = new JSONObject();
String location = jsonObject.getString("location"); String location = jsonObject.getString("location");
// 解析经纬度
String[] coordinates = location.split(",");
if (coordinates.length != 2) {
return AjaxResult.error("location格式错误应为经度,纬度");
}
try {
double longitude = Double.parseDouble(coordinates[1]); // 经度
double latitude = Double.parseDouble(coordinates[0]); // 纬度
// 将经纬度添加到返回结果中
json.put("longitude", longitude);
json.put("latitude", latitude);
json.put("coordinates", coordinates);
logger.info("解析到的坐标 - 经度: {}, 纬度: {}", longitude, latitude);
} catch (NumberFormatException e) {
return AjaxResult.error("经纬度格式错误");
}
String url = baiduConfig.getUrl().replace("#AK#", baiduConfig.getAk()) + location; String url = baiduConfig.getUrl().replace("#AK#", baiduConfig.getAk()) + location;
String result = HttpUtils.sendGet(url); String result = HttpUtils.sendGet(url);
result = result.replaceAll("\n", "").replaceAll("\t", ""); result = result.replaceAll("\n", "").replaceAll("\t", "");
JSONObject resultJson = JSONObject.parseObject(result); JSONObject resultJson = JSONObject.parseObject(result);
if("0".equals(resultJson.getString("status"))){ if("0".equals(resultJson.getString("status"))){
JSONObject addressJson = resultJson.getJSONObject("result").getJSONObject("addressComponent"); JSONObject addressJson = resultJson.getJSONObject("result").getJSONObject("addressComponent");
logger.info("百度地图获取到的地址 :" + addressJson);
String provinceName = addressJson.getString("province"); String provinceName = addressJson.getString("province");
logger.info("provinceName :" + provinceName); logger.info("provinceName :" + provinceName);
SysArea provinceArea = iSysAreaService.selectByName(provinceName, null); SysArea provinceArea = iSysAreaService.selectByName(provinceName, null);
@ -53,9 +78,25 @@ public class BaiduController extends BaseController {
String countryName = addressJson.getString("district"); String countryName = addressJson.getString("district");
logger.info("countryName :" + countryName); logger.info("countryName :" + countryName);
SysArea countryArea = iSysAreaService.selectByName(countryName, cityArea.getAreaCode()); SysArea countryArea = iSysAreaService.selectByName(countryName, cityArea.getAreaCode());
String streetName = addressJson.getString("town");
logger.info("streetName :" + streetName);
SysArea streetArea = iSysAreaService.selectByName(streetName, countryArea.getAreaCode());
// 添加地址信息
json.put("provinceArea", provinceArea); json.put("provinceArea", provinceArea);
json.put("cityArea", cityArea); json.put("cityArea", cityArea);
json.put("countryArea", countryArea); json.put("countryArea", countryArea);
json.put("streetArea", streetArea);
// 添加完整地址
String fullAddress = (provinceName != null ? provinceName : "") +
(cityName != null ? cityName : "") +
(countryName != null ? countryName : "") +
(streetName != null ? streetName : "");
json.put("fullAddress", fullAddress);
// 保留原有的location字段用于兼容
json.put("location", location);
}else { }else {
return AjaxResult.error("Api服务异常!"); return AjaxResult.error("Api服务异常!");
} }
@ -67,6 +108,56 @@ public class BaiduController extends BaseController {
} }
} }
/**
* 百度地图正向地理编码地址 -> 经纬度
* 接收JSON{provinceName, cityName, countryName, streetName, address}
*/
@PostMapping("/geocode")
@ResponseBody
public AjaxResult geocode(@RequestBody JSONObject jsonObject) {
try {
String provinceName = jsonObject.getString("provinceName");
String cityName = jsonObject.getString("cityName");
String countryName = jsonObject.getString("countryName");
String streetName = jsonObject.getString("streetName");
String detailAddress = jsonObject.getString("address");
StringBuilder full = new StringBuilder();
if (provinceName != null) { full.append(provinceName); }
if (cityName != null) { full.append(cityName); }
if (countryName != null) { full.append(countryName); }
if (streetName != null) { full.append(streetName); }
if (detailAddress != null) { full.append(detailAddress); }
String address = full.toString();
if (address == null || address.trim().isEmpty()) {
return AjaxResult.error("地址不能为空");
}
String encoded = URLEncoder.encode(address, StandardCharsets.UTF_8.name());
// 使用百度正向地理编码API
String url = "https://api.map.baidu.com/geocoding/v3/?output=json&ak="
+ baiduConfig.getAk() + "&address=" + encoded;
String result = HttpUtils.sendGet(url);
result = result.replaceAll("\n", "").replaceAll("\t", "");
JSONObject resultJson = JSONObject.parseObject(result);
if ("0".equals(resultJson.getString("status"))) {
JSONObject location = resultJson.getJSONObject("result").getJSONObject("location");
JSONObject data = new JSONObject();
data.put("longitude", location.getBigDecimal("lng"));
data.put("latitude", location.getBigDecimal("lat"));
data.put("fullAddress", address);
return AjaxResult.success(data);
} else {
return AjaxResult.error("百度地理编码失败:" + resultJson.getString("msg"));
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
return AjaxResult.error(ExceptionUtil.getExceptionMessage(e));
}
}
public static void main(String[] args) { public static void main(String[] args) {
String result = " {\"status\":0,\"result\":{\"location\":{\"lng\":113.29950224957551,\"lat\":23.019282373814027},\"formatted_address\":\"广东省广州市番禺区安平路\",\"business\":\"大石\",\"addressComponent\":{\"country\":\"中国\",\"country_code\":0,\"country_code_iso\":\"CHN\",\"country_code_iso2\":\"CN\",\"province\":\"广东省\",\"city\":\"广州市\",\"city_level\":2,\"district\":\"番禺区\",\"town\":\"\",\"town_code\":\"\",\"distance\":\"\",\"direction\":\"\",\"adcode\":\"440113\",\"street\":\"安平路\",\"street_number\":\"\"},\"pois\":[],\"roads\":[],\"poiRegions\":[],\"sematic_description\":\"\",\"cityCode\":257}}\n"; String result = " {\"status\":0,\"result\":{\"location\":{\"lng\":113.29950224957551,\"lat\":23.019282373814027},\"formatted_address\":\"广东省广州市番禺区安平路\",\"business\":\"大石\",\"addressComponent\":{\"country\":\"中国\",\"country_code\":0,\"country_code_iso\":\"CHN\",\"country_code_iso2\":\"CN\",\"province\":\"广东省\",\"city\":\"广州市\",\"city_level\":2,\"district\":\"番禺区\",\"town\":\"\",\"town_code\":\"\",\"distance\":\"\",\"direction\":\"\",\"adcode\":\"440113\",\"street\":\"安平路\",\"street_number\":\"\"},\"pois\":[],\"roads\":[],\"poiRegions\":[],\"sematic_description\":\"\",\"cityCode\":257}}\n";

View File

@ -1,5 +1,8 @@
package com.ghy.web.controller.tool; package com.ghy.web.controller.tool;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ghy.common.config.WxConfig; import com.ghy.common.config.WxConfig;
import com.ghy.common.core.controller.BaseController; import com.ghy.common.core.controller.BaseController;
@ -8,6 +11,7 @@ import com.ghy.common.enums.OrderStatus;
import com.ghy.common.exception.ServiceException; import com.ghy.common.exception.ServiceException;
import com.ghy.common.utils.ExceptionUtil; import com.ghy.common.utils.ExceptionUtil;
import com.ghy.common.utils.StringUtils; import com.ghy.common.utils.StringUtils;
import com.ghy.common.utils.WechatMsgUtils;
import com.ghy.common.utils.WxUtils; import com.ghy.common.utils.WxUtils;
import com.ghy.common.utils.http.HttpUtils; import com.ghy.common.utils.http.HttpUtils;
import com.ghy.customer.domain.Customer; import com.ghy.customer.domain.Customer;
@ -28,7 +32,9 @@ import javax.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
/** /**
* @author clunt * @author clunt
@ -184,9 +190,205 @@ public class WxController extends BaseController {
} }
String data = HttpUtils.sendGet(url, null); String data = HttpUtils.sendGet(url, null);
JSONObject result = JSONObject.parseObject(data); JSONObject result = JSONObject.parseObject(data);
// 如果是师傅端,需要调用公众号的获取用户列表接口 -- 遍历列表去找到unionId和openid关联并入库
// if(!"customer".equals(from)){
// String openid = result.getString("openid");
// String unionId = result.getString("unionid");
// // 查询openid是否入库已经入库则不管
// Worker param = new Worker();
// param.setOpenId(openid);
// Worker worker = workerService.selectByOpenId(param);
// if(worker != null && StringUtils.isEmpty(worker.getWxOpenId())){
// // 公众号token
// String wxToken = WechatMsgUtils.getToken();
// String wxUserOpenidList = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/user/get?access_token="+wxToken+"&next_openid=");
// logger.info("公众号获取的用户列表集合:{}", wxUserOpenidList);
// JSONObject wxOpenidJson = JSONObject.parseObject(wxUserOpenidList);
// JSONObject openIdListJson = wxOpenidJson.getJSONObject("data");
// List<String> openidList = openIdListJson.getObject("openid", ArrayList.class);
// JSONArray openidJsonArray = new JSONArray();
// openidList.forEach(model->{
// JSONObject openidJson = new JSONObject();
// openidJson.put("openid", model);
// openidJson.put("lang", "zh_CN");
// openidJsonArray.add(openidJson);
// });
// JSONObject jsonParam = new JSONObject();
// xw jsonParam.put("user_list", openidJsonArray);
// String unionUrl = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="+WechatMsgUtils.getToken();;
// logger.info("调用获取用户信息,请求url:{}, 请求body:{}", unionUrl, jsonParam.toJSONString());
// String getUnionResult = HttpUtil.post(unionUrl, jsonParam.toJSONString());
// logger.info("获取公众号union列表:{}", getUnionResult);
// JSONObject unionJson = JSONObject.parseObject(getUnionResult);
// JSONArray unionJsonArray = unionJson.getJSONArray("user_info_list");
// for (int index = 0 ; index<unionJsonArray.size(); index ++){
// JSONObject json = unionJsonArray.getJSONObject(index);
// if(StringUtils.isEmpty(json.getString("unionid"))||StringUtils.isEmpty(unionId)){
// return AjaxResult.success(result);
// }
// if(json.getString("unionid").equals(unionId)){
// Worker updateWorker = new Worker();
// updateWorker.setWorkerId(worker.getWorkerId());
// updateWorker.setWxOpenId(json.getString("openid"));
// logger.info("关联后的worker信息:{}", worker);
// workerService.updateWorker(updateWorker);
// }
// }
// }
//
// }
return AjaxResult.success(result); return AjaxResult.success(result);
} }
@GetMapping("/check")
@ResponseBody
public AjaxResult check(HttpServletRequest request) {
String url;
boolean flag = false;
String deptId = request.getHeader("deptId");
String from = request.getHeader("from");
SysDeptConfig sysDeptConfig = sysDeptConfigService.selectByDeptId(Long.parseLong(deptId));
String code = request.getHeader("code");
if("customer".equals(from)){
url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getWxAppId() + "&secret=" + sysDeptConfig.getWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
}else {
url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getServWxAppId() + "&secret=" + sysDeptConfig.getServWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
}
String data = HttpUtils.sendGet(url, null);
JSONObject result = JSONObject.parseObject(data);
// 如果是师傅端,需要调用公众号的获取用户列表接口 -- 遍历列表去找到unionId和openid关联并入库
if(!"customer".equals(from)){
String openid = result.getString("openid");
String unionId = result.getString("unionid");
// 查询openid是否入库已经入库则不管
Worker param = new Worker();
param.setOpenId(openid);
Worker worker = workerService.selectByOpenId(param);
if(worker != null){
// 公众号token
String wxToken = WechatMsgUtils.getToken();
String wxUserOpenidList = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/user/get?access_token="+wxToken+"&next_openid=");
logger.info("公众号获取的用户列表集合:{}", wxUserOpenidList);
JSONObject wxOpenidJson = JSONObject.parseObject(wxUserOpenidList);
JSONObject openIdListJson = wxOpenidJson.getJSONObject("data");
List<String> openidList = openIdListJson.getObject("openid", ArrayList.class);
List<List<String>> batchList = ListUtil.partition(openidList, 99);
for (List<String> childOpenidList : batchList) {
JSONArray openidJsonArray = new JSONArray();
childOpenidList.forEach(model->{
JSONObject openidJson = new JSONObject();
openidJson.put("openid", model);
openidJson.put("lang", "zh_CN");
openidJsonArray.add(openidJson);
});
JSONObject jsonParam = new JSONObject();
jsonParam.put("user_list", openidJsonArray);
String unionUrl = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="+WechatMsgUtils.getToken();;
logger.info("调用获取用户信息,请求url:{}, 请求body:{}", unionUrl, jsonParam.toJSONString());
String getUnionResult = HttpUtil.post(unionUrl, jsonParam.toJSONString());
logger.info("获取公众号union列表:{}", getUnionResult);
JSONObject unionJson = JSONObject.parseObject(getUnionResult);
JSONArray unionJsonArray = unionJson.getJSONArray("user_info_list");
for (int index = 0 ; index<unionJsonArray.size(); index ++){
JSONObject json = unionJsonArray.getJSONObject(index);
if(StringUtils.isNotEmpty(json.getString("unionid") )&& StringUtils.isNotEmpty(unionId)){
if(json.getString("unionid").equals(unionId)){
Worker updateWorker = new Worker();
updateWorker.setWorkerId(worker.getWorkerId());
updateWorker.setWxOpenId(json.getString("openid"));
logger.info("关联后的worker信息:{}", worker);
workerService.updateWorker(updateWorker);
flag = true;
break;
}
}
}
if(flag){
break;
}
}
}
}
return AjaxResult.success(true);
}
@GetMapping("/neCheck")
@ResponseBody
public AjaxResult neCheck(HttpServletRequest request) {
try {
String url;
boolean flag = false;
String deptId = request.getHeader("deptId");
String from = request.getHeader("from");
SysDeptConfig sysDeptConfig = sysDeptConfigService.selectByDeptId(Long.parseLong(deptId));
String code = request.getHeader("code");
if("customer".equals(from)){
url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getWxAppId() + "&secret=" + sysDeptConfig.getWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
}else {
url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + sysDeptConfig.getServWxAppId() + "&secret=" + sysDeptConfig.getServWxSecret() + "&js_code=" + code + "&grant_type=authorization_code";
}
String data = HttpUtils.sendGet(url, null);
JSONObject result = JSONObject.parseObject(data);
// 如果是师傅端,需要调用公众号的获取用户列表接口 -- 遍历列表去找到unionId和openid关联并入库
if(!"customer".equals(from)){
String openid = result.getString("openid");
String unionId = result.getString("unionid");
// 查询openid是否入库已经入库则不管
Worker param = new Worker();
param.setOpenId(openid);
Worker worker = workerService.selectByOpenId(param);
if(worker != null){
// 公众号token
String wxToken = WechatMsgUtils.getToken();
String wxUserOpenidList = HttpUtils.sendGet("https://api.weixin.qq.com/cgi-bin/user/get?access_token="+wxToken+"&next_openid=");
logger.info("公众号获取的用户列表集合:{}", wxUserOpenidList);
JSONObject wxOpenidJson = JSONObject.parseObject(wxUserOpenidList);
JSONObject openIdListJson = wxOpenidJson.getJSONObject("data");
List<String> openidList = openIdListJson.getObject("openid", ArrayList.class);
List<List<String>> batchList = ListUtil.partition(openidList, 99);
for (List<String> childOpenidList : batchList) {
JSONArray openidJsonArray = new JSONArray();
childOpenidList.forEach(model->{
JSONObject openidJson = new JSONObject();
openidJson.put("openid", model);
openidJson.put("lang", "zh_CN");
openidJsonArray.add(openidJson);
});
JSONObject jsonParam = new JSONObject();
jsonParam.put("user_list", openidJsonArray);
String unionUrl = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token="+WechatMsgUtils.getToken();;
logger.info("调用获取用户信息,请求url:{}, 请求body:{}", unionUrl, jsonParam.toJSONString());
String getUnionResult = HttpUtil.post(unionUrl, jsonParam.toJSONString());
logger.info("获取公众号union列表:{}", getUnionResult);
JSONObject unionJson = JSONObject.parseObject(getUnionResult);
JSONArray unionJsonArray = unionJson.getJSONArray("user_info_list");
for (int index = 0 ; index<unionJsonArray.size(); index ++){
JSONObject json = unionJsonArray.getJSONObject(index);
if(StringUtils.isNotEmpty(json.getString("unionid") )&& StringUtils.isNotEmpty(unionId)){
if(json.getString("unionid").equals(unionId)){
Worker updateWorker = new Worker();
updateWorker.setWorkerId(worker.getWorkerId());
updateWorker.setWxOpenId(json.getString("openid"));
logger.info("关联后的worker信息:{}", worker);
workerService.updateWorker(updateWorker);
flag = true;
break;
}
}
}
if(flag){
break;
}
}
}
}
return AjaxResult.success(flag);
}catch (Exception e){
return AjaxResult.success(false);
}
}
@GetMapping("/openid") @GetMapping("/openid")
@ResponseBody @ResponseBody

View File

@ -1,7 +1,10 @@
package com.ghy.web.controller.worker; package com.ghy.web.controller.worker;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.core.page.TableDataInfo;
import com.ghy.common.core.text.Convert; import com.ghy.common.core.text.Convert;
import com.ghy.order.domain.OrderGoods;
import com.ghy.system.domain.SysArea; import com.ghy.system.domain.SysArea;
import com.ghy.system.service.ISysAreaService; import com.ghy.system.service.ISysAreaService;
import com.ghy.worker.domain.WorkerArea; import com.ghy.worker.domain.WorkerArea;
@ -11,6 +14,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -26,7 +30,7 @@ import java.util.stream.Collectors;
@Slf4j @Slf4j
@Controller @Controller
@RequestMapping("worker/area") @RequestMapping("worker/area")
public class WorkerAreaController { public class WorkerAreaController extends BaseController {
@Resource @Resource
private WorkerAreaService workerAreaService; private WorkerAreaService workerAreaService;
@ -34,42 +38,154 @@ public class WorkerAreaController {
@Autowired @Autowired
private ISysAreaService sysAreaService; private ISysAreaService sysAreaService;
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(WorkerArea workerArea) {
startPage();
List<WorkerArea> list = workerAreaService.getWorkerAreaList(workerArea);
return getDataTable(list);
}
@GetMapping()
public String area(Long workerId, ModelMap mmap)
{
mmap.put("workerId", workerId);
return "worker/areaDetail";
}
/** /**
* 查询某个师傅的所有接单地区 * 查询某个师傅的所有接单地区
* *
* @param workerId 师傅ID * @param workerId 师傅ID
* @param serviceType 服务类型1=服务, 2=商品不传则查询所有
*/ */
@GetMapping("worker") @GetMapping("worker")
@ResponseBody @ResponseBody
public AjaxResult getByWorker(Long workerId) { public AjaxResult getByWorker(Long workerId, Integer serviceType) {
return AjaxResult.success(workerAreaService.getByWorker(workerId)); if (serviceType != null) {
// 根据服务类型查询
return AjaxResult.success(workerAreaService.getByWorkerIdAndType(workerId, serviceType));
} else {
// 查询所有区域保持向后兼容
return AjaxResult.success(workerAreaService.getByWorker(workerId));
}
}
/**
* 查询某个师傅的服务区域类型1
*
* @param workerId 师傅ID
*/
@GetMapping("worker/service")
@ResponseBody
public AjaxResult getServiceAreasByWorker(Long workerId) {
return AjaxResult.success(workerAreaService.getByWorkerIdAndType(workerId, 1));
}
/**
* 查询某个师傅的商品区域类型2
*
* @param workerId 师傅ID
*/
@GetMapping("worker/goods")
@ResponseBody
public AjaxResult getGoodsAreasByWorker(Long workerId) {
return AjaxResult.success(workerAreaService.getByWorkerIdAndType(workerId, 2));
} }
@GetMapping("worker/edit") @GetMapping("worker/edit")
@ResponseBody @ResponseBody
public AjaxResult getEditWorker(Long workerId){ public AjaxResult getEditWorker(Long workerId, Integer type){
Map<Long, List<String>> countryMap = new HashMap<>(); Map<Long, List<String>> countryMap = new HashMap<>();
List<WorkerArea> byWorker = workerAreaService.getByWorker(workerId);
for (WorkerArea area : byWorker){ // 需求1根据类型查询对应的区域数据
List<String> ids; List<WorkerArea> byWorker;
if(countryMap.containsKey(area.getDistrictId())){ if (Integer.valueOf(1).equals(type)) {
ids = countryMap.get(area.getDistrictId()); // 服务类型查询服务区域
}else { byWorker = workerAreaService.getByWorkerIdAndType(workerId, 1);
ids = new ArrayList<>(); } else if (Integer.valueOf(2).equals(type)) {
} // 商品类型查询商品区域
ids.add(String.valueOf(area.getStreetId())); byWorker = workerAreaService.getByWorkerIdAndType(workerId, 2);
countryMap.put(area.getDistrictId(), ids); } else {
// 不传类型查询所有区域
byWorker = workerAreaService.getByWorker(workerId);
} }
// 收集只有cityId没有districtId的城市ID集合用于单独处理
Set<Long> cityOnlyIds = new HashSet<>();
// 按districtId分组收集cityIds
Map<Long, Set<Long>> districtCityMap = new HashMap<>();
for (WorkerArea area : byWorker){
Long districtId = area.getDistrictId();
// 如果有districtId按districtId分组处理
if (districtId != null) {
List<String> ids;
if(countryMap.containsKey(districtId)){
ids = countryMap.get(districtId);
} else {
ids = new ArrayList<>();
}
// 收集该district下的城市ID
if (area.getCityId() != null) {
districtCityMap.computeIfAbsent(districtId, k -> new HashSet<>()).add(area.getCityId());
}
// 添加街道ID
if (area.getStreetId() != null) {
ids.add(String.valueOf(area.getStreetId()));
}
countryMap.put(districtId, ids);
} else {
// 如果只有cityId没有districtId收集到cityOnlyIds
if (area.getCityId() != null) {
cityOnlyIds.add(area.getCityId());
}
}
}
List<WorkerArea> result = new ArrayList<>(); List<WorkerArea> result = new ArrayList<>();
// 处理有districtId的情况正常流程
for (Map.Entry<Long, List<String>> longListEntry : countryMap.entrySet()) { for (Map.Entry<Long, List<String>> longListEntry : countryMap.entrySet()) {
WorkerArea model = new WorkerArea(); WorkerArea model = new WorkerArea();
SysArea countryArea = sysAreaService.selectById(longListEntry.getKey()); Long districtId = longListEntry.getKey();
SysArea countryArea = sysAreaService.selectById(districtId);
model.setDistrictArea(countryArea); model.setDistrictArea(countryArea);
SysArea cityArea = sysAreaService.selectById(Long.valueOf(countryArea.getParentCode())); SysArea cityArea = sysAreaService.selectById(Long.valueOf(countryArea.getParentCode()));
model.setCityArea(cityArea); model.setCityArea(cityArea);
SysArea provinceArea = sysAreaService.selectById(Long.valueOf(cityArea.getParentCode())); SysArea provinceArea = sysAreaService.selectById(Long.valueOf(cityArea.getParentCode()));
model.setProvinceArea(provinceArea); model.setProvinceArea(provinceArea);
// 设置该district下的cityIds
Set<Long> districtCityIds = districtCityMap.getOrDefault(districtId, new HashSet<>());
List<Long> cityIdList = new ArrayList<>(districtCityIds);
model.setCityIds(cityIdList);
// 设置街道ID列表
model.setStreetIds(longListEntry.getValue()); model.setStreetIds(longListEntry.getValue());
result.add(model);
}
// 处理只有cityId没有districtId的情况只返回省市信息
for (Long cityId : cityOnlyIds) {
WorkerArea model = new WorkerArea();
SysArea cityArea = sysAreaService.selectById(cityId);
model.setCityArea(cityArea);
// 获取省份信息
SysArea provinceArea = sysAreaService.selectById(Long.valueOf(cityArea.getParentCode()));
model.setProvinceArea(provinceArea);
// 只设置城市ID列表
List<Long> cityIdList = new ArrayList<>();
cityIdList.add(cityId);
model.setCityIds(cityIdList);
// 不设置district和street信息
result.add(model); result.add(model);
} }
return AjaxResult.success(result); return AjaxResult.success(result);

View File

@ -21,6 +21,7 @@ import com.huifu.adapay.core.exception.BaseAdaPayException;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -57,6 +58,8 @@ public class WorkerBankController extends BaseController {
return AjaxResult.error("师傅未通过审核,不能绑定银行卡"); return AjaxResult.error("师傅未通过审核,不能绑定银行卡");
} }
Set<Merchant> merchants = AdapayConfig.getMerchants(); Set<Merchant> merchants = AdapayConfig.getMerchants();
String phone = request.getPhone();
phone = StringUtils.trimAllWhitespace(phone);
for (Merchant merchant : merchants) { for (Merchant merchant : merchants) {
String memberId = AdapayUtils.getWorkerMemberId(request.getWorkerId(), merchant.getDeptId()); String memberId = AdapayUtils.getWorkerMemberId(request.getWorkerId(), merchant.getDeptId());
@ -66,7 +69,7 @@ public class WorkerBankController extends BaseController {
logger.info("用户[memberId={}]已存在 跳过实名直接绑卡", memberId); logger.info("用户[memberId={}]已存在 跳过实名直接绑卡", memberId);
} else { } else {
// 先在Adapay创建实名用户 // 先在Adapay创建实名用户
Map<String, Object> result1 = adapayService.createMember(merchant.getDeptId(), memberId, request.getPhone(), Map<String, Object> result1 = adapayService.createMember(merchant.getDeptId(), memberId, phone,
request.getName(), request.getCertId()); request.getName(), request.getCertId());
if (!AdapayStatusEnum.succeeded.code.equals(result1.get("status"))) { if (!AdapayStatusEnum.succeeded.code.equals(result1.get("status"))) {
logger.error("实名认证失败[{}]", JSON.toJSONString(result1)); logger.error("实名认证失败[{}]", JSON.toJSONString(result1));
@ -76,11 +79,11 @@ public class WorkerBankController extends BaseController {
// 开始创建结算账户 // 开始创建结算账户
JSONObject result2 = adapayService.createSettleAccount(merchant.getDeptId(), memberId, request.getBankNum(), request.getName(), JSONObject result2 = adapayService.createSettleAccount(merchant.getDeptId(), memberId, request.getBankNum(), request.getName(),
"2", request.getCertId(), request.getPhone(), null, null, null); "2", request.getCertId(), phone, null, null, null);
if (!AdapayStatusEnum.succeeded.code.equals(result2.get("status"))) { if (!AdapayStatusEnum.succeeded.code.equals(result2.get("status"))) {
if ("account_exists".equals(result2.get("error_code"))) { if ("account_exists".equals(result2.get("error_code"))) {
logger.info("用户[memberId={}]结算账户已存在 跳过", memberId); logger.info("用户[memberId={}]结算账户已存在 跳过", memberId);
continue;
} else { } else {
logger.error("创建结算账户失败[{}]", JSON.toJSONString(result2)); logger.error("创建结算账户失败[{}]", JSON.toJSONString(result2));
return AjaxResult.error("个人信息与银行卡不匹配或不支持信用卡绑定"); return AjaxResult.error("个人信息与银行卡不匹配或不支持信用卡绑定");
@ -93,7 +96,7 @@ public class WorkerBankController extends BaseController {
workerBank.setName(request.getName()); workerBank.setName(request.getName());
workerBank.setCertId(request.getCertId()); workerBank.setCertId(request.getCertId());
workerBank.setBankNum(request.getBankNum()); workerBank.setBankNum(request.getBankNum());
workerBank.setPhone(request.getPhone()); workerBank.setPhone(phone);
workerBank.setDeptId(merchant.getDeptId()); workerBank.setDeptId(merchant.getDeptId());
workerBank.setAdapayMemberId(memberId); workerBank.setAdapayMemberId(memberId);
workerBank.setSettleAccount(1); workerBank.setSettleAccount(1);
@ -156,7 +159,10 @@ public class WorkerBankController extends BaseController {
@ResponseBody @ResponseBody
public AjaxResult getByWorkerId(@RequestBody WorkerBindBankCardRequest request) { public AjaxResult getByWorkerId(@RequestBody WorkerBindBankCardRequest request) {
try { try {
return AjaxResult.success(workerBankService.getByWorkerId(request.getWorkerId())); if(request.getDeptId() == null){
request.setDeptId(101L);
}
return AjaxResult.success(workerBankService.getByWorkerId(request.getWorkerId(), request.getDeptId()));
} catch (Exception e) { } catch (Exception e) {
return AjaxResult.error(ExceptionUtil.getExceptionMessage(e)); return AjaxResult.error(ExceptionUtil.getExceptionMessage(e));

View File

@ -6,11 +6,8 @@ import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.core.page.TableDataInfo; import com.ghy.common.core.page.TableDataInfo;
import com.ghy.common.enums.BusinessType; import com.ghy.common.enums.BusinessType;
import com.ghy.common.enums.WorkerCertifyStatus; import com.ghy.common.enums.WorkerCertifyStatus;
import com.ghy.common.enums.WorkerStatus;
import com.ghy.common.json.JSONObject;
import com.ghy.common.utils.ExceptionUtil; import com.ghy.common.utils.ExceptionUtil;
import com.ghy.common.utils.ObjectUtils; import com.ghy.common.utils.ObjectUtils;
import com.ghy.common.utils.StringUtils;
import com.ghy.common.utils.poi.ExcelUtil; import com.ghy.common.utils.poi.ExcelUtil;
import com.ghy.goods.domain.DeptGoodsCategory; import com.ghy.goods.domain.DeptGoodsCategory;
import com.ghy.goods.service.DeptGoodsCategoryService; import com.ghy.goods.service.DeptGoodsCategoryService;
@ -30,7 +27,6 @@ import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
@ -81,7 +77,13 @@ public class WorkerCertificationController extends BaseController
public TableDataInfo list(WorkerCertification workerCertification) public TableDataInfo list(WorkerCertification workerCertification)
{ {
startPage(); startPage();
if(this.getSysUser().getDept().getParentId() != 101){
workerCertification.setDeptId(this.getSysUser().getDept().getParentId());
}
List<WorkerCertification> list = workerCertificationService.selectWorkerCertificationList(workerCertification); List<WorkerCertification> list = workerCertificationService.selectWorkerCertificationList(workerCertification);
list.forEach(worker->{
worker.setName(worker.getSurname() + worker.getName());
});
return getDataTable(list); return getDataTable(list);
} }
@ -160,6 +162,8 @@ public class WorkerCertificationController extends BaseController
@ResponseBody @ResponseBody
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public AjaxResult appAddCertify(@RequestBody WorkerCertification request) { public AjaxResult appAddCertify(@RequestBody WorkerCertification request) {
Worker worker = workerService.selectById(request.getWorkerId());
request.setWorkerPhone(worker != null ? worker.getPhone() : null);
// 将师傅状态设置为冻结 // 将师傅状态设置为冻结
// Worker worker = new Worker(); // Worker worker = new Worker();
// worker.setWorkerId(request.getWorkerId()); // worker.setWorkerId(request.getWorkerId());
@ -222,7 +226,7 @@ public class WorkerCertificationController extends BaseController
for (String id : idArray){ for (String id : idArray){
WorkerCertification workerCertification = workerCertificationService.selectWorkerCertificationByWorkerCertificationId(id); WorkerCertification workerCertification = workerCertificationService.selectWorkerCertificationByWorkerCertificationId(id);
// 是否绑定了银行卡 // 是否绑定了银行卡
WorkerBank workerBank = workerBankService.getByWorkerId(workerCertification.getWorkerId()); WorkerBank workerBank = workerBankService.getByWorkerId(workerCertification.getWorkerId(), 101L);
// 没有绑定了银行卡的用户 // 没有绑定了银行卡的用户
if(ObjectUtils.isEmpty(workerBank)){ if(ObjectUtils.isEmpty(workerBank)){
return AjaxResult.success("操作成功!"); return AjaxResult.success("操作成功!");

View File

@ -10,6 +10,7 @@ import com.ghy.common.enums.WorkerStatus;
import com.ghy.common.enums.WorkerType; import com.ghy.common.enums.WorkerType;
import com.ghy.common.utils.CacheUtils; import com.ghy.common.utils.CacheUtils;
import com.ghy.common.utils.ExceptionUtil; import com.ghy.common.utils.ExceptionUtil;
import com.ghy.common.utils.StringUtils;
import com.ghy.goods.domain.Goods; import com.ghy.goods.domain.Goods;
import com.ghy.goods.domain.GoodsCategory; import com.ghy.goods.domain.GoodsCategory;
import com.ghy.goods.service.GoodsCategoryService; import com.ghy.goods.service.GoodsCategoryService;
@ -24,6 +25,7 @@ import com.ghy.worker.domain.WorkerArea;
import com.ghy.worker.domain.WorkerBank; import com.ghy.worker.domain.WorkerBank;
import com.ghy.worker.domain.WorkerGoodsCategory; import com.ghy.worker.domain.WorkerGoodsCategory;
import com.ghy.worker.service.*; import com.ghy.worker.service.*;
import com.github.pagehelper.PageInfo;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.util.Assert; import org.apache.shiro.util.Assert;
@ -81,9 +83,18 @@ public class WorkerController extends BaseController {
public AjaxResult login(@RequestBody Worker worker){ public AjaxResult login(@RequestBody Worker worker){
try { try {
Assert.notNull(worker.getPhone(), "手机号码为空"); Assert.notNull(worker.getPhone(), "手机号码为空");
List<Worker> workerList = workerService.getWorkList(worker); List<Worker> workerList = workerService.getWorkByPhoneAndPwd(worker);
if(workerList.size() > 0){ if(workerList.size() > 0){
return AjaxResult.success(workerList.get(0)); Worker loginWorker = workerList.get(0);
// 检查师傅状态0=生效,1=冻结,2=删除
if(loginWorker.getStatus() == WorkerStatus.DELETED.getCode()){
return AjaxResult.error("账户已被删除,无法登录!");
}
// 检查登录状态0=允许登录,1=禁止登录
if(loginWorker.getLoginStatus() != null && loginWorker.getLoginStatus() == 1){
return AjaxResult.error("账户登录已被禁用,无法登录!");
}
return AjaxResult.success(loginWorker);
}else { }else {
return AjaxResult.error("用户名或密码错误!"); return AjaxResult.error("用户名或密码错误!");
} }
@ -98,11 +109,13 @@ public class WorkerController extends BaseController {
@ResponseBody @ResponseBody
public AjaxResult register(@RequestBody Worker request){ public AjaxResult register(@RequestBody Worker request){
try { try {
logger.info("注册师傅信息:{}", request);
if (CacheUtils.get(request.getPhone()) == null){ if (CacheUtils.get(request.getPhone()) == null){
return AjaxResult.error("验证码无效!"); return AjaxResult.error("验证码无效!");
} }
// 验证码校验正确 // 验证码校验正确
if(CacheUtils.get(request.getPhone()).toString().equals(request.getRegisterCode())){ if(CacheUtils.get(request.getPhone()).toString().equals(request.getRegisterCode())){
logger.info("验证码信息:{}", CacheUtils.get(request.getPhone()));
int result = workerService.updateWorker(request); int result = workerService.updateWorker(request);
if(result > 0){ if(result > 0){
CacheUtils.remove(request.getPhone()); CacheUtils.remove(request.getPhone());
@ -129,28 +142,108 @@ public class WorkerController extends BaseController {
try { try {
// 查询满足区域条件的师傅区域记录 // 查询满足区域条件的师傅区域记录
WorkerArea workerArea = new WorkerArea(); List<Long> workerIdsByArea = new ArrayList<>();
workerArea.setDistrictId(workerListRequest.getAreaId()); if(workerListRequest.getAreaId() != null){
List<WorkerArea> workerAreaList = workerAreaService.getWorkerAreaList(workerArea); WorkerArea workerArea = new WorkerArea();
List<Long> workerIdsByArea = workerAreaList.stream().map(WorkerArea::getWorkerId).collect(Collectors.toList()); workerArea.setDistrictId(workerListRequest.getAreaId());
// 查询满足技能条件的师傅技能记录 // 如果有省市区的查询条件,需要构建完整的区域查询条件
WorkerGoodsCategory workerGoodsCategory = new WorkerGoodsCategory(); boolean flag = StringUtils.isNotEmpty(workerListRequest.getDistrictId()) || StringUtils.isNotEmpty(workerListRequest.getProvinceId())
workerGoodsCategory.setGoodsCategoryId(workerListRequest.getGoodsCategoryId()); || StringUtils.isNotEmpty(workerListRequest.getCityId()) || StringUtils.isNotEmpty(workerListRequest.getStreetId());
List<WorkerGoodsCategory> workerGoodsCategoryList = workerGoodsCategoryService.getWorkerGoodsCategory(workerGoodsCategory); if(flag){
List<Long> workerIdsByCategory = workerGoodsCategoryList.stream().map(WorkerGoodsCategory::getWorkerId).collect(Collectors.toList()); workerArea.setDistrictId(null);
// 两个list中的workerid取交集 }
List<Long> resWorkerIds = new ArrayList<>(CollectionUtils.intersection(workerIdsByArea, workerIdsByCategory)); if(StringUtils.isNotEmpty(workerListRequest.getDistrictId())){
workerArea.setDistrictId(Long.valueOf(workerListRequest.getDistrictId()));
}
if(StringUtils.isNotEmpty(workerListRequest.getProvinceId())) {
workerArea.setProvinceId(Long.valueOf(workerListRequest.getProvinceId()));
}
if(StringUtils.isNotEmpty(workerListRequest.getCityId())) {
workerArea.setCityId(Long.valueOf(workerListRequest.getCityId()));
}
if(StringUtils.isNotEmpty(workerListRequest.getStreetId())) {
workerArea.setStreetId(Long.valueOf(workerListRequest.getStreetId()));
}
List<WorkerArea> workerAreaList = workerAreaService.getWorkerAreaList(workerArea);
workerIdsByArea = workerAreaList.stream()
.map(WorkerArea::getWorkerId)
.collect(Collectors.toList());
}
if (CollectionUtils.isEmpty(resWorkerIds)) { // 查询满足技能条件的师傅技能记录
// 交集不存在的情况直接返回空list List<Long> workerIdsByCategory = new ArrayList<>();
return getDataTable(resList); WorkerGoodsCategory workerGoodsCategory = new WorkerGoodsCategory();
if(workerListRequest.getGoodsCategoryId() != null){
workerGoodsCategory.setGoodsCategoryId(workerListRequest.getGoodsCategoryId());
}
// 如果选择了上级类目但未选择最终类目,则查询该类目下所有子类目
if(StringUtils.isNotEmpty(workerListRequest.getCategoryLevel1())
&& StringUtils.isEmpty(workerListRequest.getCategoryLevel2()) && workerListRequest.getGoodsCategoryId() == null) {
// 1. 先查找二级类目
GoodsCategory param = new GoodsCategory();
param.setParentCategoryId(Long.valueOf(workerListRequest.getCategoryLevel1()));
List<GoodsCategory> secondCategories = goodsCategoryService.selectGoodsCategoryList(param);
// 2. 用二级类目查找三级类目
List<String> categoryIds = new ArrayList<>();
for (GoodsCategory secondCategory : secondCategories) {
param.setParentCategoryId(secondCategory.getGoodsCategoryId());
List<GoodsCategory> thirdCategories = goodsCategoryService.selectGoodsCategoryList(param);
categoryIds.addAll(thirdCategories.stream()
.map(x->x.getGoodsCategoryId().toString())
.collect(Collectors.toList()));
}
workerGoodsCategory.setCategoryIds(categoryIds);
}
// 如果选择了二级类目但未选择三级类目
else if(StringUtils.isNotEmpty(workerListRequest.getCategoryLevel2())
&& workerListRequest.getGoodsCategoryId() == null) {
GoodsCategory param = new GoodsCategory();
param.setParentCategoryId(Long.valueOf(workerListRequest.getCategoryLevel2()));
List<GoodsCategory> subCategories = goodsCategoryService.selectGoodsCategoryList(param);
List<String> categoryIds = subCategories.stream()
.map(x->x.getGoodsCategoryId().toString())
.collect(Collectors.toList());
workerGoodsCategory.setCategoryIds(categoryIds);
}
if(CollectionUtils.isNotEmpty(workerGoodsCategory.getCategoryIds()) || workerGoodsCategory.getGoodsCategoryId() != null){
List<WorkerGoodsCategory> workerGoodsCategoryList = workerGoodsCategoryService.getWorkerGoodsCategory(workerGoodsCategory);
workerIdsByCategory = workerGoodsCategoryList.stream()
.map(WorkerGoodsCategory::getWorkerId)
.collect(Collectors.toList());
}
// 两个list中的workerid取交集
List<Long> resWorkerIds = new ArrayList<>();
if(!workerIdsByArea.isEmpty() && !workerIdsByCategory.isEmpty()) {
resWorkerIds.addAll(CollectionUtils.intersection(workerIdsByArea, workerIdsByCategory));
} else if(!workerIdsByArea.isEmpty()) {
resWorkerIds.addAll(workerIdsByArea);
} else if(!workerIdsByCategory.isEmpty()) {
resWorkerIds.addAll(workerIdsByCategory);
}
if (!resWorkerIds.isEmpty() ||
workerListRequest.getAreaId() != null ||
workerListRequest.getGoodsCategoryId() != null) {
// 有查询条件但无匹配结果时直接返回空列表
if(resWorkerIds.isEmpty()) {
return getDataTable(resList);
}
} }
startPage(); startPage();
Worker worker = new Worker(); Worker worker = new Worker();
worker.setWorkerIds(CollectionUtils.isNotEmpty(resWorkerIds) ? resWorkerIds : null); worker.setWorkerIds(CollectionUtils.isNotEmpty(resWorkerIds) ? resWorkerIds : null);
worker.setName(workerListRequest.getWorkerName()); worker.setKeyWords(workerListRequest.getWorkerName());
if(StringUtils.isNotEmpty(workerListRequest.getWorkerPhone())){
worker.setPhone(workerListRequest.getWorkerPhone());
}
if(this.getSysUser().getDept().getParentId() != 101){
worker.setDeptId(this.getSysUser().getDept().getParentId());
}
List<Worker> list = workerService.getWorkList(worker); List<Worker> list = workerService.getWorkList(worker);
TableDataInfo dataTable = getDataTable(list);
list.forEach(w -> { list.forEach(w -> {
Goods goods = new Goods(); Goods goods = new Goods();
goods.setWorkerId(w.getWorkerId()); goods.setWorkerId(w.getWorkerId());
@ -161,13 +254,18 @@ public class WorkerController extends BaseController {
workerListResponse.setGoodsCategories(workerGoodsCategoryService.getByWorker(w.getWorkerId())); workerListResponse.setGoodsCategories(workerGoodsCategoryService.getByWorker(w.getWorkerId()));
workerListResponse.setSpecialSkills(specialSkillService.getByWorker(w.getWorkerId())); workerListResponse.setSpecialSkills(specialSkillService.getByWorker(w.getWorkerId()));
resList.add(workerListResponse); resList.add(workerListResponse);
}); });
TableDataInfo rspData = new TableDataInfo();
rspData.setCode(0);
rspData.setRows(resList);
rspData.setTotal(dataTable.getTotal());
return rspData;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
logger.error(ExceptionUtil.getExceptionMessage(e)); logger.error(ExceptionUtil.getExceptionMessage(e));
return getDataTable(new ArrayList<>());
} }
return getDataTable(resList);
} }
@PostMapping("/app/list") @PostMapping("/app/list")
@ -238,6 +336,7 @@ public class WorkerController extends BaseController {
startPage(); startPage();
// worker.setWorkerIds(CollectionUtils.isNotEmpty(resWorkerIds) ? resWorkerIds : null); // worker.setWorkerIds(CollectionUtils.isNotEmpty(resWorkerIds) ? resWorkerIds : null);
worker.setName(workerListRequest.getWorkerName()); worker.setName(workerListRequest.getWorkerName());
worker.setStatus(0);
List<Worker> list = workerService.getWorkList(worker); List<Worker> list = workerService.getWorkList(worker);
list.forEach(w -> { list.forEach(w -> {
Goods goods = new Goods(); Goods goods = new Goods();
@ -252,7 +351,12 @@ public class WorkerController extends BaseController {
setDistrictIds(worker.getDistrictIds()); setDistrictIds(worker.getDistrictIds());
}})); }}));
} else { } else {
workerListResponse.setWorkerAreas(workerAreaService.getByWorker(w.getWorkerId())); List<WorkerArea> workerAreas = workerAreaService.getByWorker(w.getWorkerId());
if(workerAreas.size() > 10){
workerListResponse.setWorkerAreas(workerAreas.subList(0,10));
}else {
workerListResponse.setWorkerAreas(workerAreas);
}
} }
workerListResponse.setGoodsCategories(workerGoodsCategoryService.getByWorker(w.getWorkerId())); workerListResponse.setGoodsCategories(workerGoodsCategoryService.getByWorker(w.getWorkerId()));
workerListResponse.setSpecialSkills(specialSkillService.getByWorker(w.getWorkerId())); workerListResponse.setSpecialSkills(specialSkillService.getByWorker(w.getWorkerId()));
@ -317,19 +421,106 @@ public class WorkerController extends BaseController {
} }
} }
@PostMapping("/changeLoginStatus")
@ResponseBody
public AjaxResult changeLoginStatus(Worker worker){
try {
workerService.updateWorker(worker);
return AjaxResult.success("登录状态修改成功");
}catch (Exception e){
logger.error(ExceptionUtil.getExceptionMessage(e));
return AjaxResult.error(e.getMessage());
}
}
@PostMapping("/settled") @PostMapping("/settled")
@ResponseBody @ResponseBody
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public AjaxResult settled(@RequestBody WorkerSettledRequest request) { public AjaxResult settled(@RequestBody WorkerSettledRequest request) {
// 入驻区域信息持久化 // 入驻服务区域信息持久化类型1
workerAreaService.updateWorkerServArea(request.getWorkerId(), request.getWorkerAreas()); workerAreaService.updateWorkerAreaByType(request.getWorkerId(), request.getWorkerAreas(), 1);
// 入驻服务品类信息持久化
workerGoodsCategoryService.updateWorkerGoodsCategory(request.getWorkerId(), request.getGoodsCategories()); // 入驻商品区域信息持久化类型2
workerAreaService.updateWorkerAreaByType(request.getWorkerId(), request.getWorkerGoodsAreas(), 2);
// 入驻服务类目信息持久化类型1
if (request.getServiceCategories() != null && !request.getServiceCategories().isEmpty()) {
// 使用对象数组方式
workerGoodsCategoryService.updateWorkerGoodsCategoryByType(request.getWorkerId(), request.getServiceCategories(), 1);
} else if (request.getServiceCategoryIds() != null && !request.getServiceCategoryIds().isEmpty()) {
// 使用ID数组方式兼容旧版本
List<WorkerGoodsCategory> serviceCategories = request.getServiceCategoryIds().stream()
.map(id -> {
WorkerGoodsCategory category = new WorkerGoodsCategory();
category.setGoodsCategoryId(id);
return category;
}).collect(Collectors.toList());
workerGoodsCategoryService.updateWorkerGoodsCategoryByType(request.getWorkerId(), serviceCategories, 1);
}
// 入驻商品类目信息持久化类型2
if (request.getGoodsCategories() != null && !request.getGoodsCategories().isEmpty()) {
// 使用对象数组方式
workerGoodsCategoryService.updateWorkerGoodsCategoryByType(request.getWorkerId(), request.getGoodsCategories(), 2);
} else if (request.getGoodsCategoryIds() != null && !request.getGoodsCategoryIds().isEmpty()) {
// 使用ID数组方式兼容旧版本
List<WorkerGoodsCategory> goodsCategories = request.getGoodsCategoryIds().stream()
.map(id -> {
WorkerGoodsCategory category = new WorkerGoodsCategory();
category.setGoodsCategoryId(id);
return category;
}).collect(Collectors.toList());
workerGoodsCategoryService.updateWorkerGoodsCategoryByType(request.getWorkerId(), goodsCategories, 2);
}
// 更新师傅入驻类型为服务商 // 更新师傅入驻类型为服务商
Worker worker = new Worker(); Worker worker = new Worker();
worker.setWorkerId(request.getWorkerId()); worker.setWorkerId(request.getWorkerId());
worker.setType(WorkerType.SP.getCode()); worker.setType(WorkerType.SP.getCode());
workerService.updateWorker(worker); workerService.updateWorker(worker);
return AjaxResult.success("保存成功"); return AjaxResult.success("保存成功");
} }
/**
* 通过师傅ID获取师傅详情
* @param workerId 师傅ID
* @return 师傅实体对象
*/
@GetMapping("/detail/{workerId}")
@ResponseBody
public AjaxResult getWorkerDetailById(@PathVariable("workerId") Long workerId) {
try {
// 参数校验
if (workerId == null) {
return AjaxResult.error("师傅ID不能为空");
}
// 查询师傅基本信息
Worker worker = workerService.selectById(workerId);
if (worker == null) {
return AjaxResult.error("师傅不存在");
}
return AjaxResult.success(worker);
} catch (Exception e) {
logger.error("获取师傅详情失败: " + ExceptionUtil.getExceptionMessage(e));
return AjaxResult.error("获取师傅详情失败: " + e.getMessage());
}
}
/**
* 删除师傅软删除
*/
@RequiresPermissions("worker:worker:remove")
@PostMapping("/remove")
@ResponseBody
public AjaxResult remove(String ids) {
try {
return toAjax(workerService.deleteWorkerByIds(ids));
} catch (Exception e) {
logger.error(ExceptionUtil.getExceptionMessage(e));
return AjaxResult.error("删除失败: " + e.getMessage());
}
}
} }

View File

@ -1,11 +1,14 @@
package com.ghy.web.controller.worker; package com.ghy.web.controller.worker;
import com.ghy.common.constant.Constants; import com.ghy.common.constant.Constants;
import com.ghy.common.core.controller.BaseController;
import com.ghy.common.core.domain.AjaxResult; import com.ghy.common.core.domain.AjaxResult;
import com.ghy.common.core.page.TableDataInfo;
import com.ghy.common.core.text.Convert; import com.ghy.common.core.text.Convert;
import com.ghy.common.utils.StringUtils; import com.ghy.common.utils.StringUtils;
import com.ghy.goods.domain.GoodsCategory; import com.ghy.goods.domain.GoodsCategory;
import com.ghy.goods.service.GoodsCategoryService; import com.ghy.goods.service.GoodsCategoryService;
import com.ghy.worker.domain.WorkerArea;
import com.ghy.worker.domain.WorkerGoodsCategory; import com.ghy.worker.domain.WorkerGoodsCategory;
import com.ghy.worker.request.WorkerGoodsCategorySaveRequest; import com.ghy.worker.request.WorkerGoodsCategorySaveRequest;
import com.ghy.worker.service.WorkerGoodsCategoryService; import com.ghy.worker.service.WorkerGoodsCategoryService;
@ -13,6 +16,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.ModelMap;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -28,7 +32,7 @@ import java.util.stream.Collectors;
@Slf4j @Slf4j
@Controller @Controller
@RequestMapping("worker/goods/category") @RequestMapping("worker/goods/category")
public class WorkerGoodsCategoryController { public class WorkerGoodsCategoryController extends BaseController {
@Resource @Resource
private WorkerGoodsCategoryService workerGoodsCategoryService; private WorkerGoodsCategoryService workerGoodsCategoryService;
@ -36,15 +40,51 @@ public class WorkerGoodsCategoryController {
@Autowired @Autowired
private GoodsCategoryService goodsCategoryService; private GoodsCategoryService goodsCategoryService;
@PostMapping("/list")
@ResponseBody
public TableDataInfo list(WorkerGoodsCategory workerGoodsCategory) {
startPage();
List<WorkerGoodsCategory> list = workerGoodsCategoryService.getByWorker(workerGoodsCategory.getWorkerId());
for (WorkerGoodsCategory item: list) {
List<String> nameList = new ArrayList<String>();
// 查询所有父级服务类目拼接服务名称
GoodsCategory goodsCategory = goodsCategoryService.selectById(item.getGoodsCategoryId());
while (goodsCategory.getParentCategoryId() != null) {
nameList.add(goodsCategory.getGoodsCategoryName());
goodsCategory = goodsCategoryService.selectById(goodsCategory.getParentCategoryId());
}
Collections.reverse(nameList);
item.setMergeName(StringUtils.join(nameList, Constants.JOIN_SYMBOL));
}
return getDataTable(list);
}
@GetMapping()
public String category(Long workerId, ModelMap mmap)
{
mmap.put("workerId", workerId);
return "worker/categoryDetail";
}
/** /**
* 查询某个师傅的所有服务类目 * 查询某个师傅的所有服务类目
* *
* @param workerId 师傅ID * @param workerId 师傅ID
* @param serviceType 服务类型1=服务, 2=商品不传则查询所有
*/ */
@GetMapping("worker") @GetMapping("worker")
@ResponseBody @ResponseBody
public AjaxResult getByWorker(Long workerId) { public AjaxResult getByWorker(Long workerId, Integer serviceType) {
List<WorkerGoodsCategory> list = workerGoodsCategoryService.getByWorker(workerId); List<WorkerGoodsCategory> list;
if (serviceType != null) {
// 根据服务类型查询
list = workerGoodsCategoryService.getByWorkerIdAndType(workerId, serviceType);
} else {
// 查询所有类目保持向后兼容
list = workerGoodsCategoryService.getByWorker(workerId);
}
for (WorkerGoodsCategory item: list) { for (WorkerGoodsCategory item: list) {
List<String> nameList = new ArrayList<String>(); List<String> nameList = new ArrayList<String>();
// 查询所有父级服务类目拼接服务名称 // 查询所有父级服务类目拼接服务名称
@ -58,14 +98,75 @@ public class WorkerGoodsCategoryController {
} }
return AjaxResult.success(list); return AjaxResult.success(list);
} }
/**
* 查询某个师傅的服务类目类型1
*
* @param workerId 师傅ID
*/
@GetMapping("worker/service")
@ResponseBody
public AjaxResult getServiceCategoriesByWorker(Long workerId) {
List<WorkerGoodsCategory> list = workerGoodsCategoryService.getByWorkerIdAndType(workerId, 1);
for (WorkerGoodsCategory item: list) {
List<String> nameList = new ArrayList<String>();
// 查询所有父级服务类目拼接服务名称
GoodsCategory goodsCategory = goodsCategoryService.selectById(item.getGoodsCategoryId());
while (goodsCategory.getParentCategoryId() != null) {
nameList.add(goodsCategory.getGoodsCategoryName());
goodsCategory = goodsCategoryService.selectById(goodsCategory.getParentCategoryId());
}
Collections.reverse(nameList);
item.setMergeName(StringUtils.join(nameList, Constants.JOIN_SYMBOL));
}
return AjaxResult.success(list);
}
/**
* 查询某个师傅的商品类目类型2
*
* @param workerId 师傅ID
*/
@GetMapping("worker/goods")
@ResponseBody
public AjaxResult getGoodsCategoriesByWorker(Long workerId) {
List<WorkerGoodsCategory> list = workerGoodsCategoryService.getByWorkerIdAndType(workerId, 2);
for (WorkerGoodsCategory item: list) {
List<String> nameList = new ArrayList<String>();
// 查询所有父级服务类目拼接服务名称
GoodsCategory goodsCategory = goodsCategoryService.selectById(item.getGoodsCategoryId());
while (goodsCategory.getParentCategoryId() != null) {
nameList.add(goodsCategory.getGoodsCategoryName());
goodsCategory = goodsCategoryService.selectById(goodsCategory.getParentCategoryId());
}
Collections.reverse(nameList);
item.setMergeName(StringUtils.join(nameList, Constants.JOIN_SYMBOL));
}
return AjaxResult.success(list);
}
@GetMapping("worker/edit") @GetMapping("worker/edit")
@ResponseBody @ResponseBody
public AjaxResult getEditWorker(Long workerId) { public AjaxResult getEditWorker(Long workerId, Integer type) {
Map<Long, List<String>> twoMap = new HashMap<>(); Map<Long, List<String>> twoMap = new HashMap<>();
List<WorkerGoodsCategory> list = workerGoodsCategoryService.getByWorker(workerId);
// 根据类型查询对应的商品分类数据
List<WorkerGoodsCategory> list;
if (Integer.valueOf(1).equals(type)) {
// 服务类型查询服务商品分类
list = workerGoodsCategoryService.getByWorkerIdAndType(workerId, 1);
} else if (Integer.valueOf(2).equals(type)) {
// 商品类型查询商品分类
list = workerGoodsCategoryService.getByWorkerIdAndType(workerId, 2);
} else {
// 不传类型查询所有商品分类
list = workerGoodsCategoryService.getByWorker(workerId);
}
if(CollectionUtils.isEmpty(list)){ if(CollectionUtils.isEmpty(list)){
return AjaxResult.success(); return AjaxResult.success();
} }
for (WorkerGoodsCategory item: list) { for (WorkerGoodsCategory item: list) {
List<String> ids; List<String> ids;
GoodsCategory goodsCategory = goodsCategoryService.selectById(item.getGoodsCategoryId()); GoodsCategory goodsCategory = goodsCategoryService.selectById(item.getGoodsCategoryId());
@ -77,6 +178,7 @@ public class WorkerGoodsCategoryController {
ids.add(String.valueOf(goodsCategory.getGoodsCategoryId())); ids.add(String.valueOf(goodsCategory.getGoodsCategoryId()));
twoMap.put(goodsCategory.getParentCategoryId(), ids); twoMap.put(goodsCategory.getParentCategoryId(), ids);
} }
List<WorkerGoodsCategory> result = new ArrayList<>(); List<WorkerGoodsCategory> result = new ArrayList<>();
for (Map.Entry<Long, List<String>> longListEntry : twoMap.entrySet()) { for (Map.Entry<Long, List<String>> longListEntry : twoMap.entrySet()) {
WorkerGoodsCategory model = new WorkerGoodsCategory(); WorkerGoodsCategory model = new WorkerGoodsCategory();

View File

@ -0,0 +1,38 @@
package com.ghy.web.core.config;
import com.aliyun.dytnsapi20200217.Client;
import com.aliyun.teaopenapi.models.Config;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
public class AliApiConfig {
@Value("${aliyun.accessKey}")
private String accessKey;
@Value("${aliyun.accessSecret}")
private String accessSecret;
@Value("${aliyun.endpoint}")
private String endpoint;
@Value("${aliyun.authCode}")
private String authCode;
@Bean
public Client createClient() throws Exception {
// 建议使用更安全的 STS 方式更多鉴权访问方式请参见https://help.aliyun.com/document_detail/378657.html
Config config = new Config()
// 必填请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID
.setAccessKeyId(accessKey)
// 必填请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET
.setAccessKeySecret(accessSecret)
.setEndpoint(endpoint);
return new Client(config);
}
}

View File

@ -41,7 +41,7 @@ public class SwaggerConfig
// 扫描所有有注解的api用这种方式更灵活 // 扫描所有有注解的api用这种方式更灵活
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// 扫描指定包中的swagger注解 // 扫描指定包中的swagger注解
.apis(RequestHandlerSelectors.basePackage("com.ghy.web.controller.tool")) .apis(RequestHandlerSelectors.basePackage("com.ghy.web.controller.order"))
// 扫描所有 .apis(RequestHandlerSelectors.any()) // 扫描所有 .apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()) .paths(PathSelectors.any())
.build(); .build();

View File

@ -0,0 +1,14 @@
package com.ghy.web.pojo.vo;
import lombok.Data;
@Data
public class CertNoTwoElementReq {
private Long workerId;
private String certNo;
private String certName;
}

View File

@ -0,0 +1,23 @@
package com.ghy.web.pojo.vo;
import lombok.Data;
@Data
public class InsuranceOrderEditReq {
private String requestNo;
private String channelCode = "NNDD0806QH";
private String sign;
private String orderNumber;
private String workName;
private String workerID;
private String shangmenTime;
private String shangmenNum;
}

View File

@ -0,0 +1,36 @@
package com.ghy.web.pojo.vo;
import lombok.Data;
import java.util.Date;
@Data
public class InsuranceOrderReq {
private String requestNo;
private String channelCode = "NNDD0806QH";
private String sign;
private String orderNumber;
private String orderProductType = "0002";
private String orderStatus = "1";
private String orderStartat;
private String orderEndat;
private String customerAddress;
private String customerPhone;
private String workName;
private String workerID;
}

View File

@ -8,6 +8,7 @@ import java.math.BigDecimal;
/** /**
* 改价请求实体 * 改价请求实体
*
* @author clunt * @author clunt
*/ */
@Data @Data
@ -21,4 +22,10 @@ public class OrderChangePriceRequest implements Serializable {
private Integer type; private Integer type;
private String remark; private String remark;
private String urls;
private String fileNames;
private String reason;
} }

View File

@ -29,4 +29,13 @@ public class OrderListRequest {
private Integer shelveStatus; private Integer shelveStatus;
private Integer allSelfAssigned; private Integer allSelfAssigned;
/**
* 是否超时 1= 0=
*/
private Integer timeout;
private Boolean needImgs = true;
private Integer orderType;
} }

View File

@ -2,10 +2,15 @@ package com.ghy.web.pojo.vo;
import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.ghy.common.annotation.Excel;
import com.ghy.goods.domain.Goods;
import com.ghy.goods.domain.GoodsArea; import com.ghy.goods.domain.GoodsArea;
import com.ghy.goods.domain.InsuranceManager;
import com.ghy.order.domain.AfterServiceRecord; import com.ghy.order.domain.AfterServiceRecord;
import com.ghy.payment.domain.FinancialChangeRecord; import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.OrderTimeoutRecord; import com.ghy.payment.domain.OrderTimeoutRecord;
import com.ghy.shop.domain.Shop;
import lombok.Data; import lombok.Data;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -15,16 +20,29 @@ import java.util.List;
@Data @Data
public class OrderListResponse { public class OrderListResponse {
// 商品品牌 -- 后台发单才有
private String goodsBrand;
// 商品规格 -- 后台发单才有
private String goodsSpecification;
private String totalName;
private String isCall;
private Long orderMasterId; private Long orderMasterId;
private String orderMasterCode; private String orderMasterCode;
private String originalOrderMasterCode;
private Long orderDetailId; private Long orderDetailId;
private String orderDetailCode; private String orderDetailCode;
private Long workerId; private Long workerId;
private Long masterWorkerId;
private String workerName; private String workerName;
private String workerPhone; private String workerPhone;
@ -35,6 +53,8 @@ public class OrderListResponse {
private String masterCompanyName; private String masterCompanyName;
private String masterCompanyPhone;
private String customerName; private String customerName;
private String customerPhone; private String customerPhone;
@ -67,14 +87,23 @@ public class OrderListResponse {
private Integer orderStatus; private Integer orderStatus;
private String orderStatusName;
private Integer payStatus; private Integer payStatus;
/**
* 退款支付状态0=未支付1=已支付
*/
private Integer refundPayStatus;
private Integer payType; private Integer payType;
private BigDecimal totalMoney; private BigDecimal totalMoney;
private BigDecimal payMoney; private BigDecimal payMoney;
private BigDecimal payAddMoney;
private BigDecimal finalRecvMoney; private BigDecimal finalRecvMoney;
private BigDecimal changeMoney; private BigDecimal changeMoney;
@ -137,4 +166,174 @@ public class OrderListResponse {
* 提现到账时间 arrival_time * 提现到账时间 arrival_time
*/ */
private Date arrivalTime; private Date arrivalTime;
/**
* 是否超时 1= 0=
*/
private Integer timeout;
/**
* 超时扣款次数
*/
private Integer timeoutFineTimes;
/**
* 超时时间用于排序
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date timeoutTime;
private Integer afterTimeout;
private String orderMode;
/*是否合约订单*/
private String consultMode;
private Goods goods;
/*是否有保险id*/
private Long insuranceId;
private InsuranceManager insuranceManager;
private Long cityId;
/*街道id*/
private Long streetId;
private Long provinceId;
private String name;
private String phone;
private String provinceName;
private String cityName;
private String countryName;
private String streetName;
private Long countryId;
/**
* 是否为监控但
* */
private Boolean isMonitoredOrder;
private BigDecimal addMoney;
private String addMoneyRemark;
private BigDecimal paymentMoney;
/**
* 是否已派发服务订单0=未派发1=已派发
*/
private Integer hasServiceOrder;
/**
* 下单图片
*/
@Excel(name = "下单图片", cellType = Excel.ColumnType.STRING)
private String orderImages;
/**
* 是否发货到服务店0=1=
*/
@Excel(name = "是否发货到服务店", cellType = Excel.ColumnType.NUMERIC)
private Integer isDeliveryToStore;
/**
* 是否已开票0=1=
*/
@Excel(name = "是否已开票", cellType = Excel.ColumnType.NUMERIC, readConverterExp = "0=是,1=否")
private Integer isInvoiced;
/**
* 是否需要开票0=不需要1=需要
*/
@Excel(name = "是否需要开票", cellType = Excel.ColumnType.NUMERIC, readConverterExp = "0=不需要,1=需要")
private Integer isNeedBill;
/**
* 原师傅id转单前的师傅
*/
@Excel(name = "原师傅id", cellType = Excel.ColumnType.NUMERIC)
private Long originalWorkerId;
private Long serverGoodsId;
/**
* 服务店铺ID
*/
private Long serviceShopId;
private Date confirmStartTime;
private Integer deliveryType;
private Long goodsId;
/**
* 发货备注
*/
@Excel(name = "发货备注", cellType = Excel.ColumnType.STRING)
private String deliveryRemark;
/**
* 发货图片
*/
@Excel(name = "发货图片", cellType = Excel.ColumnType.STRING)
private String deliveryImages;
@Excel(name = "交货图片", cellType = Excel.ColumnType.STRING)
private String handoverImages;
@Excel(name = "交货备注", cellType = Excel.ColumnType.STRING)
private String handoverRemark;
/**
* 快递单号
*/
private String trackingNumber;
/**
* 分账倒计时结束时间
*/
@Excel(name = "分账倒计时结束时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date shareAccountCountdownEndTime;
/**
* 分账倒计时时长小时
*/
@Excel(name = "分账倒计时时长(小时)")
private Integer shareAccountCountdownDuration;
private Shop shop;
private Shop serviceShop;
private Long goodsOrderMasterId;
/**
* 是否已撤销服务主单0=未撤销1=已撤销
*/
@Excel(name = "是否已撤销服务主单", cellType = Excel.ColumnType.NUMERIC, readConverterExp = "0=未撤销,1=已撤销")
private Integer serviceCancelled;
/**
* 是否显示售后记录0=不显示1=显示
*/
private Integer showAfterServiceRecord = 0;
@Excel(name = "是否显示在监控单", cellType = Excel.ColumnType.NUMERIC, readConverterExp = "0=不显示,1=显示在监控单")
private Integer showInMonitor;
@Excel(name = "售后状态0-无售后1-售后纠纷,2-售后已完成,3-售后已取消")
private Integer afterPlatformServiceStatus;
} }

View File

@ -55,4 +55,83 @@ public class OrderStandardDetail {
private Boolean isOverTime; private Boolean isOverTime;
private BigDecimal serverMoney; private BigDecimal serverMoney;
/**
* draw_cash_status
* 0 未分账
* 1 已分账
* 2 已到账
* -1 提现失败
*/
private Integer drawCashStatus;
/**
* 发起提现时间 draw_cash_time
*/
private Date drawCashTime;
/**
* 是否超时 1= 0=
*/
private Integer timeout;
/**
* 超时扣款次数
*/
private Integer timeoutFineTimes;
private Integer afterTimeout;
private BigDecimal addMoney;
/**
* 退单原因
*/
private String returnReason;
/**
* 退单原因详情
*/
private String returnReasonDetail;
/**
* 退单图片
*/
private String returnImages;
/**
* 发货类型 - 订单的发货方式
*/
private Integer deliveryType;
/**
* 发货备注 - 发货相关备注信息
*/
private String deliveryRemark;
/**
* 发货图片 - 发货凭证图片
*/
private String deliveryImages;
/**
* 快递单号 - 物流跟踪单号
*/
private String trackingNumber;
private String handoverImages;
private String handoverRemark;
private String orderImages;
//= "售后状态0-无售后1-售后纠纷,2-售后已完成,3-售后已取消"
private Integer afterPlatformServiceStatus;
private Integer payStatus;
private Integer refundPayStatus;
} }

View File

@ -11,4 +11,8 @@ import lombok.Data;
@Data @Data
public class OrderStatisticsRequest { public class OrderStatisticsRequest {
private Long workerId; private Long workerId;
private Long deptId;
private Integer orderType;
} }

View File

@ -0,0 +1,54 @@
package com.ghy.web.pojo.vo;
import com.ghy.system.domain.SysGlobalConfig;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.springframework.beans.BeanUtils;
/**
* @Author 但星霖
* @Date 2023-03-20 203716
* 说明系统配置返回vo
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Schema(description = "系统配置请求返回vo")
public class SysGlobalConfigRequestVO {
@Schema(description = "配置项主键ID")
private Long id;
@Schema(description = "配置项名称")
private String name;
@Schema(description = "配置项内容json串")
private String content;
@Schema(description = "排序号")
private Integer sort;
@Schema(description = "描述")
private String describe;
@Schema(description = "配置类型")
private Integer type;
@Schema(description = "数据内容类型")
private Integer dataType;
@Schema(description = "单位")
private String configUnit;
public static SysGlobalConfig toModel(SysGlobalConfigRequestVO vo){
SysGlobalConfig sysConfig = new SysGlobalConfig();
BeanUtils.copyProperties(vo, sysConfig);
return sysConfig;
}
}

View File

@ -0,0 +1,116 @@
package com.ghy.web.pojo.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.ghy.common.annotation.SysConstants;
import com.ghy.common.enums.SysGlobalConfigDataTypeEnum;
import com.ghy.common.enums.SysGlobalConfigEnum;
import com.ghy.common.utils.ObjectVerifyUtils;
import com.ghy.system.domain.SysGlobalConfig;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* @Author 但星霖
* @Date 2023-03-20 203716
* 说明系统配置返回vo
*/
@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
@Schema(description = "系统配置返回vo")
public class SysGlobalConfigResponseVO {
@Schema(description = "配置项主键ID")
private Long id;
@Schema(description = "配置项名称")
private String name;
@Schema(description = "配置项内容json串")
private String content;
@Schema(description = "排序号")
private Integer sort;
@Schema(description = "描述")
private String describe;
@Schema(description = "配置类型")
private Integer type;
@Schema(description = "配置类型枚举")
private SysGlobalConfigEnum typeEnum;
@Schema(description = "配置类型Desc")
private String typeEnumDesc;
@Schema(description = "数据内容类型")
private Integer dataType;
@Schema(description = "数据内容类型")
private SysGlobalConfigDataTypeEnum dataTypeEnum;
@Schema(description = "数据内容类型")
private String dataTypeEnumDesc;
@Schema(description = "单位")
private String configUnit;
@JsonInclude(value = JsonInclude.Include.NON_NULL)
@JsonFormat(pattern = SysConstants.DATE_TIME_FORMAT, locale = "zh", timezone = "GMT+8")
@Schema(description = "创建时间")
private Date createTime;
@JsonInclude(value = JsonInclude.Include.NON_NULL)
@JsonFormat(pattern = SysConstants.DATE_TIME_FORMAT, locale = "zh", timezone = "GMT+8")
@Schema(description = "更新时间")
private Date updateTime;
public static SysGlobalConfigResponseVO toVo(SysGlobalConfig model) {
if (ObjectVerifyUtils.isNull(model)) {
return null;
}
SysGlobalConfigResponseVO vo = new SysGlobalConfigResponseVO();
BeanUtils.copyProperties(model, vo);
// 配置类型
if (ObjectVerifyUtils.isNotNull(model.getType())) {
SysGlobalConfigEnum configEnum = SysGlobalConfigEnum.parse(model.getType());
if (ObjectVerifyUtils.isNotNull(configEnum)) {
vo.setTypeEnum(configEnum);
vo.setTypeEnumDesc(configEnum.desc());
}
}
// 配置类型数据类型
if (ObjectVerifyUtils.isNotNull(model.getDataType())) {
SysGlobalConfigDataTypeEnum sysConfigDataTypeEnum = SysGlobalConfigDataTypeEnum.parse(model.getDataType());
if (ObjectVerifyUtils.isNotNull(sysConfigDataTypeEnum)) {
vo.setDataTypeEnum(sysConfigDataTypeEnum);
vo.setDataTypeEnumDesc(sysConfigDataTypeEnum.desc());
}
}
// 时间类单独处理
vo.setCreateTime(ObjectVerifyUtils.isNotNull(model.getCreateTime()) ? new Date(model.getCreateTime()) : null);
vo.setUpdateTime(ObjectVerifyUtils.isNotNull(model.getUpdateTime()) ? new Date(model.getUpdateTime()) : null);
return vo;
}
public static List<SysGlobalConfigResponseVO> toVoList(List<SysGlobalConfig> sysConfigList) {
List<SysGlobalConfigResponseVO> voList = new ArrayList<>();
if (ObjectVerifyUtils.isNotEmpty(sysConfigList)) {
sysConfigList.forEach(sysConfig -> voList.add(toVo(sysConfig)));
}
return voList;
}
}

View File

@ -0,0 +1,77 @@
package com.ghy.web.pojo.vo;
import com.ghy.common.annotation.Excel;
import lombok.Data;
@Data
public class SysOrderRequest {
@Excel(name = "seq")
private String seq;
@Excel(name = "category")
private String category;
@Excel(name = "lastCategory")
private String lastCategory;
@Excel(name = "brand")
private String brand;
@Excel(name = "date")
private String date;
@Excel(name = "time")
private String time;
@Excel(name = "mode")
private String mode;
@Excel(name = "num")
private String num;
@Excel(name = "price")
private String price;
@Excel(name = "name")
private String name;
@Excel(name = "phone")
private String phone;
@Excel(name = "address")
private String address;
@Excel(name = "remark")
private String remark;
@Excel(name = "money")
private String money;
@Excel(name = "award")
private String award;
@Excel(name = "infoMoney")
private String infoMoney;
@Excel(name = "url")
private String url;
@Excel(name = "logistics")
private String logistics;
@Excel(name = "needHll")
private String needHll;
@Excel(name = "bh")
private String bh;
@Excel(name = "floor")
private String floor;
@Excel(name = "floorUp")
private String floorUp;
@Excel(name = "bhry")
private String bhry;
}

View File

@ -1,5 +1,6 @@
package com.ghy.web.pojo.vo; package com.ghy.web.pojo.vo;
import com.ghy.common.core.domain.BaseEntity;
import com.ghy.worker.domain.Worker; import com.ghy.worker.domain.Worker;
import lombok.Data; import lombok.Data;
@ -10,7 +11,7 @@ import java.util.List;
* @date : 2022-06-24 17:38 * @date : 2022-06-24 17:38
*/ */
@Data @Data
public class WorkerListRequest { public class WorkerListRequest extends BaseEntity {
private Long areaId; private Long areaId;
private List<Long> areaIds; private List<Long> areaIds;
@ -19,9 +20,25 @@ public class WorkerListRequest {
private String workerName; private String workerName;
private String workerPhone;
private Long workerId; private Long workerId;
private Long exceptParentAreaId; private Long exceptParentAreaId;
private boolean justShowCurWorkerArea; private boolean justShowCurWorkerArea;
private String keyWords;
private String provinceId;
private String cityId;
private String districtId;
private String streetId;
private String categoryLevel1;
private String categoryLevel2;
} }

View File

@ -21,9 +21,21 @@ public class WorkerSettledRequest {
// 入驻区域 // 入驻区域
private List<WorkerArea> workerAreas; private List<WorkerArea> workerAreas;
// 服务品类 // 入驻商品区域
private List<WorkerArea> workerGoodsAreas;
// 入驻服务类目
private List<WorkerGoodsCategory> serviceCategories;
// 入驻商品类目
private List<WorkerGoodsCategory> goodsCategories; private List<WorkerGoodsCategory> goodsCategories;
// 入驻服务类目ID列表兼容旧版本
private List<Long> serviceCategoryIds;
// 入驻商品类目ID列表兼容旧版本
private List<Long> goodsCategoryIds;
// 特殊技能 // 特殊技能
// private List<WorkerSpecialSkill> specialSkills; // private List<WorkerSpecialSkill> specialSkills;
} }

View File

@ -0,0 +1,14 @@
package com.ghy.web.service;
import com.ghy.web.pojo.vo.CertNoTwoElementReq;
import org.springframework.web.bind.annotation.RequestBody;
/**
* <p>阿里云api合集,二次包装在服务内</p>
* @author clunt
*/
public interface AliCloudService {
void certNoTwoElementVerification(@RequestBody CertNoTwoElementReq certNoTwoElementReq) throws Exception;
}

View File

@ -0,0 +1,13 @@
package com.ghy.web.service;
import com.ghy.order.domain.OrderDetailInsuranceUser;
public interface InsuranceService {
void clockInsurance(Long orderDetailId) throws Exception;
void orderInsurance(String orderCode) throws Exception;
void editInsurance(OrderDetailInsuranceUser orderDetailInsuranceUser) throws Exception ;
}

View File

@ -0,0 +1,38 @@
package com.ghy.web.service.impl;
import cn.hutool.core.lang.Assert;
import cn.hutool.json.JSONUtil;
import com.aliyun.dytnsapi20200217.Client;
import com.aliyun.dytnsapi20200217.models.CertNoTwoElementVerificationRequest;
import com.aliyun.dytnsapi20200217.models.CertNoTwoElementVerificationResponse;
import com.ghy.web.core.config.AliApiConfig;
import com.ghy.web.pojo.vo.CertNoTwoElementReq;
import com.ghy.web.service.AliCloudService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AliCloudServiceImpl implements AliCloudService {
private final AliApiConfig aliApiConfig;
@Override
public void certNoTwoElementVerification(CertNoTwoElementReq certNoTwoElementReq) throws Exception{
// 校验是否是历史记录
Client client = aliApiConfig.createClient();
CertNoTwoElementVerificationRequest request = new CertNoTwoElementVerificationRequest();
request.setAuthCode(aliApiConfig.getAuthCode());
request.setCertNo(certNoTwoElementReq.getCertNo());
request.setCertName(certNoTwoElementReq.getCertName());
log.info("调用身份证二要素校验接口,入参:{}", certNoTwoElementReq);
CertNoTwoElementVerificationResponse response =client.certNoTwoElementVerification(request);
log.info("调用身份证二要素校验接口,响应:{}", JSONUtil.toJsonStr(response.getBody()));
Assert.isTrue("OK".equals(response.getBody().getCode()), Exception::new);
Assert.isTrue("1".equals(response.getBody().getData().getIsConsistent()), "身份二要素验证失败!");
}
}

View File

@ -0,0 +1,153 @@
package com.ghy.web.service.impl;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.utils.security.Md5Utils;
import com.ghy.customer.domain.CustomerAddress;
import com.ghy.customer.service.CustomerAddressService;
import com.ghy.order.domain.OrderDetail;
import com.ghy.order.domain.OrderDetailInsuranceUser;
import com.ghy.order.domain.OrderMaster;
import com.ghy.order.service.IOrderDetailInsuranceUserService;
import com.ghy.order.service.OrderDetailService;
import com.ghy.order.service.OrderMasterService;
import com.ghy.web.pojo.vo.CertNoTwoElementReq;
import com.ghy.web.pojo.vo.InsuranceOrderEditReq;
import com.ghy.web.pojo.vo.InsuranceOrderReq;
import com.ghy.web.service.InsuranceService;
import com.ghy.worker.domain.Worker;
import com.ghy.worker.domain.WorkerCertification;
import com.ghy.worker.service.IWorkerCertificationService;
import com.ghy.worker.service.WorkerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class InsuranceServiceImpl implements InsuranceService {
private final static String Key = "96ndsd26k25jm";
private final static String baseUrl = "https://pre-hbhp-xianding.hzins.com/api/external/";
@Autowired
private OrderMasterService orderMasterService;
@Autowired
private CustomerAddressService customerAddressService;
@Autowired
private WorkerService workerService;
@Autowired
private OrderDetailService orderDetailService;
@Autowired
private IOrderDetailInsuranceUserService orderDetailInsuranceUserService;
@Override
public void orderInsurance(String orderCode) throws Exception{
InsuranceOrderReq req = new InsuranceOrderReq();
OrderMaster master = orderMasterService.selectByCode(orderCode);
if(master.getInsuranceId() == null){
return;
}
req.setOrderNumber(master.getCode());
req.setRequestNo(master.getCode() + System.currentTimeMillis());
req.setSign(Md5Utils.hash(req.getRequestNo() + req.getChannelCode() + Key));
// 查询客户地址信息
CustomerAddress customerAddress = customerAddressService.selectByCustomerAddressId(master.getAddressId());
req.setCustomerAddress(customerAddress.getAddress());
req.setCustomerPhone(customerAddress.getPhone());
// 查师傅信息
Worker worker = workerService.selectById(master.getWorkerId());
CertNoTwoElementReq certNoTwoElementReq = JSONUtil.toBean(worker.getRemark(), CertNoTwoElementReq.class);
req.setWorkerID(certNoTwoElementReq.getCertNo());
req.setWorkName(certNoTwoElementReq.getCertName());
req.setOrderStartat(DateUtil.format(DateUtil.offset(new Date(), DateField.SECOND, 30), DatePattern.NORM_DATETIME_PATTERN));
req.setOrderEndat(DateUtil.format(DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, 30),DatePattern.NORM_DATETIME_PATTERN));
log.info("调用保险请求url:{},内容:{}", baseUrl+"/platInterface/order", JSONUtil.toJsonStr(req));
String result = HttpUtil.post(baseUrl+"/platInterface/order", JSONUtil.toJsonStr(req));
log.info("调用保险返回内容:{}", result);
if(!"1".equals(JSONObject.parseObject(result).getString("code")) && !JSONObject.parseObject(result).getString("msg").contains("已存在该工单")){
throw new Exception(JSONObject.parseObject(result).getString("msg"));
}
}
@Override
public void editInsurance(OrderDetailInsuranceUser orderDetailInsuranceUser) throws Exception {
// 查询子单
OrderDetail detail = orderDetailService.selectById(orderDetailInsuranceUser.getOrderDetailId());
// 查询主单
OrderMaster master = orderMasterService.selectById(detail.getOrderMasterId());
// 查师傅信息
Worker worker = workerService.selectById(master.getWorkerId());
CertNoTwoElementReq certNoTwoElementReq = JSONUtil.toBean(worker.getRemark(), CertNoTwoElementReq.class);
// 查询主单下的所有子单
List<OrderDetail> detailList = orderDetailService.selectByOrderMasterId(detail.getOrderMasterId());
StringBuilder workerName = new StringBuilder();
StringBuilder workerId = new StringBuilder();
// 拼上主单信息
workerName.append(certNoTwoElementReq.getCertName());
workerId.append(certNoTwoElementReq.getCertNo());
detailList.forEach(model->{
OrderDetailInsuranceUser param = new OrderDetailInsuranceUser();
param.setOrderDetailId(model.getId());
List<OrderDetailInsuranceUser> users = orderDetailInsuranceUserService.selectOrderDetailInsuranceUserList(param);
if(!CollectionUtils.isEmpty(users)){
users.forEach(user->{
workerName.append(",").append(user.getName());
workerId.append(",").append(user.getIdCardNum());
});
}
});
// 再拼上 现在要加入的师傅的信息
workerName.append(",").append(orderDetailInsuranceUser.getName());
workerId.append(",").append(orderDetailInsuranceUser.getIdCardNum());
InsuranceOrderEditReq editReq = new InsuranceOrderEditReq();
editReq.setOrderNumber(master.getCode());
editReq.setRequestNo(master.getCode() + System.currentTimeMillis());
editReq.setSign(Md5Utils.hash(editReq.getRequestNo() + editReq.getChannelCode() + Key));
editReq.setOrderNumber(master.getCode());
editReq.setWorkName(workerName.toString());
editReq.setWorkerID(workerId.toString());
log.info("调用保险请求url:{},内容:{}", baseUrl+"/platInterface/updateOrder", JSONUtil.toJsonStr(editReq));
String result = HttpUtil.post(baseUrl+"/platInterface/updateOrder", JSONUtil.toJsonStr(editReq));
log.info("调用保险返回内容:{}", result);
if(!"1".equals(JSONObject.parseObject(result).getString("code"))){
throw new Exception(JSONObject.parseObject(result).getString("msg"));
}
}
@Override
public void clockInsurance(Long orderDetailId) throws Exception {
// 查询子单
OrderDetail detail = orderDetailService.selectById(orderDetailId);
// 查询主单
OrderMaster master = orderMasterService.selectById(detail.getOrderMasterId());
if(master.getInsuranceId() != null){
InsuranceOrderEditReq editReq = new InsuranceOrderEditReq();
editReq.setOrderNumber(master.getCode());
editReq.setRequestNo(master.getCode() + System.currentTimeMillis());
editReq.setSign(Md5Utils.hash(editReq.getRequestNo() + editReq.getChannelCode() + Key));
editReq.setOrderNumber(master.getCode());
editReq.setShangmenTime(DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
editReq.setShangmenNum("1");
log.info("调用保险请求url:{},内容:{}", baseUrl+"/platInterface/service", JSONUtil.toJsonStr(editReq));
String result = HttpUtil.post(baseUrl+"/platInterface/service", JSONUtil.toJsonStr(editReq));
log.info("调用保险返回内容:{}", result);
if(!"1".equals(JSONObject.parseObject(result).getString("code"))){
throw new Exception(JSONObject.parseObject(result).getString("msg"));
}
}
}
}

View File

@ -3,10 +3,16 @@ package com.ghy.web.timer;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.AdapayStatusEnum; import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.enums.AdapayOrderType;
import com.ghy.common.utils.AdapayUtils;
import com.ghy.customer.domain.CustomerBank;
import com.ghy.customer.service.CustomerBankService;
import com.ghy.order.service.OrderDetailService; import com.ghy.order.service.OrderDetailService;
import com.ghy.payment.domain.DrawCashRecord; import com.ghy.payment.domain.DrawCashRecord;
import com.ghy.payment.mapper.DrawCashRecordMapper; import com.ghy.payment.mapper.DrawCashRecordMapper;
import com.ghy.payment.service.AdapayService; import com.ghy.payment.service.AdapayService;
import com.ghy.worker.domain.WorkerBank;
import com.ghy.worker.service.WorkerBankService;
import com.huifu.adapay.core.exception.BaseAdaPayException; import com.huifu.adapay.core.exception.BaseAdaPayException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -17,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -32,10 +39,82 @@ public class AdapaySyncTimer {
@Resource @Resource
private AdapayService adapayService; private AdapayService adapayService;
@Resource @Resource
private WorkerBankService workerBankService;
@Resource
private CustomerBankService customerBankService;
@Resource
private OrderDetailService orderDetailService; private OrderDetailService orderDetailService;
@Resource @Resource
private DrawCashRecordMapper drawCashRecordMapper; private DrawCashRecordMapper drawCashRecordMapper;
/**
* 补偿提现定时器
* 某些订单分账成功但是提现失败需要在这里为它重新发起提现
*/
@Scheduled(fixedRate = 5 * 60 * 1000L)
public void autoDrawCash() {
List<WorkerBank> workerBanks = workerBankService.select(new WorkerBank());
for (WorkerBank workerBank : workerBanks) {
Long deptId = workerBank.getDeptId();
String memberId = workerBank.getAdapayMemberId();
String settleAccountId = workerBank.getSettleAccountId();
if (deptId == null || StringUtils.isBlank(memberId) || StringUtils.isBlank(settleAccountId)) {
continue;
}
try {
JSONObject accountBalance = adapayService.queryAccountBalance(deptId, memberId, settleAccountId, "01");
if (AdapayStatusEnum.succeeded.code.equals(accountBalance.getString("status"))) {
// 可提现金额
String avlBalance = accountBalance.getString("avl_balance");
if (BigDecimal.ZERO.compareTo(new BigDecimal(avlBalance)) > -1) {
continue;
}
// 提现
log.info("Worker[{},{}]开始提现: avlBalance={}", workerBank.getWorkerId(), workerBank.getName(), avlBalance);
String orderNo = AdapayUtils.createOrderNo(AdapayOrderType.DRAW_CASH);
JSONObject drawCash = adapayService.drawCash(deptId, orderNo, "T1", avlBalance, memberId, "提现", null);
log.info("Worker[{},{}]提现结果: {}", workerBank.getWorkerId(), workerBank.getName(), drawCash.toJSONString());
} else {
log.error("Worker[{},{}]查询账户余额失败: {}", workerBank.getWorkerId(), workerBank.getName(), accountBalance.toJSONString());
}
} catch (BaseAdaPayException e) {
log.error(e.getMessage(), e);
}
}
List<CustomerBank> customerBanks = customerBankService.getCustomerBankList(new CustomerBank());
for (CustomerBank customer : customerBanks) {
Long deptId = customer.getDeptId();
String memberId = customer.getAdapayMemberId();
String settleAccountId = customer.getSettleAccountId();
if (deptId == null || StringUtils.isBlank(memberId) || StringUtils.isBlank(settleAccountId)) {
continue;
}
try {
JSONObject accountBalance = adapayService.queryAccountBalance(deptId, memberId, settleAccountId, "01");
if (AdapayStatusEnum.succeeded.code.equals(accountBalance.getString("status"))) {
// 可提现金额
String avlBalance = accountBalance.getString("avl_balance");
if (BigDecimal.ZERO.compareTo(new BigDecimal(avlBalance)) > -1) {
continue;
}
// 提现
log.info("Customer[{},{}]开始提现: avlBalance={}", customer.getCustomerId(), customer.getName(), avlBalance);
String orderNo = AdapayUtils.createOrderNo(AdapayOrderType.DRAW_CASH);
JSONObject drawCash = adapayService.drawCash(deptId, orderNo, "T1", avlBalance, memberId, "提现", null);
log.info("Customer[{},{}]提现结果: {}", customer.getCustomerId(), customer.getName(), drawCash.toJSONString());
} else {
log.error("Customer[{},{}]查询账户余额失败: {}", customer.getCustomerId(), customer.getName(), accountBalance.toJSONString());
}
} catch (BaseAdaPayException e) {
log.error(e.getMessage(), e);
}
}
}
/**
* 定时同步提现状态
*/
@Scheduled(fixedRate = 5 * 60 * 1000L) @Scheduled(fixedRate = 5 * 60 * 1000L)
public void syncDrawCash() { public void syncDrawCash() {
List<DrawCashRecord> records = drawCashRecordMapper.selectByStatus("pending"); List<DrawCashRecord> records = drawCashRecordMapper.selectByStatus("pending");
@ -75,7 +154,7 @@ public class AdapaySyncTimer {
// 更新提现记录表状态 // 更新提现记录表状态
drawCashRecordMapper.updateStatus(record.getId(), "succeeded"); drawCashRecordMapper.updateStatus(record.getId(), "succeeded");
// 更新子订单表状态 // 更新子订单表状态
orderDetailService.updateDrawCashStatus(record.getId(), 2, new Date()); orderDetailService.updateDrawCashStatus(record.getId(), 2, null, new Date());
break; break;
// 提现失败 // 提现失败
case "F": case "F":
@ -83,7 +162,7 @@ public class AdapaySyncTimer {
// 更新提现记录表状态 // 更新提现记录表状态
drawCashRecordMapper.updateStatus(record.getId(), "failed"); drawCashRecordMapper.updateStatus(record.getId(), "failed");
// 更新子订单表状态 // 更新子订单表状态
orderDetailService.updateDrawCashStatus(record.getId(), -1, null); orderDetailService.updateDrawCashStatus(record.getId(), -1, null, null);
break; break;
default: default:
break; break;

View File

@ -24,7 +24,7 @@ shiro:
cipherKey: cipherKey:
session: session:
# Session超时时间-1代表永不过期默认30分钟 # Session超时时间-1代表永不过期默认30分钟
expireTime: 30 expireTime: 720
# 同步session到数据库的周期默认1分钟 # 同步session到数据库的周期默认1分钟
dbSyncPeriod: 1 dbSyncPeriod: 1
# 相隔多久检查一次session的有效性默认就是10分钟 # 相隔多久检查一次session的有效性默认就是10分钟
@ -45,9 +45,9 @@ spring:
druid: druid:
# 主库数据源 # 主库数据源
master: master:
url: jdbc:mysql://121.4.113.60:3306/gqz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 url: jdbc:mysql://8.138.169.236:3306/gqz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
username: admin username: root
password: Clunt@12345 password: clunt@12345
# 从库数据源 # 从库数据源
slave: slave:
# 从数据源开关/默认关闭 # 从数据源开关/默认关闭
@ -58,9 +58,9 @@ spring:
# 初始连接数 # 初始连接数
initialSize: 5 initialSize: 5
# 最小连接池数量 # 最小连接池数量
minIdle: 10 minIdle: 5
# 最大连接池数量 # 最大连接池数量
maxActive: 20 maxActive: 10
# 配置获取连接等待超时的时间 # 配置获取连接等待超时的时间
maxWait: 60000 maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

View File

@ -7,7 +7,7 @@ ruoyi:
# 版权年份 # 版权年份
copyrightYear: 2021 copyrightYear: 2021
# 实例演示开关 # 实例演示开关
demoEnabled: true demoEnabled: false
# 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath # 文件路径 示例( Windows配置D:/ruoyi/uploadPathLinux配置 /home/ruoyi/uploadPath
profile: /home/ruoyi/uploadPath profile: /home/ruoyi/uploadPath
# 获取ip地址开关 # 获取ip地址开关
@ -16,7 +16,7 @@ ruoyi:
# 开发环境配置 # 开发环境配置
server: server:
# 服务器的HTTP端口默认为80 # 服务器的HTTP端口默认为80
port: 80 port: 19001
servlet: servlet:
# 应用的访问路径 # 应用的访问路径
context-path: / context-path: /
@ -59,7 +59,7 @@ spring:
time-zone: GMT+8 time-zone: GMT+8
date-format: yyyy-MM-dd HH:mm:ss date-format: yyyy-MM-dd HH:mm:ss
profiles: profiles:
active: dev active: druid
# 文件上传 # 文件上传
servlet: servlet:
multipart: multipart:
@ -116,12 +116,12 @@ qiniu:
accessKey: 'QTNOppkvtufxTxLjt1V7YZwvzV2Rc6WLD5yXLBVY' accessKey: 'QTNOppkvtufxTxLjt1V7YZwvzV2Rc6WLD5yXLBVY'
secretKey: 'V8SM9nkbO-dft4JmG7UaCH6RYxXdqzrvQ0zWO2W3' secretKey: 'V8SM9nkbO-dft4JmG7UaCH6RYxXdqzrvQ0zWO2W3'
bucketName: 'gqz' bucketName: 'gqz'
mediaUrl: 'http://gqz.opsoul.com/' mediaUrl: 'https://gqz.opsoul.com/'
adapay: adapay:
debug: true debug: true
prod-mode: true prod-mode: true
notifyUrl: 'https://www.opsoul.com:8881/adapay/callback' notifyUrl: 'https://gmhl.gmjlb.com/adapay/callback'
jim: jim:
appKey: '110e8830290152d76e2f1d97' appKey: '110e8830290152d76e2f1d97'
@ -130,7 +130,7 @@ jim:
# 百度地图应用api # 百度地图应用api
baidu: baidu:
ak: 'ZQTgMW7W0GTuE7Ripb0HDp5TqRaOI6PZ' ak: 'i0sdnIsMmJVik7vJhfqMHA6DmS6d0fMB'
url: 'https://api.map.baidu.com/reverse_geocoding/v3/?ak=#AK#&output=json&coordtype=wgs84ll&location=' url: 'https://api.map.baidu.com/reverse_geocoding/v3/?ak=#AK#&output=json&coordtype=wgs84ll&location='
sms: sms:
@ -138,3 +138,31 @@ sms:
account: '8a216da85f008800015f0eb223620557' account: '8a216da85f008800015f0eb223620557'
appId: '8a216da85f008800015f0eb224db055d' appId: '8a216da85f008800015f0eb224db055d'
token: '3cef1bc80d814637a236d93004e7ffa5' token: '3cef1bc80d814637a236d93004e7ffa5'
# 阿里云api接口, 这里是身份证二要素的
aliyun:
accessKey: LTAI5tDmv3T3Ze1Mt9wi5Be6
accessSecret: EV4dzWRfKTQaPRjf3tFziMuVBCsThU
endpoint: dytnsapi.aliyuncs.com
authCode: od2FgE9a9g
# 物流API配置
# logistics:
# kdniao:
# # 快递鸟 API配置
# appId: '1889454' # 快递鸟应用ID需要到快递鸟官网申请
# appKey: 'b2483529-807d-49af-b0e1-1ed218baa4db' # 快递鸟API密钥需要到快递鸟官网申请
# url: 'https://api.kdniao.com/api/dist' # 快递鸟即时查询接口地址
# 快递鸟支持两种接口:
# 1. 即时查询接口https://api.kdniao.com/api/dist
# 2. 物流跟踪接口https://api.kdniao.com/Ebusiness/EbusinessOrderHandle.aspx
logistics:
# 阿里云快递查询API配置
aliyun:
# 阿里云API网关AppCode需要在阿里云市场购买快递查询服务后获取
appCode: "78064b8aaa294f64ab07a285f129aea6"
# API主机地址
host: "https://kzexpress.market.alicloudapi.com"
# API路径
path: "/api-mall/api/express/query"

View File

@ -273,8 +273,7 @@
var _defaultRootFlag = item[options.parentCode] == '0' || var _defaultRootFlag = item[options.parentCode] == '0' ||
item[options.parentCode] == 0 || item[options.parentCode] == 0 ||
item[options.parentCode] == null || item[options.parentCode] == null ||
item[options.parentCode] == '' || item[options.parentCode] == '';
$.inArray(item[options.code], parentCodes) > 0 && !rootFlag;
if (!item[options.parentCode] || (_root ? (item[options.parentCode] == options.rootIdValue) : _defaultRootFlag)) { if (!item[options.parentCode] || (_root ? (item[options.parentCode] == options.rootIdValue) : _defaultRootFlag)) {
rootFlag = true; rootFlag = true;
if (!target.data_list["_root_"]) { if (!target.data_list["_root_"]) {

View File

@ -0,0 +1,164 @@
* {
list-style: none;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
body {
padding: 100px;
box-sizing: border-box;
}
.cascader-wrap {
min-height: 40px;
border: 1px solid #dcdfe6;
box-sizing: border-box;
border-radius: 4px;
position: relative;
z-index: 100;
}
.cascader-wrap:after {
/*opacity: 1;*/
content: "展开";
padding: 5px 10px;
background-color: #1d85c6;
color: #feffff;
border-radius: 4px;
text-align: center;
position: absolute;
top: 12%;
right: 5px;
/*border-color: transparent transparent #888 transparent;*/
/*border-style: solid;*/
/*height: 0;*/
/*margin-top: -2px;*/
/*position: absolute;*/
/*top: 50%;*/
/*right: 10px;*/
/*width: 0;*/
/*border-width: 0 4px 5px 4px;*/
/*transform: rotate(180deg);*/
transition: all 0.1s;
}
.cascader-wrap.is-show:after {
/*transform: rotate(0deg);*/
content: "收起";
background-color: #e82d2d;
color: #feffff;
}
.cascader-wrap.is-show .eo-cascader-panel {
display: block;
display: flex;
}
.cascader-wrap .eo-clear-btn {
display: none;
}
.cascader-wrap.is-clear .eo-clear-btn {
font-style: normal;
position: absolute;
right: 7px;
top: 50%;
margin-top: -7px;
font-size: 12px;
width: 12px;
height: 12px;
border: 1px solid #c0c4cc;
border-radius: 50%;
text-align: center;
line-height: 9px;
color: #c0c4cc;
display: block;
cursor: pointer;
z-index: 9;
}
.cascader-wrap.is-clear:after {
/*opacity: 0;*/
}
.eo-cascader-panel {
display: flex;
position: absolute;
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
top: 40px;
left: 0;
overflow: hidden;
display: none;
}
.eo-cascader-menu {
min-width: 200px;
box-sizing: border-box;
color: #606266;
border-right: 1px solid #e4e7ed;
position: relative;
padding: 6px 0;
max-height: 350px;
overflow-y: auto;
}
.eo-cascader-menu:last-child {
border-right: none;
}
.eo-cascader-menu li {
line-height: 30px;
cursor: pointer;
padding: 0 15px;
position: relative;
}
.eo-cascader-menu li.has-child:after {
content: '>';
position: absolute;
right: 10px;
top: -2px;
transform: scaleY(1.8);
font-size: 12px;
color: #606266;
}
.eo-cascader-menu li:hover {
background: #f5f7fa;
}
.eo-cascader-menu li span {
margin-left: 6px;
}
.eo-checked-wrap {
padding: 5px;
position: relative;
width: 90%;
}
.eo-checked-wrap li {
display: flex;
font-size: 12px;
color: #909399;
line-height: 24px;
margin: 2px 0 2px 0px;
background: #f0f2f5;
padding: 0 10px;
height: 24px;
border-radius: 4px;
box-sizing: border-box;
align-items: center;
}
.eo-checked-wrap li i {
font-style: normal;
margin-left: 10px;
cursor: pointer;
width: 12px;
height: 12px;
background: #c0c4cc;
border-radius: 50%;
text-align: center;
line-height: 9px;
color: #fff;
}
.eo-checked-wrap li p {
margin: 0;
}
input[type="checkbox"].is-indeterminate {
width: 13px;
height: 13px;
background-color: #dfedff;
-webkit-appearance: none;
border: 1px solid #61aaff;
border-radius: 2px;
outline: none;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
(function(r){r.fn.qrcode=function(h){var s;function u(a){this.mode=s;this.data=a}function o(a,c){this.typeNumber=a;this.errorCorrectLevel=c;this.modules=null;this.moduleCount=0;this.dataCache=null;this.dataList=[]}function q(a,c){if(void 0==a.length)throw Error(a.length+"/"+c);for(var d=0;d<a.length&&0==a[d];)d++;this.num=Array(a.length-d+c);for(var b=0;b<a.length-d;b++)this.num[b]=a[b+d]}function p(a,c){this.totalCount=a;this.dataCount=c}function t(){this.buffer=[];this.length=0}u.prototype={getLength:function(){return this.data.length},
write:function(a){for(var c=0;c<this.data.length;c++)a.put(this.data.charCodeAt(c),8)}};o.prototype={addData:function(a){this.dataList.push(new u(a));this.dataCache=null},isDark:function(a,c){if(0>a||this.moduleCount<=a||0>c||this.moduleCount<=c)throw Error(a+","+c);return this.modules[a][c]},getModuleCount:function(){return this.moduleCount},make:function(){if(1>this.typeNumber){for(var a=1,a=1;40>a;a++){for(var c=p.getRSBlocks(a,this.errorCorrectLevel),d=new t,b=0,e=0;e<c.length;e++)b+=c[e].dataCount;
for(e=0;e<this.dataList.length;e++)c=this.dataList[e],d.put(c.mode,4),d.put(c.getLength(),j.getLengthInBits(c.mode,a)),c.write(d);if(d.getLengthInBits()<=8*b)break}this.typeNumber=a}this.makeImpl(!1,this.getBestMaskPattern())},makeImpl:function(a,c){this.moduleCount=4*this.typeNumber+17;this.modules=Array(this.moduleCount);for(var d=0;d<this.moduleCount;d++){this.modules[d]=Array(this.moduleCount);for(var b=0;b<this.moduleCount;b++)this.modules[d][b]=null}this.setupPositionProbePattern(0,0);this.setupPositionProbePattern(this.moduleCount-
7,0);this.setupPositionProbePattern(0,this.moduleCount-7);this.setupPositionAdjustPattern();this.setupTimingPattern();this.setupTypeInfo(a,c);7<=this.typeNumber&&this.setupTypeNumber(a);null==this.dataCache&&(this.dataCache=o.createData(this.typeNumber,this.errorCorrectLevel,this.dataList));this.mapData(this.dataCache,c)},setupPositionProbePattern:function(a,c){for(var d=-1;7>=d;d++)if(!(-1>=a+d||this.moduleCount<=a+d))for(var b=-1;7>=b;b++)-1>=c+b||this.moduleCount<=c+b||(this.modules[a+d][c+b]=
0<=d&&6>=d&&(0==b||6==b)||0<=b&&6>=b&&(0==d||6==d)||2<=d&&4>=d&&2<=b&&4>=b?!0:!1)},getBestMaskPattern:function(){for(var a=0,c=0,d=0;8>d;d++){this.makeImpl(!0,d);var b=j.getLostPoint(this);if(0==d||a>b)a=b,c=d}return c},createMovieClip:function(a,c,d){a=a.createEmptyMovieClip(c,d);this.make();for(c=0;c<this.modules.length;c++)for(var d=1*c,b=0;b<this.modules[c].length;b++){var e=1*b;this.modules[c][b]&&(a.beginFill(0,100),a.moveTo(e,d),a.lineTo(e+1,d),a.lineTo(e+1,d+1),a.lineTo(e,d+1),a.endFill())}return a},
setupTimingPattern:function(){for(var a=8;a<this.moduleCount-8;a++)null==this.modules[a][6]&&(this.modules[a][6]=0==a%2);for(a=8;a<this.moduleCount-8;a++)null==this.modules[6][a]&&(this.modules[6][a]=0==a%2)},setupPositionAdjustPattern:function(){for(var a=j.getPatternPosition(this.typeNumber),c=0;c<a.length;c++)for(var d=0;d<a.length;d++){var b=a[c],e=a[d];if(null==this.modules[b][e])for(var f=-2;2>=f;f++)for(var i=-2;2>=i;i++)this.modules[b+f][e+i]=-2==f||2==f||-2==i||2==i||0==f&&0==i?!0:!1}},setupTypeNumber:function(a){for(var c=
j.getBCHTypeNumber(this.typeNumber),d=0;18>d;d++){var b=!a&&1==(c>>d&1);this.modules[Math.floor(d/3)][d%3+this.moduleCount-8-3]=b}for(d=0;18>d;d++)b=!a&&1==(c>>d&1),this.modules[d%3+this.moduleCount-8-3][Math.floor(d/3)]=b},setupTypeInfo:function(a,c){for(var d=j.getBCHTypeInfo(this.errorCorrectLevel<<3|c),b=0;15>b;b++){var e=!a&&1==(d>>b&1);6>b?this.modules[b][8]=e:8>b?this.modules[b+1][8]=e:this.modules[this.moduleCount-15+b][8]=e}for(b=0;15>b;b++)e=!a&&1==(d>>b&1),8>b?this.modules[8][this.moduleCount-
b-1]=e:9>b?this.modules[8][15-b-1+1]=e:this.modules[8][15-b-1]=e;this.modules[this.moduleCount-8][8]=!a},mapData:function(a,c){for(var d=-1,b=this.moduleCount-1,e=7,f=0,i=this.moduleCount-1;0<i;i-=2)for(6==i&&i--;;){for(var g=0;2>g;g++)if(null==this.modules[b][i-g]){var n=!1;f<a.length&&(n=1==(a[f]>>>e&1));j.getMask(c,b,i-g)&&(n=!n);this.modules[b][i-g]=n;e--; -1==e&&(f++,e=7)}b+=d;if(0>b||this.moduleCount<=b){b-=d;d=-d;break}}}};o.PAD0=236;o.PAD1=17;o.createData=function(a,c,d){for(var c=p.getRSBlocks(a,
c),b=new t,e=0;e<d.length;e++){var f=d[e];b.put(f.mode,4);b.put(f.getLength(),j.getLengthInBits(f.mode,a));f.write(b)}for(e=a=0;e<c.length;e++)a+=c[e].dataCount;if(b.getLengthInBits()>8*a)throw Error("code length overflow. ("+b.getLengthInBits()+">"+8*a+")");for(b.getLengthInBits()+4<=8*a&&b.put(0,4);0!=b.getLengthInBits()%8;)b.putBit(!1);for(;!(b.getLengthInBits()>=8*a);){b.put(o.PAD0,8);if(b.getLengthInBits()>=8*a)break;b.put(o.PAD1,8)}return o.createBytes(b,c)};o.createBytes=function(a,c){for(var d=
0,b=0,e=0,f=Array(c.length),i=Array(c.length),g=0;g<c.length;g++){var n=c[g].dataCount,h=c[g].totalCount-n,b=Math.max(b,n),e=Math.max(e,h);f[g]=Array(n);for(var k=0;k<f[g].length;k++)f[g][k]=255&a.buffer[k+d];d+=n;k=j.getErrorCorrectPolynomial(h);n=(new q(f[g],k.getLength()-1)).mod(k);i[g]=Array(k.getLength()-1);for(k=0;k<i[g].length;k++)h=k+n.getLength()-i[g].length,i[g][k]=0<=h?n.get(h):0}for(k=g=0;k<c.length;k++)g+=c[k].totalCount;d=Array(g);for(k=n=0;k<b;k++)for(g=0;g<c.length;g++)k<f[g].length&&
(d[n++]=f[g][k]);for(k=0;k<e;k++)for(g=0;g<c.length;g++)k<i[g].length&&(d[n++]=i[g][k]);return d};s=4;for(var j={PATTERN_POSITION_TABLE:[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62],[6,26,46,66],[6,26,48,70],[6,26,50,74],[6,30,54,78],[6,30,56,82],[6,30,58,86],[6,34,62,90],[6,28,50,72,94],[6,26,50,74,98],[6,30,54,78,102],[6,28,54,80,106],[6,32,58,84,110],[6,30,58,86,114],[6,34,62,90,118],[6,26,50,74,98,122],[6,30,54,78,102,126],[6,26,52,
78,104,130],[6,30,56,82,108,134],[6,34,60,86,112,138],[6,30,58,86,114,142],[6,34,62,90,118,146],[6,30,54,78,102,126,150],[6,24,50,76,102,128,154],[6,28,54,80,106,132,158],[6,32,58,84,110,136,162],[6,26,54,82,110,138,166],[6,30,58,86,114,142,170]],G15:1335,G18:7973,G15_MASK:21522,getBCHTypeInfo:function(a){for(var c=a<<10;0<=j.getBCHDigit(c)-j.getBCHDigit(j.G15);)c^=j.G15<<j.getBCHDigit(c)-j.getBCHDigit(j.G15);return(a<<10|c)^j.G15_MASK},getBCHTypeNumber:function(a){for(var c=a<<12;0<=j.getBCHDigit(c)-
j.getBCHDigit(j.G18);)c^=j.G18<<j.getBCHDigit(c)-j.getBCHDigit(j.G18);return a<<12|c},getBCHDigit:function(a){for(var c=0;0!=a;)c++,a>>>=1;return c},getPatternPosition:function(a){return j.PATTERN_POSITION_TABLE[a-1]},getMask:function(a,c,d){switch(a){case 0:return 0==(c+d)%2;case 1:return 0==c%2;case 2:return 0==d%3;case 3:return 0==(c+d)%3;case 4:return 0==(Math.floor(c/2)+Math.floor(d/3))%2;case 5:return 0==c*d%2+c*d%3;case 6:return 0==(c*d%2+c*d%3)%2;case 7:return 0==(c*d%3+(c+d)%2)%2;default:throw Error("bad maskPattern:"+
a);}},getErrorCorrectPolynomial:function(a){for(var c=new q([1],0),d=0;d<a;d++)c=c.multiply(new q([1,l.gexp(d)],0));return c},getLengthInBits:function(a,c){if(1<=c&&10>c)switch(a){case 1:return 10;case 2:return 9;case s:return 8;case 8:return 8;default:throw Error("mode:"+a);}else if(27>c)switch(a){case 1:return 12;case 2:return 11;case s:return 16;case 8:return 10;default:throw Error("mode:"+a);}else if(41>c)switch(a){case 1:return 14;case 2:return 13;case s:return 16;case 8:return 12;default:throw Error("mode:"+
a);}else throw Error("type:"+c);},getLostPoint:function(a){for(var c=a.getModuleCount(),d=0,b=0;b<c;b++)for(var e=0;e<c;e++){for(var f=0,i=a.isDark(b,e),g=-1;1>=g;g++)if(!(0>b+g||c<=b+g))for(var h=-1;1>=h;h++)0>e+h||c<=e+h||0==g&&0==h||i==a.isDark(b+g,e+h)&&f++;5<f&&(d+=3+f-5)}for(b=0;b<c-1;b++)for(e=0;e<c-1;e++)if(f=0,a.isDark(b,e)&&f++,a.isDark(b+1,e)&&f++,a.isDark(b,e+1)&&f++,a.isDark(b+1,e+1)&&f++,0==f||4==f)d+=3;for(b=0;b<c;b++)for(e=0;e<c-6;e++)a.isDark(b,e)&&!a.isDark(b,e+1)&&a.isDark(b,e+
2)&&a.isDark(b,e+3)&&a.isDark(b,e+4)&&!a.isDark(b,e+5)&&a.isDark(b,e+6)&&(d+=40);for(e=0;e<c;e++)for(b=0;b<c-6;b++)a.isDark(b,e)&&!a.isDark(b+1,e)&&a.isDark(b+2,e)&&a.isDark(b+3,e)&&a.isDark(b+4,e)&&!a.isDark(b+5,e)&&a.isDark(b+6,e)&&(d+=40);for(e=f=0;e<c;e++)for(b=0;b<c;b++)a.isDark(b,e)&&f++;a=Math.abs(100*f/c/c-50)/5;return d+10*a}},l={glog:function(a){if(1>a)throw Error("glog("+a+")");return l.LOG_TABLE[a]},gexp:function(a){for(;0>a;)a+=255;for(;256<=a;)a-=255;return l.EXP_TABLE[a]},EXP_TABLE:Array(256),
LOG_TABLE:Array(256)},m=0;8>m;m++)l.EXP_TABLE[m]=1<<m;for(m=8;256>m;m++)l.EXP_TABLE[m]=l.EXP_TABLE[m-4]^l.EXP_TABLE[m-5]^l.EXP_TABLE[m-6]^l.EXP_TABLE[m-8];for(m=0;255>m;m++)l.LOG_TABLE[l.EXP_TABLE[m]]=m;q.prototype={get:function(a){return this.num[a]},getLength:function(){return this.num.length},multiply:function(a){for(var c=Array(this.getLength()+a.getLength()-1),d=0;d<this.getLength();d++)for(var b=0;b<a.getLength();b++)c[d+b]^=l.gexp(l.glog(this.get(d))+l.glog(a.get(b)));return new q(c,0)},mod:function(a){if(0>
this.getLength()-a.getLength())return this;for(var c=l.glog(this.get(0))-l.glog(a.get(0)),d=Array(this.getLength()),b=0;b<this.getLength();b++)d[b]=this.get(b);for(b=0;b<a.getLength();b++)d[b]^=l.gexp(l.glog(a.get(b))+c);return(new q(d,0)).mod(a)}};p.RS_BLOCK_TABLE=[[1,26,19],[1,26,16],[1,26,13],[1,26,9],[1,44,34],[1,44,28],[1,44,22],[1,44,16],[1,70,55],[1,70,44],[2,35,17],[2,35,13],[1,100,80],[2,50,32],[2,50,24],[4,25,9],[1,134,108],[2,67,43],[2,33,15,2,34,16],[2,33,11,2,34,12],[2,86,68],[4,43,27],
[4,43,19],[4,43,15],[2,98,78],[4,49,31],[2,32,14,4,33,15],[4,39,13,1,40,14],[2,121,97],[2,60,38,2,61,39],[4,40,18,2,41,19],[4,40,14,2,41,15],[2,146,116],[3,58,36,2,59,37],[4,36,16,4,37,17],[4,36,12,4,37,13],[2,86,68,2,87,69],[4,69,43,1,70,44],[6,43,19,2,44,20],[6,43,15,2,44,16],[4,101,81],[1,80,50,4,81,51],[4,50,22,4,51,23],[3,36,12,8,37,13],[2,116,92,2,117,93],[6,58,36,2,59,37],[4,46,20,6,47,21],[7,42,14,4,43,15],[4,133,107],[8,59,37,1,60,38],[8,44,20,4,45,21],[12,33,11,4,34,12],[3,145,115,1,146,
116],[4,64,40,5,65,41],[11,36,16,5,37,17],[11,36,12,5,37,13],[5,109,87,1,110,88],[5,65,41,5,66,42],[5,54,24,7,55,25],[11,36,12],[5,122,98,1,123,99],[7,73,45,3,74,46],[15,43,19,2,44,20],[3,45,15,13,46,16],[1,135,107,5,136,108],[10,74,46,1,75,47],[1,50,22,15,51,23],[2,42,14,17,43,15],[5,150,120,1,151,121],[9,69,43,4,70,44],[17,50,22,1,51,23],[2,42,14,19,43,15],[3,141,113,4,142,114],[3,70,44,11,71,45],[17,47,21,4,48,22],[9,39,13,16,40,14],[3,135,107,5,136,108],[3,67,41,13,68,42],[15,54,24,5,55,25],[15,
43,15,10,44,16],[4,144,116,4,145,117],[17,68,42],[17,50,22,6,51,23],[19,46,16,6,47,17],[2,139,111,7,140,112],[17,74,46],[7,54,24,16,55,25],[34,37,13],[4,151,121,5,152,122],[4,75,47,14,76,48],[11,54,24,14,55,25],[16,45,15,14,46,16],[6,147,117,4,148,118],[6,73,45,14,74,46],[11,54,24,16,55,25],[30,46,16,2,47,17],[8,132,106,4,133,107],[8,75,47,13,76,48],[7,54,24,22,55,25],[22,45,15,13,46,16],[10,142,114,2,143,115],[19,74,46,4,75,47],[28,50,22,6,51,23],[33,46,16,4,47,17],[8,152,122,4,153,123],[22,73,45,
3,74,46],[8,53,23,26,54,24],[12,45,15,28,46,16],[3,147,117,10,148,118],[3,73,45,23,74,46],[4,54,24,31,55,25],[11,45,15,31,46,16],[7,146,116,7,147,117],[21,73,45,7,74,46],[1,53,23,37,54,24],[19,45,15,26,46,16],[5,145,115,10,146,116],[19,75,47,10,76,48],[15,54,24,25,55,25],[23,45,15,25,46,16],[13,145,115,3,146,116],[2,74,46,29,75,47],[42,54,24,1,55,25],[23,45,15,28,46,16],[17,145,115],[10,74,46,23,75,47],[10,54,24,35,55,25],[19,45,15,35,46,16],[17,145,115,1,146,116],[14,74,46,21,75,47],[29,54,24,19,
55,25],[11,45,15,46,46,16],[13,145,115,6,146,116],[14,74,46,23,75,47],[44,54,24,7,55,25],[59,46,16,1,47,17],[12,151,121,7,152,122],[12,75,47,26,76,48],[39,54,24,14,55,25],[22,45,15,41,46,16],[6,151,121,14,152,122],[6,75,47,34,76,48],[46,54,24,10,55,25],[2,45,15,64,46,16],[17,152,122,4,153,123],[29,74,46,14,75,47],[49,54,24,10,55,25],[24,45,15,46,46,16],[4,152,122,18,153,123],[13,74,46,32,75,47],[48,54,24,14,55,25],[42,45,15,32,46,16],[20,147,117,4,148,118],[40,75,47,7,76,48],[43,54,24,22,55,25],[10,
45,15,67,46,16],[19,148,118,6,149,119],[18,75,47,31,76,48],[34,54,24,34,55,25],[20,45,15,61,46,16]];p.getRSBlocks=function(a,c){var d=p.getRsBlockTable(a,c);if(void 0==d)throw Error("bad rs block @ typeNumber:"+a+"/errorCorrectLevel:"+c);for(var b=d.length/3,e=[],f=0;f<b;f++)for(var h=d[3*f+0],g=d[3*f+1],j=d[3*f+2],l=0;l<h;l++)e.push(new p(g,j));return e};p.getRsBlockTable=function(a,c){switch(c){case 1:return p.RS_BLOCK_TABLE[4*(a-1)+0];case 0:return p.RS_BLOCK_TABLE[4*(a-1)+1];case 3:return p.RS_BLOCK_TABLE[4*
(a-1)+2];case 2:return p.RS_BLOCK_TABLE[4*(a-1)+3]}};t.prototype={get:function(a){return 1==(this.buffer[Math.floor(a/8)]>>>7-a%8&1)},put:function(a,c){for(var d=0;d<c;d++)this.putBit(1==(a>>>c-d-1&1))},getLengthInBits:function(){return this.length},putBit:function(a){var c=Math.floor(this.length/8);this.buffer.length<=c&&this.buffer.push(0);a&&(this.buffer[c]|=128>>>this.length%8);this.length++}};"string"===typeof h&&(h={text:h});h=r.extend({},{render:"canvas",width:256,height:256,typeNumber:-1,
correctLevel:2,background:"#ffffff",foreground:"#000000"},h);return this.each(function(){var a;if("canvas"==h.render){a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();var c=document.createElement("canvas");c.width=h.width;c.height=h.height;for(var d=c.getContext("2d"),b=h.width/a.getModuleCount(),e=h.height/a.getModuleCount(),f=0;f<a.getModuleCount();f++)for(var i=0;i<a.getModuleCount();i++){d.fillStyle=a.isDark(f,i)?h.foreground:h.background;var g=Math.ceil((i+1)*b)-Math.floor(i*b),
j=Math.ceil((f+1)*b)-Math.floor(f*b);d.fillRect(Math.round(i*b),Math.round(f*e),g,j)}}else{a=new o(h.typeNumber,h.correctLevel);a.addData(h.text);a.make();c=r("<table></table>").css("width",h.width+"px").css("height",h.height+"px").css("border","0px").css("border-collapse","collapse").css("background-color",h.background);d=h.width/a.getModuleCount();b=h.height/a.getModuleCount();for(e=0;e<a.getModuleCount();e++){f=r("<tr></tr>").css("height",b+"px").appendTo(c);for(i=0;i<a.getModuleCount();i++)r("<td></td>").css("width",
d+"px").css("background-color",a.isDark(e,i)?h.foreground:h.background).appendTo(f)}}a=c;jQuery(a).appendTo(this)})}})(jQuery);

View File

@ -0,0 +1,596 @@
/**
* Name: 级联选择器控件
* Version: 2020-06-16
* Author: 王海峰 <wanghaifeng@iyiou.com>
* Function List:
* 1. 级联面板 - 支持多选 - 单选
* 2. 支持回显已选中数据的完整路径 父级-父级-子级(可通过配置项 separator 自定义分隔符)
* 3. 支持删除单个选中的数据项
* 4. 支持一键删除所有选中数据项(可通过配置项 clearable 是否启用改功能)
* 5. 接口: 一键获取所选中的所有文本数组
* 6. 接口: 一键获取所选中的所有ID数组
*/
(function() {
/**
* cascader_node 适配器模式
* 将用户传入的数据通过该适配器进行处理
* 数据驱动的思路一个 CascaderNode 实例对应一个数据项不管是子级还是父级
*/
var cascader_node = function () {
/**
* @param {Object} data 数据
* @param {Object} config 配置项
* @param {Object} parentNode 父级 递归时传入
*/
function CascaderNode(data, config, parentNode) {
this.data = data // 原始数据
this.config = config // 配置项
this.indeterminate = false // 该父级下的子级是否全选,用于控制父级显示状态(只有子级全选,父级才全选)
this.parent = parentNode || null // 该项的父级
this.level = !this.parent ? 1 : this.parent.level + 1 // 等级序列号
this.uid = data[config.value] // 数据ID
// 因是数据驱动的方式一个数据项对应一个DOMDOM选中与否
this.checked = false // 该项数据是否选中
this.initState()
this.initChildren()
}
/**
* 初始化数据
*/
CascaderNode.prototype.initState = function initState() {
var _config = this.config,
valueKey = _config.value,
labelKey = _config.label
this.value = this.data[valueKey]
this.label = this.data[labelKey]
this.pathNodes = this.calculatePathNodes()
this.path = this.pathNodes.map(function (node) {
return node.value
})
this.pathLabels = this.pathNodes.map(function (node) {
return node.label
})
}
/**
* 初始化该数据下的子级
* 内部通过递归生成 CascaderNode 实例即子级
*/
CascaderNode.prototype.initChildren = function initChildren() {
var _this = this
var config = this.config
var childrenKey = config.children
var childrenData = this.data[childrenKey]
this.hasChildren = Array.isArray(childrenData)
this.children = (childrenData || []).map(function (child) {
return new CascaderNode(child, config, _this)
})
}
/**
* 计算路径
*/
CascaderNode.prototype.calculatePathNodes = function calculatePathNodes() {
var nodes = [this]
var parent = this.parent
while (parent) {
nodes.unshift(parent)
parent = parent.parent
}
return nodes
}
/**
* 获取该项的路径包含父级+
*/
CascaderNode.prototype.getPath = function getPath() {
return this.path
}
/**
* 获取该项的路径不包含父级
*/
CascaderNode.prototype.getValue = function getPath() {
return this.value
}
/**
* 多选 - 父级选中操作让所有子级选中
* @param {Boolean} checked
*/
CascaderNode.prototype.onParentCheck = function onParentCheck(checked) {
var child = this.children.length ? this.children : this
this.checked = checked
this.indeterminate = false
this.doAllCheck(child, checked)
}
/**
* 多选 - 父级选中时子级全选
* @param {Array} child
* @param {Boolean} checked
*/
CascaderNode.prototype.doAllCheck = function doAllCheck(child, checked) {
var _this = this
if (Array.isArray(child) && child.length) {
child.forEach(function (c) {
c.checked = checked
c.indeterminate = false
_this.doAllCheck(c.children, checked)
})
}
}
/**
* 多选 - 子级选中操作父级
* @param {*} checked
*/
CascaderNode.prototype.onChildCheck = function onChildCheck(checked) {
this.checked = checked
var parent = this.parent
var isChecked = parent.children.every(function (child) {
return child.checked
})
this.setCheckState(this.parent, isChecked);
}
/**
* 设置父级相应的状态
* 当该项有同级且都没有选中父级为 无选中 状态
* 当该项有同级且同级的所有数据都为选中时父级为 选中 状态
* 当该项有同级但同级中有且只有一项没有被选中父级为 半选中 状态 -
* @param {Object} parent
* @param {Boolean} isChecked
*/
CascaderNode.prototype.setCheckState = function setCheckState(parent, isChecked) {
parent.checked = isChecked
var totalNum = parent.children.length;
var checkedNum = parent.children.reduce(function (c, p) {
var num = p.checked ? 1 : p.indeterminate ? 0.5 : 0;
return c + num;
}, 0);
parent.indeterminate = checkedNum !== totalNum && checkedNum > 0;
parent.parent && this.setCheckState(parent.parent, isChecked)
}
return CascaderNode
}()
/**
* eo_cascader 生成级联选择器
* 绑定相关事件操作数据渲染选择器 回显选中列表
*/
var eo_cascader = function () {
// 默认配置
var defaultConfig = {
disabled: 'disabled',
emitPath: true,
value: 'id',
label: 'label',
children: 'children'
}
/**
* 级联选择器构造函数
* @param {Array} data
* @param {Object} config
*/
function EoCascader(data, config) {
this.config = Object.assign(defaultConfig, config) || null
this.multiple = config.multiple // 是否多选
this.separator = config.separator // 自定义数据之间分隔符
this.data = data // 原始数据
this.clearable = config.clearable // 是否可一键清空
this.panelShowState = false // 控制级联选择器显示
this.storageChecked = {} // 存储已选中的数据项
this.checkedText = [] // 选中的文本
this.checkedID = [] // 选中的ID
this.ele = document.getElementById(config.elementID) // DOM容器
this.panelWrap = this.initPanel() // 级联选择器DOM容器
this.checkedWrap = this.initCheckedWrap() // 回显选中列表DOM容器
this.checkedCallback = config.checkedCallback || (() => {});
this.initNodes(data)
this.initEvents()
}
/**
* 事件绑定
*/
EoCascader.prototype.initEvents = function initEvents(e) {
this.ele.addEventListener('click', this.bindCascaderClick.bind(this))
document.body.addEventListener('click', this.bindBodyClick.bind(this), true)
if(this.clearable) {
this.ele.addEventListener('mouseover', this.bindCascaderHover.bind(this))
this.ele.addEventListener('mouseout', this.bindCascaderOut.bind(this))
}
}
/**
* body点击隐藏级联面板
*/
EoCascader.prototype.bindBodyClick = function bindCascaderClick(e) {
if(e.target.tagName !== 'BODY') return
this.panelShowState = false
this.ele.className = 'cascader-wrap'
}
/**
* 点击容器控制切换级联面板显示
*/
EoCascader.prototype.bindCascaderClick = function bindCascaderClick(e) {
e.stopPropagation();
if(e.target.id !== this.ele.id ) return
this.panelShowState = !this.panelShowState
this.ele.className = this.panelShowState? 'cascader-wrap is-show': 'cascader-wrap'
}
/**
* 当且仅当 clearable true 时绑定
* 鼠标移入容器显示一键清空按钮
*/
EoCascader.prototype.bindCascaderHover = function bindCascaderHover(e) {
e.stopPropagation();
if(e.target.id !== this.ele.id && e.target.className !== 'eo-clear-btn' ) return
if(JSON.stringify(this.storageChecked) !== '{}') {
this.ele.className = this.panelShowState? 'cascader-wrap is-show is-clear': 'cascader-wrap is-clear'
}
}
/**
* 当且仅当 clearable true 时绑定
* 鼠标移出容器隐藏一键清空按钮
*/
EoCascader.prototype.bindCascaderOut = function bindCascaderOut(e) {
e.stopPropagation();
if(e.target.id !== this.ele.id) return
this.ele.className = this.panelShowState? 'cascader-wrap is-show': 'cascader-wrap'
}
/**
* 动态生成级联面板DOM容器
*/
EoCascader.prototype.initPanel = function initPanel() {
var panel = document.createElement('div')
panel.className = 'eo-cascader-panel'
return panel
}
/**
* 动态生成回显选中列表DOM容器
*/
EoCascader.prototype.initCheckedWrap = function initCheckedWrap() {
var checkedWrap = document.createElement('div')
checkedWrap.className = 'eo-checked-wrap'
return checkedWrap
}
/**
* 动态生成一键清空按钮
*/
EoCascader.prototype.initClearDom = function initClearDom() {
var clearBtn = document.createElement('i')
clearBtn.className = 'eo-clear-btn'
clearBtn.innerHTML = 'x'
var _this = this
// 绑定事件,初始化所有数据,重新渲染级联面板
clearBtn.addEventListener('click', function(e) {
e.stopPropagation();
_this.storageChecked = {}
_this.checkedCallback();
_this.config.checkedValue = null
_this.checkedText = []
_this.checkedID = []
_this.initNodes(_this.data)
_this.initCheckedLi()
_this.panelWrap.style.top = _this.ele.offsetHeight + 2 + 'px'
})
return clearBtn
}
/**
* 通过 CascaderNode 适配器对原始数据进行改造并赋值给当前构造函数的 nodes 对象
* @param {Array} data 用户传入的原始数据
*/
EoCascader.prototype.initNodes = function initNodes(data) {
var _this = this
this.nodes = data.map(function (nodeData) {
// 访问适配器
return new cascader_node(nodeData, _this.config)
})
// 级联面板
this.menus = [this.nodes]
// 当为编辑页面时,往往需要回显上次提交的数据,即,
// 如果存在 checkedValue
// 那么调用 findChecked 方法,通过传入的已选 ID渲染级联面板、回显列表
// 反之,根据初始数据正常渲染即可
this.config.checkedValue ? this.findChecked(this.config.checkedValue) : this.createNodes(this.menus)
// 如果可一键清空,动态添加清空按钮
this.clearable && this.ele.appendChild(this.initClearDom())
}
/**
* @param {Object} currentMenu 级联面板中当前的点击项
* 点击同级项时通过操作 menus使对应的子级进行渲染
*/
EoCascader.prototype.renderNodes = function (currentMenu) {
// 操作 menus
var menus = this.menus.slice(0, currentMenu.level)
currentMenu.children.length && menus.push(currentMenu.children)
this.menus = menus
var wrap = this.panelWrap
var wrapChild = wrap.children
// 操作DOM
for (let j = currentMenu.level; j < wrap.children.length; j++) {
wrap.removeChild(wrapChild[j])
j = j - 1
}
return menus
}
/**
* 数据驱动的方式通过 menus 渲染DOM
* 每次操作 menus增删都需要修改 menus进而再次调用改方法进行渲染
* @param {Array} menus 级联面板数据
*/
EoCascader.prototype.createNodes = function (menus) {
var wrap = this.panelWrap
wrap.innerHTML = ''
var _this = this
for (let i = 0; i < menus.length; i++) {
var menu = document.createElement('div')
menu.className = 'eo-cascader-menu'
var ul = document.createElement('ul')
var menusList = menus[i];
for (let k = 0; k < menusList.length; k++) {
var li = document.createElement('li')
if(menusList[k].children.length) li.className = 'has-child'
// 当且仅当多选时 创建 label checkbox
if(_this.multiple) {
var label = document.createElement('label')
var checkbox = document.createElement('input')
checkbox.type = 'checkbox'
checkbox.checked = menusList[k].checked
checkbox.setAttribute('uid', menusList[k].uid)
checkbox.className = menusList[k].indeterminate ? 'is-indeterminate' : ''
checkbox.addEventListener('click', _this.bindClickEvent.bind(checkbox,
_this, _this.handleCheckCb)
)
label.appendChild(checkbox)
li.appendChild(label)
}
// 创建文本
var span = document.createElement('span')
span.innerHTML = menusList[k]['label']
span.setAttribute('uid', menusList[k].uid)
li.addEventListener('click', _this.bindClickEvent.bind(span, _this, _this.handleDanxuanCb))
// 将 label 及 文本追加到 li
li.appendChild(span)
ul.appendChild(li)
}
menu.appendChild(ul)
wrap.appendChild(menu)
wrap.style.top = _this.ele.offsetHeight + 2 + 'px'
}
this.ele.appendChild(wrap)
}
/**
* 点击 checkbox 文本回调函数
* @param {this} _this 当前实例
* @param {Function} cb 回调函数
* 当且仅当点击 checkbox 传入 cb
*/
EoCascader.prototype.bindClickEvent = function bindClickEvent(_this, cb) {
var uid = this.getAttribute('uid')
var _thisMenu = _this.menus.flat(Infinity).filter(function (menu) {
return menu.uid == uid
})
typeof cb === 'function' && cb.call(this, _thisMenu, _this, this.checked)
_this.createNodes(_this.renderNodes(_thisMenu[0]))
}
EoCascader.prototype.handleDanxuanCb = function handleDanxuanCb(currentMenu, _this) {
if(_this.multiple) return
var child = currentMenu[0].children
if(!child.length) {
_this.storageChecked = {};
_this.storageChecked[currentMenu[0].uid] = {};
_this.storageChecked[currentMenu[0].uid].pathLabels = currentMenu[0].pathLabels
_this.storageChecked[currentMenu[0].uid].path = currentMenu[0].path
_this.checkedWrap.innerHTML = ''
// 渲染回显列表
_this.initCheckedLi()
_this.checkedCallback();
}
}
/**
* 点击 checkbox 触发回调
* 内部对父级子级选中状态进行修改
* 同时对选中的数据进行存储调用渲染回显列表函数
* @param {Array} currentMenu 当前点击的面板项
* @param {this} _this
* @param {Boolean} isChecked
*/
EoCascader.prototype.handleCheckCb = function handleCheckCb(currentMenu, _this, isChecked) {
// 如果当前点击项为第一级,那么让所有子级都选中
// 如果当前项有父级,设置父级选中状态
if (currentMenu[0].level !== 1) {
currentMenu[0].onChildCheck(isChecked)
}
currentMenu[0].onParentCheck(isChecked)
// 存储当前选中状态
currentMenu[0].children.length ?
_this.showReviewCheckedOb(currentMenu[0]) :
_this.handleReviewCheckedOb(currentMenu[0])
_this.checkedWrap.innerHTML = ''
// 渲染回显列表
_this.initCheckedLi()
}
EoCascader.prototype.initCheckedLi = function () {
var ul = document.createElement('ul')
var _this = this
if(JSON.stringify(this.storageChecked) === '{}') {
return this.checkedWrap.innerHTML = ''
}
for (const key in this.storageChecked) {
if (this.storageChecked.hasOwnProperty(key)) {
var li = document.createElement('li')
var p = document.createElement('p')
var i = document.createElement('i')
li.setAttribute('uid', key)
p.innerHTML = this.storageChecked[key].pathLabels.join(_this.separator)
i.innerHTML = 'x'
i.addEventListener('click', function () {
var uidd = this.parentElement.getAttribute('uid')
delete _this.storageChecked[uidd]
var fn = function (parent) {
for (let i = 0; i < parent.length; i++) {
if (parent[i].children.length) {
fn(parent[i].children)
} else {
if (parent[i].uid == uidd) {
_this.handleCheckCb([parent[i]], _this, false)
_this.createNodes(_this.menus)
}
}
}
}
fn(_this.nodes)
})
li.appendChild(p)
li.appendChild(i)
ul.appendChild(li)
_this.checkedWrap.appendChild(ul)
}
}
this.ele.appendChild(this.checkedWrap)
}
/**
* 根据编辑页面传入的已选ID数组修改面板数据 menus
* @param {Array} uidArr
*/
EoCascader.prototype.findChecked = function (uidArr) {
var _this = this
// 获取上次已经提交过的三级标签
var checkedNodesMatch = []
var nodes = this.nodes
var recursionFn = function (parent) {
for (let i = 0; i < parent.length; i++) {
if (parent[i].children.length) {
recursionFn(parent[i].children)
} else {
if (uidArr.includes(parent[i].uid)) {
parent[i].checked = true
_this.handleCheckCb([parent[i]], _this, true)
checkedNodesMatch.push(parent[i])
}
}
}
}
recursionFn(nodes)
var menus = []
var getMenusMatch = function (menu) {
if (menu.parent) {
menus.push(menu.parent.children)
return getMenusMatch(menu.parent)
}
}
getMenusMatch(checkedNodesMatch[0])
menus.reverse().forEach(function (m) {
_this.menus.push(m)
})
_this.createNodes(this.menus)
}
/**
* 递归的找到当前 node 下最后一个子级并将其存入 storageChecked
* @param {Object} node
*/
EoCascader.prototype.showReviewCheckedOb = function (node) {
if (!node.children.length) {
this.handleReviewCheckedOb(node)
} else {
for (let k = 0; k < node.children.length; k++) {
this.showReviewCheckedOb(node.children[k])
}
}
}
/**
* 如果当前 node 已选中存入 storageChecked 反之删除 storageChecked 中的当前 node
* @param {Object} node
*/
EoCascader.prototype.handleReviewCheckedOb = function (node) {
if (node.checked) {
this.storageChecked[node.uid] = {};
this.storageChecked[node.uid].pathLabels = node.pathLabels;
this.storageChecked[node.uid].path = node.path;
} else {
delete this.storageChecked[node.uid]
}
this.checkedCallback();
}
/**
* 接口获取所有选中的文本
*/
EoCascader.prototype.getCheckedByText = function () {
this.checkedText = []
for (const key in this.storageChecked) {
if (this.storageChecked.hasOwnProperty(key)) {
this.checkedText.push(this.storageChecked[key].pathLabels.join(this.separator))
}
}
return this.checkedText
}
/**
* 接口获取所有选中的ID
*/
EoCascader.prototype.getCheckedByID = function () {
this.checkedID = []
for (const key in this.storageChecked) {
if (this.storageChecked.hasOwnProperty(key)) {
this.checkedID.push(key - 0)
}
}
return this.checkedID
}
/**
* 接口获取所有层级id
*/
EoCascader.prototype.getCheckedPaths = function () {
this.checkedPaths = []
for (const key in this.storageChecked) {
if (this.storageChecked.hasOwnProperty(key)) {
this.checkedPaths.push(this.storageChecked[key].path)
}
}
return this.checkedPaths
}
return EoCascader
}()
window.eo_cascader = eo_cascader
}(window))

View File

@ -391,7 +391,7 @@ var table = {
importTemplate: function() { importTemplate: function() {
$.get(activeWindow().table.options.importTemplateUrl, function(result) { $.get(activeWindow().table.options.importTemplateUrl, function(result) {
if (result.code == web_status.SUCCESS) { if (result.code == web_status.SUCCESS) {
window.location.href = ctx + "common/download?fileName=" + encodeURI(result.msg) + "&delete=" + true; window.location.href = "http://gqz.opsoul.com/%E6%89%B9%E9%87%8F%E4%B8%8B%E5%8D%95%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xls";
} else if (result.code == web_status.WARNING) { } else if (result.code == web_status.WARNING) {
$.modal.alertWarning(result.msg) $.modal.alertWarning(result.msg)
} else { } else {

View File

@ -5,6 +5,41 @@ $(function() {
var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random(); var url = ctx + "captcha/captchaImage?type=" + captchaType + "&s=" + Math.random();
$(".imgcode").attr("src", url); $(".imgcode").attr("src", url);
}); });
$.ajax({
type: "POST",
dataType:"json",
url: ctx + "system/dept/list",
data: { parentId: 100 },
success: function (data) {
$.each(data, function (index, value) {
$('#deptId').append("<option value=" + value.deptId + ">" + value.deptName + "</option>");
});
}
})
// $('#deptId').select2({
// placeholder: '请选择公司编码',
// minimumResultsForSearch: -1,
// ajax: {
// type: "POST",
// dataType:"json",
// url: ctx + "system/dept/list",
// data: { parentId: 100 },
// processResults: function (data) {
// var processedData = [];
// $.each(data, function (index, value) {
// processedData.push({
// id: value.deptId,
// text: value.deptName
// })
// });
// return {
// results: processedData
// };
// },
// cache: true
// }
// });
}); });
$.validator.setDefaults({ $.validator.setDefaults({
@ -16,6 +51,8 @@ $.validator.setDefaults({
function register() { function register() {
$.modal.loading($("#btnSubmit").data("loading")); $.modal.loading($("#btnSubmit").data("loading"));
var username = $.common.trim($("input[name='username']").val()); var username = $.common.trim($("input[name='username']").val());
var phonenumber = $.common.trim($("input[name='phonenumber']").val());
var deptId = $.common.trim($('#deptId').val());
var password = $.common.trim($("input[name='password']").val()); var password = $.common.trim($("input[name='password']").val());
var validateCode = $("input[name='validateCode']").val(); var validateCode = $("input[name='validateCode']").val();
$.ajax({ $.ajax({
@ -23,6 +60,8 @@ function register() {
url: ctx + "register", url: ctx + "register",
data: { data: {
"loginName": username, "loginName": username,
"phonenumber": phonenumber,
"deptId": deptId,
"password": password, "password": password,
"validateCode": validateCode "validateCode": validateCode
}, },
@ -49,15 +88,23 @@ function register() {
function validateRule() { function validateRule() {
var icon = "<i class='fa fa-times-circle'></i> "; var icon = "<i class='fa fa-times-circle'></i> ";
$.validator.addMethod("checkPhone",function(value,element,params){
var regex = /^1[345678]\d{9}$/;
return regex.test(value);
}, "请输入正确的手机号码");
$("#registerForm").validate({ $("#registerForm").validate({
rules: { rules: {
username: { username: {
required: true, required: true,
minlength: 2 rangelength: [2,20]
},
phonenumber: {
required: true,
checkPhone: true
}, },
password: { password: {
required: true, required: true,
minlength: 5 rangelength: [5,20]
}, },
confirmPassword: { confirmPassword: {
required: true, required: true,
@ -66,15 +113,18 @@ function validateRule() {
}, },
messages: { messages: {
username: { username: {
required: icon + "请输入您的用户名", required: icon + "请输入用户名",
minlength: icon + "用户名不能小于2个字符" rangelength: icon + "账户长度必须在2到20个字符之间"
},
phonenumber: {
required: icon + "请输入手机号码"
}, },
password: { password: {
required: icon + "请输入您的密码", required: icon + "请输入密码",
minlength: icon + "密码不能小于5个字符", rangelength: icon + "密码长度必须在5到20个字符之间"
}, },
confirmPassword: { confirmPassword: {
required: icon + "请再次输入您的密码", required: icon + "请再次输入密码",
equalTo: icon + "两次密码输入不一致" equalTo: icon + "两次密码输入不一致"
} }
} }

View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增发单加价记录')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-record-add">
<div class="form-group">
<label class="col-sm-3 control-label is-required">订单id</label>
<div class="col-sm-8">
<input name="orderId" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">申请师傅:</label>
<div class="col-sm-8">
<input name="workerId" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">报价金额:</label>
<div class="col-sm-8">
<input name="addMoney" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">备注:</label>
<div class="col-sm-8">
<input name="remark" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "worker/record"
$("#form-record-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-record-add').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改发单加价记录')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-record-edit" th:object="${orderAddRecord}">
<input name="id" th:field="*{id}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label is-required">订单id</label>
<div class="col-sm-8">
<input name="orderId" th:field="*{orderId}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">申请师傅:</label>
<div class="col-sm-8">
<input name="workerId" th:field="*{workerId}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">报价金额:</label>
<div class="col-sm-8">
<input name="addMoney" th:field="*{addMoney}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">备注:</label>
<div class="col-sm-8">
<input name="remark" th:field="*{remark}" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "worker/record";
$("#form-record-edit").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-record-edit').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('发单加价记录列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>订单id</label>
<input type="text" name="orderId"/>
</li>
<li>
<label>申请师傅:</label>
<input type="text" name="workerId"/>
</li>
<li>
<label>报价金额:</label>
<input type="text" name="addMoney"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="worker:record:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="worker:record:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="worker:record:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="worker:record:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('worker:record:edit')}]];
var removeFlag = [[${@permission.hasPermi('worker:record:remove')}]];
var prefix = ctx + "worker/record";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "发单加价记录",
columns: [{
checkbox: true
},
{
field: 'id',
title: '主键',
visible: false
},
{
field: 'orderId',
title: '订单id'
},
{
field: 'workerId',
title: '申请师傅'
},
{
field: 'addMoney',
title: '报价金额'
},
{
field: 'status',
title: '状态 01初始 02选中'
},
{
field: 'remark',
title: '备注'
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
</script>
</body>
</html>

View File

@ -0,0 +1,139 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('')"/>
<th:block th:include="include :: select2-css"/>
</head>
<body>
<div class="main-content">
<form id="form-goods-add" class="form-horizontal">
<h4 class="form-header h4">基本信息</h4>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">主订单已发布更新提示音:</label>
<div class="col-sm-8">
<input name="orderMasterHaveReleasedUrl" id="orderMasterHaveReleasedUrl" placeholder="主订单已发布更新提示音" class="form-control" type="text"
required>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">主订单新订单更新提示音:</label>
<div class="col-sm-8">
<input name="orderMasterNewOrderUrl" id="orderMasterNewOrderUrl" placeholder="主订单新订单更新提示音" class="form-control" type="text"
required>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">子订单售后更新提示音:</label>
<div class="col-sm-8">
<input name="orderDetailsAfterUrl" id="orderDetailsAfterUrl" placeholder="子订单售后更新提示音" class="form-control" type="text"
required>
</div>
</div>
</div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-4 control-label is-required">子订单售后纠纷更新提示音:</label>
<div class="col-sm-8">
<input name="orderDetailsAfterSalesDisputeUrl" id="orderDetailsAfterSalesDisputeUrl" placeholder="子订单售后纠纷更新提示音" class="form-control" type="text"
required>
</div>
</div>
</div>
</div>
<a class="btn btn-primary btn-rounded btn-sm" onclick="tijiao()">提交</a>
</form>
</div>
<th:block th:include="include :: footer"/>
<th:block th:include="include :: select2-js"/>
<script>
var prefix = ctx + "goods/goods";
var id = "";
var name = "";
var sort = "";
var describe = "";
var type = "";
var dataType = "";
var configUnit = "";
//请求接口加载页面输入框值
function globalConfiginit(){
$.ajax({
type: "GET",
dataType:"json",
url: "/config/globalConfig/search/type/1001",
data: { },
success: function (data) {
id = data.data.id;
name = data.data.name;
sort = data.data.sort;
describe = data.data.describe;
type = data.data.type;
dataType = data.data.dataType;
configUnit = data.data.configUnit;
//alert(data.data.content);
var response = JSON.parse(data.data.content);
$('#orderMasterHaveReleasedUrl').val(response.orderMasterHaveReleasedUrl);
$('#orderMasterNewOrderUrl').val(response.orderMasterNewOrderUrl);
$('#orderDetailsAfterUrl').val(response.orderDetailsAfterUrl);
$('#orderDetailsAfterSalesDisputeUrl').val(response.orderDetailsAfterSalesDisputeUrl);
}
})
}
//页面加载
window.onload = function () {
//请求接口加载页面输入框值
globalConfiginit();
}
//提交按钮
function tijiao(){
$.ajax({
type: "PUT",
dataType:"json",
contentType: 'application/json',
url: "/config/globalConfig/update",
data: JSON.stringify({
id: id,
name: name,
content: JSON.stringify({
"orderMasterHaveReleasedUrl":$('#orderMasterHaveReleasedUrl').val(),
"orderMasterNewOrderUrl":$('#orderMasterNewOrderUrl').val(),
"orderDetailsAfterUrl":$('#orderDetailsAfterUrl').val(),
"orderDetailsAfterSalesDisputeUrl":$('#orderDetailsAfterSalesDisputeUrl').val()
}),
sort: sort,
describe: describe,
type: type,
dataType: dataType,
unit: configUnit
}),
success: function (data) {
if(data.code == 0){
//请求接口加载页面输入框值
globalConfiginit();
alert("成功");
}else {
alert("失败");
}
}
})
}
</script>
</body>
</html>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改上级分销')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-change-insurance">
<input name="customerId" type="hidden" th:value="${customerId}" />
<div class="form-group">
<label class="col-sm-3 control-label">上级分销:</label>
<div class="col-sm-8">
<select id="customerPlace" name="customerPlace" class="form-control control-label" required>
<option th:each="customerPlace:${customerPlaces}" th:value="${customerPlace.customerId}" th:text="${customerPlace.phone} + ${customerPlace.placeName}" ></option>
</select>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script type="text/javascript">
function submitHandler() {
if ($.validate.form()) {
$.operate.save(ctx + "customer/changePlace", $('#form-change-insurance').serialize());
}
}
</script>
</body>
</html>

View File

@ -118,6 +118,22 @@
field: 'phone', field: 'phone',
title: '手机号' title: '手机号'
}, },
{
field: 'customerPlaceName',
title: '上级分销'
},
{
field: 'customerPlacePhone',
title: '上级手机号'
},
{
field: 'parentCustomerPlaceName',
title: '最上级分销'
},
{
field: 'parentCustomerPlacePhone',
title: '最上级手机号'
},
{ {
field: 'openId', field: 'openId',
title: '微信唯一id', title: '微信唯一id',
@ -130,7 +146,8 @@
var actions = []; var actions = [];
actions.push('<img class="img-circle" src="' + row.customerLogoUrl + '" alt="消费者头像" />'); actions.push('<img class="img-circle" src="' + row.customerLogoUrl + '" alt="消费者头像" />');
return actions.join(''); return actions.join('');
} },
visible: false
}, },
{ {
visible: editFlag == 'hidden' ? false : true, visible: editFlag == 'hidden' ? false : true,
@ -151,6 +168,7 @@
formatter: function(value, row, index) { formatter: function(value, row, index) {
if (row.customerId != 1) { if (row.customerId != 1) {
var actions = []; var actions = [];
actions.push('<a class="btn btn-success btn-xs " href="javascript:void(0)" onclick="changePlace(\'' + row.customerId + '\')"></i>修改上级分销</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.customerId + '\')"><i class="fa fa-remove"></i>删除</a> '); actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.customerId + '\')"><i class="fa fa-remove"></i>删除</a> ');
return actions.join(''); return actions.join('');
} else { } else {
@ -162,6 +180,11 @@
$.table.init(options); $.table.init(options);
} }
function changePlace(customerId) {
var url = ctx + "customer/changePlace/" + customerId;
$.modal.open("修改上级分销", url, '600', '300');
}
/* 用户管理-重置密码 */ /* 用户管理-重置密码 */
function resetPwd(customerId) { function resetPwd(customerId) {

View File

@ -42,9 +42,9 @@
<a class="btn btn-danger multiple disabled" onclick="auditStatus(1)" shiro:hasPermission="customer:place:remove"> <a class="btn btn-danger multiple disabled" onclick="auditStatus(1)" shiro:hasPermission="customer:place:remove">
<i class="fa fa-remove"></i> 拒绝 <i class="fa fa-remove"></i> 拒绝
</a> </a>
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="customer:place:edit"> <!-- <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="customer:place:edit">-->
<i class="fa fa-edit"></i> 修改 <!-- <i class="fa fa-edit"></i> 修改-->
</a> <!-- </a>-->
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="customer:place:export"> <a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="customer:place:export">
<i class="fa fa-download"></i> 导出 <i class="fa fa-download"></i> 导出
</a> </a>
@ -79,17 +79,33 @@
field: 'name', field: 'name',
title: '名字' title: '名字'
}, },
{ // {
field: 'customerId', // field: 'customerId',
title: '关联消费者id' // title: '关联消费者id'
}, // },
{ {
field: 'phone', field: 'phone',
title: '注册手机号' title: '注册手机号'
}, },
{ {
field: 'city', field: 'customerPlaceName',
title: '城市id' title: '上级分销'
},
{
field: 'customerPlacePhone',
title: '上级手机号'
},
{
field: 'parentCustomerPlaceName',
title: '最上级分销'
},
{
field: 'parentCustomerPlacePhone',
title: '最上级手机号'
},
{
field: 'cityName',
title: '城市名'
}, },
{ {
field: 'status', field: 'status',
@ -107,7 +123,7 @@
align: 'center', align: 'center',
formatter: function(value, row, index) { formatter: function(value, row, index) {
var actions = []; var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> '); // actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>'); actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join(''); return actions.join('');
} }

View File

@ -46,6 +46,18 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-xs-2 control-label">保险设定:</label>
<div class="col-xs-10">
<label th:each="insurance:${insurances}" class="check-box">
<input name="insurance" type="checkbox" th:value="${insurance.id}" th:text="${insurance.companyName}">
</label>
</div>
</div>
</div>
</div>
</form> </form>
</div> </div>
<th:block th:include="include :: footer" /> <th:block th:include="include :: footer" />
@ -87,9 +99,38 @@
function submitHandler() { function submitHandler() {
if ($.validate.form()) { if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-dept-add').serialize()); // 方法一使用saveModal新增成功后不刷新表格只显示提示信息
//$.operate.saveModal(prefix + "/add", $('#form-dept-add').serialize());
// 方法二使用自定义Ajax保存如果需要更多控制
customSave();
} }
} }
// 自定义保存方法(可选)
function customSave() {
$.ajax({
url: prefix + "/add",
type: "post",
dataType: "json",
data: $('#form-dept-add').serialize(),
beforeSend: function () {
$.modal.loading("正在处理中,请稍候...");
},
success: function(result) {
$.modal.closeLoading();
if (result.code == web_status.SUCCESS) {
$.modal.alertSuccess(result.msg);
// 如果需要关闭窗口,取消注释下面这行
$.modal.close();
} else if (result.code == web_status.WARNING) {
$.modal.alertWarning(result.msg);
} else {
$.modal.alertError(result.msg);
}
}
});
}
/*部门管理-新增-选择父部门树*/ /*部门管理-新增-选择父部门树*/
function selectDeptTree() { function selectDeptTree() {

View File

@ -124,8 +124,29 @@
function remove(id) { function remove(id) {
$.modal.confirm("确认要删除吗", function () { $.modal.confirm("确认要删除吗", function () {
$.operate.post(prefix + '/remove/' + id); customRemove(id);
}) });
}
function customRemove(id) {
$.ajax({
url: prefix + '/remove/' + id,
type: "post",
dataType: "json",
beforeSend: function () {
$.modal.loading("正在处理中,请稍候...");
},
success: function(result) {
$.modal.closeLoading();
if (result.code == web_status.SUCCESS) {
$.modal.alertSuccess(result.msg);
} else if (result.code == web_status.WARNING) {
$.modal.alertWarning(result.msg);
} else {
$.modal.alertError(result.msg);
}
}
});
} }
</script> </script>
</body> </body>

View File

@ -17,15 +17,15 @@
<!-- </div>--> <!-- </div>-->
<!-- </div>--> <!-- </div>-->
<!-- </div>--> <!-- </div>-->
<div class="form-group"> <!-- <div class="form-group">-->
<label class="col-sm-3 control-label is-required">上级类目:</label> <!-- <label class="col-sm-3 control-label is-required">上级类目:</label>-->
<div class="col-sm-8"> <!-- <div class="col-sm-8">-->
<div class="input-group"> <!-- <div class="input-group">-->
<input class="form-control" type="text" onclick="selectDeptTree()" id="treeName" readonly="true" th:value="${goodsCategoryName}" required> <!-- <input class="form-control" type="text" onclick="selectDeptTree()" id="treeName" readonly="true" th:value="${goodsCategoryName}" required>-->
<span class="input-group-addon"><i class="fa fa-search"></i></span> <!-- <span class="input-group-addon"><i class="fa fa-search"></i></span>-->
</div> <!-- </div>-->
</div> <!-- </div>-->
</div> <!-- </div>-->
<div class="form-group"> <div class="form-group">
<label class="col-sm-3 control-label is-required">类别名称:</label> <label class="col-sm-3 control-label is-required">类别名称:</label>
<div class="col-sm-8"> <div class="col-sm-8">
@ -48,7 +48,8 @@
<label class="col-sm-3 control-label">类目类别:</label> <label class="col-sm-3 control-label">类目类别:</label>
<div class="col-sm-8"> <div class="col-sm-8">
<div class="radio-box" th:each="dict : ${@dict.getType('goods_category_type')}"> <div class="radio-box" th:each="dict : ${@dict.getType('goods_category_type')}">
<input type="radio" th:id="${dict.dictCode}" name="type" th:value="${dict.dictValue}" th:checked="${dict.default}"> <input type="radio" th:id="${dict.dictCode}" name="type" th:value="${dict.dictValue}"
th:checked="${goodsCategory.type != null ? goodsCategory.type.toString() == dict.dictValue : dict.default}">
<label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label> <label th:for="${dict.dictCode}" th:text="${dict.dictLabel}"></label>
</div> </div>
</div> </div>
@ -62,6 +63,18 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-xs-2 control-label">保险设定:</label>
<div class="col-xs-10">
<label th:each="insurance:${insurances}" class="check-box">
<input name="insurance" type="checkbox" th:value="${insurance.id}" th:text="${insurance.companyName}" th:checked="${insurance.flag}">
</label>
</div>
</div>
</div>
</div>
</form> </form>
</div> </div>
<th:block th:include="include :: footer" /> <th:block th:include="include :: footer" />
@ -103,10 +116,39 @@
function submitHandler() { function submitHandler() {
if ($.validate.form()) { if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-dept-edit').serialize()); var data = $("#form-dept-edit").serializeArray();
var insuranceIds = $.form.selectCheckeds("insurance");
data.push({"name": "insuranceIds", "value": insuranceIds});
// 自定义保存,不刷新表格
customEditSave(data);
} }
} }
// 自定义编辑保存方法
function customEditSave(data) {
$.ajax({
url: prefix + "/edit",
type: "post",
dataType: "json",
data: data,
beforeSend: function () {
$.modal.loading("正在处理中,请稍候...");
},
success: function(result) {
$.modal.closeLoading();
if (result.code == web_status.SUCCESS) {
$.modal.alertSuccess(result.msg);
$.modal.close();
} else if (result.code == web_status.WARNING) {
$.modal.alertWarning(result.msg);
} else {
$.modal.alertError(result.msg);
}
}
});
}
/*部门管理-修改-选择部门树*/ /*部门管理-修改-选择部门树*/
function selectDeptTree() { function selectDeptTree() {
var treeId = $("#treeId").val(); var treeId = $("#treeId").val();

View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('选择服务类目')" />
<th:block th:include="include :: ztree-css" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-tree">
<div class="form-group">
<label class="col-sm-3 control-label">服务类目:</label>
<div class="col-sm-8">
<div class="input-group">
<input class="form-control" type="text" id="treeName" readonly="true">
<input type="hidden" id="treeId">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label"></label>
<div class="col-sm-8">
<div id="tree" class="ztree"></div>
</div>
</div>
<!-- <div class="form-group">
<div class="form-control-static col-sm-offset-9">
<button type="button" class="btn btn-sm btn-primary" onclick="submitHandler()"><i class="fa fa-check"></i>保 存</button>&nbsp;
<button type="button" class="btn btn-sm btn-danger" onclick="closeItem()"><i class="fa fa-reply-all"></i>关 闭</button>
</div>
</div> -->
</form>
</div>
<th:block th:include="include :: footer" />
<th:block th:include="include :: ztree-js" />
<script type="text/javascript">
$(function() {
var url = ctx + "goods/category/serviceTreeData";
var options = {
url: url,
expandLevel: 2,
onClick : zOnClick
};
$.tree.init(options);
});
function zOnClick(event, treeId, treeNode) {
$("#treeId").val(treeNode.id);
$("#treeName").val(treeNode.name);
}
function submitHandler() {
var treeId = $("#treeId").val();
var treeName = $("#treeName").val();
if (treeId == "" || treeName == "") {
$.modal.alertWarning("请选择服务类目");
return;
}
var index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
}
function closeItem() {
var index = parent.layer.getFrameIndex(window.name);
parent.layer.close(index);
}
</script>
</body>
</html>

View File

@ -145,9 +145,7 @@
formatter: function (value, row, index) { formatter: function (value, row, index) {
if (row.parentId !== 0) { if (row.parentId !== 0) {
var actions = []; var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.editTab(\'' + row.deptGoodsCategoryId + '\')"><i class="fa fa-edit"></i>编辑</a> '); actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.deptGoodsCategoryId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
// actions.push('<a class="btn btn-info btn-xs ' + addFlag + '" href="javascript:void(0)" onclick="$.operate.add(\'' + row.deptGoodsCategoryId + '\')"><i class="fa fa-plus"></i>新增</a> ');
// actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="remove(\'' + row.deptGoodsCategoryId + '\')"><i class="fa fa-trash"></i>删除</a>');
return actions.join(''); return actions.join('');
} else { } else {
return ""; return "";

View File

@ -11,6 +11,7 @@
<div class="main-content"> <div class="main-content">
<form class="form-horizontal" id="form-deptGoodsCategory-edit" th:object="${deptGoodsCategory}"> <form class="form-horizontal" id="form-deptGoodsCategory-edit" th:object="${deptGoodsCategory}">
<input id="deptGoodsCategoryId" name="deptGoodsCategoryId" type="hidden" th:field="*{deptGoodsCategoryId}"/> <input id="deptGoodsCategoryId" name="deptGoodsCategoryId" type="hidden" th:field="*{deptGoodsCategoryId}"/>
<input id="type" name="type" type="hidden" th:field="*{type}"/>
<div class="row"> <div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
@ -23,6 +24,21 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6" th:if="*{type != 1}">
<div class="form-group">
<label class="col-sm-6 control-label">服务类目:</label>
<div class="col-sm-6">
<div class="input-group">
<input class="form-control" type="text" onclick="selectServiceCategoryTree()" id="treeName" readonly="true" th:value="*{serviceCategoryName}">
<input type="hidden" id="treeId" name="serviceCategoryId" th:value="*{serviceCategoryId}">
<input type="hidden" id="serviceCategoryName" name="serviceCategoryName" th:value="*{serviceCategoryName}">
<span class="input-group-addon"><i class="fa fa-search"></i></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-group"> <div class="form-group">
<label class="col-sm-6 control-label is-required">一级分销扣点比例:</label> <label class="col-sm-6 control-label is-required">一级分销扣点比例:</label>
@ -33,6 +49,16 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-6 control-label is-required">PC一级分销扣点比例</label>
<div class="col-sm-6">
<input name="pcOneRate" placeholder="请输入PC一级分销扣点比例" class="form-control" type="text" maxlength="12"
th:field="*{pcOneRate}"
required>
</div>
</div>
</div>
</div> </div>
<div class="row"> <div class="row">
@ -46,6 +72,18 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-6 control-label is-required">PC二级分销扣点比例</label>
<div class="col-sm-6">
<input name="pcTwoRate" placeholder="请输入PC二级分销扣点比例" class="form-control" type="text"
th:field="*{pcTwoRate}"
maxlength="12" required>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-group"> <div class="form-group">
<label class="col-sm-6 control-label is-required">三级分销扣点比例:</label> <label class="col-sm-6 control-label is-required">三级分销扣点比例:</label>
@ -56,6 +94,16 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-6 control-label is-required">PC三级分销扣点比例</label>
<div class="col-sm-6">
<input name="pcThreeRate" placeholder="PC请输入三级分销扣点比例" class="form-control" type="text" maxlength="12"
th:field="*{pcThreeRate}"
required>
</div>
</div>
</div>
</div> </div>
<div class="row"> <div class="row">
@ -69,6 +117,19 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-6 control-label is-required">PC平台扣点比例</label>
<div class="col-sm-6">
<input name="pcDeptRate" placeholder="请输入PC平台扣点比例" class="form-control" type="text"
th:field="*{pcDeptRate}"
maxlength="12" required>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-group"> <div class="form-group">
<label class="col-sm-6 control-label is-required">平台固定扣金额:</label> <label class="col-sm-6 control-label is-required">平台固定扣金额:</label>
@ -79,6 +140,16 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-6 control-label is-required">PC平台固定扣金额</label>
<div class="col-sm-6">
<input name="pcDeptMoney" placeholder="请输入PC平台固定扣金额" class="form-control" type="text" maxlength="12"
th:field="*{pcDeptMoney}"
required>
</div>
</div>
</div>
</div> </div>
<div class="row"> <div class="row">
@ -92,6 +163,19 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-6 control-label is-required">PC截留扣点</label>
<div class="col-sm-6">
<input name="pcRetainRate" placeholder="请输入PC截留扣点" class="form-control" type="text"
th:field="*{pcRetainRate}"
maxlength="12" required>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-group"> <div class="form-group">
<label class="col-sm-6 control-label is-required">截留金额:</label> <label class="col-sm-6 control-label is-required">截留金额:</label>
@ -102,6 +186,16 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-sm-6">
<div class="form-group">
<label class="col-sm-6 control-label is-required">PC截留金额</label>
<div class="col-sm-6">
<input name="pcRetainMoney" placeholder="请输入PC截留金额" class="form-control" type="text" maxlength="12"
th:field="*{pcRetainMoney}"
required>
</div>
</div>
</div>
</div> </div>
<div class="row"> <div class="row">
@ -160,12 +254,38 @@
</div> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-group"> <div class="form-group">
<label class="col-sm-6 control-label">是否需要保险</label> <label class="col-sm-6 control-label">倒计时小时数</label>
<div class="col-sm-6"> <div class="col-sm-6">
<select name="isSure" class="form-control m-b" th:field="*{isSure}" th:with="type=${@dict.getType('sys_user_sex')}"> <input name="countdownHours" placeholder="请输入倒计时小时数" class="form-control" type="number" min="1" max="168"
<option th:text="否" th:value="0"/> th:field="*{countdownHours}">
<option th:text="是" th:value="1"/> </div>
</select> </div>
</div>
</div>
<div class="row">
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-xs-3 control-label">PC保险设定</label>
<div class="col-xs-9">
<label th:each="insurance:${pcInsurances}" class="check-box">
<input name="pcInsurance" type="checkbox" th:value="${insurance.id}" th:text="${insurance.insuranceName}" th:checked="${insurance.flag}">
</label>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="row">
<div class="col-sm-12">
<div class="form-group">
<label class="col-xs-3 control-label">商城保险设定:</label>
<div class="col-xs-9">
<label th:each="insurance:${shopInsurances}" class="check-box">
<input name="shopInsurance" type="checkbox" th:value="${insurance.id}" th:text="${insurance.insuranceName}" th:checked="${insurance.flag}">
</label>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -213,6 +333,10 @@
function submitHandler() { function submitHandler() {
if ($.validate.form()) { if ($.validate.form()) {
var data = $("#form-deptGoodsCategory-edit").serializeArray(); var data = $("#form-deptGoodsCategory-edit").serializeArray();
var pcInsuranceIds = $.form.selectCheckeds("pcInsurance");
var shopInsuranceIds = $.form.selectCheckeds("shopInsurance");
data.push({"name": "pcInsuranceIds", "value": pcInsuranceIds});
data.push({"name": "shopInsuranceIds", "value": shopInsuranceIds});
$.operate.saveTab(prefix + "/edit", data); $.operate.saveTab(prefix + "/edit", data);
$.modal.close(); $.modal.close();
} }
@ -274,6 +398,26 @@
} }
}); });
/*选择服务类目树*/
function selectServiceCategoryTree() {
var treeId = $("#treeId").val();
var options = {
title: '服务类目选择',
width: "380",
url: ctx + "goods/category/selectServiceCategoryTree",
callBack: doSubmit
};
$.modal.openOptions(options);
}
function doSubmit(index, layero) {
var body = $.modal.getChildFrame(index);
$("#treeId").val(body.find('#treeId').val());
$("#treeName").val(body.find('#treeName').val());
$("#serviceCategoryName").val(body.find('#treeName').val());
$.modal.close(index);
}
</script> </script>
</body> </body>
</html> </html>

View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('新增保险管理')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-manager-add">
<div class="form-group">
<label class="col-sm-3 control-label">保险公司名称:</label>
<div class="col-sm-8">
<input name="companyName" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">保险项目名称:</label>
<div class="col-sm-8">
<input name="insuranceName" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">保险费用:</label>
<div class="col-sm-8">
<input name="insuranceAmount" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">保险条例url</label>
<div class="col-sm-8">
<textarea name="insuranceUrl" class="form-control"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">备注:</label>
<div class="col-sm-8">
<input name="remark" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "goods/manager"
$("#form-manager-add").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/add", $('#form-manager-add').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('修改保险管理')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-manager-edit" th:object="${insuranceManager}">
<input name="id" th:field="*{id}" type="hidden">
<div class="form-group">
<label class="col-sm-3 control-label">保险公司名称:</label>
<div class="col-sm-8">
<input name="companyName" th:field="*{companyName}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">保险项目名称:</label>
<div class="col-sm-8">
<input name="insuranceName" th:field="*{insuranceName}" class="form-control" type="text">
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label is-required">保险费用:</label>
<div class="col-sm-8">
<input name="insuranceAmount" th:field="*{insuranceAmount}" class="form-control" type="text" required>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">保险条例url</label>
<div class="col-sm-8">
<textarea name="insuranceUrl" class="form-control">[[*{insuranceUrl}]]</textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-3 control-label">备注:</label>
<div class="col-sm-8">
<input name="remark" th:field="*{remark}" class="form-control" type="text">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var prefix = ctx + "goods/manager";
$("#form-manager-edit").validate({
focusCleanup: true
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(prefix + "/edit", $('#form-manager-edit').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('保险管理列表')" />
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li>
<label>保险公司名称:</label>
<input type="text" name="companyName"/>
</li>
<li>
<label>保险项目名称:</label>
<input type="text" name="insuranceName"/>
</li>
<li>
<label>保险费用:</label>
<input type="text" name="insuranceAmount"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()"><i class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()"><i class="fa fa-refresh"></i>&nbsp;重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
<a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="goods:manager:add">
<i class="fa fa-plus"></i> 添加
</a>
<a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="goods:manager:edit">
<i class="fa fa-edit"></i> 修改
</a>
<a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="goods:manager:remove">
<i class="fa fa-remove"></i> 删除
</a>
<a class="btn btn-warning" onclick="$.table.exportExcel()" shiro:hasPermission="goods:manager:export">
<i class="fa fa-download"></i> 导出
</a>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
<script th:inline="javascript">
var editFlag = [[${@permission.hasPermi('goods:manager:edit')}]];
var removeFlag = [[${@permission.hasPermi('goods:manager:remove')}]];
var prefix = ctx + "goods/manager";
$(function() {
var options = {
url: prefix + "/list",
createUrl: prefix + "/add",
updateUrl: prefix + "/edit/{id}",
removeUrl: prefix + "/remove",
exportUrl: prefix + "/export",
modalName: "保险管理",
columns: [{
checkbox: true
},
{
field: 'id',
title: '主键',
visible: false
},
{
field: 'companyName',
title: '保险公司名称'
},
{
field: 'insuranceName',
title: '保险项目名称'
},
{
field: 'insuranceAmount',
title: '保险费用'
},
{
field: 'insuranceUrl',
title: '保险条例url'
},
{
field: 'remark',
title: '备注'
},
{
title: '操作',
align: 'center',
formatter: function(value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.id + '\')"><i class="fa fa-remove"></i>删除</a>');
return actions.join('');
}
}]
};
$.table.init(options);
});
</script>
</body>
</html>

View File

@ -2,8 +2,14 @@
<html lang="en" xmlns:th="http://www.thymeleaf.org"> <html lang="en" xmlns:th="http://www.thymeleaf.org">
<head> <head>
<th:block th:include="include :: header('模板新增')"/> <th:block th:include="include :: header('模板新增')"/>
<th:block th:include="include :: layout-latest-css"/>
<th:block th:include="include :: bootstrap-fileinput-css"/>
<style> <style>
body {
padding: 0 !important;
}
.pane1 { .pane1 {
padding-bottom: 0; padding-bottom: 0;
} }
@ -14,6 +20,7 @@
.template-div { .template-div {
display: inline-block; display: inline-block;
margin-right: 10px;
} }
.template-body { .template-body {
@ -67,9 +74,44 @@
color: red; color: red;
font-size: large; font-size: large;
} }
.multiply-symbol {
font-size: large;
text-align: center;
}
.goodsNumList {
padding: 5px 8px 14px 5px;
min-height: 40px;
border: 1px solid #dcdfe6;
box-sizing: border-box;
border-radius: 4px;
}
.oneGoodsNumList {
padding: 5px 8px 5px 5px;
min-height: 40px;
border: 1px solid #dcdfe6;
box-sizing: border-box;
border-radius: 4px;
}
.goodsNum {
margin: 2px 0;
height: 24px;
}
#categoryCxSelect {
z-index: 101
}
#categoryCxSelect .eo-cascader-menu:nth-child(-n+3) .has-child label {
display: none;
}
</style> </style>
<th:block th:include="include :: datetimepicker-css" /> <th:block th:include="include :: datetimepicker-css" />
<link rel="stylesheet" href="../../../static/css/cascader.css" th:href="@{/css/cascader.css}">
</head> </head>
<body class="gray-bg"> <body class="gray-bg">
<form id="addTemplateForm"> <form id="addTemplateForm">
@ -89,22 +131,24 @@
<div class="form-horizontal m"> <div class="form-horizontal m">
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label is-required">服务类目:</label> <label class="col-sm-2 control-label is-required">服务类目:</label>
<div id="categoryCxSelect" class="col-sm-6 row"> <div class="col-sm-6" style="padding-right: 0">
<div class="col-sm-3"> <div id="categoryCxSelect" class="cascader-wrap">
<select class="category1 form-control m-b" name="category1" required></select> <!-- <div class="col-sm-3">-->
</div> <!-- <select class="category1 form-control m-b" name="category1" required></select>-->
<div class="col-sm-3"> <!-- </div>-->
<select class="category2 form-control m-b" name="category2" required></select> <!-- <div class="col-sm-3">-->
</div> <!-- <select class="category2 form-control m-b" name="category2" required></select>-->
<div class="col-sm-3"> <!-- </div>-->
<select class="category3 form-control m-b" name="category3" required></select> <!-- <div class="col-sm-3">-->
</div> <!-- <select class="category3 form-control m-b" name="category3" required></select>-->
<div class="col-sm-3"> <!-- </div>-->
<select class="category4 form-control m-b" name="category4" required></select> <!-- <div class="col-sm-3">-->
<!-- <select class="category4 form-control m-b" name="category4" required></select>-->
<!-- </div>-->
</div> </div>
</div> </div>
<div class="col-sm-1">×</div> <div class="col-sm-1 multiply-symbol">×</div>
<div class="col-sm-1"> <div id="goodsNumList" class="col-sm-1 oneGoodsNumList">
<input type="number" name="goodsNum" class="form-control" required> <input type="number" name="goodsNum" class="form-control" required>
</div> </div>
</div> </div>
@ -131,20 +175,17 @@
<div class="col-sm-4"> <div class="col-sm-4">
<div class="input-group date"> <div class="input-group date">
<span class="input-group-addon"><i class="fa fa-calendar"></i></span> <span class="input-group-addon"><i class="fa fa-calendar"></i></span>
<input type="text" class="form-control" id="servDate" name="servDate" required> <input type="text" class="form-control" id="servDate" name="servDate" required readonly style="background: white;">
</div> </div>
</div> </div>
<div class="col-sm-4"> <div class="col-sm-4">
<select class="form-control" name="servTime" required> <select class="form-control" name="servTime" required>
<option value="8:00-12:00">8:00-12:00</option> <option value="08:00-10:00">08:00-10:00</option>
<option value="8:00-12:00">12:00-16:00</option> <option value="10:00-12:00">10:00-12:00</option>
<option value="8:00-12:00">16:00-20:00</option> <option value="12:00-14:00">12:00-14:00</option>
<option value="8:00-12:00">8:00-10:00</option> <option value="14:00-16:00">14:00-16:00</option>
<option value="8:00-12:00">10:00-12:00</option> <option value="16:00-18:00">16:00-18:00</option>
<option value="8:00-12:00">12:00-14:00</option> <option value="18:00-20:00">18:00-20:00</option>
<option value="8:00-12:00">14:00-16:00</option>
<option value="8:00-12:00">16:00-18:00</option>
<option value="8:00-12:00">18:00-20:00</option>
</select> </select>
</div> </div>
</div> </div>
@ -159,26 +200,27 @@
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label is-required">图片上传:</label> <label class="col-sm-2 control-label is-required">图片上传:</label>
<div class="col-sm-8"> <div class="col-sm-8">
<div class="file-loading"> <input type="text" name="imageUrl" value="" hidden>
<input id="multipleFile" name="files" type="file" multiple> <input type="file" name="imageUrlStr" id="imageUrlStr" multiple class="file" />
</div>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label is-required">服务地址:</label> <label class="col-sm-2 control-label is-required">服务地址:</label>
<div id="areaCxSelect" class="col-sm-6 row"> <div class="col-sm-6">
<div class="col-sm-3"> <div id="areaCxSelect" class="cascader-wrap">
<select class="province form-control m-b" name="province" id="province" required onchange="selectRegion('province', 'city')"></select> <!-- <div class="col-sm-3">-->
</div> <!-- <select class="province form-control m-b" name="province" id="province" required onchange="selectRegion('province', 'city')"></select>-->
<div class="col-sm-3"> <!-- </div>-->
<select class="city form-control m-b" name="city" id="city" required onchange="selectRegion('city', 'district')"></select> <!-- <div class="col-sm-3">-->
</div> <!-- <select class="city form-control m-b" name="city" id="city" required onchange="selectRegion('city', 'district')"></select>-->
<div class="col-sm-3"> <!-- </div>-->
<select class="district form-control m-b" name="district" id="district" required onchange="selectRegion('district', 'street')"></select> <!-- <div class="col-sm-3">-->
</div> <!-- <select class="district form-control m-b" name="district" id="district" required onchange="selectRegion('district', 'street')"></select>-->
<div class="col-sm-3"> <!-- </div>-->
<select class="street form-control m-b" name="streetId" id="streetId" required></select> <!-- <div class="col-sm-3">-->
<!-- <select class="street form-control m-b" name="streetId" id="streetId" required></select>-->
<!-- </div>-->
</div> </div>
</div> </div>
</div> </div>
@ -201,15 +243,15 @@
<div class="form-group"> <div class="form-group">
<label class="col-sm-2 control-label is-required">下单模式:</label> <label class="col-sm-2 control-label is-required">下单模式:</label>
<div class="col-sm-8 row"> <div class="col-sm-8 row" id="orderModeRadioGroup">
<div class="col-sm-2"> <div class="col-sm-2">
<label><input type="radio" checked="" value="1" name="orderMode"> 带价发布</label> <label><input type="radio" value="02" name="orderMode" checked > 带价发布</label>
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
<label><input type="radio" value="2" name="orderMode"> 一票价发布</label> <label><input type="radio" value="01" name="orderMode"> 一票价发布</label>
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
<label><input type="radio" value="3" name="orderMode"> 回收模式</label> <label><input type="radio" value="03" name="orderMode"> 回收模式</label>
</div> </div>
</div> </div>
</div> </div>
@ -230,7 +272,7 @@
</div> </div>
<div class="col-sm-2"> <div class="col-sm-2">
<div class="input-group"> <div class="input-group">
<input type="text" name="informationFee" class="form-control" required placeholder="信息费"> <input type="text" name="informationFee" class="form-control" placeholder="信息费">
<div class="input-group-btn"> <div class="input-group-btn">
<button data-toggle="dropdown" class="btn btn-white dropdown-toggle dropdown-btn" type="button" id="informationFeeUnit">单位<span class="caret"></span></button> <button data-toggle="dropdown" class="btn btn-white dropdown-toggle dropdown-btn" type="button" id="informationFeeUnit">单位<span class="caret"></span></button>
<ul class="dropdown-menu pull-right"> <ul class="dropdown-menu pull-right">
@ -300,11 +342,15 @@
<span class="yuan-symbol">¥</span> <span class="yuan-symbol">¥</span>
<span class="yuan-symbol" id="totalMoney">0</span> <span class="yuan-symbol" id="totalMoney">0</span>
</div> </div>
<div class="oper-banner-end col-sm-5"> <div class="oper-banner-end col-sm-5" >
<div class="m-r"> <div class="m-r">
<div class="checkbox"> <div class="checkbox">
<label> <a href="#" shiro:hasPermission="consult:order:add"><input id="consultOrder" type="checkbox" value="02" name="consultOrder" onclick="changeConsultOrder(this)" >合约订单</a>
<input type="checkbox" value="1" name="isPayOffline">线下到付</label> </div>
</div>
<div class="m-r">
<div class="checkbox">
<label><input id="payOnDoorMode" type="checkbox" value="02" name="payMode" onclick="changePayOnDoorMode(this)">上门到付/保外单</label>
</div> </div>
</div> </div>
<div class="m-r"> <div class="m-r">
@ -320,10 +366,33 @@
</form> </form>
<th:block th:include="include :: footer"/> <th:block th:include="include :: footer"/>
<th:block th:include="include :: layout-latest-js"/>
<th:block th:include="include :: jquery-cxselect-js" /> <th:block th:include="include :: jquery-cxselect-js" />
<th:block th:include="include :: datetimepicker-js" /> <th:block th:include="include :: datetimepicker-js" />
<th:block th:include="include :: bootstrap-fileinput-js"/>
<script th:src="@{/js/plugins/miniCascader/cascader.js}"></script>
<script th:src="@{/data/four-level-area.js}"></script>
<script type="text/javascript"> <script type="text/javascript">
// 级联下拉
let categoryCascader = new eo_cascader([], {
elementID: 'categoryCxSelect',
multiple: true, // 是否多选
separator: '-', // 分割符 山西-太原-小店区 || 山西/太原/小店区
clearable: true, // 是否可一键删除已选
value: 'goodsCategoryId',
label: 'goodsCategoryName',
children: 'child',
checkedCallback: checkedCategoryCallback
});
let areaCascader = new eo_cascader(fourLevelAreaList, {
elementID: 'areaCxSelect',
multiple: false, // 是否多选
separator: '-', // 分割符 山西-太原-小店区 || 山西/太原/小店区
clearable: false, // 是否可一键删除已选
value: 'areaId',
label: 'areaName',
children: 'child'
});
$(function(){ $(function(){
var icon = "<i class='fa fa-times-circle'></i> "; var icon = "<i class='fa fa-times-circle'></i> ";
// $("#addTemplateForm").validate({ // $("#addTemplateForm").validate({
@ -333,7 +402,6 @@
// } // }
// }); // });
// 级联下拉
$.ajax({ $.ajax({
type: "POST", type: "POST",
dataType:"json", dataType:"json",
@ -342,36 +410,47 @@
contentType: 'application/json', contentType: 'application/json',
success: function (result) { success: function (result) {
if (result.code == web_status.SUCCESS) { if (result.code == web_status.SUCCESS) {
$('#categoryCxSelect').cxSelect({ <!-- $('#categoryCxSelect').cxSelect({-->
selects: ['category1', 'category2', 'category3', 'category4'], <!-- selects: ['category1', 'category2', 'category3', 'category4'],-->
jsonValue: 'deptGoodsCategoryId', <!-- jsonValue: 'deptGoodsCategoryId',-->
jsonName: 'goodsCategoryName', <!-- jsonName: 'goodsCategoryName',-->
jsonSub: 'child', <!-- jsonSub: 'child',-->
data: result.data <!-- data: result.data-->
}); <!-- });-->
categoryCascader = new eo_cascader(result.data, {
elementID: 'categoryCxSelect',
multiple: true, // 是否多选
checkedValue: null,
separator: '-', // 分割符 山西-太原-小店区 || 山西/太原/小店区
clearable: true, // 是否可一键删除已选
value: 'deptGoodsCategoryId',
label: 'goodsCategoryName',
children: 'child',
checkedCallback: checkedCategoryCallback
})
} else { } else {
$.modal.msgError("数据加载错误,请重试!") $.modal.msgError("数据加载错误,请重试!")
} }
} }
}) })
$.ajax({ <!-- $.ajax({-->
type: "POST", <!-- type: "POST",-->
dataType:"json", <!-- dataType:"json",-->
url: ctx + "system/area/list", <!-- url: ctx + "system/area/list",-->
success: function (result) { <!-- success: function (result) {-->
if (result.code == web_status.SUCCESS) { <!-- if (result.code == web_status.SUCCESS) {-->
$('#areaCxSelect').cxSelect({ <!-- $('#areaCxSelect').cxSelect({-->
selects: ['province', 'city', 'district', 'street'], <!-- selects: ['province', 'city', 'district', 'street'],-->
jsonValue: 'areaId', <!-- jsonValue: 'areaId',-->
jsonName: 'areaName', <!-- jsonName: 'areaName',-->
data: result.data <!-- data: result.data-->
}); <!-- });-->
} else { <!-- } else {-->
$.modal.msgError("数据加载错误,请重试!") <!-- $.modal.msgError("数据加载错误,请重试!")-->
} <!-- }-->
} <!-- }-->
}) <!-- })-->
$("#servDate").datetimepicker({ $("#servDate").datetimepicker({
format: "yyyy-mm-dd", format: "yyyy-mm-dd",
@ -409,44 +488,156 @@
// }) // })
}); });
function checkedCategoryCallback() {
let checkedIdArr = categoryCascader.getCheckedByID();
if (checkedIdArr && checkedIdArr.length > 0) {
$('#goodsNumList').html(null);
$('#goodsNumList').removeClass('oneGoodsNumList');
$('#goodsNumList').addClass('goodsNumList');
checkedIdArr.forEach(function(id, index) {
$('#goodsNumList').append('<input type="number" name="goodsNum' + id + '" class="form-control goodsNum" required>');
});
} else {
$('#goodsNumList').removeClass('goodsNumList');
$('#goodsNumList').addClass('oneGoodsNumList');
$('#goodsNumList').html('<input type="number" name="goodsNum" class="form-control" required>');
}
}
function changeInformationFeeUnit(unit) { function changeInformationFeeUnit(unit) {
this.$('#informationFeeUnit').html(unit + '<span class="caret"></span>'); this.$('#informationFeeUnit').html(unit + '<span class="caret"></span>');
} }
function selectRegion(regionLevelName, nextRegionLevelName) { <!-- function selectRegion(regionLevelName, nextRegionLevelName) {-->
var regionId = $("#" + regionLevelName).val(); <!-- var regionId = $("#" + regionLevelName).val();-->
if ($.common.isEmpty(regionId)) { <!-- if ($.common.isEmpty(regionId)) {-->
return; <!-- return;-->
} <!-- }-->
//Ajax调用处理 <!-- //Ajax调用处理-->
$.ajax({ <!-- $.ajax({-->
type: "POST", <!-- type: "POST",-->
dataType:"json", <!-- dataType:"json",-->
url: ctx + "system/area/list", <!-- url: ctx + "system/area/list",-->
data: {parentCode: regionId}, <!-- data: {parentCode: regionId},-->
success: function (result) { <!-- success: function (result) {-->
if (result.code == web_status.SUCCESS) { <!-- if (result.code == web_status.SUCCESS) {-->
$('#areaCxSelect').cxSelect({ <!-- $('#areaCxSelect').cxSelect({-->
selects: [nextRegionLevelName], <!-- selects: [nextRegionLevelName],-->
jsonValue: 'areaId', <!-- jsonValue: 'areaId',-->
jsonName: 'areaName', <!-- jsonName: 'areaName',-->
data: result.data <!-- data: result.data-->
}); <!-- });-->
} else { <!-- } else {-->
$.modal.msgError("数据加载错误,请重试!") <!-- $.modal.msgError("数据加载错误,请重试!")-->
} <!-- }-->
} <!-- }-->
}) <!-- })-->
<!-- }-->
function changeConsultOrder(e){
if ($(e).is(':checked')) {
$('#consultOrder').prop("value", '01');
} else {
$('#consultOrder').prop("value", '02');
}
} }
function changePayOnDoorMode(e) {
if ($(e).is(':checked')) {
$('#payOnDoorMode').prop("value", '01');
} else {
$('#payOnDoorMode').prop("value", '02');
}
}
function validSpecialComponent() {
// 类目
let categoryIds = categoryCascader.getCheckedByID();
if (!categoryIds || categoryIds.length === 0) {
$.modal.msgError("服务类目不能为空")
return false;
}
// 图片是否上传
if (!$('input[name=imageUrl]').val()) {
$.modal.msgError("图片未上传")
return false;
}
// 地区
let checkedAreaPathList = areaCascader.getCheckedPaths();
if (!checkedAreaPathList || checkedAreaPathList.length === 0) {
$.modal.msgError("服务地址不能为空")
return false;
}
// 下单模式
if (!$('#orderModeRadioGroup input[name=orderMode]').is(':checked')) {
$.modal.msgError("请录入完整必填信息")
return false;
}
return true;
}
function translateForm(data) {
var params = {};
data.forEach(function (item){
params[item.name] = item.value;
});
let categoryIds = categoryCascader.getCheckedByID();
let orderGoodsStandards = [];
categoryIds.forEach(function (item){
orderGoodsStandards.push({
deptCategoryId: item,
goodsStandardNum: $(".goodsNum[name=goodsNum" + item + "]").val()
});
});
params.orderGoodsStandards = orderGoodsStandards;
params.categoryId1 = categoryCascader.getCheckedPaths()[0][0];
params.categoryId2 = categoryCascader.getCheckedPaths()[0][1];
params.categoryId3 = categoryCascader.getCheckedPaths()[0][2];
params.provinceId = areaCascader.getCheckedPaths()[0][0];
params.cityId = areaCascader.getCheckedPaths()[0][1];
params.districtId = areaCascader.getCheckedPaths()[0][2];
params.streetId = areaCascader.getCheckedPaths()[0][3];
params.payMode = $('#payOnDoorMode').val();
params.consultMode = $('#consultOrder').val();
return params;
}
// 营业执照上传
$('#imageUrlStr').fileinput({
language: 'zh', //设置语言
dropZoneEnabled: false, //是否显示拖拽区域
showPreview: false,
uploadExtraData: {
"name": "imageUrlStr"
},
dropZoneTitle: "可以将图片拖放到这里", //拖拽区域显示文字
uploadUrl: ctx + 'tool/qiniu/dept/upload', //上传路径
allowedFileExtensions: ['jpg', 'png', 'gif', 'jpeg'], //指定上传文件类型
maxFileSize: 0,
maxFileSize: 2048, //上传文件最大值单位kb
uploadAsync: true, //异步上传
maxFileCount: 2 //上传文件最大个数。
}).on("fileuploaded", function(event,data) { //异步上传成功后回调
if(data.response.code === 0){
$("input[name='imageUrl']").val(data.response.url)
}else {
alert("上传失败!");
}
});
function submitOrder() { function submitOrder() {
if (!validSpecialComponent()) return;
if ($.validate.form()) { if ($.validate.form()) {
var data = $("#addTemplateForm").serializeArray(); var data = $("#addTemplateForm").serializeArray();
var params= {}; var params= translateForm(data);
data.forEach(function (item){
params[item.name] = item.value;
});
$.ajax({ $.ajax({
type: "POST", type: "POST",
@ -456,22 +647,37 @@
contentType: 'application/json', contentType: 'application/json',
success: function (result) { success: function (result) {
if (result.code == web_status.SUCCESS) { if (result.code == web_status.SUCCESS) {
$.modal.msgSuccess("提交成功") layer.open({
type: 0,
area: ['250px', '180px'],
fix: false,
//不固定
maxmin: true,
shade: 0.3,
title: '系统通知',
content: '发单成功,是否前往发单管理?',
btn: ['确定','继续下单'],
// 弹层外区域关闭
shadeClose: true,
yes: function(index) {
$.modal.parentTab('发单管理', 'order/master/pc');
}
});
} else { } else {
$.modal.msgError("请求失败") $.modal.msgError(result.msg)
} }
} }
}) })
} else {
$.modal.msgError("请录入完整必填信息")
} }
} }
function addTemplate() { function addTemplate() {
if (!validSpecialComponent()) return;
if ($.validate.form()) { if ($.validate.form()) {
var data = $("#addTemplateForm").serializeArray(); var data = $("#addTemplateForm").serializeArray();
var params= {}; var params= translateForm(data);
data.forEach(function (item){
params[item.name] = item.value;
});
$.ajax({ $.ajax({
type: "POST", type: "POST",
@ -483,7 +689,7 @@
if (result.code == web_status.SUCCESS) { if (result.code == web_status.SUCCESS) {
$.modal.msgSuccess("提交成功") $.modal.msgSuccess("提交成功")
} else { } else {
$.modal.msgError("请求失败") $.modal.msgError(result.msg)
} }
} }
}) })

View File

@ -30,7 +30,7 @@
<script th:src="@{/ajax/libs/validate/jquery.validate.extend.js?v=1.19.3}"></script> <script th:src="@{/ajax/libs/validate/jquery.validate.extend.js?v=1.19.3}"></script>
<script th:src="@{/ajax/libs/validate/messages_zh.js?v=1.19.3}"></script> <script th:src="@{/ajax/libs/validate/messages_zh.js?v=1.19.3}"></script>
<!-- bootstrap-table 表格树插件 --> <!-- bootstrap-table 表格树插件 -->
<script th:src="@{/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.min.js?v=1.18.3}"></script> <script th:src="@{/ajax/libs/bootstrap-table/extensions/tree/bootstrap-table-tree.js?v=1.18.3}"></script>
<!-- 遮罩层 --> <!-- 遮罩层 -->
<script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js?v=2.70.0}"></script> <script th:src="@{/ajax/libs/blockUI/jquery.blockUI.js?v=2.70.0}"></script>
<script th:src="@{/ajax/libs/iCheck/icheck.min.js?v=1.0.3}"></script> <script th:src="@{/ajax/libs/iCheck/icheck.min.js?v=1.0.3}"></script>

View File

@ -4,7 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<title>工圈子管理系统</title> <title>管理系统</title>
<!-- 避免IE使用兼容模式 --> <!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<link th:href="@{favicon.ico}" rel="shortcut icon"/> <link th:href="@{favicon.ico}" rel="shortcut icon"/>
@ -26,7 +26,7 @@
</div> </div>
<a th:href="@{/index}"> <a th:href="@{/index}">
<li class="logo hidden-xs"> <li class="logo hidden-xs">
<span class="logo-lg">工圈子</span> <span class="logo-lg">后台系统</span>
</li> </li>
</a> </a>
<div class="sidebar-collapse"> <div class="sidebar-collapse">

View File

@ -3,8 +3,8 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>追风者</title> <title>叮咚工链</title>
<meta name="description" content="叮咚工链后台管理框架"> <meta name="description" content="后台管理框架">
<link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/> <link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/> <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
<link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/> <link href="../static/css/style.min.css" th:href="@{/css/style.min.css}" rel="stylesheet"/>
@ -26,14 +26,13 @@
<div class="col-sm-7"> <div class="col-sm-7">
<div class="signin-info"> <div class="signin-info">
<div class="logopanel m-b"> <div class="logopanel m-b">
<h1>[ 叮咚工链 ]</h1> <h1>[ 后台管理系统 ]</h1>
</div> </div>
<div class="m-b"></div> <div class="m-b"></div>
<h4>欢迎使用 <strong>叮咚工链 后台管理系统</strong></h4> <h4>欢迎使用 <strong>后台管理系统</strong></h4>
<ul class="m-b"> <ul class="m-b">
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 再多平方米</li> <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 再多平方米</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 不如我懂你</li> <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 不如我懂你</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 叮咚工链</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 在你需要的时候</li> <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 在你需要的时候</li>
<li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 总在您身边</li> <li><i class="fa fa-arrow-circle-o-right m-r-xs"></i> 总在您身边</li>
</ul> </ul>
@ -65,8 +64,9 @@
</div> </div>
<div class="signup-footer"> <div class="signup-footer">
<div class="pull-left"> <div class="pull-left">
Copyright © 2018-2021 opsoul.com All Rights Reserved. <br> Copyright © 2018-2021 gmjlb.com All Rights Reserved. <br>
备案号 粤ICP备2021044349号-1 <a href="https://beian.miit.gov.cn/" target="_blank">备案号:</a>
<a href="https://beian.miit.gov.cn/" target="_blank">桂ICP备2024024616号-3</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -4,7 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<!--360浏览器优先以webkit内核解析--> <!--360浏览器优先以webkit内核解析-->
<title>工圈子介绍</title> <title>介绍</title>
<link rel="shortcut icon" href="favicon.ico"> <link rel="shortcut icon" href="favicon.ico">
<link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/> <link href="../static/css/bootstrap.min.css" th:href="@{/css/bootstrap.min.css}" rel="stylesheet"/>
<link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/> <link href="../static/css/font-awesome.min.css" th:href="@{/css/font-awesome.min.css}" rel="stylesheet"/>
@ -22,14 +22,11 @@
<br> <br>
</div> </div>
<div class="col-sm-5"> <div class="col-sm-5">
<h2>工圈子后台管理框架</h2> <h2>后台管理框架</h2>
<p>一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了工圈子管理系统。她可以用于所有的Web应用程序<b>网站管理后台</b><b>网站会员中心</b><b>CMS</b><b>CRM</b><b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。</p> <p>一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了管理系统。她可以用于所有的Web应用程序<b>网站管理后台</b><b>网站会员中心</b><b>CMS</b><b>CRM</b><b>OA</b>等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。</p>
<p> <p>
<b>当前版本:</b><span>v[[${version}]]</span> <b>当前版本:</b><span>v[[${version}]]</span>
</p> </p>
<p>
<span class="label label-warning">叮咚链家</span>
</p>
<br> <br>
</div> </div>
<div class="col-sm-4"> <div class="col-sm-4">

View File

@ -0,0 +1,289 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<th:block th:include="include :: header('指派师傅')"/>
<th:block th:include="include :: layout-latest-css"/>
<style>
.custom-container {
padding: 0 30px 20px 30px;
}
.flex-board {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
}
.flex-board-no-wrap {
display: flex;
justify-content: flex-start;
align-items: center;
}
.flex-board.select-content {
flex-basis: 100%
}
.flex-board.select-content .flex-board-no-wrap {
flex-basis: 90%
}
.flex-board.input-content {
flex-basis: 50%;
}
.flex-board.input-content input {
flex-basis: 75%
}
.specCanAssignNum {
text-align: center;
line-height: 31px;
}
</style>
</head>
<body class="gray-bg">
<div class="animated fadeInRight row custom-container">
<div class="col-sm-12 search-collapse">
<form class="m" id="canAssignSpecForm">
<div id="canAssignSpecList" class="m-b">
</div>
<div class="row">
<div class="col-sm-4">
<span>派单金额:</span>
<span id="moneyCanAssign"></span>
<span></span>
</div>
<!-- <div class="col-sm-5">-->
<!-- <div class="flex-board input-content">-->
<!-- <label class="form-control-label">派出金额:</label>-->
<!-- <input name="totalPay" type="number" class="form-control">-->
<!-- </div>-->
<!-- </div>-->
</div>
</form>
</div>
<div class="col-sm-12 search-collapse">
<form class="flex-board m" id="workerForm">
<div class="flex-board select-content m-t">
<label class="form-control-label">区域筛选:</label>
<div id="areaCxSelect" class="flex-board-no-wrap">
<select class="province form-control cx-select-input m-r" name="province" id="province" data-first-title="选择省" onchange="selectRegion('province', 'city')"></select>
<select class="city form-control cx-select-input m-r" name="city" id="city" data-first-title="选择市" onchange="selectRegion('city', 'district')"></select>
<select class="district form-control cx-select-input m-r" name="areaId" id="district" data-first-title="选择区" onchange="selectRegion('district', 'street')"></select>
<select class="street form-control cx-select-input m-r" name="streetId" id="streetId" data-first-title="选择街道" ></select>
</div>
</div>
<div class="flex-board select-content m-t">
<label class="form-control-label">类别筛选:</label>
<div id="categoryCxSelect" class="flex-board-no-wrap">
<select class="category1 form-control cx-select-input m-r" name="category1" id="category1" data-first-title="选择一类"></select>
<select class="category2 form-control cx-select-input m-r" name="category2" id="category2" data-first-title="选择二类"></select>
<select class="category3 form-control cx-select-input m-r" name="goodsCategoryId" id="category3" data-first-title="选择三类"></select>
<select class="category4 form-control cx-select-input m-r" name="category4" id="category4" data-first-title="选择四类" ></select>
</div>
</div>
<div class="flex-board input-content m-t">
<label class="form-control-label">名称/手机号:</label>
<input name="keyWords" type="text" class="form-control normal-input m-r">
</div>
<div class="m-t">
<a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search('workerForm')"><i
class="fa fa-search"></i>&nbsp;搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset('workerForm')"><i
class="fa fa-refresh"></i>&nbsp;重置</a>
</div>
</form>
</div>
<div class="col-sm-12 select-table table-striped">
<table id="bootstrap-table"></table>
</div>
</div>
<th:block th:include="include :: footer"/>
<th:block th:include="include :: jquery-cxselect-js" />
<script type="text/javascript">
var orderMasterId = '[[${orderId}]]';
var prefix = ctx + "worker"
$(function () {
loadCanAssignSpecInfo();
initForm();
initTable();
});
function loadCanAssignSpecInfo() {
$.ajax({
type: "POST",
dataType:"json",
url: ctx + "order/can/assign",
data: JSON.stringify({orderMasterId: orderMasterId}),
contentType: 'application/json',
success: function (result) {
if (result.code == web_status.SUCCESS) {
$('#canAssignSpecList').html('');
$.each(result.data, function(index, spec) {
$('#canAssignSpecList').append(
'<div class="row m-b">' +
' <div class="col-sm-6">' +
' <input disabled class="form-control" value="' + spec.goodsName +'">' +
' </div>' +
' <div class="col-sm-2 specCanAssignNum">' +
spec.goodsNum +
' </div>' +
'</div>'
)
});
} else {
$.modal.msgError("数据加载错误,请重试!")
}
}
})
$.ajax({
type: "POST",
dataType:"json",
url: ctx + "order/master/app/detail",
data: JSON.stringify({id: orderMasterId}),
contentType: 'application/json',
success: function (result) {
if (result.code == web_status.SUCCESS) {
$('#moneyCanAssign').html(result.data.serverMoney);
} else {
$.modal.msgError("数据加载错误,请重试!")
}
}
})
}
function initForm() {
$.ajax({
type: "POST",
dataType:"json",
url: ctx + "system/area/list",
success: function (result) {
if (result.code == web_status.SUCCESS) {
$('#areaCxSelect').cxSelect({
selects: ['province', 'city', 'district', 'street'],
jsonValue: 'areaId',
jsonName: 'areaName',
data: result.data
});
} else {
$.modal.msgError("数据加载错误,请重试!")
}
}
})
$.ajax({
type: "POST",
dataType:"json",
url: ctx + "goods/deptcategory/app/list",
data: JSON.stringify({deptId: 101, goodsCategoryId: 1}),
contentType: 'application/json',
success: function (result) {
if (result.code == web_status.SUCCESS) {
$('#categoryCxSelect').cxSelect({
selects: ['category1', 'category2', 'category3', 'category4'],
jsonValue: 'goodsCategoryId',
jsonName: 'goodsCategoryName',
jsonSub: 'child',
data: result.data
});
} else {
$.modal.msgError("数据加载错误,请重试!")
}
}
})
}
function initTable() {
var options = {
url: prefix + "/list",
modalName: "师傅派单列表",
firstLoad: false,
columns: [
{
checkbox: true
}, {
field: 'name',
title: '人员名称',
align: "left"
}, {
field: 'phone',
title: '手机号',
align: "left"
}, {
title: '操作',
align: 'left',
formatter: function (value, row, index) {
var actions = [];
actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="assign(' + row.workerId + ')">指派</a> ');
return actions.join('');
}
}
]
};
$.table.init(options);
$.table.search('workerForm');
}
function selectRegion(regionLevelName, nextRegionLevelName) {
var regionId = $("#" + regionLevelName).val();
if ($.common.isEmpty(regionId)) {
return;
}
//Ajax调用处理
$.ajax({
type: "POST",
dataType:"json",
url: ctx + "system/area/list",
data: {parentCode: regionId},
success: function (result) {
if (result.code == web_status.SUCCESS) {
$('#areaCxSelect').cxSelect({
selects: [nextRegionLevelName],
jsonValue: 'areaId',
jsonName: 'areaName',
data: result.data
});
} else {
$.modal.msgError("数据加载错误,请重试!")
}
}
})
}
function assign(workerId) {
var params = {
id: orderMasterId,
workerId: workerId,
orderStatus: 0
};
$.ajax({
type: "POST",
dataType:"json",
url: ctx + "order/master/editOrderMaster",
data: JSON.stringify(params),
contentType: 'application/json',
success: function (result) {
if (result.code == web_status.SUCCESS) {
$.modal.msgSuccess("指派成功")
parent.layer.close(parent.layer.getFrameIndex(window.name));
} else {
$.modal.msgError("指派失败")
}
}
})
}
</script>
</body>
</html>

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('批量改价')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-change-price">
<input name="orderIds" type="hidden" th:value="${orderIds}" />
<div class="form-group">
<label class="col-sm-3 control-label">输入修改后价格:</label>
<div class="col-sm-8">
<input class="form-control" type="text" name="changePrice" id="changePrice">
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script type="text/javascript">
$("#changePrice").validate({
rules:{
changePrice:{
required:true
},
}
});
function submitHandler() {
if ($.validate.form()) {
$.operate.save(ctx + "order/master/batchChangePrice", $('#form-change-price').serialize());
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
<head>
<th:block th:include="include :: header('选择保险')" />
</head>
<body class="white-bg">
<div class="wrapper wrapper-content animated fadeInRight ibox-content">
<form class="form-horizontal m" id="form-change-insurance">
<input name="orderMasterIds" type="hidden" th:value="${orderIds}" />
<div class="form-group">
<label class="col-sm-3 control-label">保险:</label>
<div class="col-sm-8">
<select id="insuranceId" name="insuranceId" class="form-control control-label" required>
<option th:each="insurance:${insurances}" th:value="${insurance.id}" th:text="${insurance.insuranceName}" ></option>
</select>
</div>
</div>
</form>
</div>
<th:block th:include="include :: footer" />
<script type="text/javascript">
function submitHandler() {
if ($.validate.form()) {
$.operate.save(ctx + "order/master/pcOrderWorker/batchChangeInsurance", $('#form-change-insurance').serialize());
}
}
</script>
</body>
</html>

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