Compare commits

...

371 Commits

Author SHA1 Message Date
lzh
4098d590bf Merge branch 'dev-lzh-1009' 2025-10-10 10:35:31 +08:00
lzh
db58773aea 新增使用类型字段 2025-10-10 10:29:46 +08:00
b2a96ad465 Merge branch 'feature-costType-daiyb' 2025-10-10 09:18:42 +08:00
6702083fd6 修改字段 2025-10-10 09:11:30 +08:00
5da9d19112 Merge branch 'main' of http://gitea.tools.fontree.cn:3000/fiee/fonchain-fiee 2025-10-10 08:54:15 +08:00
lzh
87d46af603 更新proto文件 2025-10-09 17:11:33 +08:00
15072f9e49 导出 2025-10-09 14:45:16 +08:00
sxy
c72d45c020 修改图片传入类型判断 2025-09-28 20:46:27 +08:00
sxy
f3c5cbff2a 导入修改-1 2025-09-28 19:17:19 +08:00
ebe59394cf Merge branch 'feature-tiktok-daiyb' 2025-09-28 19:14:10 +08:00
5746dab3e0 添加更新视频的过滤字段 2025-09-28 19:13:58 +08:00
6c4aeb8193 Merge branch 'feature-tiktok-daiyb' 2025-09-28 17:55:32 +08:00
7200099204 更新字段 2025-09-28 17:55:17 +08:00
c70c5913d4 Update README.md 2025-09-28 15:09:42 +08:00
JNG
414735bc54 Merge branch 'jng-0924' 2025-09-28 15:09:08 +08:00
JNG
3f5e4e3bc8 Update reconciliation.go 2025-09-28 15:08:45 +08:00
JNG
af4c370b84 Merge branch 'jng-0924' 2025-09-28 14:42:13 +08:00
JNG
9f7e2d1667 Update reconciliation.go 2025-09-28 14:41:24 +08:00
lzh
557739aeff 更新proto 2025-09-28 14:17:50 +08:00
sxy
91e1dfa196 导入修改 2025-09-28 10:53:18 +08:00
2825ca826e 合并正式 2025-09-28 10:40:08 +08:00
90d088101c 重新发布不扣除 2025-09-26 15:19:31 +08:00
24cc34462e 分类 2025-09-26 12:28:27 +08:00
9b7fbe73fd Update media.go 2025-09-26 10:54:01 +08:00
1c6172a848 更新proto 2025-09-26 09:25:09 +08:00
af7fa93b4d 修改同步 2025-09-25 16:41:08 +08:00
48dea8eaac 是否授权 2025-09-25 15:56:33 +08:00
sxy
761b9b656b Merge branch 'feat-sxy-import919' 2025-09-25 13:47:13 +08:00
sxy
e2d87cb5e0 导入修改 2025-09-25 13:46:27 +08:00
6a6bd459e6 Update conf.ini 2025-09-25 11:12:59 +08:00
47473df3be Update work.go 2025-09-24 17:16:10 +08:00
fd908ec72b Update work.go 2025-09-24 16:49:48 +08:00
JNG
6e6f159b23 Update reconciliation.go 2025-09-24 16:07:23 +08:00
97f79df433 Update media.go 2025-09-24 11:58:22 +08:00
e037f91507 Update media.go 2025-09-24 11:56:42 +08:00
b35278771e 跳转 2025-09-24 11:47:16 +08:00
38e7e1aac6 fix: 自动刷订单的,过期时间10年变1年 2025-09-23 16:20:21 +08:00
sxy
e33aaac2b9 导入日志shuhcu 2025-09-22 18:31:51 +08:00
sxy
430304cd1e 导入修改url-1 2025-09-22 18:27:00 +08:00
sxy
b4520ccf94 导入修改url 2025-09-22 17:03:18 +08:00
sxy
74b5c28cc4 修改配置文件-1 2025-09-22 16:42:08 +08:00
4dba6c7669 视频封面 2025-09-22 16:41:40 +08:00
8271683614 添加信息查询 2025-09-22 16:29:38 +08:00
sxy
26a4fe0413 修改配置文件 2025-09-22 16:27:38 +08:00
sxy
be7e522219 导入不删除源文件 2025-09-22 15:40:52 +08:00
sxy
fcb33cc715 fiee第二次导入修改 2025-09-22 13:37:31 +08:00
sxy
3cb95a8f65 fiee第二次空指针修改 2025-09-22 11:47:55 +08:00
sxy
5dc0b1cbf5 fiee第二次导入测试-2 2025-09-22 11:42:06 +08:00
sxy
0f6e0abf33 fiee第二次导入测试-1 2025-09-22 11:40:27 +08:00
sxy
3d13747ad9 fiee第二次导入测试 2025-09-22 11:27:29 +08:00
39ca08605e 视频发布 2025-09-22 11:12:19 +08:00
b4dd5d0778 完成视频发布 2025-09-22 10:02:44 +08:00
sxy
ef6d40cf81 单价模式增加总价 2025-09-11 14:50:42 +08:00
gy
1c3e0b8f52 feat 修改头部字段 2025-09-10 13:24:06 +08:00
gy
e85207132f feat 增加一个jwt检验的校验绕过逻辑 2025-09-09 18:51:25 +08:00
6d34d7d4f2 复制隐私文件 2025-09-03 11:48:40 +08:00
e667837d6a Merge branch 'feat-xjj-aschatFunction#A116' 2025-09-01 11:23:50 +08:00
09a4df2b21 Update handler.go 2025-09-01 11:15:26 +08:00
d20cd6d41b Merge branch 'feat-xjj-aschatFunction#A116' 2025-09-01 10:03:15 +08:00
0e1c8df1ee Update check_login.go 2025-08-28 14:45:15 +08:00
645770c9fc Update check_login.go 2025-08-28 14:08:53 +08:00
077f743e54 Update check_login.go 2025-08-28 11:01:26 +08:00
fe9173b872 Update check_login.go 2025-08-28 10:43:19 +08:00
41e28c9aed Merge branch 'jng' 2025-08-27 13:59:21 +08:00
d54a3df245 Update reconciliation.go 2025-08-27 11:29:01 +08:00
e2962353b9 更新 2025-08-27 10:23:47 +08:00
07326e3af8 feat: 增加自动回复开关 2025-08-21 14:16:51 +08:00
c135849195 Merge branch 'feature-multicast-daiyb' 2025-08-13 09:18:53 +08:00
sxy
7488f76c08 Merge branch 'feat-sxy-import' 2025-08-13 09:17:03 +08:00
sxy
bca6eb9009 修改 2025-08-12 17:02:32 +08:00
8aab8ff4e6 更新 pkg/service/upload/upload.go
增加日志
2025-08-12 06:03:27 +00:00
857b7712ae Merge branch 'jng' 2025-08-12 13:35:23 +08:00
adb956dacb update oss config 2025-08-12 11:59:31 +08:00
sxy
e7f8993fa5 记录时间和uuid 2025-08-12 10:24:48 +08:00
sxy
eaa48b9d5e 过滤特殊数据处理-1 2025-08-11 16:58:35 +08:00
sxy
bd59b2dc69 过滤特殊数据处理 2025-08-11 16:42:13 +08:00
b063a38f76 Merge branch 'jng' 2025-08-11 16:41:50 +08:00
6c4578b8aa update oss config 2025-08-11 16:27:26 +08:00
sxy
9bf59916a6 修改查询条件 2025-08-11 16:08:35 +08:00
sxy
2c49b28d0f 修改查询条件 2025-08-11 15:50:18 +08:00
sxy
3c964140f3 导入数据脚本-1 2025-08-11 15:29:54 +08:00
sxy
c20e90d45a 导入数据脚本 2025-08-11 13:29:49 +08:00
25eed16be5 添加source 2025-08-07 11:59:25 +08:00
sxy
2d7269148a 修改symbol-1 2025-07-31 14:11:20 +08:00
sxy
e9d74c99fb 修改sec symbol-1 2025-07-31 14:11:05 +08:00
sxy
512bfe4d15 修改symbol 2025-07-31 13:43:31 +08:00
sxy
d2ef31f289 修改sec symbol 2025-07-31 13:42:28 +08:00
2ff956bb30 fix: map中增加两个新金额 2025-07-17 14:23:17 +08:00
3ff698e94f Merge branch 'jng' 2025-07-16 19:27:48 +08:00
130bb26ebf 修改 2025-07-16 17:54:15 +08:00
sxy
f672ecf670 Merge branch 'sxy-sec'
"x修改symbol"
2025-07-16 10:45:46 +08:00
sxy
2220a78c19 修改官网symbol 2025-07-16 10:44:43 +08:00
36aaa0a365 fix: map中增加两个新金额 2025-07-15 10:31:53 +08:00
b86e759146 修改 2025-07-11 09:39:44 +08:00
fa468e0130 修改 2025-07-08 16:21:06 +08:00
403f065486 11 2025-07-08 16:18:46 +08:00
54326ebe01 对账单添加手续费 2025-07-08 16:13:30 +08:00
9c6f1ae832 fix: 处理pb 2025-07-08 15:22:58 +08:00
80e45457ec Merge branch 'feat-zjy-issue-013' into main
# Conflicts:
#	api/bundle/bundle.pb.go
2025-07-08 15:21:49 +08:00
6bb22e019a 修改 2025-07-08 14:57:12 +08:00
7d6f141d4e 111 2025-07-08 14:19:54 +08:00
eba1083fe7 修改 2025-07-08 14:18:26 +08:00
f36fadb1bf 修改 2025-07-08 13:51:27 +08:00
78279cbc82 修改 2025-07-08 13:40:15 +08:00
sxy
bc1bdf1fc0 Merge branch 'sxy-sec'
"官网sec文件"
2025-07-08 13:07:11 +08:00
sxy
817c685190 修改官网link 2025-07-08 13:02:54 +08:00
46957da638 fix: 提交支持自动创建用户和订单代码- 调整映射map 2025-07-08 11:59:13 +08:00
314891e85b fix: 提交支持自动创建用户和订单代码- 打印日志 2025-07-08 11:50:15 +08:00
sxy
c3009b2086 修改官网link 2025-07-08 11:47:22 +08:00
57f10eb7b9 fix: 提交支持自动创建用户和订单代码- 调整map 2025-07-08 11:17:39 +08:00
13688ddeb2 fix: 提交支持自动创建用户和订单代码-0元购的serial_number调整 2025-07-08 10:44:55 +08:00
e734fadfc6 fix: 提交支持自动创建用户和订单代码-子订单初始化的时候是未支付 2025-07-08 10:23:08 +08:00
96e3ddda46 修改 2025-07-08 09:45:50 +08:00
493624dfcb 添加excel导入 2025-07-07 19:35:54 +08:00
cdf4b77aa7 Update dubbogo.yaml 2025-07-07 15:28:30 +08:00
f6164cd455 fix: 提交支持自动创建用户和订单代码 2025-07-07 13:32:19 +08:00
lzh
7c2f3b5545 proto更新 2025-07-07 11:59:28 +08:00
173cb0af0f Merge branch 'jng' 2025-07-03 16:53:51 +08:00
d03049762f 修改 2025-07-03 16:53:08 +08:00
f1bb8d54ca Merge branch 'jng' 2025-07-03 16:12:17 +08:00
aecd26d08c 11 2025-07-03 16:05:48 +08:00
3c618f52c8 修改 2025-07-03 16:02:06 +08:00
e7b3fe54bd 修改 2025-07-03 15:50:53 +08:00
db9edc057d Merge branch 'jng' 2025-07-02 15:36:42 +08:00
a0afa6f17a 修改 2025-07-02 15:33:22 +08:00
3e003ca581 修改 2025-07-02 14:02:10 +08:00
bb7184c480 Merge branch 'feat-zjy-fixbug-003' into main 2025-06-27 17:44:55 +08:00
633c903f33 fix: 处理对账单金额问题 2025-06-27 17:43:09 +08:00
eea1b146eb Merge branch 'main' of http://172.16.100.91:3000/fiee/fonchain-fiee 2025-06-27 17:19:27 +08:00
6848e73ac6 管理人是我 2025-06-27 17:19:22 +08:00
sxy
f0c81cc22f Merge branch 'sxy-fix' 2025-06-27 15:59:45 +08:00
sxy
6406396d75 修改路由认证-1 2025-06-27 15:59:28 +08:00
b8e9353a99 Merge branch 'feat-zjy-fixbug-003' into main 2025-06-27 15:51:18 +08:00
58abfab434 fix: 处理对账单金额问题 2025-06-27 15:50:17 +08:00
8f5caf80bf 修改审批接口 2025-06-27 15:31:39 +08:00
d1181e4460 修改 2025-06-27 14:58:39 +08:00
gy
d71d77647f 1 2025-06-27 11:54:15 +08:00
sxy
7934b253b0 修改路由认证 2025-06-27 11:11:17 +08:00
sxy
5caf271d18 修改路由 2025-06-27 10:52:35 +08:00
sxy
06e764dfd1 "修改路由重复-冲突" 2025-06-26 18:22:35 +08:00
sxy
23ef741181 Merge branch 'main' of https://gitea-inner.fontree.cn/fiee/fonchain-fiee 2025-06-26 17:47:45 +08:00
sxy
ef16bf69f9 "修改msg-冲突" 2025-06-26 17:47:24 +08:00
sxy
24fe5e3760 Merge branch 'sxy' 2025-06-26 17:46:33 +08:00
7ea988ccc5 解决冲突 2025-06-26 17:39:51 +08:00
lzh
7735b710dd Merge branch 'dev-lzh' 2025-06-26 17:18:46 +08:00
9546978e3c fix: 处理pb冲突 2025-06-26 17:10:01 +08:00
bbf093e104 Merge branch 'feat-zjy-issue-008' into main
# Conflicts:
#	api/bundle/bundle.pb.go
#	api/bundle/bundle_triple.pb.go
#	docs/dev/dubbogo.yaml
#	pkg/router/bundle.go
#	pkg/service/init.go
2025-06-26 17:07:16 +08:00
4af106da5d Update bundle.validator.pb.go 2025-06-26 16:56:44 +08:00
2fc8ee5cb2 合并代码 2025-06-26 16:54:59 +08:00
62efe6a80d 短信通知 2025-06-26 09:19:18 +08:00
f583a771d6 修改 2025-06-25 16:30:34 +08:00
cd40e1c9ca Merge branch 'chat' 2025-06-25 15:53:57 +08:00
2ea9d6bc45 Update handler.go 2025-06-25 15:49:52 +08:00
23cf374c95 修改 2025-06-25 15:32:51 +08:00
9e3445319b Update work.go 2025-06-25 14:16:21 +08:00
85567c24a5 Update work.go 2025-06-25 11:08:55 +08:00
ce9deac980 1 2025-06-25 10:25:24 +08:00
e0d7b3775c 添加作品数量 2025-06-24 18:27:55 +08:00
b9ca6c67ef 添加取号 2025-06-24 16:38:26 +08:00
3890d74c0c 添加取号 2025-06-24 16:33:06 +08:00
b5ec90382f 1 2025-06-24 16:01:50 +08:00
sxy
0d529d47db 修改套餐proto文件-1 2025-06-24 16:01:39 +08:00
44bff5db82 修改 2025-06-24 15:53:24 +08:00
422b426c37 添加日志 2025-06-24 15:43:38 +08:00
786347f0d5 修改 2025-06-24 14:38:34 +08:00
sxy
a30636b387 修改套餐proto文件 2025-06-24 14:26:13 +08:00
490b0d7787 添加合同删除 2025-06-24 13:56:22 +08:00
a8f0107656 修改 2025-06-24 13:42:57 +08:00
62c48b2ea9 修改日志排序 2025-06-24 13:19:41 +08:00
090538be0d 修改 2025-06-24 10:55:59 +08:00
sxy
4344f1ff2c 修改多语言msg 2025-06-23 16:28:39 +08:00
382a32bec4 fix: 处理金额比较问题 2025-06-23 15:53:04 +08:00
94cf7ba83e 修改 2025-06-23 15:31:34 +08:00
0788c6a770 修改 2025-06-23 15:14:53 +08:00
7588bf4b28 绑定 2025-06-20 16:41:24 +08:00
a3f38b8377 修改 2025-06-20 15:51:16 +08:00
sxy
e53d3decd7 修改多语言msg-1 2025-06-20 15:30:27 +08:00
sxy
81115cee52 修改多语言msg 2025-06-20 14:57:53 +08:00
b51d4d39ca Update approval.go 2025-06-20 13:32:44 +08:00
sxy
42eac3d70b 修改bug-msg 2025-06-20 13:10:00 +08:00
cf413538fa fix: 处理bug 2025-06-20 11:48:20 +08:00
42522327a5 1 2025-06-20 11:46:06 +08:00
sxy
051f4d9f1d 修改bug 2025-06-20 11:42:04 +08:00
c20c6871c9 fix: 处理冲突,增加自行购买 2025-06-20 11:26:16 +08:00
383f8bef10 Merge branch 'jng' into feat-zjy-issue-008
# Conflicts:
#	api/bundle/bundle.pb.go
#	api/bundle/bundle_triple.pb.go
2025-06-20 11:21:22 +08:00
sxy
87e9701f72 修改h5 list接口 2025-06-20 11:15:01 +08:00
e663606c78 Update work.go 2025-06-20 11:11:49 +08:00
acf472f1ef fix: 注掉没用信息,太强说会更新两次 2025-06-20 11:02:48 +08:00
7c6edab53d fix: 去掉单独购买增值服务的0远金额限制 2025-06-20 10:23:32 +08:00
sxy
736e3b1bd0 修改H5套餐列表 2025-06-19 16:19:37 +08:00
8cfcbf345e 修改 2025-06-19 15:32:54 +08:00
2facb5c0fb Merge branch 'chat' 2025-06-19 15:07:05 +08:00
bc17428bd6 fix: 增加筛选过滤 2025-06-19 14:40:09 +08:00
301e94808d Update chat.go 2025-06-19 14:23:01 +08:00
6eb8e2cef8 fix: 处理订单金额是0的情况,直接返回 2025-06-19 13:57:12 +08:00
293f3e5c09 fix: 修复不同类型的回复规则同时生效的问题 2025-06-19 12:34:54 +08:00
sxy
d96222ba1e 修改错误信息返回 2025-06-19 11:53:45 +08:00
d1d305a638 fix: 找回丢失的代码 2025-06-19 11:31:15 +08:00
3a94e21ab3 Update robot.go 2025-06-19 11:13:50 +08:00
2757de0f03 fix: update 2025-06-19 11:12:15 +08:00
480551a738 添加重新发布 2025-06-19 11:04:37 +08:00
e1d750c24a fix: 重构回复规则校验逻辑 2025-06-19 11:02:27 +08:00
a9474f1a3d 修改 2025-06-19 10:32:44 +08:00
17e3b6513f fix: debug4 2025-06-19 10:24:35 +08:00
e97bd859fc debug3 2025-06-19 10:24:35 +08:00
eaf04ae02d fix: debug2 2025-06-19 10:24:35 +08:00
03adb50fee fix: debug 2025-06-19 10:24:34 +08:00
bf28865012 fix: 处理订单金额是0的情况 2025-06-19 09:51:44 +08:00
48a47a8681 Update ruler_replyWhenUserJoinSession.go 2025-06-18 20:06:51 +08:00
65c14cc10c Update ruler_replyWhenUserJoinSession.go 2025-06-18 19:57:44 +08:00
0c682db6e8 Update ruler_replyWhenUserJoinSession.go 2025-06-18 19:53:07 +08:00
543514dae9 Update dto.go 2025-06-18 19:49:48 +08:00
e1fbbfce04 fix: 重构回复规则 2025-06-18 19:47:43 +08:00
42b6c1262d fix: 修复闭包概率性拿不到变量的问题 2025-06-18 17:52:25 +08:00
1ba87f9c30 fix: 用户的消息统计只需要显示自己的会话即可 2025-06-18 16:57:54 +08:00
d42b82381e Update handler.go 2025-06-18 16:43:20 +08:00
62a0a2c0af fix: 打日志 2025-06-18 16:27:17 +08:00
65f12cc019 fix: 修复未读数量统计无法清零的问题 2025-06-18 16:19:42 +08:00
5c84210272 perf: 调试重置未读消息数 2025-06-18 16:10:30 +08:00
ac79481ec5 perf: 未实名用户显示手机号 2025-06-18 15:59:01 +08:00
sxy
039cd019e9 修改套餐中间表 2025-06-18 15:51:31 +08:00
b39f315ac2 Update chatAutoReplyRulerHandler.go 2025-06-18 15:33:07 +08:00
be6d4dbb63 perf: 优化缓存key的读取 2025-06-18 15:27:26 +08:00
1424e76f54 Update cache.go 2025-06-18 15:17:11 +08:00
613057182e fix: 修复自动回复的问题,修复回复规则筛选问题 2025-06-18 14:22:33 +08:00
ac5fe7a266 Update chat.go 2025-06-18 11:41:20 +08:00
sxy
ef2a15879c 修改返回语言 2025-06-18 11:38:53 +08:00
sxy
a4e8774077 Merge branch 'sxy-sec' 2025-06-18 10:53:31 +08:00
sxy
70fe9ae034 修改返回语言 2025-06-18 10:51:57 +08:00
lzh
eebaada8f6 修改protoc版本 2025-06-17 21:29:00 +08:00
lzh
4495e996cb 1 2025-06-17 21:25:39 +08:00
sxy
8ba1cd7101 Merge branch 'sxy-sec' 2025-06-17 20:28:37 +08:00
sxy
c98591b2bb Revert "修改"
This reverts commit 8f8e28ca3d.
2025-06-17 19:55:01 +08:00
lzh
e250a5dbc9 忽略未上线消费者 2025-06-17 19:45:50 +08:00
lzh
096f691067 忽略未上线消费者 2025-06-17 19:43:47 +08:00
lzh
d00a4d48ad Merge branch 'dev-lzh' 2025-06-17 19:34:51 +08:00
sxy
5aaf8d92bf Merge branch 'sxy-sec' 2025-06-17 18:33:52 +08:00
sxy
8f8e28ca3d 修改 2025-06-17 18:30:36 +08:00
lzh
e2fb31e67d Merge branch 'dev-lzh' 2025-06-17 18:26:27 +08:00
7b76dd5142 feat: 回复列表支持类型搜索 2025-06-17 16:14:24 +08:00
28cd572cbd 修改 2025-06-17 15:39:47 +08:00
sxy
8d28627e5f 修改接口认证 2025-06-17 14:46:09 +08:00
1fc1ea9285 Update replyAndRuler.go 2025-06-17 14:26:15 +08:00
e1df94bb5e fix: 解决冲突 2025-06-17 14:25:46 +08:00
sxy
0a5cb9f175 修改接口认证 2025-06-17 14:21:18 +08:00
sxy
d14dbaaf99 修改官网数据 2025-06-17 14:07:30 +08:00
3fa1bfcb2a Update chat.go 2025-06-17 11:28:00 +08:00
4643de4f6e fix: 修复role没有值的问题 2025-06-17 11:21:53 +08:00
cd2d8863a7 Update logging.go 2025-06-17 10:57:20 +08:00
ef5362e1c4 fix: 修复上传后文件url无法访问的问题;修复中间件打印二进制文件的问题 2025-06-17 10:52:08 +08:00
c796d3f507 fix: 修改oss配置 2025-06-17 10:26:59 +08:00
9460473581 Update conf.ini 2025-06-17 10:10:59 +08:00
sxy
73537c1a21 修改数据返回 2025-06-17 10:07:39 +08:00
6558e373c6 修改测试环境oss配置 2025-06-17 10:06:27 +08:00
6f52c9ff98 fix: debug 聊天室 2025-06-17 09:31:47 +08:00
sxy
9f5948a253 修改proto-color 2025-06-17 09:27:20 +08:00
3e5d70a8a3 feat: 机器人重载回复规则 2025-06-17 09:13:20 +08:00
1d62e95910 fix: 聊天消息增加角色 2025-06-16 18:28:16 +08:00
980880533c fix: 重构规则 2025-06-16 17:58:15 +08:00
58eb0d0b52 Update dto.go 2025-06-16 16:18:06 +08:00
cee0d67de1 fix: 更新配置 2025-06-16 16:10:48 +08:00
55c74ea17c fix: 修复卡片类型内容不展示 2025-06-16 15:51:52 +08:00
31d401e213 fix: 优化机器人监听事件的逻辑 2025-06-16 15:22:42 +08:00
c1dc0821e9 fix: 完成关键字回复 2025-06-16 15:04:11 +08:00
sxy
80fd028885 修改page-1 2025-06-16 14:32:18 +08:00
sxy
d0a51000d0 修改page 2025-06-16 14:26:00 +08:00
eb99e251bf fix: 修复部分聊天机器人相关问题 2025-06-16 14:02:55 +08:00
7bc66c7107 fix: 处理支付更新对账单id错误问题 2025-06-16 13:57:30 +08:00
sxy
de1ad8e06e 增加 修改 2025-06-16 13:22:20 +08:00
af9a59227f fix: 新增app端的根据orderNo查询子套餐 2025-06-16 13:05:29 +08:00
ac14cabe1b Update work.go 2025-06-16 11:52:30 +08:00
sxy
4d8b89c68c 增加 page 2025-06-16 11:48:11 +08:00
1e6e026aae 添加日志修改提示 2025-06-16 11:37:05 +08:00
21f6837fec 修改 2025-06-16 11:19:42 +08:00
92364e194f merge jng 2025-06-16 10:53:22 +08:00
abe68c7f6e 1 2025-06-16 10:37:18 +08:00
cde4488548 Update wsMessageHandle.go 2025-06-16 09:58:43 +08:00
638f2a9554 fix: 调整代码,创建支付的时候加入创建对账单。支付成功通知时更新对账单 2025-06-16 09:56:09 +08:00
aac5d05d13 Update wsMessageHandle.go 2025-06-16 09:55:13 +08:00
d415621631 Update wsMessageHandle.go 2025-06-16 09:52:07 +08:00
f9921d2ba0 Update upload.go 2025-06-16 09:43:45 +08:00
sxy
549b5f05c6 增加 form list 2025-06-16 09:31:23 +08:00
7b2b64e8f6 Update wsMessageHandle.go 2025-06-16 00:17:01 +08:00
ff25d74c61 Update wsMessageHandle.go 2025-06-16 00:10:10 +08:00
16a7f5ed78 Update wsMessageHandle.go 2025-06-16 00:04:28 +08:00
f65fe9d5aa fix: 修改token查询逻辑 2025-06-15 23:57:13 +08:00
156e127776 Update chatRoom.go 2025-06-15 23:21:43 +08:00
e370308b10 fix: 调整校验状态 2025-06-15 20:57:02 +08:00
cf18598b96 Merge branch 'jng' into feat-zjy-issue-008
# Conflicts:
#	api/bundle/bundle.pb.go
2025-06-15 20:54:42 +08:00
c5ee0d1ae7 获取用户余量 2025-06-15 20:46:05 +08:00
f3e0ae8672 fix: update 2025-06-15 20:38:08 +08:00
9839f3b358 Update common.go 2025-06-15 20:21:56 +08:00
0fbc4a4f87 Update common.go 2025-06-15 20:16:34 +08:00
98168623b1 Update common.go 2025-06-15 20:10:51 +08:00
6f16137b43 Update common.go 2025-06-15 20:05:26 +08:00
905d2077d3 fix: 完成用户进入聊天室直接回复 2025-06-15 19:58:02 +08:00
057565b0aa fix: 新增接口,根据orderNo,仅查询它单独购买的增值服务,调整支付创建时候仅增值的情况 2025-06-15 19:19:10 +08:00
bf21a5b906 Update conf.ini 2025-06-15 18:36:14 +08:00
f10b996656 fix: update 2025-06-15 18:34:17 +08:00
32cf742fa8 fix: detail接口增加addBundle的字段 2025-06-15 18:29:10 +08:00
9ecc24cbbe Update handler.go 2025-06-15 18:20:04 +08:00
de4389b6f1 Update common.go 2025-06-15 17:07:19 +08:00
f90be904e4 fix: update 2025-06-15 16:23:01 +08:00
2827c3a921 fix: update 2025-06-15 16:09:25 +08:00
4269f34670 fix: 聊天机器人 2025-06-15 16:02:31 +08:00
d332b0e1d4 修改 2025-06-15 15:59:40 +08:00
8000f56c06 修改 2025-06-15 15:27:51 +08:00
59ed859aae fix: 调整支付配置文件 2025-06-15 14:50:26 +08:00
3c4375964e Update common.go 2025-06-15 13:31:20 +08:00
e26c9f0c51 fix: 调整创建支付的代码逻辑 2025-06-15 13:23:11 +08:00
3533242855 Update common.go 2025-06-15 12:28:30 +08:00
701b27215f 详情添加分类 2025-06-15 12:12:17 +08:00
b991b6f7d8 fix: update 2025-06-15 12:07:03 +08:00
f41e053e08 feat: debug 2025-06-15 10:20:36 +08:00
b75a07c4dd Merge branch 'jng' into feat-zjy-issue-008 2025-06-15 10:12:06 +08:00
eb3e1f809b 修改 2025-06-15 10:06:57 +08:00
f8c6a2ff96 完成套餐查询 2025-06-15 00:33:25 +08:00
48c27ae476 Update common.go 2025-06-14 19:58:07 +08:00
cb7e875f2d Update common.go 2025-06-14 19:53:46 +08:00
1617c6170d APP接口 2025-06-14 19:46:02 +08:00
025d64087f fix: update 2025-06-14 19:30:37 +08:00
8d56ba48f6 Update common.go 2025-06-14 19:14:58 +08:00
f987f964b5 1 2025-06-14 19:00:37 +08:00
3c5f500c6d Update common.go 2025-06-14 18:55:51 +08:00
dd7b217748 Update common.go 2025-06-14 18:37:45 +08:00
2db47664a3 1 2025-06-14 18:29:26 +08:00
6fd82f1770 fix: 修改domain 2025-06-14 18:11:31 +08:00
sxy
9402bad9fd 修改语言传输 2025-06-14 17:40:06 +08:00
19e1ce9182 feat: 增加调试记录 2025-06-14 17:39:58 +08:00
f86d6b5db6 Update router.go 2025-06-14 17:27:43 +08:00
39fc87c859 fix: update 2025-06-14 17:10:52 +08:00
sxy
637fc47188 z增加详情接口 2025-06-14 17:10:28 +08:00
sxy
1bab9a17e6 修改proto 2025-06-14 17:09:14 +08:00
sxy
f36758d8ac 修改proto 2025-06-14 17:01:47 +08:00
sxy
ba65fbe5b7 修改 2025-06-14 16:41:21 +08:00
0907469573 fix: 使用account替换成用户手机号 2025-06-14 16:32:38 +08:00
ae0c5f0c84 fix: 修复token转chatUser id丢失问题 2025-06-14 15:56:51 +08:00
c4e72efcb5 11 2025-06-14 15:23:14 +08:00
d6216c1103 Update common.go 2025-06-14 15:12:03 +08:00
e01ea1d9c2 Update handler.go 2025-06-14 15:04:51 +08:00
94f01d2ee1 Update handler.go 2025-06-14 14:59:01 +08:00
c81b87d824 feat: 客服聊天 2025-06-14 14:46:01 +08:00
584938b537 更新自媒体账号ID 2025-06-14 14:44:12 +08:00
48343889e2 修改配置 2025-06-14 14:10:55 +08:00
129d3fafa1 更新审批 2025-06-13 19:00:38 +08:00
sxy
b71fef10ef 修改 2025-06-13 16:48:38 +08:00
b979be1484 fix: 修复聊天中的token校验问题 2025-06-13 15:28:23 +08:00
sxy
cd79fe7319 修改 2025-06-13 15:00:40 +08:00
sxy
8d9260aca5 修改返回数据 2025-06-13 14:44:24 +08:00
fb076dd4db feat: update 2025-06-13 11:04:33 +08:00
sxy
a63b001e5b 修改 2025-06-13 10:53:59 +08:00
sxy
76e30e9211 修改冲突 2025-06-13 10:47:42 +08:00
sxy
63da647619 修改冲突 2025-06-13 10:45:30 +08:00
a92cca188d fix: 优化注册聊天用户逻辑 2025-06-13 10:44:25 +08:00
sxy
49a935d6c6 修改 2025-06-13 10:34:36 +08:00
af0fefc3bd Update wsMessageHandle.go 2025-06-13 10:30:11 +08:00
72c1ad35b7 feat: 回复规则 2025-06-12 19:31:40 +08:00
cc328eee8d 备份 2025-06-12 18:10:07 +08:00
47c77fcdbb feat: 客服聊天 2025-06-12 17:07:49 +08:00
7c54d3ce30 更新审批信息 2025-06-12 15:20:11 +08:00
sxy
78246a5b2a 修改 2025-06-12 11:59:19 +08:00
347b97f9d9 添加详情 2025-06-12 11:38:19 +08:00
ca0023a1e6 1 2025-06-12 10:23:57 +08:00
sxy
7b228e0c03 修改节省金额 2025-06-12 10:20:32 +08:00
1f77285201 1 2025-06-11 17:02:28 +08:00
7ccebd8621 修改设置 2025-06-11 16:52:04 +08:00
sxy
9120e6acfd 修改路由接口-2 2025-06-11 16:23:49 +08:00
a6078341ab 更新列表接口 2025-06-11 16:11:16 +08:00
sxy
463404d774 修改路由接口-1 2025-06-11 15:55:42 +08:00
sxy
99f4ca986a 修改路由接口 2025-06-11 15:41:04 +08:00
88333063d7 feat: .gitignore 2025-06-11 14:33:23 +08:00
130 changed files with 25008 additions and 4207 deletions

15
.gitignore vendored
View File

@ -1,17 +1,12 @@
.gitignore
.idea
.scannerwork
.vscode
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
*.log
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
@ -32,7 +27,7 @@ yarn-error.log*
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
/cmd/runtime
/cmd/logs/*.log
/cmd/runtime/log/*.log
/build/*
/build/*

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

File diff suppressed because one or more lines are too long

9
.idea/fonchain-fiee.iml Normal file
View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxBlameSettings">
<option name="version" value="2" />
</component>
</project>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/fonchain-fiee.iml" filepath="$PROJECT_DIR$/.idea/fonchain-fiee.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,13 @@
## 测试服后台
http://172.16.100.99:9028/
13580848136
https://erp.fiee.com/older_list
13580848136
Aa.123456
测试h5
## https://saas-test.szjixun.cn
正式h5
https://saas.fiee.com

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,5 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@ -18,9 +20,9 @@
syntax = "proto3";
package accountFiee;
import "github.com/mwitkow/go-proto-validators@v0.3.2/validator.proto";
option go_package = "./;accountFiee";
//protoc -I . -I C:\Users\lenovo\go\src --go_out=. --go-triple_out=. ./accountFiee.proto
service AccountFiee {
rpc Login (LoginRequest) returns (TokenInfo) {}
rpc RefreshToken (RefreshTokenRequest) returns (TokenInfo) {} //token
@ -29,7 +31,7 @@ service AccountFiee {
rpc OnlineLog (LoginInfosByUserIdRequest) returns (LoginLogsResponse) {}//id获取登录的信息
rpc OnlineLogById (OnlineLogByIdRequest) returns (LoginLog) {}//id获取登录的信息
rpc CheckPwd (CheckPwdRequest) returns (UpdateResponse) {}//
// rpc RegisterOrExist (RegistRequest) returns (RequestStatus) {}
// rpc RegisterOrExist (RegistRequest) returns (RequestStatus) {}
rpc SendMsg (SendMsgRequest) returns (SendMsgStatusResponse) {} //
rpc SendCustomMsg (SendCustomMsgRequest) returns (SendMsgStatusResponse) {}//
rpc SendExCustomMsg (SendCustomMsgRequest) returns (SendMsgStatusResponse) {}//
@ -62,9 +64,41 @@ service AccountFiee {
rpc VerifySliderCaptcha(VerifySliderCaptchaRequest) returns (VerifySliderCaptchaResponse) {}//
rpc SendNationMsg (SendNationMsgRequest) returns (SendMsgStatusResponse) {} // --
rpc VerifySliderStatus(VerifySliderStatusRequest) returns (VerifySliderStatusResponse) {}//
rpc SendNationTemplateMsg (SendNationMsgRequest) returns (SendMsgStatusResponse) {} // --
rpc CreateUserAndRealName (CreateUserAndRealNameRequest) returns (CreateUserAndRealNameResponse) {}// ,
// submit info
rpc SaveSubmitInfo(SubmitInfoRequest) returns (CommonResponse);
//-------------------------------------------------------------
rpc CreateChatUser ( ChatUserData )returns( CreateChatUserResp ){} //
rpc UpdateChatUser ( ChatUserData )returns( CommonMsg ){} //
rpc SaveChatUser ( ChatUserData )returns( CommonMsg ){} //
rpc DeleteChatUser ( DeleteChatUserRequest )returns( CommonMsg ){} //
rpc GetChatUserDetail ( GetChatUserByIdRequest )returns( ChatUserData ){} //
rpc GetChatUserList ( GetChatUserListRequest )returns( GetChatUserListResp ){} //
rpc GetChatUserList2 ( GetChatUserListRequest2 )returns( GetChatUserListResp2 ){} //2
rpc RegisterWaiter ( RegisterWaiterRequest )returns( RegisterWaiterResp ){} //
rpc CreateChatRecord ( ChatRecordData )returns( CreateChatRecordResp ){} //ChatRecord
rpc UpdateChatRecord ( ChatRecordData )returns( CommonMsg ){} //ChatRecord
rpc SaveChatRecord ( ChatRecordData )returns( CommonMsg ){} //ChatRecord
rpc DeleteChatRecord ( DeleteChatRecordRequest )returns( CommonMsg ){} //ChatRecord
rpc GetChatRecordDetail ( GetChatRecordByIdRequest )returns( ChatRecordData ){} //ChatRecord详情
rpc GetChatRecordList ( GetChatRecordListRequest )returns( GetChatRecordListResp ){} //ChatRecord列表
rpc CreateChatMedia ( ChatMediaData )returns( CreateChatMediaResp ){} //ChatMedia
rpc UpdateChatMedia ( ChatMediaData )returns( CommonMsg ){} //ChatMedia
rpc SaveChatMedia ( ChatMediaData )returns( CommonMsg ){} //ChatMedia
rpc DeleteChatMedia ( DeleteChatMediaRequest )returns( CommonMsg ){} //ChatMedia
rpc GetChatMediaDetail ( GetChatMediaByIdRequest )returns( ChatMediaData ){} //ChatMedia详情
rpc GetChatMediaList ( GetChatMediaListRequest )returns( GetChatMediaListResp ){} //ChatMedia列表
rpc CreateChatAutoReplyRuler ( ChatAutoReplyRulerData )returns( CreateChatAutoReplyRulerResp ){} //
rpc UpdateChatAutoReplyRuler ( ChatAutoReplyRulerData )returns( CommonMsg ){} //
rpc SaveChatAutoReplyRuler ( ChatAutoReplyRulerData )returns( CommonMsg ){} //
rpc DeleteChatAutoReplyRuler ( DeleteChatAutoReplyRulerRequest )returns( CommonMsg ){} //
rpc GetChatAutoReplyRulerDetail ( GetChatAutoReplyRulerByIdRequest )returns( ChatAutoReplyRulerData ){} //
rpc GetChatAutoReplyRulerList ( GetChatAutoReplyRulerListRequest )returns( GetChatAutoReplyRulerListResp ){} //
}
message VerifySliderStatusRequest {
@ -158,6 +192,7 @@ message UserListRequest{
uint64 pageSize = 9;
string blurNameTel = 10;
repeated int64 ids = 11;
string nationality = 12;
}
message UserInfoResponse{
uint64 id = 1;
@ -178,6 +213,7 @@ message UserInfoResponse{
string subscriberNumber = 16;
string nickName = 17;
string telNum = 18;
string telAreaCode = 19;
}
message RealNameResponse{
uint64 id = 1;
@ -778,7 +814,7 @@ message ClockBatchBindRequest{
repeated uint64 deviceId =3;
}
message ClockBatchListResponse{
repeated ClockUserDeviceBatch data = 1;
repeated ClockUserDeviceBatch data = 1;
}
message ClockUserDeviceBatch{
uint64 userId = 1;
@ -829,4 +865,224 @@ message SubmitInfoRequest{
string email = 3;
string company = 4;
string phone = 5;
}
message CommonMsg{
string msg = 1;
}
enum MsgType{
UnknownMsgType = 0 ;//
TextMsgType = 1 ;//
ImageMsgType = 2 ;//
AudioMsgType = 3 ;//
VideoMsgType = 4 ;//
CardType = 5 ;//
}
message ChatRecordData{
int64 ID=1;
string createdAt=2;
string updatedAt=3;
int64 deletedAt=4;
string sessionId = 5; //UID
int64 userId = 6; //ID
string name = 7; //
string avatar = 8; //
MsgType msgType = 9; //
string content = 10; //
repeated ChatMediaData medias = 11; //
int32 waiterRead=12;// 1= 2=
int64 localStamp = 13; //
string domain =14;//
int32 role=15;//: 1= 2= 3=
}
message CreateChatRecordResp{
ChatRecordData data=1;
string msg=2;
}
message DeleteChatRecordRequest{
int64 id=1; //id
repeated int64 ids=2;//id列表
}
message GetChatRecordByIdRequest{
int64 id=1; //id
}
message GetChatRecordListRequest{
ChatRecordData query =1;
int64 page=2;
int64 pageSize=3;
string where=4;
string order=5;
}
message GetChatRecordListResp{
repeated ChatRecordData list=1;
int64 page=2;
int64 pageSize=3;
int64 Total=4;
}
message RegisterWaiterRequest{
string origin=1; //
int64 originId=2; //ID
string nickName=3; //
string avatar=4; //
string telNum=5; //
string invitationCode=6; //
string account=7;
}
message RegisterWaiterResp{
int64 userId=1;
}
message ChatMediaData{
int64 ID=1;
string createdAt=2;
string updatedAt=3;
int64 deletedAt=4;
string url = 5; //url
string md5 = 6; //md5值
string size = 7; //
string ext = 8; //
string convText=9; //
int64 duration=10;//
}
message CreateChatMediaResp{
ChatMediaData data=1;
string msg=2;
}
message DeleteChatMediaRequest{
int64 id=1; //id
repeated int64 ids=2;//id列表
}
message GetChatMediaByIdRequest{
int64 id=1; //id
}
message GetChatMediaListRequest{
ChatMediaData query =1;
int64 page=2;
int64 pageSize=3;
string where=4;
string order=5;
}
message GetChatMediaListResp{
repeated ChatMediaData list=1;
int64 page=2;
int64 pageSize=3;
int64 Total=4;
}
message GetChatUserListRequest2{
int64 page=1;
int64 pageSize=2;
string where=3;
string name=4;
repeated int64 userIdIn=5;
string account=6;
repeated int32 roleIn=7;
}
message ChatUser2{
int64 userId=1;
string name=2;
string avatar=3;
string origin=4;
int64 originId=5;
}
message GetChatUserListResp2{
repeated ChatUser2 list=1;
int64 page=2;
int64 pageSize=3;
int64 Total=4;
string where=5;
}
message ChatAutoReplyRulerData{
int64 ID = 1; //
string createdAt = 2; //
string updatedAt = 3; //
int64 deletedAt = 4; //
string title = 5; //
string ruler = 6; //
int32 status = 7; //: 1= 2=
string response =8; //
}
message CreateChatAutoReplyRulerResp{
ChatAutoReplyRulerData data=1;
string msg=2;
}
message DeleteChatAutoReplyRulerRequest{
int64 id=1; //id
repeated int64 ids=2;//id列表
}
message GetChatAutoReplyRulerByIdRequest{
int64 id=1; //id
}
message GetChatAutoReplyRulerListRequest{
ChatAutoReplyRulerData query =1;
int64 page=2;
int64 pageSize=3;
string where=4;
string order=5;
}
message GetChatAutoReplyRulerListResp{
repeated ChatAutoReplyRulerData list=1;
int64 page=2;
int64 pageSize=3;
int64 Total=4;
}
message ChatUserData{
int64 ID = 1; //
string createdAt = 2; //
string updatedAt = 3; //
int64 deletedAt = 4; //
string nickName = 5; //
string account = 6; //
int32 role = 7; // 1= 2= 3=
string origin = 8; //
int64 originId = 9; //ID
string avatar = 10; //
}
message CreateChatUserResp{
ChatUserData data=1;
string msg=2;
}
message DeleteChatUserRequest{
int64 id=1; //id
repeated int64 ids=2;//id列表
}
message GetChatUserByIdRequest{
int64 id=1; //id
}
message GetChatUserListRequest{
ChatUserData query =1;
int64 page=2;
int64 pageSize=3;
string where=4;
string order=5;
}
message GetChatUserListResp{
repeated ChatUserData list=1;
int64 page=2;
int64 pageSize=3;
int64 Total=4;
}
message CreateUserAndRealNameRequest{
string userNum = 1;
string userName = 2;
string userTelArea = 3;
string userTel = 4;
string userSex = 5;
string nationality = 6;
string placeOfResidence = 7;
int32 documentType = 8;
string userIdCardFrontUrl = 9;
string userIdCardReverseUrl = 10;
string userIdCardValidity = 11;
string auditTime = 12;
}
message CreateUserAndRealNameResponse {
int64 userId = 1;
string userNum = 2;
string userName = 3;
}

View File

@ -5,11 +5,11 @@ package accountFiee
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
_ "github.com/mwitkow/go-proto-validators"
regexp "regexp"
github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators"
math "math"
regexp "regexp"
)
// Reference imports to suppress errors if they are not otherwise used.
@ -525,3 +525,181 @@ func (this *ClockLogListResponse) Validate() error {
func (this *SubmitInfoRequest) Validate() error {
return nil
}
func (this *CommonMsg) Validate() error {
return nil
}
func (this *ChatRecordData) Validate() error {
for _, item := range this.Medias {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Medias", err)
}
}
}
return nil
}
func (this *CreateChatRecordResp) Validate() error {
if this.Data != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Data); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
}
}
return nil
}
func (this *DeleteChatRecordRequest) Validate() error {
return nil
}
func (this *GetChatRecordByIdRequest) Validate() error {
return nil
}
func (this *GetChatRecordListRequest) Validate() error {
if this.Query != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Query); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Query", err)
}
}
return nil
}
func (this *GetChatRecordListResp) Validate() error {
for _, item := range this.List {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("List", err)
}
}
}
return nil
}
func (this *RegisterWaiterRequest) Validate() error {
return nil
}
func (this *RegisterWaiterResp) Validate() error {
return nil
}
func (this *ChatMediaData) Validate() error {
return nil
}
func (this *CreateChatMediaResp) Validate() error {
if this.Data != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Data); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
}
}
return nil
}
func (this *DeleteChatMediaRequest) Validate() error {
return nil
}
func (this *GetChatMediaByIdRequest) Validate() error {
return nil
}
func (this *GetChatMediaListRequest) Validate() error {
if this.Query != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Query); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Query", err)
}
}
return nil
}
func (this *GetChatMediaListResp) Validate() error {
for _, item := range this.List {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("List", err)
}
}
}
return nil
}
func (this *GetChatUserListRequest2) Validate() error {
return nil
}
func (this *ChatUser2) Validate() error {
return nil
}
func (this *GetChatUserListResp2) Validate() error {
for _, item := range this.List {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("List", err)
}
}
}
return nil
}
func (this *ChatAutoReplyRulerData) Validate() error {
return nil
}
func (this *CreateChatAutoReplyRulerResp) Validate() error {
if this.Data != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Data); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
}
}
return nil
}
func (this *DeleteChatAutoReplyRulerRequest) Validate() error {
return nil
}
func (this *GetChatAutoReplyRulerByIdRequest) Validate() error {
return nil
}
func (this *GetChatAutoReplyRulerListRequest) Validate() error {
if this.Query != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Query); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Query", err)
}
}
return nil
}
func (this *GetChatAutoReplyRulerListResp) Validate() error {
for _, item := range this.List {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("List", err)
}
}
}
return nil
}
func (this *ChatUserData) Validate() error {
return nil
}
func (this *CreateChatUserResp) Validate() error {
if this.Data != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Data); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
}
}
return nil
}
func (this *DeleteChatUserRequest) Validate() error {
return nil
}
func (this *GetChatUserByIdRequest) Validate() error {
return nil
}
func (this *GetChatUserListRequest) Validate() error {
if this.Query != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Query); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Query", err)
}
}
return nil
}
func (this *GetChatUserListResp) Validate() error {
for _, item := range this.List {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("List", err)
}
}
}
return nil
}
func (this *CreateUserAndRealNameRequest) Validate() error {
return nil
}
func (this *CreateUserAndRealNameResponse) Validate() error {
return nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -447,3 +447,22 @@ func (this *ConfirmWorkReq) Validate() error {
func (this *ConfirmWorkResp) Validate() error {
return nil
}
func (this *AutoCreateUserAndOrderRequest) Validate() error {
return nil
}
func (this *UnfinishedInfos) Validate() error {
for _, item := range this.UnfinishedInfos {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("UnfinishedInfos", err)
}
}
}
return nil
}
func (this *UnfinishedInfo) Validate() error {
return nil
}
func (this *SoftDeleteUnfinishedInfoRequest) Validate() error {
return nil
}

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-triple. DO NOT EDIT.
// versions:
// - protoc-gen-go-triple v1.0.8
// - protoc v3.20.3
// - protoc v3.12.4
// source: pb/bundle.proto
package bundle
@ -80,6 +80,9 @@ type BundleClient interface {
CreateReconciliation(ctx context.Context, in *ReconciliationInfo, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
UpdateReconciliation(ctx context.Context, in *ReconciliationInfo, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
UpdateReconciliationStatusBySerialNumber(ctx context.Context, in *UpdateStatusAndPayTimeBySerialNumber, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
// 查出没处理的数据
ListUnfinishedInfos(ctx context.Context, in *AutoCreateUserAndOrderRequest, opts ...grpc_go.CallOption) (*UnfinishedInfos, common.ErrorWithAttachment)
SoftDeleteUnfinishedInfo(ctx context.Context, in *SoftDeleteUnfinishedInfoRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
}
type bundleClient struct {
@ -134,6 +137,8 @@ type BundleClientImpl struct {
CreateReconciliation func(ctx context.Context, in *ReconciliationInfo) (*CommonResponse, error)
UpdateReconciliation func(ctx context.Context, in *ReconciliationInfo) (*CommonResponse, error)
UpdateReconciliationStatusBySerialNumber func(ctx context.Context, in *UpdateStatusAndPayTimeBySerialNumber) (*CommonResponse, error)
ListUnfinishedInfos func(ctx context.Context, in *AutoCreateUserAndOrderRequest) (*UnfinishedInfos, error)
SoftDeleteUnfinishedInfo func(ctx context.Context, in *SoftDeleteUnfinishedInfoRequest) (*CommonResponse, error)
}
func (c *BundleClientImpl) GetDubboStub(cc *triple.TripleConn) BundleClient {
@ -430,6 +435,18 @@ func (c *bundleClient) UpdateReconciliationStatusBySerialNumber(ctx context.Cont
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateReconciliationStatusBySerialNumber", in, out)
}
func (c *bundleClient) ListUnfinishedInfos(ctx context.Context, in *AutoCreateUserAndOrderRequest, opts ...grpc_go.CallOption) (*UnfinishedInfos, common.ErrorWithAttachment) {
out := new(UnfinishedInfos)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/ListUnfinishedInfos", in, out)
}
func (c *bundleClient) SoftDeleteUnfinishedInfo(ctx context.Context, in *SoftDeleteUnfinishedInfoRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment) {
out := new(CommonResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/SoftDeleteUnfinishedInfo", in, out)
}
// BundleServer is the server API for Bundle service.
// All implementations must embed UnimplementedBundleServer
// for forward compatibility
@ -486,6 +503,9 @@ type BundleServer interface {
CreateReconciliation(context.Context, *ReconciliationInfo) (*CommonResponse, error)
UpdateReconciliation(context.Context, *ReconciliationInfo) (*CommonResponse, error)
UpdateReconciliationStatusBySerialNumber(context.Context, *UpdateStatusAndPayTimeBySerialNumber) (*CommonResponse, error)
// 查出没处理的数据
ListUnfinishedInfos(context.Context, *AutoCreateUserAndOrderRequest) (*UnfinishedInfos, error)
SoftDeleteUnfinishedInfo(context.Context, *SoftDeleteUnfinishedInfoRequest) (*CommonResponse, error)
mustEmbedUnimplementedBundleServer()
}
@ -635,6 +655,12 @@ func (UnimplementedBundleServer) UpdateReconciliation(context.Context, *Reconcil
func (UnimplementedBundleServer) UpdateReconciliationStatusBySerialNumber(context.Context, *UpdateStatusAndPayTimeBySerialNumber) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateReconciliationStatusBySerialNumber not implemented")
}
func (UnimplementedBundleServer) ListUnfinishedInfos(context.Context, *AutoCreateUserAndOrderRequest) (*UnfinishedInfos, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListUnfinishedInfos not implemented")
}
func (UnimplementedBundleServer) SoftDeleteUnfinishedInfo(context.Context, *SoftDeleteUnfinishedInfoRequest) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SoftDeleteUnfinishedInfo not implemented")
}
func (s *UnimplementedBundleServer) XXX_SetProxyImpl(impl protocol.Invoker) {
s.proxyImpl = impl
}
@ -2026,6 +2052,64 @@ func _Bundle_UpdateReconciliationStatusBySerialNumber_Handler(srv interface{}, c
return interceptor(ctx, in, info, handler)
}
func _Bundle_ListUnfinishedInfos_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(AutoCreateUserAndOrderRequest)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("ListUnfinishedInfos", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Bundle_SoftDeleteUnfinishedInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(SoftDeleteUnfinishedInfoRequest)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("SoftDeleteUnfinishedInfo", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
// Bundle_ServiceDesc is the grpc_go.ServiceDesc for Bundle service.
// It's only intended for direct use with grpc_go.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -2221,6 +2305,14 @@ var Bundle_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "UpdateReconciliationStatusBySerialNumber",
Handler: _Bundle_UpdateReconciliationStatusBySerialNumber_Handler,
},
{
MethodName: "ListUnfinishedInfos",
Handler: _Bundle_ListUnfinishedInfos_Handler,
},
{
MethodName: "SoftDeleteUnfinishedInfo",
Handler: _Bundle_SoftDeleteUnfinishedInfo_Handler,
},
},
Streams: []grpc_go.StreamDesc{},
Metadata: "pb/bundle.proto",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-triple. DO NOT EDIT.
// versions:
// - protoc-gen-go-triple v1.0.8
// - protoc v3.21.1
// - protoc v6.32.0--rc2
// source: pb/fiee/cast.proto
package cast
@ -31,7 +31,7 @@ const _ = grpc_go.SupportPackageIsVersion7
type CastClient interface {
MediaUserList(ctx context.Context, in *MediaUserListReq, opts ...grpc_go.CallOption) (*MediaUserListResp, common.ErrorWithAttachment)
UpdateMediaAccount(ctx context.Context, in *UpdateMediaAccountReq, opts ...grpc_go.CallOption) (*UpdateMediaAccountResp, common.ErrorWithAttachment)
UnbindManager(ctx context.Context, in *UnbindManagerReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
UnbindManager(ctx context.Context, in *UnbindManagerReq, opts ...grpc_go.CallOption) (*UnbindManagerResp, common.ErrorWithAttachment)
BindManager(ctx context.Context, in *BindManagerReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
UpdateWorkImage(ctx context.Context, in *UpdateWorkImageReq, opts ...grpc_go.CallOption) (*UpdateWorkImageResp, common.ErrorWithAttachment)
UpdateWorkVideo(ctx context.Context, in *UpdateWorkVideoReq, opts ...grpc_go.CallOption) (*UpdateWorkVideoResp, common.ErrorWithAttachment)
@ -40,6 +40,14 @@ type CastClient interface {
UpdateStatus(ctx context.Context, in *UpdateStatusReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
MediaAccounts(ctx context.Context, in *MediaAccountsReq, opts ...grpc_go.CallOption) (*MediaAccountsResp, common.ErrorWithAttachment)
MediaWorks(ctx context.Context, in *MediaWorksReq, opts ...grpc_go.CallOption) (*MediaWorksResp, common.ErrorWithAttachment)
RePublish(ctx context.Context, in *RePublishReq, opts ...grpc_go.CallOption) (*RePublishResp, common.ErrorWithAttachment)
DelWork(ctx context.Context, in *DelWorkReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
WorkInfo(ctx context.Context, in *WorkInfoReq, opts ...grpc_go.CallOption) (*WorkInfoResp, common.ErrorWithAttachment)
OAuthAccount(ctx context.Context, in *OAuthAccountReq, opts ...grpc_go.CallOption) (*OAuthAccountResp, common.ErrorWithAttachment)
OAuthCodeToToken(ctx context.Context, in *OAuthCodeToTokenReq, opts ...grpc_go.CallOption) (*OAuthCodeToTokenResp, common.ErrorWithAttachment)
RefreshToken(ctx context.Context, in *RefreshTokenReq, opts ...grpc_go.CallOption) (*RefreshTokenResp, common.ErrorWithAttachment)
PublishMediaInfo(ctx context.Context, in *PublishMediaInfoReq, opts ...grpc_go.CallOption) (*PublishMediaInfoResp, common.ErrorWithAttachment)
Test(ctx context.Context, in *emptypb.Empty, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
}
type castClient struct {
@ -49,7 +57,7 @@ type castClient struct {
type CastClientImpl struct {
MediaUserList func(ctx context.Context, in *MediaUserListReq) (*MediaUserListResp, error)
UpdateMediaAccount func(ctx context.Context, in *UpdateMediaAccountReq) (*UpdateMediaAccountResp, error)
UnbindManager func(ctx context.Context, in *UnbindManagerReq) (*emptypb.Empty, error)
UnbindManager func(ctx context.Context, in *UnbindManagerReq) (*UnbindManagerResp, error)
BindManager func(ctx context.Context, in *BindManagerReq) (*emptypb.Empty, error)
UpdateWorkImage func(ctx context.Context, in *UpdateWorkImageReq) (*UpdateWorkImageResp, error)
UpdateWorkVideo func(ctx context.Context, in *UpdateWorkVideoReq) (*UpdateWorkVideoResp, error)
@ -58,6 +66,14 @@ type CastClientImpl struct {
UpdateStatus func(ctx context.Context, in *UpdateStatusReq) (*emptypb.Empty, error)
MediaAccounts func(ctx context.Context, in *MediaAccountsReq) (*MediaAccountsResp, error)
MediaWorks func(ctx context.Context, in *MediaWorksReq) (*MediaWorksResp, error)
RePublish func(ctx context.Context, in *RePublishReq) (*RePublishResp, error)
DelWork func(ctx context.Context, in *DelWorkReq) (*emptypb.Empty, error)
WorkInfo func(ctx context.Context, in *WorkInfoReq) (*WorkInfoResp, error)
OAuthAccount func(ctx context.Context, in *OAuthAccountReq) (*OAuthAccountResp, error)
OAuthCodeToToken func(ctx context.Context, in *OAuthCodeToTokenReq) (*OAuthCodeToTokenResp, error)
RefreshToken func(ctx context.Context, in *RefreshTokenReq) (*RefreshTokenResp, error)
PublishMediaInfo func(ctx context.Context, in *PublishMediaInfoReq) (*PublishMediaInfoResp, error)
Test func(ctx context.Context, in *emptypb.Empty) (*emptypb.Empty, error)
}
func (c *CastClientImpl) GetDubboStub(cc *triple.TripleConn) CastClient {
@ -84,8 +100,8 @@ func (c *castClient) UpdateMediaAccount(ctx context.Context, in *UpdateMediaAcco
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateMediaAccount", in, out)
}
func (c *castClient) UnbindManager(ctx context.Context, in *UnbindManagerReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment) {
out := new(emptypb.Empty)
func (c *castClient) UnbindManager(ctx context.Context, in *UnbindManagerReq, opts ...grpc_go.CallOption) (*UnbindManagerResp, common.ErrorWithAttachment) {
out := new(UnbindManagerResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UnbindManager", in, out)
}
@ -138,13 +154,61 @@ func (c *castClient) MediaWorks(ctx context.Context, in *MediaWorksReq, opts ...
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/MediaWorks", in, out)
}
func (c *castClient) RePublish(ctx context.Context, in *RePublishReq, opts ...grpc_go.CallOption) (*RePublishResp, common.ErrorWithAttachment) {
out := new(RePublishResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/RePublish", in, out)
}
func (c *castClient) DelWork(ctx context.Context, in *DelWorkReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment) {
out := new(emptypb.Empty)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/DelWork", in, out)
}
func (c *castClient) WorkInfo(ctx context.Context, in *WorkInfoReq, opts ...grpc_go.CallOption) (*WorkInfoResp, common.ErrorWithAttachment) {
out := new(WorkInfoResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/WorkInfo", in, out)
}
func (c *castClient) OAuthAccount(ctx context.Context, in *OAuthAccountReq, opts ...grpc_go.CallOption) (*OAuthAccountResp, common.ErrorWithAttachment) {
out := new(OAuthAccountResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/OAuthAccount", in, out)
}
func (c *castClient) OAuthCodeToToken(ctx context.Context, in *OAuthCodeToTokenReq, opts ...grpc_go.CallOption) (*OAuthCodeToTokenResp, common.ErrorWithAttachment) {
out := new(OAuthCodeToTokenResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/OAuthCodeToToken", in, out)
}
func (c *castClient) RefreshToken(ctx context.Context, in *RefreshTokenReq, opts ...grpc_go.CallOption) (*RefreshTokenResp, common.ErrorWithAttachment) {
out := new(RefreshTokenResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/RefreshToken", in, out)
}
func (c *castClient) PublishMediaInfo(ctx context.Context, in *PublishMediaInfoReq, opts ...grpc_go.CallOption) (*PublishMediaInfoResp, common.ErrorWithAttachment) {
out := new(PublishMediaInfoResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/PublishMediaInfo", in, out)
}
func (c *castClient) Test(ctx context.Context, in *emptypb.Empty, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment) {
out := new(emptypb.Empty)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/Test", in, out)
}
// CastServer is the server API for Cast service.
// All implementations must embed UnimplementedCastServer
// for forward compatibility
type CastServer interface {
MediaUserList(context.Context, *MediaUserListReq) (*MediaUserListResp, error)
UpdateMediaAccount(context.Context, *UpdateMediaAccountReq) (*UpdateMediaAccountResp, error)
UnbindManager(context.Context, *UnbindManagerReq) (*emptypb.Empty, error)
UnbindManager(context.Context, *UnbindManagerReq) (*UnbindManagerResp, error)
BindManager(context.Context, *BindManagerReq) (*emptypb.Empty, error)
UpdateWorkImage(context.Context, *UpdateWorkImageReq) (*UpdateWorkImageResp, error)
UpdateWorkVideo(context.Context, *UpdateWorkVideoReq) (*UpdateWorkVideoResp, error)
@ -153,6 +217,14 @@ type CastServer interface {
UpdateStatus(context.Context, *UpdateStatusReq) (*emptypb.Empty, error)
MediaAccounts(context.Context, *MediaAccountsReq) (*MediaAccountsResp, error)
MediaWorks(context.Context, *MediaWorksReq) (*MediaWorksResp, error)
RePublish(context.Context, *RePublishReq) (*RePublishResp, error)
DelWork(context.Context, *DelWorkReq) (*emptypb.Empty, error)
WorkInfo(context.Context, *WorkInfoReq) (*WorkInfoResp, error)
OAuthAccount(context.Context, *OAuthAccountReq) (*OAuthAccountResp, error)
OAuthCodeToToken(context.Context, *OAuthCodeToTokenReq) (*OAuthCodeToTokenResp, error)
RefreshToken(context.Context, *RefreshTokenReq) (*RefreshTokenResp, error)
PublishMediaInfo(context.Context, *PublishMediaInfoReq) (*PublishMediaInfoResp, error)
Test(context.Context, *emptypb.Empty) (*emptypb.Empty, error)
mustEmbedUnimplementedCastServer()
}
@ -167,7 +239,7 @@ func (UnimplementedCastServer) MediaUserList(context.Context, *MediaUserListReq)
func (UnimplementedCastServer) UpdateMediaAccount(context.Context, *UpdateMediaAccountReq) (*UpdateMediaAccountResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateMediaAccount not implemented")
}
func (UnimplementedCastServer) UnbindManager(context.Context, *UnbindManagerReq) (*emptypb.Empty, error) {
func (UnimplementedCastServer) UnbindManager(context.Context, *UnbindManagerReq) (*UnbindManagerResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UnbindManager not implemented")
}
func (UnimplementedCastServer) BindManager(context.Context, *BindManagerReq) (*emptypb.Empty, error) {
@ -194,6 +266,30 @@ func (UnimplementedCastServer) MediaAccounts(context.Context, *MediaAccountsReq)
func (UnimplementedCastServer) MediaWorks(context.Context, *MediaWorksReq) (*MediaWorksResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method MediaWorks not implemented")
}
func (UnimplementedCastServer) RePublish(context.Context, *RePublishReq) (*RePublishResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method RePublish not implemented")
}
func (UnimplementedCastServer) DelWork(context.Context, *DelWorkReq) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method DelWork not implemented")
}
func (UnimplementedCastServer) WorkInfo(context.Context, *WorkInfoReq) (*WorkInfoResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method WorkInfo not implemented")
}
func (UnimplementedCastServer) OAuthAccount(context.Context, *OAuthAccountReq) (*OAuthAccountResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method OAuthAccount not implemented")
}
func (UnimplementedCastServer) OAuthCodeToToken(context.Context, *OAuthCodeToTokenReq) (*OAuthCodeToTokenResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method OAuthCodeToToken not implemented")
}
func (UnimplementedCastServer) RefreshToken(context.Context, *RefreshTokenReq) (*RefreshTokenResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method RefreshToken not implemented")
}
func (UnimplementedCastServer) PublishMediaInfo(context.Context, *PublishMediaInfoReq) (*PublishMediaInfoResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method PublishMediaInfo not implemented")
}
func (UnimplementedCastServer) Test(context.Context, *emptypb.Empty) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method Test not implemented")
}
func (s *UnimplementedCastServer) XXX_SetProxyImpl(impl protocol.Invoker) {
s.proxyImpl = impl
}
@ -541,6 +637,238 @@ func _Cast_MediaWorks_Handler(srv interface{}, ctx context.Context, dec func(int
return interceptor(ctx, in, info, handler)
}
func _Cast_RePublish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(RePublishReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("RePublish", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Cast_DelWork_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(DelWorkReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("DelWork", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Cast_WorkInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(WorkInfoReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("WorkInfo", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Cast_OAuthAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(OAuthAccountReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("OAuthAccount", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Cast_OAuthCodeToToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(OAuthCodeToTokenReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("OAuthCodeToToken", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Cast_RefreshToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(RefreshTokenReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("RefreshToken", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Cast_PublishMediaInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(PublishMediaInfoReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("PublishMediaInfo", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _Cast_Test_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(emptypb.Empty)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("Test", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
// Cast_ServiceDesc is the grpc_go.ServiceDesc for Cast service.
// It's only intended for direct use with grpc_go.RegisterService,
// and not to be introspected or modified (even as a copy)
@ -592,6 +920,38 @@ var Cast_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "MediaWorks",
Handler: _Cast_MediaWorks_Handler,
},
{
MethodName: "RePublish",
Handler: _Cast_RePublish_Handler,
},
{
MethodName: "DelWork",
Handler: _Cast_DelWork_Handler,
},
{
MethodName: "WorkInfo",
Handler: _Cast_WorkInfo_Handler,
},
{
MethodName: "OAuthAccount",
Handler: _Cast_OAuthAccount_Handler,
},
{
MethodName: "OAuthCodeToToken",
Handler: _Cast_OAuthCodeToToken_Handler,
},
{
MethodName: "RefreshToken",
Handler: _Cast_RefreshToken_Handler,
},
{
MethodName: "PublishMediaInfo",
Handler: _Cast_PublishMediaInfo_Handler,
},
{
MethodName: "Test",
Handler: _Cast_Test_Handler,
},
},
Streams: []grpc_go.StreamDesc{},
Metadata: "pb/fiee/cast.proto",

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
syntax = "proto3";
package secFilings;
//import "descriptor.proto";
//import "validator.proto";
option go_package = "./;secFilings";
service SecFilings{
rpc CreateSecFiling(CreateSecFilingReq) returns (CommonResp) {}
rpc UpdateSecFiling(UpdateSecFilingReq) returns (CommonResp) {}
rpc DetailSecFiling(DetailSecFilingReq) returns (SecFilingDetailResp) {}
rpc ListSecFiling(ListSecFilingReq) returns (SecFilingListResp) {}
rpc DeleteSecFiling(DeleteSecFilingReq)returns(CommonResp){}
rpc IsSecFilingExist(IsSecFilingExistReq) returns (IsSecFilingExistResp) {}
rpc UpdateSecFilingStatus(UpdateSecFilingStatusReq) returns(CommonResp) {}
rpc ListFormType(ListFormTypeReq) returns (FormTypeListResp) {}
rpc WebListSecFiling(WebListSecFilingReq) returns (WebListSecFilingResp) {}
}
message ListFormTypeReq{
int32 page = 1;
int32 pageSize = 2;
}
message FormTypeListResp{
int64 total = 1;
repeated FormType formType = 2;
}
message FormType{
int32 id = 1;
string formType = 2;
}
message IsSecFilingExistReq{
string filingDate = 1;
string form = 2;
string finalLink = 3;
}
message IsSecFilingExistResp{
bool exist = 1;
}
message CommonResp{
string msg = 1 [json_name="msg"];
string filingKey = 2[json_name="filing_key"];
}
message SecFiling{
int32 idx = 1 [json_name="idx"];
string filingKey = 2[json_name="filing_key"];
string filingDate = 3[json_name="filing_date"];
string form = 4[json_name="form"];
string description = 5[json_name="description"];
string formDescription = 6[json_name="form_description"];
string fileLink = 7[json_name="file_link"];
repeated DataFiles dataFiles = 8[json_name="data_files"];
string pdfFile = 9[json_name="pdf_file"];
string wordFile = 10[json_name="word_file"];
string excelFile = 11[json_name="excel_file"];
int32 status = 12[json_name="status"];
string operator = 13[json_name="operator"];
int32 operatorId = 14[json_name="operator_id"];
string createdAt =15[json_name="created_at"];
string updatedAt=16[json_name="updated_at"];
}
message DataFiles {
string description = 1[json_name="description"];
string fileUrl = 2[json_name="file_url"];
}
message CreateSecFilingReq{
string filingDate = 1;
string form = 2;
string description = 3;
string formDescription = 4;
string fileLink = 5;
repeated DataFiles dataFiles = 6;
string pdfFile = 7;
string wordFile = 8;
string excelFile = 9;
string operator = 10;
int32 operatorId = 11;
}
message UpdateSecFilingReq{
string filingKey = 1;
string form = 2;
string description = 3;
string formDescription = 4;
string fileLink = 5;
repeated DataFiles dataFiles = 6;
string pdfFile = 7;
string wordFile = 8;
string excelFile = 9;
string operator = 10;
int32 operatorId = 11;
string filingDate = 12;
}
message DetailSecFilingReq{
string filingKey = 1;
}
message SecFilingDetailResp{
string msg = 1;
SecFiling data = 2;
}
message ListSecFilingReq{
uint32 page = 1;
uint32 pageSize = 2;
string form = 3;
string filingDateBegin = 4;
string filingDateEnd = 5;
int32 status = 6;
}
message SecFilingListResp{
string msg = 1 [json_name="msg"];
uint32 total = 2 [json_name="total"];
repeated SecFiling data = 3 [json_name="data"];
}
message WebListSecFilingReq{
uint32 page = 1;
uint32 pageSize = 2;
string year = 3;
string sortField = 4;
string sortOrder = 5;
}
message WebListSecFilingResp{
string msg = 1 [json_name="msg"];
uint32 total = 2 [json_name="total"];
repeated SecFiling data = 3 [json_name="data"];
}
message DeleteSecFilingReq {
string filingKey = 1;
string operator = 2;
int32 operatorId = 3;
}
message UpdateSecFilingStatusReq{
string filingKey = 1;
int32 status = 2;
string operator = 3;
int32 operatorId = 4;
}

View File

@ -0,0 +1,118 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: secFilings.proto
package secFilings
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
func (this *ListFormTypeReq) Validate() error {
return nil
}
func (this *FormTypeListResp) Validate() error {
for _, item := range this.FormType {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("FormType", err)
}
}
}
return nil
}
func (this *FormType) Validate() error {
return nil
}
func (this *IsSecFilingExistReq) Validate() error {
return nil
}
func (this *IsSecFilingExistResp) Validate() error {
return nil
}
func (this *CommonResp) Validate() error {
return nil
}
func (this *SecFiling) Validate() error {
for _, item := range this.DataFiles {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("DataFiles", err)
}
}
}
return nil
}
func (this *DataFiles) Validate() error {
return nil
}
func (this *CreateSecFilingReq) Validate() error {
for _, item := range this.DataFiles {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("DataFiles", err)
}
}
}
return nil
}
func (this *UpdateSecFilingReq) Validate() error {
for _, item := range this.DataFiles {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("DataFiles", err)
}
}
}
return nil
}
func (this *DetailSecFilingReq) Validate() error {
return nil
}
func (this *SecFilingDetailResp) Validate() error {
if this.Data != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Data); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
}
}
return nil
}
func (this *ListSecFilingReq) Validate() error {
return nil
}
func (this *SecFilingListResp) Validate() error {
for _, item := range this.Data {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
}
}
}
return nil
}
func (this *WebListSecFilingReq) Validate() error {
return nil
}
func (this *WebListSecFilingResp) Validate() error {
for _, item := range this.Data {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Data", err)
}
}
}
return nil
}
func (this *DeleteSecFilingReq) Validate() error {
return nil
}
func (this *UpdateSecFilingStatusReq) Validate() error {
return nil
}

View File

@ -0,0 +1,507 @@
// Code generated by protoc-gen-go-triple. DO NOT EDIT.
// versions:
// - protoc-gen-go-triple v1.0.8
// - protoc v3.20.3
// source: secFilings.proto
package secFilings
import (
context "context"
protocol "dubbo.apache.org/dubbo-go/v3/protocol"
dubbo3 "dubbo.apache.org/dubbo-go/v3/protocol/dubbo3"
invocation "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
grpc_go "github.com/dubbogo/grpc-go"
codes "github.com/dubbogo/grpc-go/codes"
metadata "github.com/dubbogo/grpc-go/metadata"
status "github.com/dubbogo/grpc-go/status"
common "github.com/dubbogo/triple/pkg/common"
constant "github.com/dubbogo/triple/pkg/common/constant"
triple "github.com/dubbogo/triple/pkg/triple"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc_go.SupportPackageIsVersion7
// SecFilingsClient is the client API for SecFilings service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type SecFilingsClient interface {
CreateSecFiling(ctx context.Context, in *CreateSecFilingReq, opts ...grpc_go.CallOption) (*CommonResp, common.ErrorWithAttachment)
UpdateSecFiling(ctx context.Context, in *UpdateSecFilingReq, opts ...grpc_go.CallOption) (*CommonResp, common.ErrorWithAttachment)
DetailSecFiling(ctx context.Context, in *DetailSecFilingReq, opts ...grpc_go.CallOption) (*SecFilingDetailResp, common.ErrorWithAttachment)
ListSecFiling(ctx context.Context, in *ListSecFilingReq, opts ...grpc_go.CallOption) (*SecFilingListResp, common.ErrorWithAttachment)
DeleteSecFiling(ctx context.Context, in *DeleteSecFilingReq, opts ...grpc_go.CallOption) (*CommonResp, common.ErrorWithAttachment)
IsSecFilingExist(ctx context.Context, in *IsSecFilingExistReq, opts ...grpc_go.CallOption) (*IsSecFilingExistResp, common.ErrorWithAttachment)
UpdateSecFilingStatus(ctx context.Context, in *UpdateSecFilingStatusReq, opts ...grpc_go.CallOption) (*CommonResp, common.ErrorWithAttachment)
ListFormType(ctx context.Context, in *ListFormTypeReq, opts ...grpc_go.CallOption) (*FormTypeListResp, common.ErrorWithAttachment)
WebListSecFiling(ctx context.Context, in *WebListSecFilingReq, opts ...grpc_go.CallOption) (*WebListSecFilingResp, common.ErrorWithAttachment)
}
type secFilingsClient struct {
cc *triple.TripleConn
}
type SecFilingsClientImpl struct {
CreateSecFiling func(ctx context.Context, in *CreateSecFilingReq) (*CommonResp, error)
UpdateSecFiling func(ctx context.Context, in *UpdateSecFilingReq) (*CommonResp, error)
DetailSecFiling func(ctx context.Context, in *DetailSecFilingReq) (*SecFilingDetailResp, error)
ListSecFiling func(ctx context.Context, in *ListSecFilingReq) (*SecFilingListResp, error)
DeleteSecFiling func(ctx context.Context, in *DeleteSecFilingReq) (*CommonResp, error)
IsSecFilingExist func(ctx context.Context, in *IsSecFilingExistReq) (*IsSecFilingExistResp, error)
UpdateSecFilingStatus func(ctx context.Context, in *UpdateSecFilingStatusReq) (*CommonResp, error)
ListFormType func(ctx context.Context, in *ListFormTypeReq) (*FormTypeListResp, error)
WebListSecFiling func(ctx context.Context, in *WebListSecFilingReq) (*WebListSecFilingResp, error)
}
func (c *SecFilingsClientImpl) GetDubboStub(cc *triple.TripleConn) SecFilingsClient {
return NewSecFilingsClient(cc)
}
func (c *SecFilingsClientImpl) XXX_InterfaceName() string {
return "secFilings.SecFilings"
}
func NewSecFilingsClient(cc *triple.TripleConn) SecFilingsClient {
return &secFilingsClient{cc}
}
func (c *secFilingsClient) CreateSecFiling(ctx context.Context, in *CreateSecFilingReq, opts ...grpc_go.CallOption) (*CommonResp, common.ErrorWithAttachment) {
out := new(CommonResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/CreateSecFiling", in, out)
}
func (c *secFilingsClient) UpdateSecFiling(ctx context.Context, in *UpdateSecFilingReq, opts ...grpc_go.CallOption) (*CommonResp, common.ErrorWithAttachment) {
out := new(CommonResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateSecFiling", in, out)
}
func (c *secFilingsClient) DetailSecFiling(ctx context.Context, in *DetailSecFilingReq, opts ...grpc_go.CallOption) (*SecFilingDetailResp, common.ErrorWithAttachment) {
out := new(SecFilingDetailResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/DetailSecFiling", in, out)
}
func (c *secFilingsClient) ListSecFiling(ctx context.Context, in *ListSecFilingReq, opts ...grpc_go.CallOption) (*SecFilingListResp, common.ErrorWithAttachment) {
out := new(SecFilingListResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/ListSecFiling", in, out)
}
func (c *secFilingsClient) DeleteSecFiling(ctx context.Context, in *DeleteSecFilingReq, opts ...grpc_go.CallOption) (*CommonResp, common.ErrorWithAttachment) {
out := new(CommonResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/DeleteSecFiling", in, out)
}
func (c *secFilingsClient) IsSecFilingExist(ctx context.Context, in *IsSecFilingExistReq, opts ...grpc_go.CallOption) (*IsSecFilingExistResp, common.ErrorWithAttachment) {
out := new(IsSecFilingExistResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/IsSecFilingExist", in, out)
}
func (c *secFilingsClient) UpdateSecFilingStatus(ctx context.Context, in *UpdateSecFilingStatusReq, opts ...grpc_go.CallOption) (*CommonResp, common.ErrorWithAttachment) {
out := new(CommonResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateSecFilingStatus", in, out)
}
func (c *secFilingsClient) ListFormType(ctx context.Context, in *ListFormTypeReq, opts ...grpc_go.CallOption) (*FormTypeListResp, common.ErrorWithAttachment) {
out := new(FormTypeListResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/ListFormType", in, out)
}
func (c *secFilingsClient) WebListSecFiling(ctx context.Context, in *WebListSecFilingReq, opts ...grpc_go.CallOption) (*WebListSecFilingResp, common.ErrorWithAttachment) {
out := new(WebListSecFilingResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/WebListSecFiling", in, out)
}
// SecFilingsServer is the server API for SecFilings service.
// All implementations must embed UnimplementedSecFilingsServer
// for forward compatibility
type SecFilingsServer interface {
CreateSecFiling(context.Context, *CreateSecFilingReq) (*CommonResp, error)
UpdateSecFiling(context.Context, *UpdateSecFilingReq) (*CommonResp, error)
DetailSecFiling(context.Context, *DetailSecFilingReq) (*SecFilingDetailResp, error)
ListSecFiling(context.Context, *ListSecFilingReq) (*SecFilingListResp, error)
DeleteSecFiling(context.Context, *DeleteSecFilingReq) (*CommonResp, error)
IsSecFilingExist(context.Context, *IsSecFilingExistReq) (*IsSecFilingExistResp, error)
UpdateSecFilingStatus(context.Context, *UpdateSecFilingStatusReq) (*CommonResp, error)
ListFormType(context.Context, *ListFormTypeReq) (*FormTypeListResp, error)
WebListSecFiling(context.Context, *WebListSecFilingReq) (*WebListSecFilingResp, error)
mustEmbedUnimplementedSecFilingsServer()
}
// UnimplementedSecFilingsServer must be embedded to have forward compatible implementations.
type UnimplementedSecFilingsServer struct {
proxyImpl protocol.Invoker
}
func (UnimplementedSecFilingsServer) CreateSecFiling(context.Context, *CreateSecFilingReq) (*CommonResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateSecFiling not implemented")
}
func (UnimplementedSecFilingsServer) UpdateSecFiling(context.Context, *UpdateSecFilingReq) (*CommonResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateSecFiling not implemented")
}
func (UnimplementedSecFilingsServer) DetailSecFiling(context.Context, *DetailSecFilingReq) (*SecFilingDetailResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method DetailSecFiling not implemented")
}
func (UnimplementedSecFilingsServer) ListSecFiling(context.Context, *ListSecFilingReq) (*SecFilingListResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListSecFiling not implemented")
}
func (UnimplementedSecFilingsServer) DeleteSecFiling(context.Context, *DeleteSecFilingReq) (*CommonResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteSecFiling not implemented")
}
func (UnimplementedSecFilingsServer) IsSecFilingExist(context.Context, *IsSecFilingExistReq) (*IsSecFilingExistResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method IsSecFilingExist not implemented")
}
func (UnimplementedSecFilingsServer) UpdateSecFilingStatus(context.Context, *UpdateSecFilingStatusReq) (*CommonResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateSecFilingStatus not implemented")
}
func (UnimplementedSecFilingsServer) ListFormType(context.Context, *ListFormTypeReq) (*FormTypeListResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListFormType not implemented")
}
func (UnimplementedSecFilingsServer) WebListSecFiling(context.Context, *WebListSecFilingReq) (*WebListSecFilingResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method WebListSecFiling not implemented")
}
func (s *UnimplementedSecFilingsServer) XXX_SetProxyImpl(impl protocol.Invoker) {
s.proxyImpl = impl
}
func (s *UnimplementedSecFilingsServer) XXX_GetProxyImpl() protocol.Invoker {
return s.proxyImpl
}
func (s *UnimplementedSecFilingsServer) XXX_ServiceDesc() *grpc_go.ServiceDesc {
return &SecFilings_ServiceDesc
}
func (s *UnimplementedSecFilingsServer) XXX_InterfaceName() string {
return "secFilings.SecFilings"
}
func (UnimplementedSecFilingsServer) mustEmbedUnimplementedSecFilingsServer() {}
// UnsafeSecFilingsServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to SecFilingsServer will
// result in compilation errors.
type UnsafeSecFilingsServer interface {
mustEmbedUnimplementedSecFilingsServer()
}
func RegisterSecFilingsServer(s grpc_go.ServiceRegistrar, srv SecFilingsServer) {
s.RegisterService(&SecFilings_ServiceDesc, srv)
}
func _SecFilings_CreateSecFiling_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateSecFilingReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("CreateSecFiling", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _SecFilings_UpdateSecFiling_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateSecFilingReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("UpdateSecFiling", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _SecFilings_DetailSecFiling_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(DetailSecFilingReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("DetailSecFiling", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _SecFilings_ListSecFiling_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(ListSecFilingReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("ListSecFiling", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _SecFilings_DeleteSecFiling_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteSecFilingReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("DeleteSecFiling", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _SecFilings_IsSecFilingExist_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(IsSecFilingExistReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("IsSecFilingExist", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _SecFilings_UpdateSecFilingStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateSecFilingStatusReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("UpdateSecFilingStatus", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _SecFilings_ListFormType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(ListFormTypeReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("ListFormType", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
func _SecFilings_WebListSecFiling_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(WebListSecFilingReq)
if err := dec(in); err != nil {
return nil, err
}
base := srv.(dubbo3.Dubbo3GrpcService)
args := []interface{}{}
args = append(args, in)
md, _ := metadata.FromIncomingContext(ctx)
invAttachment := make(map[string]interface{}, len(md))
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("WebListSecFiling", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
info := &grpc_go.UnaryServerInfo{
Server: srv,
FullMethod: ctx.Value("XXX_TRIPLE_GO_INTERFACE_NAME").(string),
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
}
return interceptor(ctx, in, info, handler)
}
// SecFilings_ServiceDesc is the grpc_go.ServiceDesc for SecFilings service.
// It's only intended for direct use with grpc_go.RegisterService,
// and not to be introspected or modified (even as a copy)
var SecFilings_ServiceDesc = grpc_go.ServiceDesc{
ServiceName: "secFilings.SecFilings",
HandlerType: (*SecFilingsServer)(nil),
Methods: []grpc_go.MethodDesc{
{
MethodName: "CreateSecFiling",
Handler: _SecFilings_CreateSecFiling_Handler,
},
{
MethodName: "UpdateSecFiling",
Handler: _SecFilings_UpdateSecFiling_Handler,
},
{
MethodName: "DetailSecFiling",
Handler: _SecFilings_DetailSecFiling_Handler,
},
{
MethodName: "ListSecFiling",
Handler: _SecFilings_ListSecFiling_Handler,
},
{
MethodName: "DeleteSecFiling",
Handler: _SecFilings_DeleteSecFiling_Handler,
},
{
MethodName: "IsSecFilingExist",
Handler: _SecFilings_IsSecFilingExist_Handler,
},
{
MethodName: "UpdateSecFilingStatus",
Handler: _SecFilings_UpdateSecFilingStatus_Handler,
},
{
MethodName: "ListFormType",
Handler: _SecFilings_ListFormType_Handler,
},
{
MethodName: "WebListSecFiling",
Handler: _SecFilings_WebListSecFiling_Handler,
},
},
Streams: []grpc_go.StreamDesc{},
Metadata: "secFilings.proto",
}

View File

@ -1,3 +1,4 @@
ls api/account/*.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}';
ls api/bundle/*.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}';
ls api/order/*.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}';
ls api/secFilings/*.pb.go | xargs -n1 -IX bash -c 'sed s/,omitempty// X > X.tmp && mv X{.tmp,}';

View File

@ -21,6 +21,8 @@ import (
"fmt"
"fonchain-fiee/cmd/config"
"fonchain-fiee/pkg/cache"
"fonchain-fiee/pkg/common"
"fonchain-fiee/pkg/logger"
"fonchain-fiee/pkg/router"
)
@ -44,6 +46,7 @@ func bootstrap() (err error) {
fmt.Println(configEnv)
fmt.Println(config.AppConfig)
logger.LogInit(config.AppConfig)
////redis
redisConfig := cache.RedisConfig{
RedisDB: configEnv.Redis.RedisDB,
@ -53,6 +56,7 @@ func bootstrap() (err error) {
}
cache.LoadRedis(redisConfig)
common.Init()
//
//gpt.InitSet(configEnv.Ai.Host, configEnv.Ai.TelNum, configEnv.Ai.Password)
return nil

View File

@ -4,10 +4,11 @@ import (
"errors"
"fmt"
"fonchain-fiee/pkg/common"
"github.com/BurntSushi/toml"
"gopkg.in/ini.v1"
"os"
"strconv"
"github.com/BurntSushi/toml"
"gopkg.in/ini.v1"
)
var (
@ -108,12 +109,16 @@ type Redis struct {
}
type System struct {
Mode string
AppMode string
Version string
HttpPort string
Host string
RedirectUri string
Mode string
AppMode string
Version string
HttpPort string
Host string
RedirectUri string
Domain string
ErpHost string
FieeHost string
AuthRedirectUrl string
}
type Oss struct {
AccessKeyId string
@ -123,6 +128,14 @@ type Oss struct {
BaseDir string
CdnHost string
}
type ZapLog struct {
Level string
Filename string
MaxSize int
MaxAge int
MaxBackups int
}
type Mobile struct {
SK string
AK string
@ -142,6 +155,7 @@ type Config struct {
Mobile Mobile `toml:"mobile"`
Ai Ai `toml:"ai"`
Oss Oss `toml:"oss"`
ZapLog ZapLog `toml:"zapLog"`
}
/********start-配置信息*********/

36
conf/conf.ini Normal file
View File

@ -0,0 +1,36 @@
[system]
Domain = "fiee"
AppMode = "debug"
HttpPort = ":8085"
Host = "http://127.0.0.1:8085"
RedirectUri = "/api/redirect/url"
[bos]
Ak = "ALTAKxrqOQHnAN525Tb2GX4Bhe"
Sk = "d2ecaa9d75114d3b9f42b99014198306"
BucketName = "dci-file-new"
BosUrl = ".bj.bcebos.com"
BosBaseDir = "fonchain-main"
BosHttp = "https://"
BosDomain = "cdns.fontree.cn"
[oss]
AccessKeyId = "${OSS_AK}"
AccessKeySecret = "${OSS_SK}"
Endpoint = "${OSS_ENDPOINTT}"
BucketName = "${OSS_BUCKETNAME}"
BaseDir = "fontree-fiee-test"
CdnHost = "${OSS_CDN}"
[redis]
RedisDB = "2"
RedisAddr = "127.0.0.1:6379"
RedisPW = ""
RedisDBNAme = "2"
[ai]
Host = "https://erpapi.fontree.cn"
TelNum = "18021272627"
Password = "Gy.123456"
[service]
IsHTTPS = false

33
conf/dubbogo.yaml Normal file
View File

@ -0,0 +1,33 @@
dubbo:
registries:
demoZK:
protocol: zookeeper
timeout: 5s
address: 127.0.0.1:2181
consumer:
references:
AccountClientImpl:
protocol: tri
retries: 0
interface: com.fontree.microservices.common.Account
filter: echo,metrics,token,accesslog,sign,tps,generic_service,execute
params:
.accessKeyId: "Accountksl"
.secretAccessKey: "BSDY-FDF1-Fontree_account"
AccountFieeClientImpl:
protocol: tri
retries: 0
interface: com.fontree.microservices.common.micro.account.fiee
# filter: cshutdown,sign,fonDomainFilter,fonValidateFilter
# params:
# .accessKeyId: "Accountksl"
# .secretAccessKey: "BSDY-FDF1-Fontree_account"
BundleClientImpl:
protocol: tri
retries: 0
interface: com.fontree.microservices.fiee.bundle # must be compatible with grpc or dubbo-java
SecFilingsClientImpl:
protocol: tri
retries: 0
interface: com.fontree.microservices.fiee.SecFiling

15
data/policy.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>隐私政策</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; }
</style>
</head>
<body>
<p>H5系统隐私政策</p><p>生效日期2025年9月2日</p><p>1. 信息收集与使用</p><p>收集的个人信息类型</p><p>基础信息手机号、微信昵称、头像、设备信息IMEI、操作系统版本</p><p>支付信息:订单号、支付金额、交易时间(通过加密方式传输,不存储银行卡信息)。</p><p>自媒体平台授权信息,例如:</p><p>抖音API接口权限仅限内容同步</p><p>内容生成数据:用户输入的关键词、风格偏好、历史生成内容。</p><p>收集目的</p><p>账号验证与支付:手机号用于身份核验,支付信息用于完成交易。</p><p>内容发布通过授权信息调用第三方平台API执行用户指令。</p><p>2. 信息共享与转让</p><p>第三方平台接口仅在用户授权范围内调用API不共享用户平台账号密码。</p><p>支付合作方:与微信支付、支付宝等服务商共享订单信息以完成交易。</p><p>法律要求:如配合司法机关调查或响应政府要求,可能披露必要信息。</p><p>3. 用户权利</p><p>访问与控制:</p><p>可随时在“个人中心”查看历史生成内容、订单记录及授权状态。</p><p>删除与撤回:</p><p>可申请删除个人账户及生成内容(不包含已同步至第三方平台的内容)。</p><p>4. 数据安全</p><p>技术措施采用HTTPS加密传输、数据库脱敏存储定期进行安全漏洞检测。</p><p>第三方SDK仅接入必要SDK如微信登录、地图服务等并签署数据保密协议。</p><p>5. 隐私政策更新</p><p>如涉及重大变更(如新增数据收集项),将通过短信/邮件通知并要求重新授权。</p><p>6. 联系我们</p><p>如有疑问,请通过以下方式联系:</p><p>客服邮箱develop@fiee.com</p>
</body>
</html>

15
data/service.html Normal file
View File

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>服务条款</title>
<style>
body { font-family: Arial, sans-serif; line-height: 1.6; }
</style>
</head>
<body>
<p>服务条款</p><p>生效日期2025年9月2日</p><p>1. 接受条款</p><p>通过注册或使用本系统(以下简称“服务”),您确认已阅读、理解并同意以下条款。若您不同意本条款,请立即停止使用本服务。</p><p>2. 服务内容</p><p>本系统提供自媒体内容生成与发布服务,用户可购买套餐后生成图文、短视频等原创内容,并通过系统接口同步至指定自媒体平台(如微信公众号、抖音、小红书等)。</p><p>服务包含AI辅助创作、内容优化建议、一键发布功能具体内容以实际功能模块为准。</p><p>3. 用户权利与义务</p><p>账号与支付</p><p>注册需提供手机号或微信授权,购买套餐需通过系统支持的支付方式(如微信支付、支付宝)。</p><p>您需确保支付账户信息真实有效,因虚假信息导致的损失由您自行承担。</p><p>内容生成与发布</p><p>生成内容为原创作品,最终发布权归用户所有。</p><p>用户需对生成内容进行人工审核,确认无误后方可发布。因内容违规导致的平台处罚或法律纠纷,责任由用户承担。</p><p>系统不对用户未审核内容的合规性负责,但有权对明显违法内容(如涉黄、涉政)进行过滤拦截。</p><p>第三方平台接口</p><p>用户需授权系统调用其自媒体平台API如tiktok开发者接口授权范围限于内容发布及数据同步。</p><p>授权信息仅用于执行用户指令,系统不存储用户平台账号密码等敏感信息。</p><p>4. 套餐与退款</p><p>套餐有效期自购买成功日起计算,逾期未使用的套餐不支持退款。</p><p>如因系统故障或服务瑕疵导致无法正常使用,可联系客服协商退款。</p><p>5. 知识产权</p><p>由系统生成的内容(如文案、图片)默认无版权归属限制,但用户需遵守以下规则:</p><p>不得将内容用于商业用途(如转售、批量分发);</p><p>不得篡改系统生成内容的署名或标识;</p><p>若内容包含第三方素材(如音乐、图片),用户需自行确保使用合法性。</p><p>6. 责任限制</p><p>系统不对以下情形承担责任:</p><p>用户未审核内容导致的平台封禁、投诉或法律风险;</p><p>第三方平台接口变更或服务中断;</p><p>因不可抗力(如网络故障)导致的发布延迟。</p><p>7. 其他</p><p>本条款解释权归服务提供方所有,更新后将在系统内公示,用户继续使用即视为同意。</p>
</body>
</html>

View File

@ -1,9 +1,12 @@
[system]
Domain = "artistinfo"
Domain = "app"
AppMode = "dev"
HttpPort = ":8085"
Host = "https://common.szjixun.cn"
RedirectUri = "/api/redirect/url"
ErpHost = "http://114.218.158.24:9020"
FieeHost = "http://114.218.158.24:9020"
AuthRedirectUrl = "http://172.16.100.99:9028/media_account"
[bos]
Ak = "ALTAKxrqOQHnAN525Tb2GX4Bhe"
@ -14,12 +17,12 @@ BosBaseDir = "fiee"
BosHttp = "https://"
BosDomain = "cdns.fontree.cn"
[oss]
AccessKeyId = "LTAI5tLz1fSK53FQAEC9uNSb"
AccessKeySecret = "oGB9chrQzQzITXR2IGv37Ji5WxZh4j"
Endpoint = "oss-cn-hangzhou.aliyuncs.com"
BucketName = "fontree-test"
BaseDir = "fiee"
CdnHost = "https://cdn-test.szjixun.cn"
AccessKeyId = "OSS_AK"
AccessKeySecret = "OSS_SK"
Endpoint = "OSS_ENDPOINTT"
BucketName = "OSS_BUCKETNAME"
BaseDir = "fontree-fiee-test"
CdnHost = "OSS_CDN"
[redis]
RedisDB = "2"
@ -34,3 +37,10 @@ Password = "Gy.123456"
[stripe]
Webhookkey = "whsec_uOQpG6IZTqtfLuePIDtfLCGJPqedSCCN"
[zapLog]
level = "info"
filename = "logs/fiee_zap.log"
max_size = 5
max_age = 30
max_backups = 30

View File

@ -4,8 +4,8 @@ dubbo:
protocol: zookeeper
timeout: 3s
# address: 121.229.45.214:9004
# address: 172.16.100.93:2181
address: 127.0.0.1:2181
# address: 127.0.0.1:2181
# address: 114.218.158.24:2181
consumer:
filter: tracing
@ -37,11 +37,53 @@ dubbo:
interface: com.fontree.microservices.common.micro.account.fiee
# filter: echo,metrics,token,accesslog,sign,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
PaymentCentClientImpl:
interface: com.fontree.microservices.common.payment # must be compatible with grpc or dubbo-java
filter: cshutdown,sign,auth
params:
.accessKeyId: "Paymentksl"
.secretAccessKey: "BSDY-FDF1-Fontree_payment"
protocol: tri
retries: 0
interface: com.fontree.microservices.common.payment.cent # must be compatible with grpc or dubbo-java
CastClientImpl:
protocol: tri
interface: com.fontree.microservices.fiee.multicast
SecFilingsClientImpl:
protocol: tri
retries: 0
interface: com.fontree.microservices.fiee.SecFiling
logger:
zap-config:
level: error # 日志级别
development: false
disableCaller: false
disableStacktrace: false
encoding: "json"
# zap encoder 配置
encoderConfig:
messageKey: "message"
levelKey: "level"
timeKey: "time"
nameKey: "logger"
callerKey: "caller"
stacktraceKey: "stacktrace"
lineEnding: ""
levelEncoder: "capitalColor"
timeEncoder: "iso8601"
durationEncoder: "seconds"
callerEncoder: "short"
nameEncoder: ""
EncodeTime: zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000"),
EncodeDuration: zapcore.SecondsDurationEncoder,
outputPaths:
- "stderr"
errorOutputPaths:
- "stderr"
lumberjack-config:
# 写日志的文件名称
filename: "runtime/logs/fiee.log"
# 每个日志文件长度的最大大小,单位是 MiB。默认 100MiB
maxSize: 5
# 日志保留的最大天数(只保留最近多少天的日志)
maxAge: 30
# 只保留最近多少个日志文件,用于控制程序总日志的大小
maxBackups: 30
# 是否使用本地时间,默认使用 UTC 时间
localTime: true
# 是否压缩日志文件,压缩方法 gzip
compress: false

View File

@ -1,10 +1,12 @@
[system]
Domain = "artistinfo"
Domain = "app"
AppMode = "prod"
HttpPort = ":8085"
Host = "https://common.szjixun.cn"
RedirectUri = "/api/redirect/url"
ErpHost = "https://erpapi.fontree.cn"
FieeHost = "https://erpapi.fiee.com"
AuthRedirectUrl = "https://erp.fiee.com/media_account"
[bos]
Ak = "ALTAKxrqOQHnAN525Tb2GX4Bhe"
Sk = "d2ecaa9d75114d3b9f42b99014198306"
@ -25,12 +27,19 @@ TelNum = "18021272627"
Password = "Gy.123456"
[oss]
AccessKeyId = "LTAI5tHfjSmWXHqfWgaL7Uo5"
AccessKeySecret = "kOPctFZ3DHsbdSSym1fLyDK39hkzPI"
Endpoint = "oss-cn-hangzhou.aliyuncs.com"
BucketName = "erp-k8s-store"
BaseDir = "fiee"
CdnHost = "https://e-cdn.fontree.cn"
AccessKeyId = "OSS_AK"
AccessKeySecret = "OSS_SK"
Endpoint = "OSS_ENDPOINTT"
BucketName = "OSS_BUCKETNAME"
BaseDir = "fontree-fiee"
CdnHost = "OSS_CDN"
[stripe]
Webhookkey = "whsec_Mol32WD1KcKHUdYsSwap0LR03q2g9qNY"
Webhookkey = "whsec_Mol32WD1KcKHUdYsSwap0LR03q2g9qNY"
[zapLog]
level = "info"
filename = "logs/fiee_zap.log"
max_size = 5
max_age = 30
max_backups = 30

View File

@ -45,3 +45,47 @@ dubbo:
CastClientImpl:
protocol: tri
interface: com.fontree.microservices.fiee.multicast
SecFilingsClientImpl:
protocol: tri
retries: 0
interface: com.fontree.microservices.fiee.SecFiling
logger:
zap-config:
level: error # 日志级别
development: false
disableCaller: false
disableStacktrace: false
encoding: "json"
# zap encoder 配置
encoderConfig:
messageKey: "message"
levelKey: "level"
timeKey: "time"
nameKey: "logger"
callerKey: "caller"
stacktraceKey: "stacktrace"
lineEnding: ""
levelEncoder: "capitalColor"
timeEncoder: "iso8601"
durationEncoder: "seconds"
callerEncoder: "short"
nameEncoder: ""
EncodeTime: zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000"),
EncodeDuration: zapcore.SecondsDurationEncoder,
outputPaths:
- "stderr"
errorOutputPaths:
- "stderr"
lumberjack-config:
# 写日志的文件名称
filename: "runtime/logs/fiee.log"
# 每个日志文件长度的最大大小,单位是 MiB。默认 100MiB
maxSize: 5
# 日志保留的最大天数(只保留最近多少天的日志)
maxAge: 30
# 只保留最近多少个日志文件,用于控制程序总日志的大小
maxBackups: 30
# 是否使用本地时间,默认使用 UTC 时间
localTime: true
# 是否压缩日志文件,压缩方法 gzip
compress: false

View File

@ -1,10 +1,13 @@
[system]
Domain = "artistinfo"
Domain = "app"
AppMode = "test"
HttpPort = ":8085"
Host = "https://common.szjixun.cn"
RedirectUri = "/api/redirect/url"
ErpHost = "http://114.218.158.24:9020"
FieeHost = "http://114.218.158.24:9020"
FieeApiHost = "https://saas-test.szjixun.cn"
AuthRedirectUrl = "http://172.16.100.99:9028/media_account"
[bos]
Ak = "ALTAKxrqOQHnAN525Tb2GX4Bhe"
Sk = "d2ecaa9d75114d3b9f42b99014198306"
@ -14,12 +17,12 @@ BosBaseDir = "fiee"
BosHttp = "https://"
BosDomain = "cdns.fontree.cn"
[oss]
AccessKeyId = "LTAI5tLz1fSK53FQAEC9uNSb"
AccessKeySecret = "oGB9chrQzQzITXR2IGv37Ji5WxZh4j"
Endpoint = "oss-cn-hangzhou.aliyuncs.com"
BucketName = "fontree-test"
BaseDir = "fiee"
CdnHost = "https://cdn-test.szjixun.cn"
AccessKeyId = "OSS_AK"
AccessKeySecret = "OSS_SK"
Endpoint = "OSS_ENDPOINTT"
BucketName = "OSS_BUCKETNAME"
BaseDir = "fontree-fiee-test"
CdnHost = "OSS_CDN"
[redis]
RedisDB = "2"
@ -34,3 +37,10 @@ Password = "Gy.123456"
[stripe]
Webhookkey = "whsec_uOQpG6IZTqtfLuePIDtfLCGJPqedSCCN"
[zapLog]
level = "info"
filename = "logs/fiee_zap.log"
max_size = 5
max_age = 30
max_backups = 30

View File

@ -37,11 +37,53 @@ dubbo:
interface: com.fontree.microservices.common.micro.account.fiee
# filter: echo,metrics,token,accesslog,sign,tps,generic_service,execute,pshutdown,auth,fonValidateFilter
PaymentCentClientImpl:
interface: com.fontree.microservices.common.payment # must be compatible with grpc or dubbo-java
filter: cshutdown,sign,auth
params:
.accessKeyId: "Paymentksl"
.secretAccessKey: "BSDY-FDF1-Fontree_payment"
protocol: tri
retries: 0
interface: com.fontree.microservices.common.payment.cent # must be compatible with grpc or dubbo-java
CastClientImpl:
protocol: tri
interface: com.fontree.microservices.fiee.multicast
SecFilingsClientImpl:
protocol: tri
retries: 0
interface: com.fontree.microservices.fiee.SecFiling
logger:
zap-config:
level: error # 日志级别
development: false
disableCaller: false
disableStacktrace: false
encoding: "json"
# zap encoder 配置
encoderConfig:
messageKey: "message"
levelKey: "level"
timeKey: "time"
nameKey: "logger"
callerKey: "caller"
stacktraceKey: "stacktrace"
lineEnding: ""
levelEncoder: "capitalColor"
timeEncoder: "iso8601"
durationEncoder: "seconds"
callerEncoder: "short"
nameEncoder: ""
EncodeTime: zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000"),
EncodeDuration: zapcore.SecondsDurationEncoder,
outputPaths:
- "stderr"
errorOutputPaths:
- "stderr"
lumberjack-config:
# 写日志的文件名称
filename: "runtime/logs/fiee.log"
# 每个日志文件长度的最大大小,单位是 MiB。默认 100MiB
maxSize: 5
# 日志保留的最大天数(只保留最近多少天的日志)
maxAge: 30
# 只保留最近多少个日志文件,用于控制程序总日志的大小
maxBackups: 30
# 是否使用本地时间,默认使用 UTC 时间
localTime: true
# 是否压缩日志文件,压缩方法 gzip
compress: false

41
go.mod
View File

@ -1,11 +1,14 @@
module fonchain-fiee
go 1.18
go 1.23.0
toolchain go1.23.10
replace (
//github.com/fonchain_enterprise/utils/objstorage => ../../tyfon-/utils/objstorage
github.com/fonchain/utils/voice => ../utils/voice
github.com/fonchain_enterprise/utils/aes => ../utils/aes
github.com/fonchain_enterprise/utils/objstorage => ../utils/objstorage
//github.com/fonchain_enterprise/utils/objstorage => ../../tyfon-/utils/objstorage
)
//
@ -46,11 +49,11 @@ require (
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/goccy/go-json v0.10.2
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/gorilla/websocket v1.5.0
github.com/jinzhu/copier v0.3.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/k0kubun/pp v3.0.1+incompatible // indirect
@ -86,10 +89,10 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.21.0
golang.org/x/crypto v0.19.0 // indirect
golang.org/x/net v0.21.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/crypto v0.38.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect
google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247 // indirect
google.golang.org/grpc v1.47.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
@ -102,22 +105,27 @@ require (
github.com/PuerkitoBio/goquery v1.8.1
github.com/disintegration/imaging v1.6.2
github.com/envoyproxy/protoc-gen-validate v0.1.0
github.com/fonchain/utils/voice v0.0.0-00010101000000-000000000000
github.com/fonchain_enterprise/utils/objstorage v0.0.0-00010101000000-000000000000
github.com/gin-contrib/pprof v1.4.0
github.com/go-redis/redis v6.15.9+incompatible
github.com/mholt/archiver v3.1.1+incompatible
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/signintech/gopdf v0.29.2
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/spf13/viper v1.7.1
github.com/tealeg/xlsx v1.0.5
github.com/u2takey/ffmpeg-go v0.5.0
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
github.com/xuri/excelize/v2 v2.9.1
golang.org/x/image v0.25.0
)
require (
cloud.google.com/go v0.65.0 // indirect
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 // indirect
github.com/alibaba/sentinel-golang v1.0.4 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1376 // indirect
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/aws/aws-sdk-go v1.38.20 // indirect
github.com/baidubce/bce-sdk-go v0.9.123 // indirect
@ -129,6 +137,8 @@ require (
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/dorlolo/simpleRequest v1.2.7 // indirect
github.com/dsnet/compress v0.0.1 // indirect
github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5 // indirect
github.com/emicklei/go-restful/v3 v3.7.4 // indirect
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1 // indirect
@ -152,13 +162,15 @@ require (
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/natefinch/lumberjack v2.0.0+incompatible // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/nxadm/tail v1.4.11 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.18.1 // indirect
github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 // indirect
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
github.com/polarismesh/polaris-go v1.1.0 // indirect
github.com/richardlehane/mscfb v1.0.4 // indirect
github.com/richardlehane/msoleps v1.0.4 // indirect
github.com/shirou/gopsutil/v3 v3.21.6 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/smartystreets/assertions v1.1.1 // indirect
@ -168,10 +180,15 @@ require (
github.com/spf13/jwalterweatherman v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/tiendc/go-deepcopy v1.6.0 // indirect
github.com/tklauser/go-sysconf v0.3.6 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/u2takey/go-utils v0.3.1 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xuri/efp v0.0.1 // indirect
github.com/xuri/nfp v0.0.1 // indirect
github.com/zouyx/agollo/v3 v3.4.5 // indirect
go.etcd.io/etcd/api/v3 v3.5.4 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect
@ -180,7 +197,7 @@ require (
go.opentelemetry.io/otel/trace v1.7.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sync v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect

62
go.sum
View File

@ -71,8 +71,9 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alibaba/sentinel-golang v1.0.4 h1:i0wtMvNVdy7vM4DdzYrlC4r/Mpk1OKUUBurKKkWhEo8=
github.com/alibaba/sentinel-golang v1.0.4/go.mod h1:Lag5rIYyJiPOylK8Kku2P+a23gdKMMqzQS7wTnjWEpk=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18 h1:zOVTBdCKFd9JbCKz9/nt+FovbjPFmb7mUnp8nH9fQBA=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1376 h1:lExo7heZgdFn5AbaNJEllbA0KSJ/Z8T7MphvMREJOOo=
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1376/go.mod h1:9CMdKNL3ynIGPpfTcdwTvIm8SGuAZYYC4jFVSSvE1YQ=
github.com/aliyun/aliyun-oss-go-sdk v2.2.4+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible h1:KXeJoM1wo9I/6xPTyt6qCxoSZnmASiAjlrr0dyTUKt8=
github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
@ -187,6 +188,11 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
github.com/dorlolo/simpleRequest v1.2.7 h1:I6AlEhMBSZPNQ4QjpCevhpxsPRDa3lgDOxJYYfmPTU8=
github.com/dorlolo/simpleRequest v1.2.7/go.mod h1:koVT8DQu+JK40UoMNBQjt+zomlCW8FqE0ffEzjTOWYY=
github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dubbogo/go-zookeeper v1.0.3/go.mod h1:fn6n2CAEer3novYgk9ULLwAjuV8/g4DdC2ENwRb6E+c=
github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5 h1:XoR8SSVziXe698dt4uZYDfsmHpKLemqAgFyndQsq5Kw=
github.com/dubbogo/go-zookeeper v1.0.4-0.20211212162352-f9d2183d89d5/go.mod h1:fn6n2CAEer3novYgk9ULLwAjuV8/g4DdC2ENwRb6E+c=
@ -284,6 +290,7 @@ github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@ -533,6 +540,8 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
@ -583,6 +592,8 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
@ -637,6 +648,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk=
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
@ -747,6 +760,11 @@ github.com/prometheus/statsd_exporter v0.21.0/go.mod h1:rbT83sZq2V+p73lHhPZfMc3M
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
@ -829,13 +847,18 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tealeg/xlsx v1.0.5 h1:+f8oFmvY8Gw1iUXzPk+kz+4GpbDZPK1FhPiQRd+ypgE=
github.com/tealeg/xlsx v1.0.5/go.mod h1:btRS8dz54TDnvKNosuAqxrM1QgN1udgk9O34bDCnORM=
github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
github.com/tevid/gohamcrest v1.1.1 h1:ou+xSqlIw1xfGTg1uq1nif/htZ2S3EzRqLm2BP+tYU0=
github.com/tevid/gohamcrest v1.1.1/go.mod h1:3UvtWlqm8j5JbwYZh80D/PVBt0mJ1eJiYgZMibh0H/k=
github.com/tiendc/go-deepcopy v1.6.0 h1:0UtfV/imoCwlLxVsyfUd4hNHnB3drXsfle+wzSCA5Wo=
github.com/tiendc/go-deepcopy v1.6.0/go.mod h1:toXoeQoUqXOOS/X4sKuiAoSk6elIdqc0pN7MTgOOo2I=
github.com/tklauser/go-sysconf v0.3.6 h1:oc1sJWvKkmvIxhDHeKWvZS4f6AW+YcoguSfRF2/Hmo4=
github.com/tklauser/go-sysconf v0.3.6/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
@ -865,10 +888,21 @@ github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxW
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc=
github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
github.com/xuri/excelize/v2 v2.9.1 h1:VdSGk+rraGmgLHGFaGG9/9IWu1nj4ufjJ7uwMDtj8Qw=
github.com/xuri/excelize/v2 v2.9.1/go.mod h1:x7L6pKz2dvo9ejrRuD8Lnl98z4JLt0TGAwjhW+EiP8s=
github.com/xuri/nfp v0.0.1 h1:MDamSGatIvp8uOmDP8FnmjuQpu90NzdJxo7242ANR9Q=
github.com/xuri/nfp v0.0.1/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@ -954,8 +988,8 @@ golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -973,8 +1007,9 @@ golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8H
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -1048,8 +1083,8 @@ golang.org/x/net v0.0.0-20211105192438-b53810dc28af/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1070,8 +1105,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1150,8 +1185,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@ -1165,8 +1200,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -1365,6 +1400,7 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=

2
pkg/cache/common.go vendored
View File

@ -17,7 +17,7 @@ type RedisConfig struct {
RedisDbName string
}
//LoadRedis 在中间件中初始化redis链接
// LoadRedis 在中间件中初始化redis链接
func LoadRedis(configEnv RedisConfig) {
db, _ := strconv.ParseUint(configEnv.RedisDbName, 10, 64)
client := redis.NewClient(&redis.Options{

11
pkg/common/file.go Normal file
View File

@ -0,0 +1,11 @@
package common
import "fonchain-fiee/pkg/utils"
func Init() {
_ = utils.CreateDirPath("./runtime")
utils.CopyFile("./data/policy.html", "./runtime")
utils.CopyFile("./data/service.html", "./runtime")
utils.CopyFile("../data/policy.html", "./runtime")
utils.CopyFile("../data/service.html", "./runtime")
}

View File

@ -17,7 +17,6 @@ func TestGptContent(t *testing.T) {
want string
wantErr bool
}{
// TODO: Add test cases.
{args: args{content: "i want many nice cars"}},
{args: args{content: "you are so beautiful,i like(把前面文字翻译成中文,去除斜杠,本括号内的忽略)"}},
{args: args{content: "有一个美丽的蓝色天空,天空下边站着一个小孩,小孩穿着绿色的衣服,绿色的帽子,帽子上有个毛毛虫(把前面文字翻译成英语,如果前面是英语则原样返回,去除斜杠,本括号内的忽略)"}},

126
pkg/common/jwt/common.go Normal file
View File

@ -0,0 +1,126 @@
// Package jwt -----------------------------
// @file : common.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/12 18:07
// -------------------------------------------
package jwt
import (
"context"
"fmt"
"fonchain-fiee/api/account"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/cmd/config"
"fonchain-fiee/pkg/common/m"
"fonchain-fiee/pkg/e"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/utils/secret"
"github.com/gin-gonic/gin"
)
// ParseToChatUser 将token信息转换为聊天室用户信息
func ParseToChatUser(c *gin.Context) (chatUserInfo *accountFiee.ChatUserData, code e.ErrorCodeType) {
//domain := c.GetHeader("Domain")
//if domain == "" {
// domain = c.GetHeader("domain")
// if domain == "" {
// domain = config.AppConfig.System.Domain
// }
//}
fmt.Println("ParseToChatUser ----------- 1")
var domain string
var err error
token := c.GetHeader(e.Authorization)
if token == "" {
fmt.Println("token is empty")
code = e.NotLogin
return
}
ctx := context.Background()
var originId int64 = 0
var newChatUser *accountFiee.ChatUserData
check := true
var fieeJwtInfo *Claims
fieeJwtInfo, err = ParseToken(token, m.JWTSecret)
if err != nil {
fmt.Printf("fiee token parse err:%v\n", err)
check = false
} else {
check = true
domain = config.AppConfig.System.Domain
originId = int64(fieeJwtInfo.ID)
newChatUser = &accountFiee.ChatUserData{
NickName: fieeJwtInfo.NickName,
Account: fieeJwtInfo.Phone,
Role: 1,
Origin: config.AppConfig.System.Domain,
OriginId: int64(fieeJwtInfo.ID),
}
domain = config.AppConfig.System.Domain
fmt.Printf("fiee token decrypt success, domain:%s , originId:%d", domain, originId)
}
fmt.Println("ParseToChatUser ----------- 2")
if !check { //erp用户校验
fmt.Println("ParseToChatUser ----------- 2.1")
token, err = secret.GetJwtFromStr(token)
if err != nil {
check = false
} else {
var fontreeJwtInfo *account.DecryptJwtResponse
fontreeJwtInfo, err = service.AccountProvider.DecryptJwt(ctx, &account.DecryptJwtRequest{Token: token, Domain: e.ErpDomain})
if err != nil || fontreeJwtInfo.IsOffline {
check = false
} else {
check = true
domain = e.ErpDomain
originId = int64(fontreeJwtInfo.ID)
newChatUser = &accountFiee.ChatUserData{
NickName: fontreeJwtInfo.NickName,
Account: fontreeJwtInfo.Account,
Role: 2,
Origin: e.ErpDomain,
OriginId: int64(fontreeJwtInfo.ID),
}
fmt.Printf("fontree token decrypt success, domain:%s , originId:%d\n", domain, originId)
}
}
}
fmt.Println("ParseToChatUser ----------- 3")
if !check {
fmt.Println("ParseToChatUser ----------- 3.1")
fmt.Println("fontree token decrypt err:", err)
code = e.NotLogin
return
}
fmt.Println("ParseToChatUser ----------- 4")
var userQueryRes *accountFiee.GetChatUserListResp
userQueryRes, err = service.AccountFieeProvider.GetChatUserList(c, &accountFiee.GetChatUserListRequest{
Query: &accountFiee.ChatUserData{Origin: domain, OriginId: originId},
Page: 1,
PageSize: 1,
})
if err != nil {
fmt.Println("ParseToChatUser ----------- 4.1")
fmt.Println("获取chat user 失败", err)
code = e.ErrorNotExistUser
return
}
if userQueryRes.Total == 0 {
fmt.Println("ParseToChatUser ----------- 4.2")
createRes, errs := service.AccountFieeProvider.CreateChatUser(c, newChatUser)
if errs == nil {
chatUserInfo = createRes.Data
} else {
fmt.Println("创建chat user 失败", errs)
code = e.ErrorNotExistUser
}
return
} else {
fmt.Println("ParseToChatUser ----------- 4.3")
chatUserInfo = userQueryRes.List[0]
}
return
}

View File

@ -44,23 +44,60 @@ var EnMessages = map[string]string{
"系统提示:已经发送过,验证码尚可用": "System message: Already sent, verification code is still available",
"您的手机号当天发送次数过多,请联系管理员通过密码登录": "Your mobile phone number is sent too many times that day, please contact the administrator to log in through the password",
"您的手机号验证码错误,请确认之后注册": "Your phone number verification code is incorrect, please confirm and register",
"手机号不合法": "The phone number is illegal",
"手机号未更改": "The phone number has not been changed",
"新手机号过期": "New phone number expired",
"验证码错误": "Verification code error",
"验证码未发送": "The verification code was not sent",
"账号不存在": "Account does not exist",
"已实名": "In real name",
"实名审核中,请勿重复提交": "During real-name audit, please do not submit repeatedly",
"用户状态异常,无法进行审核": "The user is abnormal and cannot be audited. Procedure",
"验证码已失效": "The verification code is invalid",
"服务器错误": "Server error",
"验证失败,请控制拼图对齐缺口": "Verification failed, please control puzzle alignment gap",
"滑块验证状态不存在,请退出重试": "The slider verification status does not exist. Please exit and try again",
"请先实名": "Please use your real name first",
"实名审核中": "Real-name verification is underway",
"实名审核失败": "The real-name verification failed",
"未知实名状态": "Unknown real-name status",
"手机号不合法": "The phone number is illegal",
"手机号未更改": "The phone number has not been changed",
"新手机号过期": "New phone number expired",
"验证码错误": "Verification code error",
"验证码未发送": "The verification code was not sent",
"账号不存在": "Account does not exist",
"已实名": "In real name",
"实名审核中,请勿重复提交": "During real-name audit, please do not submit repeatedly",
"用户状态异常,无法进行审核": "The user is abnormal and cannot be audited. Procedure",
"验证码已失效": "The verification code is invalid",
"服务器错误": "Server error",
"验证失败,请控制拼图对齐缺口": "Verification failed, please control puzzle alignment gap",
"滑块验证状态不存在,请退出重试": "The slider verification status does not exist. Please exit and try again",
"语言不能为空": "The language cannot be empty",
"排序参数需为正整数": "The sorting parameter must be a positive integer",
"请先创建中文版本套餐": "Please create the Chinese version bundle first",
"增值服务不存在": "Value-added service does not exist",
"所选增值服务币种与套餐币种不一致": "The selected value-added service currency is not the same as the bundle currency",
"文件转换失败": "File conversion failed",
"每种增值服务类型只可选择一个": "Each type of value-added service can only be selected once",
"保存套餐与增值服务关联失败": "Failed to save bundle with value-added service association",
"删除套餐与增值服务关联失败": "Failed to delete bundle with value-added service association",
"查询套餐与增值服务关联失败": "Failed to query bundle with value-added service association",
"更新套餐与增值服务关联失败": "Failed to update bundle with value-added service association",
"查询增值服务失败": "Failed to query value-added service",
"更新套餐状态失败": "Failed to update bundle status",
"查询增值服务详情失败": "Failed to query value-added service details",
"序列化转换失败": "Serialization conversion failed",
"保存套餐历史记录失败": "Failed to save bundle history record",
"原价不能为空": "Original price cannot be empty",
"原价格式转换失败": "Original price format conversion failed",
"数量参数需为0-99": "Quantity parameter must be between 0 and 99",
"优惠单价需小于等于原价": "The discounted price must be less than or equal to the original price",
"请先创建中文版本增值服务": "Please create the Chinese version value-added service first",
"保存增值服务失败": "Failed to save value-added service",
"保存增值服务历史记录失败": "Failed to save value-added service history record",
"更新增值服务失败": "Failed to update value-added service",
"查询增值服务列表失败": "Failed to query value-added service list",
"计算价格失败": "Failed to calculate price",
"更新成功": "Update successful",
"保存成功": "Save successful",
"优惠单价转换失败": "Discount unit price conversion failed",
"符号错误": "Symbol error",
"条件存在冲突,请重新设置": "Condition conflict exists, please reconfigure",
"币种已修改,已取消关联部分增值服务": "Currency has been modified, some value-added services have been unlinked",
"币种已修改,已取消关联部分套餐": "Currency has been modified, some packages have been unlinked",
"新增增值服务成功": "Successfully added value-added service",
"状态值无效": "Invalid status value",
"套餐已上架,请勿重复操作": "Plan is already published, do not repeat the operation",
"套餐已下架,请勿重复操作": "Plan is already unpublished, do not repeat the operation",
"请先实名": "Please use your real name first",
"实名审核中": "Real-name verification is underway",
"实名审核失败": "The real-name verification failed",
"未知实名状态": "Unknown real-name status",
}
var DeDEMessages = map[string]string{
@ -99,23 +136,60 @@ var DeDEMessages = map[string]string{
"系统提示:已经发送过,验证码尚可用": "Systemnachricht: Bereits gesendet, Verifizierungscode ist noch verfügbar",
"您的手机号当天发送次数过多,请联系管理员通过密码登录": "Ihre Telefonnummer wurde an diesem Tag zu oft gesendet. Bitte wenden Sie sich an den Administrator, um sich über das Passwort anzumelden",
"您的手机号验证码错误,请确认之后注册": "Ihre Telefonnummer Verifizierungscode ist falsch, bitte bestätigen und registrieren",
"手机号不合法": "Telefonnummer ungültig",
"手机号未更改": "Telefonnummer wurde nicht geändert",
"新手机号过期": "Neue Telefonnummer abgelaufen",
"验证码错误": "Verifizierungscode falsch",
"验证码未发送": "Der Verifizierungscode wurde nicht gesendet",
"账号不存在": "Konto existiert nicht",
"已实名": "In echt",
"实名审核中,请勿重复提交": "Während der Echtheitsprüfung bitte nicht wiederholen",
"用户状态异常,无法进行审核": "Der Benutzer ist abnorm und kann nicht geprüft werden. Verfahren",
"验证码已失效": "Der Verifizierungscode ist ungültig",
"服务器错误": "Serverfehler",
"验证失败,请控制拼图对齐缺口": "Überprüfung fehlgeschlagen, bitte Steuerung Puzzle-Ausrichtungslücke",
"滑块验证状态不存在,请退出重试": "Die krümmbestätigung existiert nicht. Bitte beenden sie den vorgang",
"请先实名": "Bitte, nur der name",
"实名审核中": "Contest läuft",
"实名审核失败": "Die confirmation hat versagt",
"未知实名状态": "Noch nicht registriert",
"手机号不合法": "Telefonnummer ungültig",
"手机号未更改": "Telefonnummer wurde nicht geändert",
"新手机号过期": "Neue Telefonnummer abgelaufen",
"验证码错误": "Verifizierungscode falsch",
"验证码未发送": "Der Verifizierungscode wurde nicht gesendet",
"账号不存在": "Konto existiert nicht",
"已实名": "In echt",
"实名审核中,请勿重复提交": "Während der Echtheitsprüfung bitte nicht wiederholen",
"用户状态异常,无法进行审核": "Der Benutzer ist abnorm und kann nicht geprüft werden. Verfahren",
"验证码已失效": "Der Verifizierungscode ist ungültig",
"服务器错误": "Serverfehler",
"验证失败,请控制拼图对齐缺口": "Überprüfung fehlgeschlagen, bitte Steuerung Puzzle-Ausrichtungslücke",
"滑块验证状态不存在,请退出重试": "Die krümmbestätigung existiert nicht. Bitte beenden sie den vorgang",
"语言不能为空": "Sprache darf nicht leer sein",
"排序参数需为正整数": "Sortierparameter muss eine positive ganze Zahl sein",
"请先创建中文版本套餐": "Bitte erstelle das Chinese Version-Paket",
"增值服务不存在": "Der Werbeangebot existiert nicht",
"所选增值服务币种与套餐币种不一致": "Die ausgewählte Währung des Werbeangebots stimmt nicht mit der Währung des Pakets überein",
"文件转换失败": "Datei-Umwandlung fehlgeschlagen",
"每种增值服务类型只可选择一个": "Jeder Werbeangebotstyp kann nur einmal ausgewählt werden",
"保存套餐与增值服务关联失败": "Fehler beim Speichern des Pakets mit Werbeangebot",
"删除套餐与增值服务关联失败": "Fehler beim Löschen des Pakets mit Werbeangebot",
"查询套餐与增值服务关联失败": "Fehler beim Abrufen des Pakets mit Werbeangebot",
"更新套餐与增值服务关联失败": "Fehler beim Aktualisieren des Pakets mit Werbeangebot",
"查询增值服务失败": "Fehler beim Abrufen des Werbeangebots",
"更新套餐状态失败": "Fehler beim Aktualisieren des Paketstatus",
"查询增值服务详情失败": "Fehler beim Abrufen der Werbeangebotsdetails",
"序列化转换失败": "Fehler beim Serialisieren",
"保存套餐历史记录失败": "Fehler beim Speichern des Pakethistorie",
"原价不能为空": "Der reguläre Preis darf nicht leer sein",
"原价格式转换失败": "Fehler beim Umwandeln des regulären Preises",
"数量参数需为0-99": "Die Anzahlsmusterparameter muss eine positive ganze Zahl sein",
"优惠单价需小于等于原价": "Der Rabattpreis muss kleiner oder gleich dem regulären Preis sein",
"请先创建中文版本增值服务": "Bitte erstelle das Chinese Version-Werbeangebot",
"保存增值服务失败": "Fehler beim Speichern des Werbeangebots",
"保存增值服务历史记录失败": "Fehler beim Speichern des Werbeangebots-Historie",
"更新增值服务失败": "Fehler beim Aktualisieren des Werbeangebots",
"查询增值服务列表失败": "Fehler beim Abrufen der Werbeangebotsliste",
"计算价格失败": "Fehler beim Berechnen des Preises",
"更新成功": "Aktualisierung erfolgreich",
"保存成功": "Speichern erfolgreich",
"优惠单价转换失败": "Rabatt-Einzelpreisumrechnung fehlgeschlagen",
"符号错误": "Symbolfehler",
"条件存在冲突,请重新设置": "Bedingungskonflikt vorhanden, bitte neu konfigurieren",
"币种已修改,已取消关联部分增值服务": "Währung wurde geändert, einige Mehrwertdienste wurden getrennt",
"币种已修改,已取消关联部分套餐": "Währung wurde geändert, einige Pakete wurden getrennt",
"新增增值服务成功": "Mehrwertdienst erfolgreich hinzugefügt",
"状态值无效": "Ungültiger Statuswert",
"套餐已上架,请勿重复操作": "Paket ist bereits veröffentlicht, bitte nicht wiederholen",
"套餐已下架,请勿重复操作": "Paket ist bereits zurückgezogen, bitte nicht wiederholen",
"请先实名": "Bitte, nur der name",
"实名审核中": "Contest läuft",
"实名审核失败": "Die confirmation hat versagt",
"未知实名状态": "Noch nicht registriert",
}
var JaJPMessages = map[string]string{
@ -167,10 +241,48 @@ var JaJPMessages = map[string]string{
"服务器错误": "サーバーエラー",
"验证失败,请控制拼图对齐缺口": "検証に失敗しました。パズルの整列ギャップを制御してください",
"滑块验证状态不存在,请退出重试": "スライダー検証状態が存在しません,リトライをログアウトしてください",
"请先实名": "まずは実名でお願いします",
"实名审核中": "実名審査中です",
"实名审核失败": "実名検証失敗です",
"未知实名状态": "未知の実名状態です",
"语言不能为空": "言語が空です",
"排序参数需为正整数": "ソートパラメーターは正の整数でなければなりません",
"请先创建中文版本套餐": "最初に中国語バージョンのパッケージを作成してください",
"增值服务不存在": "付加サービスは存在しません",
"所选增值服务币种与套餐币种不一致": "選択した付加サービスの通貨とパッケージの通貨が一致しません",
"文件转换失败": "ファイル変換に失敗しました",
"每种增值服务类型只可选择一个": "各種付加サービスタイプは一つしか選択できません",
"保存套餐与增值服务关联失败": "パッケージと付加サービスの関連付けの保存に失敗しました",
"删除套餐与增值服务关联失败": "パッケージと付加サービスの関連付けの削除に失敗しました",
"查询套餐与增值服务关联失败": "パッケージと付加サービスの関連付けの検索に失敗しました",
"更新套餐与增值服务关联失败": "パッケージと付加サービスの関連付けの更新に失敗しました",
"查询增值服务失败": "付加サービスの検索に失敗しました",
"更新套餐状态失败": "パッケージステータスの更新に失敗しました",
"查询增值服务详情失败": "付加サービスの詳細検索に失敗しました",
"序列化转换失败": "シリアライズ変換に失敗しました",
"保存套餐历史记录失败": "パッケージ履歴の保存に失敗しました",
"原价不能为空": "原価は空にできません",
"原价格式转换失败": "原価のフォーマット変換に失敗しました",
"数量参数需为0-99": "数量パラメーターは0-99でなければなりません",
"优惠单价需小于等于原价": "割引単価は原価以下でなければなりません",
"请先创建中文版本增值服务": "最初に中国語バージョンの付加サービスを作成してください",
"保存增值服务失败": "付加サービスの保存に失敗しました",
"保存增值服务历史记录失败": "付加サービス履歴の保存に失敗しました",
"更新增值服务失败": "付加サービスの更新に失敗しました",
"查询增值服务列表失败": "付加サービスリストの検索に失敗しました",
"计算价格失败": "価格計算に失敗しました",
"更新成功": "更新が成功しました",
"保存成功": "保存が成功しました",
"优惠单价转换失败": "割引単価変換に失敗しました",
"符号错误": "記号エラー",
"条件存在冲突,请重新设置": "条件が競合しています、再設定してください",
"币种已修改,已取消关联部分增值服务": "通貨が変更され、一部の付加サービスの関連付けが解除されました",
"币种已修改,已取消关联部分套餐": "通貨が変更され、一部のパッケージの関連付けが解除されました",
"新增增值服务成功": "付加サービスの追加に成功しました",
"状态值无效": "状態値が無効です",
"套餐已上架,请勿重复操作": "プランはすでに公開済みです、重複操作は避けてください",
"套餐已下架,请勿重复操作": "プランはすでに非公開です、重複操作は避けてください",
"请先实名": "まずは実名でお願いします",
"实名审核中": "実名審査中です",
"实名审核失败": "実名検証失敗です",
"未知实名状态": "未知の実名状態です",
}
var ZhTWMessages = map[string]string{
@ -222,12 +334,56 @@ var ZhTWMessages = map[string]string{
"服务器错误": "服務器錯誤",
"验证失败,请控制拼图对齐缺口": "驗證失敗,請控制拼圖對齊缺口",
"滑块验证状态不存在,请退出重试": "滑塊驗證狀態不存在,請退出重試",
"请先实名": "請先實名",
"实名审核中": "實名審覈中",
"实名审核失败": "實名審覈失敗",
"未知实名状态": "未知實名狀態",
"已存在标题相同的数据": "已存在標題相同的數據",
"展示数量不能超过5个": "展示數量不能超過5個",
"查询失败": "查詢失敗",
"操作失败": "操作失敗",
"语言不能为空": "語言不能為空",
"排序参数需为正整数": "排序參數需為正整數",
"请先创建中文版本套餐": "請先建立中文版本套餐",
"增值服务不存在": "增值服務不存在",
"所选增值服务币种与套餐币种不一致": "所選增值服務幣種與套餐幣種不一致",
"文件转换失败": "文件轉換失敗",
"每种增值服务类型只可选择一个": "每種增值服務類型只可選擇一個",
"保存套餐与增值服务关联失败": "保存套餐與增值服務關聯失敗",
"删除套餐与增值服务关联失败": "刪除套餐與增值服務關聯失敗",
"查询套餐与增值服务关联失败": "查詢套餐與增值服務關聯失敗",
"更新套餐与增值服务关联失败": "更新套餐與增值服務關聯失敗",
"查询增值服务失败": "查詢增值服務失敗",
"更新套餐状态失败": "更新套餐狀態失敗",
"查询增值服务详情失败": "查詢增值服務詳情失敗",
"序列化转换失败": "序列化轉換失敗",
"保存套餐历史记录失败": "保存套餐歷史記錄失敗",
"原价不能为空": "原價不能為空",
"原价格式转换失败": "原價格式轉換失敗",
"数量参数需为0-99": "數量參數需為0-99",
"优惠单价需小于等于原价": "優惠單價需小於等於原價",
"请先创建中文版本增值服务": "請先建立中文版本增值服務",
"保存增值服务失败": "保存增值服務失敗",
"保存增值服务历史记录失败": "保存增值服務歷史記錄失敗",
"更新增值服务失败": "更新增值服務失敗",
"查询增值服务列表失败": "查詢增值服務列表失敗",
"计算价格失败": "計算價格失敗",
"更新成功": "更新成功",
"保存成功": "儲存成功",
"优惠单价转换失败": "優惠單價轉換失敗",
"符号错误": "符號錯誤",
"条件存在冲突,请重新设置": "條件存在衝突,請重新設定",
"币种已修改,已取消关联部分增值服务": "幣種已修改,已取消關聯部分增值服務",
"币种已修改,已取消关联部分套餐": "幣種已修改,已取消關聯部分套餐",
"新增增值服务成功": "新增增值服務成功",
"状态值无效": "狀態值無效",
"套餐已上架,请勿重复操作": "套餐已上架,請勿重複操作",
"套餐已下架,请勿重复操作": "套餐已下架,請勿重複操作",
"请先实名": "請先實名",
"实名审核中": "實名審覈中",
"实名审核失败": "實名審覈失敗",
"未知实名状态": "未知實名狀態",
"已存在标题相同的数据": "已存在標題相同的數據",
"展示数量不能超过5个": "展示數量不能超過5個",
"查询失败": "查詢失敗",
"操作失败": "操作失敗",
"参数缺失": "參數缺失",
"创建失败": "創建失敗",
"更新失败": "更新失敗",
"删除失败": "刪除失敗",
"更新状态失败": "更新狀態失敗",
}

167
pkg/common/ws/base.go Normal file
View File

@ -0,0 +1,167 @@
// Package ws -----------------------------
// @file : hertzWSUpgrade.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2022/6/28 14:14
// -------------------------------------------
package ws
import (
"encoding/json"
"fonchain-fiee/pkg/e"
"fonchain-fiee/pkg/serializer"
"strings"
)
// 消息结构
type WSMessage struct {
Type string `json:"type"`
Data string `json:"data"`
}
// websocket消息内容
type WsInfo struct {
Type WsType `json:"type"` //消息类型
Content interface{} `json:"content"` //消息内容
From string `json:"from"` //发送者 0为服务端,客户端填写clientId
To string `json:"to"` //接收者 接收消息的用户id
Mark string `json:"mark"`
//Conn *websocket.Conn `json:"-"` //客户端发送消息使用
}
type WsSessionInfo struct {
Type WsType `json:"type"` //消息类型
//SessionId string `json:"sessionId"` //会话Id
Content interface{} `json:"content"` //消息内容
}
// 身份认证消息
type AuthorizationInfo struct {
Type WsType `json:"type"` //消息类型
Content AuthInfo `json:"content"`
}
type AuthInfo struct {
Auth string `json:"auth"`
Domain string `json:"domain"`
}
// 注册消息
type WsRegisterInfo struct {
Type WsType `json:"type"` //消息类型
Content UserInfo `json:"content"` //消息内容
From string `json:"from"` //发送者 0为服务端,客户端填写clientId
To string `json:"to"` //接收者 接收消息的用户id
//Conn *websocket.Conn `json:"-"` //客户端发送消息使用
}
type UserInfo struct {
Uuid string `json:"uuid"` //画家uid
UserId int64 `json:"userId"` //用户id
ClientId string `json:"clientId,omitempty"` //服务端临时签发的客户端uid
}
type TempClientInfo struct {
ClientId string `json:"clientId"`
}
func WsMessageRegisterCallback(clientId string) []byte {
var errMsg = WsInfo{
Type: RegisterType,
Content: map[string]string{
"clientId": clientId,
},
From: "0",
To: clientId,
}
byteMsg, _ := json.Marshal(errMsg)
return byteMsg
}
func WsErrorMessage(wsType WsType, clientId string, code e.ErrorCodeType, err error) []byte {
var ers string
if err != nil {
ers = err.Error()
}
var content = serializer.Response{
Code: code,
Err: ers,
Msg: code.String(),
}
var errMsg = WsInfo{
Type: wsType,
Content: content,
From: "0",
To: clientId,
}
byteMsg, _ := json.Marshal(errMsg)
return byteMsg
}
func WsErrorPermissionDenied(wsType WsType, clientId string) []byte {
var content = serializer.Response{
Code: e.PermissionDenied,
Err: "Permission Denied",
Msg: "拒绝访问",
}
var errMsg = WsInfo{
Type: wsType,
Content: content,
From: "0",
To: clientId,
}
byteMsg, _ := json.Marshal(errMsg)
return byteMsg
}
func WsErrorInvalidDataFormat(clientId string) []byte {
var content = serializer.Response{
Status: e.Failed,
Code: e.Failed,
Err: "Invalid Data Format",
Msg: "发送失败",
}
var errMsg = WsInfo{
Type: ErrorType,
Content: content,
From: "0",
To: clientId,
}
byteMsg, _ := json.Marshal(errMsg)
return byteMsg
}
func WsErrorUnknownMessageType(clientId string) []byte {
var errMsg = WsInfo{
Type: ErrorType,
Content: "Unknown notice type",
From: "0",
To: clientId,
}
byteMsg, _ := json.Marshal(errMsg)
return byteMsg
}
func WsErrorConnection(clientId string, err string, marks ...string) []byte {
mark := ""
if marks != nil {
mark = strings.Join(marks, ";")
}
var errMsg = WsInfo{
Type: ErrorType,
Content: "Connection error:" + err,
From: "0",
To: clientId,
Mark: mark,
}
byteMsg, _ := json.Marshal(errMsg)
return byteMsg
}
func WsChatMessage(clientId string, targetClientId string, msg string) []byte {
var errMsg = WsInfo{
Type: ChatType,
Content: msg,
From: clientId,
To: targetClientId,
}
byteMsg, _ := json.Marshal(errMsg)
return byteMsg
}

392
pkg/common/ws/chatRoom.go Normal file
View File

@ -0,0 +1,392 @@
// Package ws -----------------------------
// @file : chatRoom.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2022/10/21 18:17:17
// -------------------------------------------
package ws
import (
"encoding/json"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/utils"
"github.com/gorilla/websocket"
"go.uber.org/zap"
"log"
"runtime"
"strconv"
"sync"
"time"
)
const (
// Time allowed to write a notice to the peer.
writeWait = 10 * time.Second
// Time allowed to read the next pong notice from the peer.
pongWait = 60 * time.Second
// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10
// Maximum notice size allowed from peer.
maxMessageSize = 1024
)
func NewChatRoom() *ChatRoom {
var room = ChatRoom{
clientsRwLocker: &sync.RWMutex{},
clients: make(map[int64]map[string]*Client),
register: make(clientChan),
UnRegister: make(clientChan),
broadcast: make(broadcastChan),
eventBus: []*EventListener{},
EventRwLocker: &sync.RWMutex{},
}
go room.Run()
return &room
}
type broadcastMessage struct {
UserIds []int64
message []byte
}
type ChatRoomEvent struct {
ListenEvent []ListenEvent
message []byte
SenderId int64
ReceiverIds []int64
}
type (
// Client类型数据管道
clientChan chan *Client
broadcastChan chan *broadcastMessage
)
type ChatRoom struct {
clientsRwLocker *sync.RWMutex
EventRwLocker *sync.RWMutex
//clients 客户端信息存储
//// 支持多客户端连接 map[userId]map[clientId]*Client
clients map[int64]map[string]*Client
//会话 map[sessionId][]*Client
Session map[string][]*Client
//register register 注册管道
register clientChan
//unRegister 注销管道 接收需要注销的客户端
UnRegister clientChan
// 消息广播管道
broadcast broadcastChan
// 事件广播管道,向其它程序推送消息
eventBus []*EventListener
}
func (o *ChatRoom) Run() {
//消息分发
for {
select {
// 注册事件
case newClient := <-o.register:
o.pushEvent(EventUserJoin, EventProgressBefore, nil, newClient)
o.clientsRwLocker.Lock()
//添加到客户端集合中
if o.clients[newClient.UserId] == nil {
o.clients[newClient.UserId] = make(map[string]*Client)
}
o.clients[newClient.UserId][newClient.ClientId] = newClient
//添加到会话集合中
if o.Session == nil {
o.Session = make(map[string][]*Client)
}
if newClient.Waiter {
//客服人员没有默认会话窗口,而是自动加入所有用户的会话
for sessionId, _ := range o.Session {
sessionId := sessionId
if sessionId != newClient.SessionId {
for _, client := range o.clients[newClient.UserId] {
o.Session[sessionId] = append(o.Session[sessionId], client)
}
}
}
// 将自己加入会话
o.Session[newClient.SessionId] = append(o.Session[newClient.SessionId], newClient)
} else {
//普通用户添加会话的逻辑
_, ok := o.Session[newClient.SessionId]
if !ok {
o.Session[newClient.SessionId] = make([]*Client, 0)
//把客服拉入会话
for userId, clientInfo := range o.clients {
if userId == newClient.UserId {
continue
}
for i, client := range clientInfo {
if client != nil && client.Waiter {
//把客服人员客户端加入会话中
o.Session[newClient.SessionId] = append(o.Session[newClient.SessionId], clientInfo[i])
}
}
}
}
// 将自己加入会话
o.Session[newClient.SessionId] = append(o.Session[newClient.SessionId], newClient)
}
o.clientsRwLocker.Unlock() // 统一在最后解锁
o.pushEvent(EventUserJoin, EventProgressAfter, nil, newClient)
//注销事件
case client := <-o.UnRegister:
o.pushEvent(EventUserLeave, EventProgressBefore, nil, client)
//panic 恢复
defer func() {
if r := recover(); r != "" {
const size = 64 << 10
buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)]
err, ok := r.(error)
if !ok {
err = fmt.Errorf("%v", r)
}
log.Fatal("close webosocket connection occured panic , recovered!", zap.Any("client", client), zap.Error(err), zap.String("stack", string(buf)))
}
}()
fmt.Println("ws客户端注销事件触发")
//从客户端集合中删除
if _, ok := o.clients[client.UserId]; ok {
if client != nil && client.Conn != nil {
//_ = client.Conn.WriteMessage(websocket.CloseMessage, []byte{})
_ = client.Conn.Close()
}
o.clients[client.UserId][client.ClientId] = nil
delete(o.clients[client.UserId], client.ClientId)
fmt.Printf("ws客户端%s 被注销\n", client.ClientId)
}
o.pushEvent(EventUserLeave, EventProgressAfter, nil, client)
// 消息群发事件
case messageInfo := <-o.broadcast:
o.Broadcast(messageInfo.message, messageInfo.UserIds...)
}
}
}
func (o *ChatRoom) Register(c *Client) (sessionId string) {
if c.SessionId == "" && !c.Waiter {
//这里的c经常拿不到sessionId所以使用userId固定死
//c.SessionId = fmt.Sprintf("%d-%d", c.UserId, time.Now().Unix())
c.SessionId = fmt.Sprintf("%d", c.UserId)
}
o.register <- c
return c.SessionId
}
// SendSessionMessage
// sendUserId: 发送消息的用户id消息提醒时此用户将会被排除
// sessionId 会话id
// msgType 消息类型
// message: 消息内容
func (o *ChatRoom) SendSessionMessage(sender *accountFiee.ChatUserData, sessionId string, msgType WsType, message any) (userIdInSession []int64, err error) {
fmt.Println("ChatRoom.SendSessionMessage ------------------1")
o.clientsRwLocker.Lock()
defer o.clientsRwLocker.Unlock()
var msg = WsSessionInfo{
Type: msgType,
Content: message,
}
fmt.Println("ChatRoom.SendSessionMessage ------------------2")
msgBytes, _ := json.Marshal(msg)
if o.Session[sessionId] == nil {
err = fmt.Errorf("该会话不存在或已失效")
return
}
fmt.Println("ChatRoom.SendSessionMessage ------------------3")
usableClients := []*Client{}
fmt.Printf("sessionId:[%s],客户端数量%d\n", sessionId, len(o.Session[sessionId]))
pushed := false
for i, client := range o.Session[sessionId] {
if client != nil {
_, exist := o.clients[client.UserId][client.ClientId]
if exist {
usableClients = append(usableClients, o.Session[sessionId][i])
if !pushed {
go o.pushEvent(EventChatMessage, EventProgressBefore, sender, o.Session[sessionId][i], message)
pushed = true
}
}
}
fmt.Printf("client:%+v\n", client)
pushed = false
if client != nil && (client.UserId != sender.ID || sender.Role == 3) {
client.Send <- msgBytes
if !pushed {
go o.pushEvent(EventChatMessage, EventProgressAfter, sender, o.Session[sessionId][i], message)
pushed = true
}
userIdInSession = append(userIdInSession, client.UserId)
}
//client.Send <- msgBytes
}
o.Session[sessionId] = usableClients
fmt.Printf("sessionId:[%s],客户端数量%d\n", sessionId, len(o.Session[sessionId]))
fmt.Println("userIdInSession", userIdInSession)
return
}
func (o *ChatRoom) GetUserIdInSession(sessionId string, withoutUserId ...int64) (userIds []int64) {
fmt.Printf("sessionId:%s withoutUserId:%d\n", sessionId, withoutUserId)
fmt.Println("GetUserIdInSession 1")
if o.Session[sessionId] != nil {
fmt.Printf("GetUserIdInSession 2,o.Session[sessionId]:%+v", o.Session[sessionId])
for _, client := range o.Session[sessionId] {
fmt.Println("session one of userId", client.UserId)
var jump bool
if withoutUserId != nil {
for _, userId := range withoutUserId {
if client.UserId == userId {
jump = true
break
}
}
}
if !jump {
fmt.Println("ADD USER", client.UserId)
userId := client.UserId
userIds = append(userIds, userId)
}
}
}
//针对app没有连接上websocket(聊天室没有检查到用户的客户端此时websocket无法发送通知)但是需要推送app通知给用户的情况进行优化
fmt.Println("GetUserIdInSession 3,userIds:", userIds)
if len(userIds) == 0 {
sessionUserId, _ := strconv.Atoi(sessionId)
add := true
if sessionUserId != 0 {
for _, v := range withoutUserId {
if v == int64(sessionUserId) {
add = false
break
}
}
}
if add {
userIds = append(userIds, int64(sessionUserId))
}
fmt.Println("GetUserIdInSession 4,userIds:", userIds)
}
userIds = utils.Unique(userIds)
fmt.Println("GetUserIdInSession 5,userIds:", userIds)
return
}
// func (o *ChatRoom) RegisterClient(c *Client) {
// o.register <- c
// }
//
// func (o *ChatRoom) DeleteClient(c *Client) {
// o.unRegister <- c
// }
func (o *ChatRoom) Broadcast(message []byte, userIds ...int64) {
fmt.Println("Broadcast -------1")
// 如果userIds为空则群发,否则找到这个用户的ws对象
var clientsToSend []*Client
if userIds == nil {
for _, userClients := range o.clients {
for _, cli := range userClients {
if cli != nil {
clientsToSend = append(clientsToSend, cli)
}
}
}
} else {
for _, userId := range userIds {
userClients, ok := o.clients[userId]
if !ok {
continue
}
for _, cli := range userClients {
if cli != nil {
clientsToSend = append(clientsToSend, cli)
}
}
}
}
// 使用有限的goroutine池发送消息
fmt.Println("Broadcast -------2")
var wg sync.WaitGroup
for _, cli := range clientsToSend {
wg.Add(1)
go func(client *Client) {
defer wg.Done()
err := client.Conn.SetWriteDeadline(time.Now().Add(writeWait))
err = client.Conn.WriteMessage(websocket.TextMessage, message)
if err != nil {
o.UnRegister <- client
}
}(cli)
}
wg.Wait()
fmt.Println("Broadcast -------3 end")
}
// RegisterEventListener 注册聊天室事件监听者
func (o *ChatRoom) RegisterEventListener(listenerChan *EventListener) {
o.EventRwLocker.Lock()
defer o.EventRwLocker.Unlock()
o.eventBus = append(o.eventBus, listenerChan)
}
// 注销监听者
func (o *ChatRoom) UnRegisterEventListener(listenerChan *EventListener) {
o.EventRwLocker.Lock()
defer o.EventRwLocker.Unlock()
var registerListenerList []*EventListener
for i, listener := range o.eventBus {
if listener.Name == listenerChan.Name {
continue
}
registerListenerList = append(registerListenerList, o.eventBus[i])
}
o.eventBus = registerListenerList
}
// pushEvent 推送聊天室事件
func (o *ChatRoom) pushEvent(eventType EventType, progress EventProgress, chatUser *accountFiee.ChatUserData, client *Client, data ...any) {
//o.EventRwLocker.Lock()
//defer o.EventRwLocker.Unlock()
for _, listener := range o.eventBus {
hit := false
for _, need := range listener.ListenEvents {
if need.EventType == eventType && need.ProgressType == progress {
hit = true
break
}
}
if hit == false {
continue
}
msg := ""
if data != nil {
msg = fmt.Sprintf("%v", data[0])
}
listener.Chan <- ListenEventData{
ListenEvent: ListenEvent{
EventType: eventType,
ProgressType: progress,
},
ChatUser: chatUser,
Client: client,
Msg: msg,
Data: data,
}
fmt.Printf("chatRooom 推送事件给%s eventType:%v progress:%v", listener.Name, eventType, progress)
}
}

117
pkg/common/ws/client.go Normal file
View File

@ -0,0 +1,117 @@
// Package ws -----------------------------
// @file : client.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2022/10/21 18:18:05
// -------------------------------------------
package ws
import (
"context"
"fmt"
"github.com/gorilla/websocket"
uuid "github.com/satori/go.uuid"
"go.uber.org/zap"
"log"
"strings"
"time"
)
var (
// 注册事件最大等待时间
limitRegisterWaitTime = time.Second * 6
limitReadTime = time.Second * 5
)
// NewClient 创建客户端实例
//
// param userId 用户id
// param uid 用户uuid
// param conn 客户端websocket连接对象
// return *Client
func NewClient(userId int64, uid string, conn *websocket.Conn, room *ChatRoom) *Client {
uidobj, _ := uuid.NewV4()
var v = &Client{
Room: room,
UserId: userId,
Uuid: uid,
ClientId: strings.Replace(uidobj.String(), "-", "", -1),
Conn: conn,
Send: make(chan []byte, 500),
}
return v
}
type Client struct {
Room *ChatRoom `json:"-" `
UserId int64 `json:"userId" ` //用户id
Uuid string `json:"uuid"` //画家uid
ClientId string `json:"clientId"` //为用户不同设备分配不同的客户端ID
Conn *websocket.Conn `json:"-"`
Send chan []byte
SessionId string `json:"sessionId"` //会话ID同一个用户多客户端登录会话ID相同
Waiter bool `json:"waiter"` //是否是客服
}
func (c *Client) Reading(ctx context.Context, handleFunc ...func(sourceData []byte, cli *Client)) {
defer func() {
c.Room.UnRegister <- c
ctx.Done()
return
}()
//c.Conn.SetReadLimit(maxMessageSize)
c.Conn.SetReadDeadline(time.Now().Add(pongWait))
//接收到ping命令后更新读取时间
c.Conn.SetPongHandler(func(string) error {
c.Conn.SetReadDeadline(time.Now().Add(pongWait))
return nil
})
for {
msgType, byteData, err := c.Conn.ReadMessage()
if msgType == -1 {
return
}
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
log.Println("ws连接已关闭", zap.Error(err))
}
break
}
if handleFunc != nil {
handleFunc[0](byteData, c)
} else {
HandleMessage(byteData, c)
}
}
}
func (c *Client) WriteWait() {
ticker := time.NewTicker(pingPeriod)
defer func() {
ticker.Stop()
c.Conn.Close()
}()
for {
select {
case msg, ok := <-c.Send:
if !ok {
// 聊天室关闭了管道
c.Conn.WriteControl(websocket.CloseMessage, []byte{}, time.Now().Add(writeWait))
return
}
// 设置写入超时
err := c.Conn.SetWriteDeadline(time.Now().Add(writeWait))
fmt.Printf("设置写超时 err check:%v\n", err)
fmt.Printf("发送消息:%+v\n", string(msg))
err = c.Conn.WriteMessage(websocket.TextMessage, msg)
fmt.Printf("发送消息结束 err check:%v\n", err)
case <-ticker.C:
fmt.Println("ping websocket client")
err := c.Conn.SetWriteDeadline(time.Now().Add(writeWait))
fmt.Printf("ping 设置写超时 err check:%v\n", err)
if err := c.Conn.WriteControl(websocket.PingMessage, nil, time.Now().Add(pongWait)); err != nil {
return
}
}
}
}

57
pkg/common/ws/consts.go Normal file
View File

@ -0,0 +1,57 @@
// Package ws -----------------------------
// @file : consts.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/14 09:44
// -------------------------------------------
package ws
import "fonchain-fiee/api/accountFiee"
// websocket 消息类型
type WsType int
const (
RegisterType WsType = iota //用户注册消息
ErrorType //错误消息
TestType //测试消息
ChatType //聊天消息
NewChatMsgType //新消息通知
AuthorizationType //token校验通知
)
// 事件总线中的事件类型
type EventType string
const (
EventConnection EventType = "connection" //websocket连接事件
EventUserJoin EventType = "user_join" //用户/客服加入聊天事件
EventUserLeave EventType = "user_leave" //用户离开事件
EventChatMessage EventType = "chat_message" //聊天消息传递事件
)
// before
type EventProgress string
const (
EventProgressBefore EventProgress = "before"
EventProgressAfter EventProgress = "after"
)
type ListenEvent struct {
EventType EventType `json:"type"`
ProgressType EventProgress `json:"progress"`
}
type ListenEventData struct {
ListenEvent
Client *Client
ChatUser *accountFiee.ChatUserData
Msg string
Data any
}
type ListenEventChan chan ListenEventData
type EventListener struct {
Name string
ListenEvents []ListenEvent //需要监听的事件列表
Chan ListenEventChan
}

View File

@ -0,0 +1,21 @@
// Package utils -----------------------------
// @file : hertzWSUpgrade.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2022/6/28 14:19
// -------------------------------------------
package ws
import (
"github.com/gorilla/websocket"
"net/http"
)
var UpGrader = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
CheckOrigin: func(r *http.Request) bool {
// 检查请求的来源是否允许websocket连接可根据需求自行实现
return true
},
}

53
pkg/common/ws/readme.md Normal file
View File

@ -0,0 +1,53 @@
# wsscoket 对接说明
## 客户端对接测试页面
[{{服务端地址}}/ws/client](http://127.0.0.1:8088/ws/client)
## 客户端对接websocket流程
### websocket的连接
1. 客户端登录后获取uuid
2. 连接服务端websocket后在10s内发送一下格式的数据否则websocket连接将断开。
uuid请添加登录后获取的如果uuid不正确连接也会断开
```json
{
"type": "register",
"from": "",
"to": "0",
"content": {
"uuid":"用户的uuid"
}
}
```
注册成功后服务端将返回客户端临时id
```json
{"clientId":"02de5759-3f0a-47fa-a79f-afe61c39c5aa"}
```
### weboscket 数据发送测试
消息类型`type="test"`时,客户端将会把`content`内容原路返回,以此来测试最基本的通讯功能。
```json
{
"type": "test",
"from": "用户clientId",
"to": "0",
"content": {
"demo":"testdemo"
}
}
```
### websocket消息类型说明
#### 错误消息
在websocket通讯过程中服务端会对客户端发送过来的消息进行验证。
| type字段 | content字段 | 说明 |
|--------|----------------------|------------------------------|
| Error | Permission denied | 拒绝访问。 此报错一般出现在首次连接验证uuid的时候 |
| Error | Invalid data format | 无效的数据格式。消息内容未按照指定格式书写 |
| Error | Unknown message type | 未知的消息类型。接收到了未定义的type |
**错误消息示例:**
```json
{"type":"Error","content":"Permission denied","from":"0","to":"tempId"}
//{"type":"Error","content":"Invalid data format","from":"0","to":""}
//{"type":"Error","content":"Unknown notice type","from":"0","to":"0"}
```

View File

@ -0,0 +1,197 @@
// Package ws -----------------------------
// @file : handler.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2022/10/23 11:13:43
// -------------------------------------------
package ws
import (
"context"
"encoding/json"
"fmt"
"fonchain-fiee/api/account"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/cmd/config"
"fonchain-fiee/pkg/common/jwt"
"fonchain-fiee/pkg/common/m"
"fonchain-fiee/pkg/e"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/utils/secret"
)
func AuthorizationVerify(sourceData []byte) (userInfo *accountFiee.ChatUserData, ok bool, err error) {
fmt.Println("AuthorizationVerify ----------------1")
var msg AuthorizationInfo
err = json.Unmarshal(sourceData, &msg)
if err != nil {
return
}
fmt.Println("AuthorizationVerify ----------------2")
if msg.Type != AuthorizationType {
return
}
fmt.Println("AuthorizationVerify ----------------3")
if msg.Content.Auth == "" {
return
}
fmt.Println("AuthorizationVerify ----------------4")
var check = true
var ctx = context.Background()
var accountInfo accountFiee.ChatUserData
//fiee token校验
switch msg.Content.Domain {
case "app":
var fieeJwtInfo *jwt.Claims
fieeJwtInfo, err = jwt.ParseToken(msg.Content.Auth, m.JWTSecret)
if err != nil {
check = false
fmt.Printf("fiee token parse err:%v\n", err)
} else {
fmt.Printf("fieeJwtInfo :%#v\n", fieeJwtInfo)
accountInfo.Origin = config.AppConfig.System.Domain
//accountInfo.OriginId = int64(fieeJwtInfo.ID)
accountInfo.Account = fieeJwtInfo.Account
accountInfo.NickName = fieeJwtInfo.NickName
infoReq := &accountFiee.UserByTelRequest{
Tel: fieeJwtInfo.Phone,
Domain: config.AppConfig.System.Domain,
}
var accInfo *accountFiee.UserInfoResponse
accInfo, err = service.AccountFieeProvider.UserByTel(ctx, infoReq)
if err != nil {
check = false
fmt.Printf("err:%#v\n", err)
} else if accInfo != nil {
fmt.Printf("fiee accInfo :%#v\n", accInfo)
accountInfo.OriginId = int64(accInfo.Id)
accountInfo.Account = accInfo.TelNum
accountInfo.Avatar = accInfo.GroupPhoto
if accInfo.Name != "" {
accountInfo.NickName = accInfo.Name
}
}
}
case "fontree":
msg.Content.Auth, err = secret.GetJwtFromStr(msg.Content.Auth)
if err != nil {
fmt.Println("token解析失败", err.Error())
check = false
} else {
var fontreeJwtInfo *account.DecryptJwtResponse
fontreeJwtInfo, err = service.AccountProvider.DecryptJwt(ctx, &account.DecryptJwtRequest{Token: msg.Content.Auth, Domain: e.ErpDomain})
if err != nil || fontreeJwtInfo.IsOffline {
check = false
} else {
check = true
fmt.Printf("fontreeJwtInfo is %#v\n", fontreeJwtInfo)
accountInfo.Origin = e.ErpDomain
accountInfo.OriginId = int64(fontreeJwtInfo.ID)
accountInfo.Account = fontreeJwtInfo.Account
accountInfo.NickName = fontreeJwtInfo.NickName
}
}
}
if !check {
return
}
//查询是否已经注册
var chatUserQuery *accountFiee.GetChatUserListResp
chatUserQuery, err = service.AccountFieeProvider.GetChatUserList(ctx, &accountFiee.GetChatUserListRequest{
Query: &accountFiee.ChatUserData{OriginId: accountInfo.OriginId, Origin: msg.Content.Domain},
Page: 1,
PageSize: 1,
})
//如果找不到聊天用户则创建
if err != nil || chatUserQuery.Total == 0 {
//注册客服
var createUserRes *accountFiee.CreateChatUserResp
var createChatUserReq = &accountFiee.ChatUserData{
NickName: accountInfo.NickName,
Account: accountInfo.Account,
Role: 1,
Origin: msg.Content.Domain,
OriginId: accountInfo.OriginId,
}
if msg.Content.Domain == e.ErpDomain {
createChatUserReq.Role = 2
}
createUserRes, err = service.AccountFieeProvider.CreateChatUser(ctx, createChatUserReq)
if err != nil {
return
}
userInfo = createUserRes.GetData()
fmt.Printf("注册聊天用户:%#v\n", userInfo)
} else {
userInfo = chatUserQuery.List[0]
if msg.Content.Domain == config.AppConfig.System.Domain && (accountInfo.NickName != userInfo.NickName || accountInfo.Account != userInfo.Account || accountInfo.Avatar != userInfo.Avatar) {
_, _ = service.AccountFieeProvider.UpdateChatUser(ctx, &accountFiee.ChatUserData{
NickName: accountInfo.NickName,
ID: userInfo.ID,
Account: accountInfo.Account,
Avatar: accountInfo.Avatar,
})
userInfo.NickName = accountInfo.NickName
userInfo.Account = accountInfo.Account
userInfo.Avatar = accountInfo.Avatar
}
fmt.Printf("获取聊天用户:%#v\n", userInfo)
}
ok = true
return
}
func HandleMessage(sourceData []byte, cli *Client) {
var msg WsInfo
err := json.Unmarshal(sourceData, &msg)
if err != nil {
cli.Send <- WsErrorInvalidDataFormat(msg.From)
return
}
switch msg.Type {
default:
cli.Send <- WsErrorUnknownMessageType(msg.From)
//fmt.Printf("不支持的ws业务消息%#v\n", msg)
case TestType:
var newMsg = WsInfo{
Type: TestType,
Content: msg.Content,
From: "0",
To: msg.From,
}
byteMsg, _ := json.Marshal(newMsg)
cli.Send <- byteMsg
case ChatType:
if msg.From == "" {
//客户端id不能为空
cli.Send <- WsErrorMessage(ChatType, "null", e.ErrInvalidClientId, nil)
return
}
var chatInfo ChatInfo
_ = json.Unmarshal(sourceData, &chatInfo)
//解析Content
if clients, ok := cli.Room.clients[chatInfo.Content.TargetUserId]; ok {
for _, targetObj := range clients {
if targetObj != nil {
targetObj.Send <- WsChatMessage(msg.From, chatInfo.Content.TargetClientId, chatInfo.Content.Msg)
}
}
} else {
//对方不在线
cli.Send <- WsErrorMessage(ChatType, msg.From, e.ErrTargetOutLine, nil)
}
}
}
type ChatInfo struct {
Type WsType `json:"type"` //消息类型
Content ChatContent `json:"content"` //消息内容
From string `json:"from"` //发送者 0为服务端,客户端填写clientId
To string `json:"to"` //接收者 接收消息的用户id
}
type ChatContent struct {
TargetUuid string `json:"targetUuid"`
TargetUserId int64 `json:"targetUserId"`
TargetClientId string `json:"targetClientId"`
Msg string `json:"msg"`
}

127
pkg/common/ws/wsRoom.html Normal file
View File

@ -0,0 +1,127 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Chat Example</title>
<script type="text/javascript">
window.onload = function () {
var conn;
var msg = document.getElementById("msg");
var log = document.getElementById("log");
function appendLog(item) {
var doScroll = log.scrollTop > log.scrollHeight - log.clientHeight - 1;
log.appendChild(item);
if (doScroll) {
log.scrollTop = log.scrollHeight - log.clientHeight;
}
}
//时间格式化
Date.prototype.Format = function (fmt) { // author: meizz
var o = {
"M+": this.getMonth() + 1, // 月份
"d+": this.getDate(), // 日
"h+": this.getHours(), // 小时
"m+": this.getMinutes(), // 分
"s+": this.getSeconds(), // 秒
"q+": Math.floor((this.getMonth() + 3) / 3), // 季度
"S": this.getMilliseconds() // 毫秒
};
if (/(y+)/.test(fmt))
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
document.getElementById("form").onsubmit = function () {
if (!conn) {
return false;
}
if (!msg.value) {
return false;
}
conn.send(msg.value);
var item = document.createElement("div");
var now = new Date().Format("yyyy-MM-dd hh:mm:ss:S")
item.innerText = "客户端发送消息:\t"+now+"\n\t\t"+msg.value+"\n\n";
appendLog(item);
msg.value = "";
return false;
};
if (window["WebSocket"]) {
conn = new WebSocket("ws://" + document.location.host + "/ws");
conn.onclose = function (evt) {
var item = document.createElement("div");
item.innerHTML = "<b>Connection closed.</b>";
appendLog(item);
};
conn.onmessage = function (evt) {
var messages = evt.data.split('\n');
var now = new Date().Format("yyyy-MM-dd hh:mm:ss:S")
for (var i = 0; i < messages.length; i++) {
var item = document.createElement("div");
item.innerText = "服务端回复消息:\t"+now+"\n\t\t"+messages[i]+"\n\n";
appendLog(item);
}
};
} else {
var item = document.createElement("div");
item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
appendLog(item);
}
};
</script>
<style type="text/css">
html {
overflow: hidden;
}
body {
overflow: hidden;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
background: gray;
}
#log {
background: white;
margin: 0;
padding: 0.5em 0.5em 0.5em 0.5em;
position: absolute;
top: 0.5em;
left: 0.5em;
right: 0.5em;
bottom: 3em;
overflow: auto;
}
#form {
padding: 0 0.5em 0 0.5em;
margin: 0;
position: absolute;
bottom: 1em;
left: 0px;
width: 100%;
overflow: hidden;
}
input{
height: 50px;
font-size: larger;
}
</style>
</head>
<body>
<div id="log"></div>
<form id="form">
<input type="submit" value="Send" />
<input type="text" id="msg" size="64" autofocus />
</form>
</body>
</html>

View File

@ -4,9 +4,12 @@ import (
"fmt"
"fonchain-fiee/pkg/common"
"github.com/spf13/viper"
"go.uber.org/zap"
"gopkg.in/ini.v1"
"os"
"reflect"
"strconv"
"strings"
)
var (
@ -23,7 +26,6 @@ var (
DriverUrl string
AppointUrl string
MaterialHost string
//TODO
//BosAk string
//BosSk string
//BosBucketName string
@ -31,7 +33,6 @@ var (
//BosUrl string
//BosHttp string
//BosDomain string
//TODO
ProjectMapDir string
JaegerHost string
JaegerOpen bool
@ -251,5 +252,63 @@ func Viper(iniConf string) (err error) {
panic("viper.Unmarshal failed" + err.Error())
return
}
traverseFields(reflect.ValueOf(*ConfigData), "", ConfigData)
zap.L().Info("ConfigData", zap.Any("ConfigData", ConfigData))
fmt.Printf("ConfigData--%+v", ConfigData)
return
}
func traverseFields(value reflect.Value, prefix string, configPtr interface{}) {
valueType := value.Type()
prefixEnv := "${"
suffixEnv := "}"
// 遍历结构体的字段
for i := 0; i < valueType.NumField(); i++ {
field := valueType.Field(i)
fieldValue := value.Field(i)
// 拼接字段名(带有前缀)
fieldName := prefix + field.Name
// 判断字段的类型
if fieldValue.Kind() == reflect.Struct {
// 递归遍历嵌套结构体字段
traverseFields(fieldValue, fieldName+".", configPtr)
} else {
// 获取字段的值
fieldValueStr := fmt.Sprintf("%v", fieldValue.Interface())
// 判断是不是需要通过环境变量获取
if len(fieldValueStr) > 3 && strings.HasPrefix(fieldValueStr, prefixEnv) && strings.HasSuffix(fieldValueStr, suffixEnv) {
end := len(fieldValueStr) - len(suffixEnv)
var hasDefault bool
if strings.Index(fieldValueStr, "|") > 0 {
hasDefault = true
end = strings.Index(fieldValueStr, "|")
}
envStr := fieldValueStr[len(prefixEnv):end]
getValue := os.Getenv(envStr)
if getValue == "" && hasDefault {
getValue = fieldValueStr[end+1 : len(fieldValueStr)-len(suffixEnv)]
}
setSubFieldValue(configPtr, fieldName, getValue)
}
}
}
}
func setSubFieldValue(configPtr interface{}, fieldPath string, newValue interface{}) {
value := reflect.ValueOf(configPtr).Elem()
fields := strings.Split(fieldPath, ".")
for _, field := range fields {
value = value.FieldByName(field)
if !value.IsValid() {
return // 字段不存在,直接返回
}
if value.Kind() == reflect.Ptr {
value = value.Elem() // 解引用指针类型的字段
}
}
// 检查字段是否可设置
if value.CanSet() {
// 根据字段类型,将新值转换为对应类型并设置字段的值
newValue := reflect.ValueOf(newValue).Convert(value.Type())
value.Set(newValue)
}
}

63
pkg/e/chatCode.go Normal file
View File

@ -0,0 +1,63 @@
// Package e -----------------------------
// @file : chatCode.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/12 16:57
// -------------------------------------------
package e
import "fmt"
type ErrorCodeType int
func (e ErrorCodeType) String() string {
return GetCodeMsg(e)
}
func (e ErrorCodeType) Error() string {
return GetCodeMsg(e)
}
func (e ErrorCodeType) Int() int {
return int(e)
}
func GetCodeMsg(e ErrorCodeType) string {
v, ok := msgFlags[e]
if !ok {
return fmt.Sprintf("未知错误:[%d]", e)
}
return v
}
var msgFlags = map[ErrorCodeType]string{
SUCCESS: "操作成功",
UpdatePasswordSuccess: "修改密码成功",
NotExistInentifier: "该第三方账号未绑定",
ERROR: "fail",
InvalidParams: "请求参数错误",
BindError: "参数绑定错误,类型不一致",
JsonUnmarshal: "Json解析错误",
ErrorDatabase: "数据库操作出错,请重试",
ErrorOss: "OSS配置错误",
InvalidToken: "Token验证失败",
ErrorUploadFile: "上传失败",
ErrorUploadVideoCover: "视频截取封面错误",
ErrorUploadValidParam: "上传参数非法",
ErrorFileReadErr: "读取文件错误",
ErrorFileNotExists: "文件不存在",
ErrorChunkNotGt: "分块数量不一致",
ErrorChunk: "读取分块错误",
ErrorUploadBos: "上传bos错误",
ErrorFileCreate: "文件创建错误",
ErrInvalidDataFormat: "无效的数据格式",
ErrInvalidClientId: "无效的客户端ID",
ErrRegisterFailed: "注册失败",
ErrUnRegistered: "未注册客户端",
PermissionDenied: "拒绝访问",
ErrChatSendErr: "消息发送失败",
NotLogin: "请先登录",
ErrorNotExistUser: "用户不存在",
}

View File

@ -13,6 +13,7 @@ const (
const (
DomainAdmin = "blockchain"
ErpDomain = "fontree"
)
const (
@ -20,8 +21,9 @@ const (
)
const (
ErrNotLogin = "请先登录"
ErrOffline = "您已经下线"
ErrNotLogin = "请先登录"
ErrOffline = "您已经下线"
InvalidStatus = "状态非法"
)
const (
@ -139,6 +141,15 @@ const (
ERROR_Text_Irregularity = 90018
ERROR_Text_Length = 90019
ERROR_NoPermission = 90020
//聊天室
ErrInvalidDataFormat = 80100 //无效的数据格式
ErrInvalidClientId = 80101 //无效的客户端id
ErrRegisterFailed = 80102 //注册失败
ErrUnRegistered = 80103 //未注册
PermissionDenied = 80104 //拒绝访问
ErrChatSendErr = 80105 //聊天记录发送失败
ErrTargetOutLine = 80106 //目标离线
)
const (
Push = 1

56
pkg/e/fileType.go Normal file
View File

@ -0,0 +1,56 @@
package e
import "strings"
type FileType int
// 定义文件类型值
const (
Video FileType = 1
Audio FileType = 2
Image FileType = 3
File FileType = 4
Other FileType = 5
)
// 根据扩展名映射到文件类型值
var extensionToType = map[string]FileType{
// 视频文件
".3g2": Video, ".3gp": Video, ".asf": Video, ".avi": Video, ".divx": Video, ".drc": Video,
".flv": Video, ".h261": Video, ".h264": Video, ".mkv": Video, ".mov": Video, ".mp4": Video, ".mpg": Video,
".mpeg": Video, ".mpv": Video, ".mxf": Video, ".nuv": Video, ".qt": Video, ".rm": Video,
".rmvb": Video, ".srt": Video, ".swf": Video, ".vob": Video, ".vp6": Video, ".vp8": Video, ".webm": Video,
".wmv": Video, ".xesc": Video,
// 音频文件
".aac": Audio, ".aax": Audio, ".ac3": Audio, ".act": Audio, ".au": Audio, ".flac": Audio,
".m4a": Audio, ".m4p": Audio, ".m4r": Audio, ".mid": Audio, ".midi": Audio, ".mp2": Audio,
".mp3": Audio, ".mpa": Audio, ".mpc": Audio, ".ogg": Audio, ".wav": Audio, ".wma": Audio, ".wv": Audio,
// 图像文件
".bmp": Image, ".gif": Image, ".ico": Image, ".jpeg": Image, ".jpg": Image, ".jpe": Image,
".png": Image, ".psd": Image, ".tiff": Image, ".webp": Image,
// 普通文件
".a": File, ".abw": File, ".azw": File, ".bin": File, ".bz2": File, ".c": File, ".cab": File,
".class": File, ".conf": File, ".crt": File, ".css": File, ".csv": File, ".dat": File, ".deb": File,
".dll": File, ".dms": File, ".doc": File, ".docx": File, ".eot": File, ".eps": File, ".exe": File,
".gz": File, ".h": File, ".htm": File, ".html": File, ".iso": File, ".jar": File,
".js": File, ".json": File, ".log": File, ".m3u": File, ".m3u8": File, ".md": File, ".msi": File,
".otf": File, ".pcap": File, ".pdf": File, ".ppt": File, ".pptx": File, ".rar": File, ".rpm": File,
".rss": File, ".run": File, ".sh": File, ".sql": File, ".svg": File, ".tar": File, ".tgz": File,
".ttf": File, ".txt": File, ".vsd": File, ".weba": File,
".wps": File, ".xml": File, ".xpi": File, ".zip": File, ".z": File,
// 未知文件扩展名
"": Other,
}
// DetectFileTypeByExtension 通过文件扩展名判断文件类型并返回对应的值
func DetectFileTypeByExtension(extension string) FileType {
extension = strings.ToLower(extension)
if fileType, exists := extensionToType[extension]; exists {
return fileType
}
return Other
}

View File

@ -146,10 +146,13 @@ var MsgFlags = map[int]string{
ERROR_Text_Irregularity: "文字内容不合规",
ERROR_Text_Length: "文本长度超出限制",
ERROR_NoPermission: "您暂无权限,请联系客服",
ErrInvalidClientId: "无效的客户端ID",
}
const (
ErrorCreateFeedback = "请勿重复提交"
ErrorCreateFeedback = "请勿重复提交"
ErrorBalanceInsufficient = "余额不足"
)
// GetMsg 获取状态码对应信息

View File

@ -29,7 +29,7 @@ package e
ERR_NOT_NEED_BALANCE = "无需查询余额"
ErrNoBalance = "假期余额不足"
ErrNoBalance = "余额不足"
ErrHourNoBalance = "请假时长超出范围"
ErrApplyTime = "无效的请假时间"
@ -165,7 +165,7 @@ var errorMessagesZhCN = map[string]string{
"ERR_NOT_NEED_BALANCEZhCN": "无需查询余额",
"ErrNoBalanceZhCN": "假期余额不足",
"ErrNoBalanceZhCN": "余额不足",
"ErrHourNoBalanceZhCN": "请假时长超出范围",
"ErrApplyTimeZhCN": "无效的请假时间",
@ -325,7 +325,7 @@ var errorMessagesZhTW = map[string]string{
"ERR_NOT_NEED_BALANCEZhTW": "無需查詢餘額",
"ErrNoBalanceZhTW": "假期餘額不足",
"ErrNoBalanceZhTW": "餘額不足",
"ErrHourNoBalanceZhTW": "請假時長超出範圍",
"ErrApplyTimeZhTW": "無效的請假時間",

54
pkg/logger/zap_logger.go Normal file
View File

@ -0,0 +1,54 @@
package logger
import (
"fonchain-fiee/cmd/config"
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"os"
)
func LogInit(appConfig *config.Config) *zap.Logger {
var err error
writeSyncer := getLogWriter(appConfig.ZapLog.Filename, appConfig.ZapLog.MaxSize, appConfig.ZapLog.MaxBackups, appConfig.ZapLog.MaxAge)
encoder := getEncoder()
var l = new(zapcore.Level)
err = l.UnmarshalText([]byte(appConfig.ZapLog.Level))
if err != nil {
return nil
}
var core zapcore.Core
//if appConfig.System.Mode == "dev" {
// 进入开发模式,日志输出到终端
consoleEncoder := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
core = zapcore.NewTee(
zapcore.NewCore(encoder, writeSyncer, l),
zapcore.NewCore(consoleEncoder, zapcore.Lock(os.Stdout), zapcore.DebugLevel),
)
//} else {
// core = zapcore.NewCore(encoder, writeSyncer, l)
//}
lg := zap.New(core, zap.AddCaller())
zap.ReplaceGlobals(lg)
return lg
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
encoderConfig.TimeKey = "time"
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder
encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder
return zapcore.NewJSONEncoder(encoderConfig)
}
func getLogWriter(filename string, maxSize, maxBackup, maxAge int) zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: filename,
MaxSize: maxSize,
MaxBackups: maxBackup,
MaxAge: maxAge,
}
return zapcore.AddSync(lumberJackLogger)
}

View File

@ -129,7 +129,7 @@ func MakeThumbnail(imagePath, savePath string) error {
}
func (u *Upload) PutBos(filePath string, mediaType string, needRemove bool) (url string, err error) {
BOSClient, err := objstorage.NewOSS(config.ConfigData.Oss.AccessKeyId, config.ConfigData.Oss.AccessKeySecret, config.ConfigData.Oss.Endpoint)
BOSClient, err := objstorage.NewOSS(os.Getenv(config.ConfigData.Oss.AccessKeyId), os.Getenv(config.ConfigData.Oss.AccessKeySecret), os.Getenv(config.ConfigData.Oss.Endpoint))
if err != nil {
logger.Errorf("PutBos NewOOS err ", err)
err = errors.New(e.GetMsg(e.ErrorUploadBos))
@ -148,14 +148,14 @@ func (u *Upload) PutBos(filePath string, mediaType string, needRemove bool) (url
}
filePath = strings.Replace(filePath, "./runtime", "", 1)
var objectName string = fmt.Sprintf("%s/%s%s", config.ConfigData.Oss.BaseDir, config.Env, filePath)
_, err = BOSClient.PutObjectFromBytes(config.ConfigData.Oss.BucketName, objectName, fileBytes)
_, err = BOSClient.PutObjectFromBytes(os.Getenv(config.ConfigData.Oss.BucketName), objectName, fileBytes)
if err != nil {
logger.Errorf("PutBos PutObject err %+v", err.Error())
err = errors.New(e.GetMsg(e.ErrorUploadBos))
return
}
//url = fmt.Sprintf("%s%s%s/%s", config.BosHttp, config.BosBucketName, config.BosUrl, objectName)
url = fmt.Sprintf("%s/%s", config.ConfigData.Oss.CdnHost, objectName)
url = fmt.Sprintf("%s/%s", os.Getenv(config.ConfigData.Oss.CdnHost), objectName)
return
}

View File

@ -89,9 +89,10 @@ func CheckWebLogin(provider *account.AccountClientImpl) gin.HandlerFunc {
service.NotLoginRes(ctx, logic.ConvertLoginMsg(ctx, e.ErrNotLogin))
return
}
fmt.Println("authorization", authorization)
jwt, err := secret.GetJwtFromStr(authorization)
fmt.Println("jwt", jwt)
fmt.Println("jwt_err", err)
logger.Info("---------end帐号转jwt:时间:", time.Now().Sub(startTime))
if err != nil {
service.NotLoginRes(ctx, err.Error())
@ -107,19 +108,23 @@ func CheckWebLogin(provider *account.AccountClientImpl) gin.HandlerFunc {
info, err := service.AccountProvider.DecryptJwt(ctx, &req)
logger.Info("---------end帐号微服务解密:时间:", time.Now().Sub(startTime))
fmt.Println("DecryptJwt", info)
fmt.Println("DecryptJwtErr:----->", err)
if err != nil {
service.NotLoginRes(ctx, err.Error())
return
}
//if info.OfflineCode == e.OfflineSqueeze {
// service.Error(ctx, e.NotLoginSqueeze, errors.New(e.ErrOfflineSqueeze))
// return
//}
if info.IsOffline == true {
service.ErrorWeb(ctx, e.NotLogin, errors.New(logic.ConvertOfflineMsg(ctx, e.ErrOffline)))
return
//如果是来自体制外的请求,过滤挤掉校验
if !(ctx != nil && (ctx.GetHeader("origin") == "https://erp-out.szjixun.cn")) {
service.ErrorWeb(ctx, e.NotLogin, errors.New(logic.ConvertOfflineMsg(ctx, e.ErrOffline)))
return
}
}
//1 获取用户的账号信息
@ -130,7 +135,8 @@ func CheckWebLogin(provider *account.AccountClientImpl) gin.HandlerFunc {
}
infoRes, err := service.AccountProvider.Info(ctx, infoReq)
fmt.Println("infoRes", infoRes)
fmt.Println("infoResErr", err)
logger.Info("---------end帐号info时间:", time.Now().Sub(startTime))
if err != nil {

View File

@ -24,14 +24,17 @@ func NewLogger() gin.HandlerFunc {
latencyTime := endTime.Sub(startTime) // 请求方式
path := c.Request.URL.Path
query := c.Request.URL.RawQuery
data, _ := io.ReadAll(c.Request.Body)
if _, err := c.FormFile("file"); err != nil {
data, _ := io.ReadAll(c.Request.Body)
log.Printf("[%s] %s %d %s %s %s %s %s %s", path, c.Request.Method, c.Writer.Status(), query,
string(data), c.ClientIP(), c.Request.UserAgent(), c.Errors.ByType(gin.ErrorTypePrivate).String(), latencyTime.String())
c.Request.Body = io.NopCloser(bytes.NewBuffer(data))
}
val := c.GetHeader("Accept-Language")
if val == "" {
c.Request.Header.Set("Accept-Language", "zh-CN")
}
log.Printf("[%s] %s %d %s %s %s %s %s %s", path, c.Request.Method, c.Writer.Status(), query,
string(data), c.ClientIP(), c.Request.UserAgent(), c.Errors.ByType(gin.ErrorTypePrivate).String(), latencyTime.String())
c.Request.Body = io.NopCloser(bytes.NewBuffer(data))
c.Next()
}
}

View File

@ -0,0 +1,25 @@
package cast
type ApprovalDetailResponse struct {
Status int `json:"status"`
Data Data `json:"data"`
Msg string `json:"msg"`
Code int `json:"code"`
Error *string `json:"error"`
Err string `json:"err"`
Keys []string `json:"keys"`
Positions *interface{} `json:"positions"`
}
type Data struct {
Count int `json:"Count"`
Data []Item `json:"data"`
Status int `json:"Status"`
}
type Item struct {
ID int `json:"ID"`
Domain string `json:"Domain"`
Status int `json:"Status"`
Reply string `json:"Reply"`
}

10
pkg/model/cast/media.go Normal file
View File

@ -0,0 +1,10 @@
package cast
type BalanceTypeEnum int32
// 定义枚举值
const (
BalanceTypeAccountValue BalanceTypeEnum = 1
BalanceTypeImageValue BalanceTypeEnum = 2
BalanceTypeVideoValue BalanceTypeEnum = 3
)

10
pkg/model/cast/oauth.go Normal file
View File

@ -0,0 +1,10 @@
package cast
type OAuthPlatformReq struct {
MediaAccountUuid string `json:"mediaAccountUuid" form:"mediaAccountUuid" binding:"required"`
PlatformID int `json:"platformID" form:"platformID" binding:"required"`
}
type OAuthPlatformResp struct {
Url string `json:"url"`
}

11
pkg/model/cast/work.go Normal file
View File

@ -0,0 +1,11 @@
package cast
const (
WorkStatusPending = 1 // 待提交
WorkStatusReviewing = 2 // 审核中
WorkStatusReviewFailed = 3 // 审核失败
WorkStatusArtistConfirming = 4 // 待艺人确认
WorkStatusArtistRejected = 5 // 艺人驳回
WorkStatusPublishSuccess = 6 // 发布成功
WorkStatusPublishFailed = 7 // 发布失败
)

5
pkg/model/query/cast.go Normal file
View File

@ -0,0 +1,5 @@
package query
type RemindReq struct {
WorkUuid string `json:"workUuid"`
}

18
pkg/router/app/media.go Normal file
View File

@ -0,0 +1,18 @@
package app
import (
"fonchain-fiee/pkg/middleware"
"fonchain-fiee/pkg/service"
serviceCast "fonchain-fiee/pkg/service/app/cast"
"github.com/gin-gonic/gin"
)
func MediaAppRouter(r *gin.RouterGroup) {
auth := r.Group("")
auth.Use(middleware.CheckLogin(service.AccountFieeProvider))
media := auth.Group("app/media")
{
media.POST("user-accounts", serviceCast.UserAccounts)
media.POST("work-list", serviceCast.MediaWorks)
}
}

View File

@ -12,6 +12,7 @@ func BundleRouter(r *gin.RouterGroup) {
bundleRoute := r.Group("bundle")
bundleRoute.Use(middleware.CheckWebLogin(service.AccountProvider))
bundleAppRoute := r.Group("bundle")
bundleAppNoAuthRoute := r.Group("bundle")
bundleAppRoute.Use(middleware.CheckLogin(service.AccountFieeProvider))
// 套餐
{
@ -21,6 +22,7 @@ func BundleRouter(r *gin.RouterGroup) {
bundleClientRoute.POST("update", bundle.UpdateBundle)
bundleClientRoute.POST("remove", bundle.DeleteBundle)
bundleClientRoute.POST("bundle-list", bundle.BundleList)
bundleClientRoute.POST("add-value/only", bundle.OnlyAddValueListByOrderNo)
bundleExtend := bundleClientRoute.Group("extend")
{
@ -33,9 +35,16 @@ func BundleRouter(r *gin.RouterGroup) {
bundleBalance.POST("used-record", bundle.GetUsedRecordList)
}
}
bundleAppRoute = bundleAppRoute.Group("common")
bundleClientRouteV2 := bundleRoute.Group("system/v2")
{
bundleClientRouteV2.POST("save", bundle.SaveBundleV2)
bundleClientRouteV2.POST("update/shelfStatus", bundle.HandShelf)
bundleClientRouteV2.POST("bundle-list", bundle.BundleListV2)
bundleClientRouteV2.POST("bundle-detail", bundle.BundleDetailV2)
}
bundleAppRouteV1 := bundleAppRoute.Group("common")
{
bundleAppRouteV1.POST("bundle-list", bundle.BundleList)
bundleAppRoute.POST("bundle-list", bundle.BundleList)
bundleAppRoute.POST("pending-confirmation-list", bundle.GetToBeComfirmedWorks) // 作品状态变更的待确认记录
@ -45,7 +54,16 @@ func BundleRouter(r *gin.RouterGroup) {
bundleAppRoute.POST("work-detail", bundle.GetWorkDetail)
bundleAppRoute.POST("work-confirm", bundle.WorkConfirm)
}
bundleAppRouteV2 := bundleAppRoute.Group("app/system/v2")
{
bundleAppRouteV2.POST("add-value/only", bundle.OnlyAddValueListByOrderNo)
}
bundleAppNoAuthRouteV2 := bundleAppNoAuthRoute.Group("app/system/v2")
{
bundleAppNoAuthRouteV2.POST("bundle-list", bundle.BundleListH5V2)
bundleAppNoAuthRouteV2.POST("bundle-detail", bundle.BundleDetailV2)
}
}
}

View File

@ -24,6 +24,11 @@ func BundleOrderRouter(r *gin.RouterGroup) {
{
bundleOrderClientWebRoute.POST("bundle-order-list", bundle.OrderRecordsList)
bundleOrderClientWebRoute.POST("bundle-order-list-V2", bundle.OrderRecordsListV2)
bundleOrderClientWebRoute.POST("bundle-order-list-download", bundle.OrderRecordsListDownload)
bundleOrderClientWebRoute.POST("reconciliation-list", bundle.GetReconciliationList)
bundleOrderClientWebRoute.POST("reconciliation-list-download", bundle.GetReconciliationListDownload)
// 自动创建用户和订单
bundleOrderClientWebRoute.POST("auto-create-user-order", bundle.AutoCreateUserAndOrder)
}
bundleOrderClientAppRoute := bundleOrderRoute.Group("common/app")
{
@ -40,6 +45,7 @@ func BundleOrderRouter(r *gin.RouterGroup) {
{
bundleOrderAppRoute.POST("order-signature", bundle.CreateBundleOrderSignature)
bundleOrderAppRoute.POST("order-add-signature", bundle.CreateBundleOrderAddSignature)
bundleOrderAppRoute.POST("order-del", bundle.DeleteBundleOrder)
bundleOrderAppRoute.POST("update-pay", bundle.UpdateBundleOrderStatusPaid)
bundleOrderAppRoute.POST("order-detail", bundle.OrderRecordsDetail)

View File

@ -4,11 +4,12 @@ import (
"fonchain-fiee/pkg/middleware"
"fonchain-fiee/pkg/service"
serviceCast "fonchain-fiee/pkg/service/cast"
"github.com/gin-gonic/gin"
)
func MediaRouter(r *gin.RouterGroup) {
//noAuth := r.Group("")
noAuth := r.Group("")
auth := r.Group("")
auth.Use(middleware.CheckWebLogin(service.AccountProvider))
media := auth.Group("media")
@ -17,11 +18,31 @@ func MediaRouter(r *gin.RouterGroup) {
media.POST("unbind-manager", serviceCast.UnbindManager)
media.POST("bind-manager", serviceCast.BindManager)
media.POST("update-account", serviceCast.UpdateMediaAccount)
media.POST("oauth-account", serviceCast.OAuthAccount)
media.POST("refresh-token", serviceCast.RefreshToken)
}
mediaNoLogin := r.Group("media")
{
mediaNoLogin.GET("oauth2callback", serviceCast.OAuth2Callback)
mediaNoLogin.Any("test", serviceCast.Test)
//mediaNoLogin.GET("dmoauth2callback", serviceCast.DMOAuth2Callback)
}
work := auth.Group("work")
{
work.POST("update-work-image", serviceCast.UpdateWorkImage)
work.POST("update-work-video", serviceCast.UpdateWorkVideo)
work.POST("update-approval", serviceCast.UpdateApproval)
work.POST("list", serviceCast.WorkList)
work.POST("detail", serviceCast.WorkDetail)
work.POST("republish", serviceCast.RePublish)
work.POST("delete", serviceCast.DelWork)
work.POST("remind", serviceCast.Remind)
work.POST("publish-info", serviceCast.PublishInfo)
}
social := noAuth.Group("social")
{
social.GET("tiktok-redirect", serviceCast.TikTokRedirect)
}
}

View File

@ -2,11 +2,14 @@ package router
import (
"fonchain-fiee/pkg/middleware"
"fonchain-fiee/pkg/router/app"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/account"
"fonchain-fiee/pkg/service/asChat"
"fonchain-fiee/pkg/service/auth"
"fonchain-fiee/pkg/service/file"
"fonchain-fiee/pkg/service/governance"
imports "fonchain-fiee/pkg/service/import"
"fonchain-fiee/pkg/service/lang"
"fonchain-fiee/pkg/service/pressreleases"
"fonchain-fiee/pkg/service/qr"
@ -25,7 +28,10 @@ import (
func NewRouter() *gin.Engine {
//使用默认gin路由
r := gin.Default()
wsGroup := r.Group("api/fiee")
wsGroup.Use(
middleware.GinRecovery(true),
)
r.Use(gzip.Gzip(gzip.BestSpeed)) // 中间件占用绝大部分内存
//加入日志中间件,跨域中间件
r.Use(middleware.NewLogger(), middleware.Cors(), middleware.GinRecovery(true))
@ -33,6 +39,7 @@ func NewRouter() *gin.Engine {
privateGroup.Use(middleware.NewLogger(), middleware.Cors(), middleware.GinRecovery(true))
//加入日志中间件,跨域中间件
v1 := r.Group("api/fiee")
v1.Use(middleware.NewLogger(), middleware.Cors(), middleware.GinRecovery(true))
GiteaRoute(v1)
v1.GET("test", func(c *gin.Context) {
@ -45,7 +52,8 @@ func NewRouter() *gin.Engine {
BundleOrderRouter(privateGroup)
ValueAddBundleRouter(privateGroup)
MediaRouter(privateGroup)
SecFilingRouter(privateGroup)
app.MediaAppRouter(privateGroup)
{
v1.POST("version", version.Version) //版本号公共
}
@ -111,6 +119,29 @@ func NewRouter() *gin.Engine {
redirectRoute.POST("sdk/down/v2", auth.DownImgV2)
redirectRoute.POST("sdk/down/v3", auth.DownImgV3)
}
//========================================================================================
// 客服聊天
{
// websocket数据接收
wsGroup.GET("aschat/ws", asChat.ChatHandlerIns.Connection)
v1.POST("aschat/message/new", asChat.ChatHandlerIns.NewMessage)
v1.POST("aschat/media/upload", asChat.ChatHandlerIns.Upload)
v1.POST("aschat/message/list", asChat.ChatHandlerIns.MessageList)
v1.POST("aschat/user/stat", asChat.ChatHandlerIns.UserMessageStat)
v1.POST("aschat/voicetotext", asChat.ChatHandlerIns.VoiceToText)
v1.POST("aschat/userDetail", asChat.ChatHandlerIns.UserDetail)
v1.POST("aschat/autoReplyRuler/create", asChat.Handler.CreateChatAutoReplyRuler)
v1.POST("aschat/autoReplyRuler/delete", asChat.Handler.DeleteChatAutoReplyRuler)
v1.POST("aschat/autoReplyRuler/update", asChat.Handler.UpdateChatAutoReplyRuler)
v1.POST("aschat/autoReplyRuler/detail", asChat.Handler.GetChatAutoReplyRulerDetail)
v1.POST("aschat/autoReplyRuler/query", asChat.Handler.GetChatAutoReplyRulerList)
v1.POST("aschat/autoReplyRuler/userSwitch/get", asChat.ChatHandlerIns.UserSwitchAutoReplyStatus) //获取自动回复开关状态
v1.POST("aschat/autoReplyRuler/userSwitch/set", asChat.ChatHandlerIns.SetSwitchAutoReplyStatus) //设置自动回复开关状态
v1.POST("/test/user/log/erp", asChat.Handler.ErpLoginDemo)
v1.POST("/test/user/log/fiee", asChat.Handler.FieeLoginDemo)
v1.POST("/aschat/test", asChat.Handler.Test)
}
{
// 素材库
@ -156,6 +187,15 @@ func NewRouter() *gin.Engine {
pressreleasesRouteLogin.POST("/delete", pressreleases.Delete)
}
{
importRoute := v1.Group("/import")
importRoute.Use(middleware.CheckWebLogin(service.AccountProvider))
importRoute.POST("data/bind", imports.ImportBind)
importRoute.POST("data/publish", imports.ImportPublish)
importRoute.POST("data/publish2", imports.ImportPublishV2)
importRoute.POST("data/publish3", imports.ImportPublishV3)
importRoute.POST("data/confirm", imports.WorkConfirm)
}
//静态文件
r.StaticFS("/api/static", http.Dir("./runtime"))
r.NoRoute(func(c *gin.Context) {

35
pkg/router/secfiling.go Normal file
View File

@ -0,0 +1,35 @@
package router
import (
"fonchain-fiee/pkg/middleware"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/secfilings"
"github.com/gin-gonic/gin"
)
func SecFilingRouter(r *gin.RouterGroup) {
SecFilingRouter := r.Group("sec-filing")
SecNoAuthRouter := r.Group("sec-filing")
SecFilingRouter.Use(middleware.CheckWebLogin(service.AccountProvider))
// sec-filing
secFilingRoute := SecFilingRouter.Group("system")
{
secFilingRoute.POST("create", secfilings.CreateSecFiling)
secFilingRoute.POST("update", secfilings.UpdateSecFiling)
secFilingRoute.POST("list", secfilings.ListSecFiling)
secFilingRoute.POST("detail", secfilings.DetailSecFiling)
secFilingRoute.POST("delete", secfilings.DeleteSecFiling)
secFilingRoute.POST("get", secfilings.GetSecFilings)
secFilingRoute.POST("update/status", secfilings.UpdateSecFilingStatus)
secFilingRoute.POST("form/list", secfilings.GetFormList)
}
secNoAUthRouter := SecNoAuthRouter.Group("web")
{
secNoAUthRouter.POST("list", secfilings.WebListSecFiling)
secNoAUthRouter.POST("detail", secfilings.DetailSecFiling)
}
}

View File

@ -23,10 +23,22 @@ func ValueAddBundleRouter(r *gin.RouterGroup) {
bundleClientRoute.POST("list", bundle.ValueAddBundleList)
bundleClientRoute.POST("detail", bundle.ValueAddBundleDetail)
}
valueAddBundleAppRoute = valueAddBundleAppRoute.Group("system")
bundleClientRouteV2 := valueAddBundleRoute.Group("system/v2")
{
valueAddBundleAppRoute.POST("list", bundle.ValueAddBundleList)
bundleClientRouteV2.POST("save", bundle.SaveValueAddService)
bundleClientRouteV2.POST("list", bundle.ValueAddServiceList)
bundleClientRouteV2.POST("detail", bundle.ValueAddServiceDetail)
}
valueAddBundleAppRouteV1 := valueAddBundleAppRoute.Group("system")
{
valueAddBundleAppRouteV1.POST("list", bundle.ValueAddBundleList)
}
valueAddBundleAppRouteV2 := valueAddBundleAppRoute.Group("system/v2")
{
valueAddBundleAppRouteV2.POST("list", bundle.ValueAddServiceList)
valueAddBundleAppRouteV2.POST("detail", bundle.ValueAddServiceDetail)
valueAddBundleAppRouteV2.POST("detail/lang", bundle.ValueAddServiceLangDetail)
}
}

View File

@ -1,17 +1,19 @@
package serializer
import "fonchain-fiee/pkg/e"
// Response 基础序列化器
type Response struct {
Status int `json:"status"`
Data interface{} `json:"data"`
Msg string `json:"msg"`
Code int `json:"code"`
Error error `json:"error"`
Err string `json:"err"`
Keys []string `json:"keys"`
Mark string `json:"mark,omitempty"`
Page *PageInfo `json:"page,omitempty"`
Positions interface{} `json:"positions"`
Status int `json:"status"`
Data interface{} `json:"data"`
Msg string `json:"msg"`
Code e.ErrorCodeType `json:"code"`
Error error `json:"error"`
Err string `json:"err"`
Keys []string `json:"keys"`
Mark string `json:"mark,omitempty"`
Page *PageInfo `json:"page,omitempty"`
Positions interface{} `json:"positions"`
}
type PageInfo struct {
Page int32 `json:"page" query:"page"`

View File

@ -156,7 +156,7 @@ func SendMsg(c *gin.Context) {
service.Error(c, err)
return
}
service.Success(c, res)
service.Success1(c, "发送成功", res)
return
} else {
res, err := service.AccountFieeProvider.SendMsg(context.Background(), &req)
@ -165,7 +165,7 @@ func SendMsg(c *gin.Context) {
return
}
service.Success(c, res)
service.Success1(c, "发送成功", res)
return
}

View File

@ -0,0 +1,57 @@
package cast
import (
"fmt"
"fonchain-fiee/api/cast"
"fonchain-fiee/cmd/config"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
"github.com/gin-gonic/gin"
)
func UserAccounts(ctx *gin.Context) {
var req *cast.MediaAccountsReq = &cast.MediaAccountsReq{}
var err error
if config.AppConfig.System.AppMode != "dev" {
userInfo := login.GetUserInfoFromC(ctx)
req.ArtistUuid = fmt.Sprint(userInfo.ID)
} else {
req.ArtistUuid = "61"
}
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
if err = req.Validate(); err != nil {
service.Error(ctx, err)
return
}
resp, err := service.CastProvider.MediaAccounts(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
return
}
func MediaWorks(ctx *gin.Context) {
var req *cast.MediaWorksReq
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
if err = req.Validate(); err != nil {
service.Error(ctx, err)
return
}
resp, err := service.CastProvider.MediaWorks(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
return
}

View File

@ -0,0 +1,226 @@
package asChat
import (
"encoding/json"
"fmt"
"fonchain-fiee/api/account"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/cmd/config"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/asChat/dto"
"fonchain-fiee/pkg/utils"
"fonchain-fiee/pkg/utils/secret"
"fonchain-fiee/pkg/utils/stime"
"math/rand"
"time"
"github.com/gin-gonic/gin"
)
var Handler = &ChatAutoReplyRulerHandler{}
type ChatAutoReplyRulerHandler struct {
}
// 创建自动回复规则
func (a *ChatAutoReplyRulerHandler) CreateChatAutoReplyRuler(c *gin.Context) {
var req dto.ChatAutoReplyData
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
rulerBytes, _ := json.Marshal(req.Rules)
protoReq := accountFiee.ChatAutoReplyRulerData{
Title: req.Title,
Ruler: string(rulerBytes),
Response: req.Response,
}
_, err := service.AccountFieeProvider.CreateChatAutoReplyRuler(c, &protoReq)
if err != nil {
service.Error(c, err)
return
}
err = ChatHandlerIns.robot.ReloadRules(c)
if err != nil {
service.Error(c, err)
return
}
service.Success(c)
}
// 删除自动回复规则
func (a *ChatAutoReplyRulerHandler) DeleteChatAutoReplyRuler(c *gin.Context) {
var req accountFiee.DeleteChatAutoReplyRulerRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
_, err := service.AccountFieeProvider.DeleteChatAutoReplyRuler(c, &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c)
}
// 更新自动回复规则
func (a *ChatAutoReplyRulerHandler) UpdateChatAutoReplyRuler(c *gin.Context) {
var req dto.ChatAutoReplyData
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
protoReq := req.ToProtoData()
_, err := service.AccountFieeProvider.UpdateChatAutoReplyRuler(c, protoReq)
if err != nil {
service.Error(c, err)
return
}
err = ChatHandlerIns.robot.ReloadRules(c)
if err != nil {
service.Error(c, err)
return
}
service.Success(c)
}
// 使用id查询自动回复规则
func (a *ChatAutoReplyRulerHandler) GetChatAutoReplyRulerDetail(c *gin.Context) {
var req accountFiee.GetChatAutoReplyRulerByIdRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
resp, err := service.AccountFieeProvider.GetChatAutoReplyRulerDetail(c, &req)
if err != nil {
service.Error(c, err)
return
}
tmp := dto.ChatAutoReplyData{}
tmp.Parse(resp)
service.Success(c, tmp)
}
// 批量查询自动回复规则
func (a *ChatAutoReplyRulerHandler) GetChatAutoReplyRulerList(c *gin.Context) {
var req dto.GetChatAutoReplyRulerListRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
var protoReq = accountFiee.GetChatAutoReplyRulerListRequest{Query: &accountFiee.ChatAutoReplyRulerData{}}
utils.RequestDataConvert(&req, &protoReq)
if req.RuleType != "" {
protoReq.Where = fmt.Sprintf("ruler LIKE '%%%s\":{\"enable\":true%%'", req.RuleType)
}
resp, err := service.AccountFieeProvider.GetChatAutoReplyRulerList(c, &protoReq)
if err != nil {
service.Error(c, err)
return
}
var data []dto.ChatAutoReplyData
for _, v := range resp.List {
tmp := dto.ChatAutoReplyData{}
tmp.Parse(v)
data = append(data, tmp)
}
service.Success(c, map[string]interface{}{
"data": data,
"page": resp.Page,
"pagesize": resp.PageSize,
"total": resp.Total,
})
}
func (a *ChatAutoReplyRulerHandler) ErpLoginDemo(c *gin.Context) {
var req dto.ErpLoginDemoReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
loginRes, err := service.AccountProvider.Login(c, &account.LoginRequest{
Domain: "fontree",
TelNum: req.TelNum,
Password: req.Password,
})
if err != nil {
if err.Error() == "没有找到数据" || err.Error() == "No data found" {
registerRequest := account.RegistRequest{
Domain: "fontree",
NickName: req.TelNum,
TelNum: req.TelNum,
Password: req.Password,
EnterDate: time.Now().Format(stime.Format_Normal_YMD),
Extend: &account.Extend{JumpTo: "onsite"}, //origin-老平台 onsite 当前
JobNum: fmt.Sprintf("%d", rand.Intn(1000)),
}
registerRes, errs := service.AccountProvider.Register(c, &registerRequest)
if errs != nil {
service.Error(c, errs)
return
}
service.Success(c, registerRes)
} else {
service.Error(c, err)
}
return
}
departmentName := ""
if loginRes.AccountInfo != nil && len(loginRes.AccountInfo.Departments) > 0 {
departmentName = loginRes.AccountInfo.Departments[0].Name
}
loginRes.Token, err = secret.CombineSecret("xxx", departmentName, loginRes.Token)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, loginRes)
}
func (a *ChatAutoReplyRulerHandler) FieeLoginDemo(c *gin.Context) {
var req dto.ErpLoginDemoReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
loginRes, err := service.AccountFieeProvider.Login(c, &accountFiee.LoginRequest{
Domain: config.AppConfig.System.Domain,
TelNum: req.TelNum,
Password: req.Password,
})
if err != nil {
if err.Error() == "账号不存在" || err.Error() == "Account does not exist" {
registerRequest := accountFiee.RegistRequest{
Domain: config.AppConfig.System.Domain,
NickName: req.TelNum,
TelNum: req.TelNum,
//Password: req.Password,
//EnterDate: time.Now().Format(stime.Format_Normal_YMD),
//Extend: &account.Extend{JumpTo: "onsite"}, //origin-老平台 onsite 当前
//JobNum: fmt.Sprintf("%d", rand.Intn(1000)),
}
registerRes, errs := service.AccountFieeProvider.Register(c, &registerRequest)
if errs != nil {
service.Error(c, errs)
return
}
service.Success(c, registerRes)
} else {
service.Error(c, err)
}
return
}
//departmentName := ""
//if loginRes.AccountInfo != nil && len(loginRes.AccountInfo.Departments) > 0 {
// departmentName = loginRes.AccountInfo.Departments[0].Name
//}
//loginRes.Token, err = secret.CombineSecret("xxx", departmentName, loginRes.Token)
//if err != nil {
// service.Error(c, err)
// return
//}
service.Success(c, loginRes)
}
func (a *ChatAutoReplyRulerHandler) Test(c *gin.Context) {
fmt.Println(c.GetHeader("domain"))
}

View File

@ -0,0 +1,286 @@
// Package asChat -----------------------------
// @file : cache.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2024/9/11 下午5:18
// -------------------------------------------
package chatCache
import (
"context"
"errors"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/cache"
"fonchain-fiee/pkg/service/asChat/dto"
"github.com/go-redis/redis"
"github.com/goccy/go-json"
"go.uber.org/zap"
"log"
"strconv"
"strings"
"sync"
"time"
)
const CacheChatRecordKey = "fiee:chatRecord"
const CacheSessionKey = "fiee:chatSession"
const CacheNewMsgStatKey = "fiee:newMsgStat"
const CacheAutoReplySwitchKey = "fiee:AutoReplySwitch"
var chatCacheLocker sync.RWMutex
type ChatCache struct {
NewMessageStatExpireAfter time.Duration //消息统计的数据过期时间
}
// ------------------------------存储用户的会话ID--------------------------------
func (cr ChatCache) GetUserSessionCacheKey(userId int64) string {
return fmt.Sprintf("%s:%d", CacheSessionKey, userId)
}
func (cr ChatCache) SaveUserSession(userId int64, sessionId string) {
chatCacheLocker.Lock()
defer chatCacheLocker.Unlock()
////var c = context.Background()
err := cache.RedisClient.Set(cr.GetUserSessionCacheKey(userId), sessionId, 0).Err()
if err != nil {
log.Print("保存用户会话失败", zap.Error(err))
}
}
func (cr ChatCache) GetUserSession(userId int64) (sessionId string) {
fmt.Println("GetUserSession-1")
chatCacheLocker.RLock()
defer chatCacheLocker.RUnlock()
//var c = context.Background()
sessionId, err := cache.RedisClient.Get(cr.GetUserSessionCacheKey(userId)).Result()
fmt.Println("GetUserSession-2")
if err != nil {
if err.Error() == "redis: nil" {
err = nil
} else {
log.Print("获取用户会话失败", zap.Error(err))
}
}
fmt.Println("GetUserSession-3, sessionId:", sessionId)
return
}
// ------------------------------存储会话的聊天记录--------------------------------
func (cr ChatCache) GetChatRecordCacheKey(sessionId string) string {
return fmt.Sprintf("%s:%s", CacheChatRecordKey, sessionId)
}
func (cr ChatCache) AddChatRecord(sessionId string, data ...*accountFiee.ChatRecordData) (err error) {
////var c = context.Background()
messages := cr.GetChatRecord(sessionId)
fmt.Printf("AddChatRecord add data:%+v\n", data)
messages = append(messages, data...)
cacheBytes, _ := json.Marshal(messages)
fmt.Println("Marshal result", string(cacheBytes))
err = cache.RedisClient.Set(cr.GetChatRecordCacheKey(sessionId), cacheBytes, 2*time.Hour).Err()
return
}
func (cr ChatCache) CoverChatRecord(sessionId string, data []*accountFiee.ChatRecordData) (err error) {
chatCacheLocker.Lock()
defer chatCacheLocker.Unlock()
//var c = context.Background()
cacheBytes, _ := json.Marshal(data)
err = cache.RedisClient.Set(cr.GetChatRecordCacheKey(sessionId), cacheBytes, 2*time.Hour).Err()
return
}
func (cr ChatCache) GetChatRecord(sessionId string) (data []*accountFiee.ChatRecordData) {
chatCacheLocker.RLock()
defer chatCacheLocker.RUnlock()
data = make([]*accountFiee.ChatRecordData, 0)
//var c = context.Background()
messages, err := cache.RedisClient.Get(cr.GetChatRecordCacheKey(sessionId)).Bytes()
if err != nil {
if err.Error() == "redis: nil" {
err = nil
}
//log.Print("获取聊天记录失败", zap.Error(err))
return
}
//fmt.Printf("cache data: %+v", string(messages))
if len(messages) > 0 {
_ = json.Unmarshal(messages, &data)
}
return
}
// ------------------------------存储新消息统计--------------------------------
func (cr ChatCache) GetNewMsgStatCacheKey(ownerId int64) string {
return fmt.Sprintf("%s:%d", CacheNewMsgStatKey, ownerId)
}
// 消息数量自增
func (cr ChatCache) IncreaseNewMessageTotal(ownerId int64, sessionId string) (err error) {
chatCacheLocker.Lock()
defer chatCacheLocker.Unlock()
ctx := context.Background()
data := cr.GetNewMessageStat(ctx, ownerId)
if len(data) > 0 {
foundIndex := -1
for i, v := range data {
if v.SessionId == sessionId {
foundIndex = i
break
}
}
if foundIndex > -1 {
data[foundIndex].Total += 1
}
//将foundIndex之后的所有元素右移动一位
if foundIndex > 0 {
elementToMove := data[foundIndex]
copy(data[1:], data[0:foundIndex])
data[0] = elementToMove
} else if foundIndex == -1 {
data = append([]dto.UserMsgStatic{{SessionId: sessionId, Total: 1}}, data...)
}
} else {
data = []dto.UserMsgStatic{{SessionId: sessionId, Total: 1}}
}
return cr.coverOwnerNewMessageStat(ctx, ownerId, data)
}
// 重置新消息数量
func (cr ChatCache) ResetNewMessageTotal(ownerId int64, sessionId string, total ...int64) error {
fmt.Printf("ResetNewMessageTotal: %d ,sessionId:%s ,total:%v\n", ownerId, sessionId, total)
chatCacheLocker.Lock()
defer chatCacheLocker.Unlock()
var tl int64
if len(total) > 0 {
tl = total[0]
}
fmt.Println("ResetNewMessageTotal tl:", tl)
ctx := context.Background()
data := cr.GetNewMessageStat(ctx, ownerId)
fmt.Printf("ResetNewMessageTotal data:%+v\n", data)
found := false
for i, v := range data {
if v.SessionId == sessionId {
found = true
data[i].Total = tl
fmt.Println("ResetNewMessageTotal found!")
break
}
}
if !found {
fmt.Println("ResetNewMessageTotal not found!")
data = append(data, dto.UserMsgStatic{
SessionId: sessionId,
Total: tl,
})
}
err := cr.coverOwnerNewMessageStat(ctx, ownerId, data)
fmt.Println("ResetNewMessageTotal result", err)
return err
}
func (cr ChatCache) RecountNewMessageTotal(ownerId int64) {
//var c = context.Background()
var keys []string
var err error
keys, err = cache.RedisClient.Keys(CacheChatRecordKey + "*").Result()
if err != nil {
log.Print("获取聊天记录所有缓存KEY失败", zap.Error(err))
return
}
var countMap = make(map[string]int)
for _, key := range keys {
var messages []byte
var data []*accountFiee.ChatRecordData
messages, err = cache.RedisClient.Get(key).Bytes()
if err != nil {
if err.Error() == "redis: nil" {
err = nil
}
log.Print("获取聊天记录失败", zap.Error(err))
data = make([]*accountFiee.ChatRecordData, 0)
continue
}
if len(messages) > 0 {
_ = json.Unmarshal(messages, &data)
}
lastIndex := strings.Count(key, ":")
var sessionId = strings.Split(key, ":")[lastIndex]
countMap[sessionId] = 0
for _, v := range data {
if v.WaiterRead == 2 { //统计未读消息数量
countMap[sessionId]++
}
}
}
for sessionId, count := range countMap {
err = cr.ResetNewMessageTotal(ownerId, sessionId, int64(count))
if err != nil {
log.Print("重置新消息数量统计",
zap.String("function", "RecountNewMessageTotal"),
zap.Int64("ownerId", ownerId),
zap.String("sessionId", sessionId),
zap.Int("count", count),
zap.Error(err),
)
}
}
return
}
// erp获取最新的消息统计
func (cr ChatCache) GetNewMessageStat(ctx context.Context, ownerId int64) (result []dto.UserMsgStatic) {
//chatCacheLocker.RLock()
//defer chatCacheLocker.RUnlock()
result = make([]dto.UserMsgStatic, 0)
vals, err := cache.RedisClient.Get(cr.GetNewMsgStatCacheKey(ownerId)).Bytes()
if err != nil && errors.Is(err, redis.Nil) {
log.Print("从缓存获取新消息统计失败", zap.Error(err), zap.Int64("ownerId", ownerId))
return
}
if vals != nil {
_ = json.Unmarshal(vals, &result)
}
return
}
// 覆盖指定erp用户的新消息统计
func (cr ChatCache) coverOwnerNewMessageStat(ctx context.Context, ownerId int64, data []dto.UserMsgStatic) (err error) {
value, _ := json.Marshal(data)
//err = cache.RedisClient.Set(ctx, cr.GetNewMsgStatCacheKey(ownerId), value, cr.NewMessageStatExpireAfter).Err()
err = cache.RedisClient.Set(cr.GetNewMsgStatCacheKey(ownerId), value, 0).Err()
return
}
// -----------------------------------用户自动回复开关
// erp获取最新的消息统计
func (cr ChatCache) GetCacheAutoReplySwitchKey(userId int64) string {
return fmt.Sprintf("%s:%d", CacheAutoReplySwitchKey, userId)
}
func (cr ChatCache) SetAutoReplySwitch(ctx context.Context, ownerId int64, enableAutoReply bool) {
//chatCacheLocker.RLock()
//defer chatCacheLocker.RUnlock()
err := cache.RedisClient.Set(cr.GetCacheAutoReplySwitchKey(ownerId), enableAutoReply, 0).Err()
if err != nil {
log.Print("保存用户会话失败", zap.Error(err))
}
return
}
func (cr ChatCache) GetAutoReplySwitch(ctx context.Context, ownerId int64) (enableAutoReply bool) {
//chatCacheLocker.RLock()
//defer chatCacheLocker.RUnlock()
val, err := cache.RedisClient.Get(cr.GetCacheAutoReplySwitchKey(ownerId)).Bytes()
if err != nil {
log.Print("获取自动回复开关查询失败", zap.Error(err), zap.Int64("ownerId", ownerId))
return true
}
// 解析缓存值为布尔值
boolVal, err := strconv.ParseBool(string(val))
if err != nil {
log.Print("解析自动回复开关值失败", zap.Error(err), zap.String("value", string(val)), zap.Int64("ownerId", ownerId))
return true // 解析失败时也返回默认值true
}
return boolVal
}

View File

@ -0,0 +1,33 @@
// package asChat -----------------------------
// @file : chatRoom.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2022/10/21 18:17:17
// -------------------------------------------
package consts
import (
"encoding/json"
"fonchain-fiee/pkg/common/ws"
)
var (
ChatRoom = ws.NewChatRoom()
)
type WsInfo struct {
Type ws.WsType `json:"type"` //消息类型
Content any `json:"content"`
}
func WsMessageRegisterCallback(clientId string, sessionId string) []byte {
var errMsg = WsInfo{
Type: ws.RegisterType,
Content: map[string]string{
//"clientId": clientId,
"sessionId": sessionId,
},
}
byteMsg, _ := json.Marshal(errMsg)
return byteMsg
}

View File

@ -0,0 +1,7 @@
// Package consts -----------------------------
// @file : consts.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 17:40
// -------------------------------------------
package consts

View File

@ -0,0 +1,225 @@
// Package asChat -----------------------------
// @file : dto.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2024/9/10 下午6:28
// -------------------------------------------
package dto
import (
"encoding/json"
"fonchain-fiee/api/accountFiee"
"log"
"time"
)
type Message struct {
MsgType accountFiee.MsgType `json:"msgType"`
Text string `json:"text"` //文本内容
Media []MessageMedia `json:"media"`
LocalStamp int64 `json:"localStamp"`
}
type MessageMedia struct {
MediaId int64 `json:"mediaId"` //媒体文件id
MediaSize string `json:"mediaSize"` //媒体文件大小
Ext string `json:"ext"` //后缀格式
Url string `json:"url"` //文件地址
ConvText string `json:"convText"` //语音转文字内容,需要调用语音转文字接口后才会有值
Duration int64 `json:"duration"` //时长 单位:毫秒
}
// 客户端发送消息请求使用api发送消息
type NewMessageRequest struct {
Waiter bool `json:"waiter"` //是否是客服发送,客服没有userId
Robot bool `json:"-"` //是否机器人发送
SessionId string `json:"sessionId"`
Message
AtUserId int64 `json:"atUserId"` //指定发送给sessionId中的某一个用户
//EnableAutoReply bool `json:"-"`
}
// 服务端接收到消息后使用websocket发送给userId关联的客户端通知客户端有新消息然后调用接口获取消息
type NewMessageNotice struct {
Name string `json:"name"` //名字
UserId int64 `json:"userId"` //用户id
SessionId string `json:"sessionId"`
MessageId int64 `json:"messageId"` //消息id
//NewMsgTotal int64 `json:"newMsgTotal"` //新消息数量
//Active bool `json:"active"` //是否在线
}
// 获取会话列表
type SessionType struct {
NewMessageNotice
RecentMessage []*Message `json:"recentMessage"` //最近消息
}
type MessageListType struct {
ID int64 `json:"ID"`
CreatedAt string `json:"createdAt"`
UserId int64 `json:"userId"`
Role int32 `json:"role,omitempty"`
Name string `json:"name"`
Message Message `json:"message"`
}
func (m *MessageListType) BuildMessage(data *accountFiee.ChatRecordData) {
m.ID = data.ID
m.CreatedAt = data.CreatedAt
m.UserId = data.UserId
m.Name = data.Name
m.Role = data.Role
switch data.MsgType {
default:
m.Message.MsgType = data.MsgType
m.Message.Text = data.Content
m.Message.LocalStamp = data.LocalStamp
if data.Medias != nil {
for _, media := range data.Medias {
m.Message.Media = append(m.Message.Media, MessageMedia{
MediaId: media.ID,
MediaSize: media.Size,
Ext: media.Ext,
Url: media.Url,
ConvText: media.ConvText,
Duration: media.Duration,
})
}
}
case accountFiee.MsgType_TextMsgType:
m.Message = Message{
MsgType: data.MsgType,
Text: data.Content,
Media: []MessageMedia{},
LocalStamp: data.LocalStamp,
}
case accountFiee.MsgType_ImageMsgType, accountFiee.MsgType_AudioMsgType, accountFiee.MsgType_VideoMsgType:
m.Message.MsgType = data.MsgType
m.Message.Text = data.Content
m.Message.LocalStamp = data.LocalStamp
if data.Medias != nil {
for _, media := range data.Medias {
m.Message.Media = append(m.Message.Media, MessageMedia{
MediaId: media.ID,
MediaSize: media.Size,
Ext: media.Ext,
Url: media.Url,
ConvText: media.ConvText,
Duration: media.Duration,
})
}
}
}
}
func (m *MessageListType) ToJson() string {
jsonBytes, _ := json.Marshal(m)
return string(jsonBytes)
}
type UserMsgStatic struct {
UserId int64 `json:"userId"` //用户id
Name string `json:"name"` //名称
ArtistUid string `json:"artistUid,omitempty"`
SessionId string `json:"sessionId"` //会话id
Total int64 `json:"total"` //新消息数量
//NewMessageTime string `json:"newMessageTime"` //最新消息的创建时间
}
type MessageListRequest struct {
SessionId string `json:"sessionId"` //不传则获取自己的会话消息里列表
CurrentId int64 `json:"currentId"` //组合查询条件1基于某个消息id向前或向后查找。两种组合条件不能同时使用
Direction int `json:"direction"` //组合查询条件1方向 1=向前查找 2=向后查找
Recent bool `json:"recent"` //组合查询条件2查找最新的若干条消息。两种组合条件不能同时使用
InHour time.Duration `json:"inHour"` //组合查询条件2可选查询指定小时内的数据
PageSize int64 `json:"pageSize"` //查找数量
}
type VoiceToTextRequest struct {
MediaId int64 `json:"mediaId"`
}
type ArtistInfoRequest struct {
UserId int64 `json:"userId"`
}
type ArtistInfo struct {
Tnum string `json:"tnum"`
ArtistName string `json:"artistName"`
Age int64 `json:"age"`
Sex string `json:"sex"`
NativePlace string `json:"nativePlace"`
TelNum string `json:"telNum"`
RecentPhoto string `json:"recentPhoto"`
}
type GetChatAutoReplyRulerListRequest struct {
Page int64 `json:"page"`
PageSize int64 `json:"pageSize"`
accountFiee.ChatAutoReplyRulerData
RuleType string `json:"ruleType"`
}
type ErpLoginDemoReq struct {
TelNum string `json:"telNum"`
Password string `json:"password"`
Nickname string `json:"nickname"`
RealName string `json:"realName"`
}
type ChatAutoReplyData struct {
ID int64 `json:"id"`
Title string `json:"title"`
Rules map[string]*AutoReplyRule `json:"rules"`
Response string `json:"response"`
CreatedAt string `json:"createdAt"`
UpdatedAt string `json:"updatedAt"`
Status int32 `json:"status"`
}
func (r *ChatAutoReplyData) ToProtoData() (data *accountFiee.ChatAutoReplyRulerData) {
jsonBytes, _ := json.Marshal(r.Rules)
data = &accountFiee.ChatAutoReplyRulerData{
ID: r.ID,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
Title: r.Title,
Ruler: string(jsonBytes),
Status: r.Status,
Response: r.Response,
}
return
}
func (r *ChatAutoReplyData) Parse(data *accountFiee.ChatAutoReplyRulerData) {
err := json.Unmarshal([]byte(data.Ruler), &r.Rules)
log.Printf("ChatAutoReplyData parse err:%v\n", err)
r.ID = data.ID
r.CreatedAt = data.CreatedAt
r.UpdatedAt = data.UpdatedAt
r.Title = data.Title
r.Status = data.Status
r.Response = data.Response
}
type AutoReplyRule struct {
Enable bool `json:"enable"`
Content string `json:"content,omitempty"`
SecondDuration time.Duration `json:"secondDuration,omitempty"`
}
type UserDetailReq struct {
ChatUserId int64 `json:"chatUserId"` //注意是聊天用户IDchat_user表不是账号服务ID
}
type UserDetailResp struct {
UserId uint64 `json:"userId"`
ChatUserId int64 `json:"chatUserId"`
RnStatus int32 `json:"rnStatus"` //状态 1:未实名 2:审核中 3:审核失败 4:审核通过
SubNum string `json:"subNum"`
RealName string `json:"realName"`
Age string `json:"age"`
Gender string `json:"gender"`
NativePlace string `json:"nativePlace"`
Phone string `json:"phone"`
GroupPhoto string `json:"groupPhoto"`
}
type UserSwitchAutoReplyReq struct {
EnableAutoReply bool `json:"enableAutoReply"`
}

View File

@ -0,0 +1,665 @@
// package asChat -----------------------------
// @file : handler.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2022/10/23 11:13:43
// -------------------------------------------
package asChat
import (
"bytes"
"context"
"crypto/md5"
"encoding/hex"
"errors"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/jwt"
"fonchain-fiee/pkg/common/ws"
"fonchain-fiee/pkg/e"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/asChat/chatCache"
"fonchain-fiee/pkg/service/asChat/consts"
"fonchain-fiee/pkg/service/asChat/dto"
"fonchain-fiee/pkg/service/asChat/logic"
"fonchain-fiee/pkg/service/asChat/robot"
"fonchain-fiee/pkg/service/upload"
"fonchain-fiee/pkg/utils/stime"
"io"
"log"
"path"
"slices"
"sort"
"strconv"
"strings"
"time"
"github.com/fonchain/utils/voice"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
uuid "github.com/satori/go.uuid"
"go.uber.org/zap"
)
var ChatHandlerIns = NewChatHandler()
func NewChatHandler() ChatHandler {
c := ChatHandler{
cache: chatCache.ChatCache{NewMessageStatExpireAfter: 10 * time.Minute},
}
c.robot = robot.NewRobot(&c.cache)
return c
}
type ChatHandler struct {
cache chatCache.ChatCache
robot *robot.Robot
}
func (cr ChatHandler) Connection(c *gin.Context) {
conn, err := ws.UpGrader.Upgrade(c.Writer, c.Request, nil)
conn.SetReadDeadline(time.Now().Add(time.Second * 10))
if err != nil {
log.Print("无法升级为websocket连接", zap.Error(err))
c.String(500, "无法转为websocket连接")
return
}
defer func() {
if conn != nil {
conn.Close()
}
}()
_, byteData, err := conn.ReadMessage()
if err != nil {
_ = conn.WriteMessage(websocket.TextMessage, ws.WsErrorConnection("null", err.Error(), "conn.ReadMessag1"))
return
}
fmt.Println("22222222222222,AuthorizationVerify")
var ok bool
var userInfo *accountFiee.ChatUserData
userInfo, ok, err = ws.AuthorizationVerify(byteData)
if err != nil {
_ = conn.WriteMessage(websocket.TextMessage, ws.WsErrorConnection("null", err.Error(), "AuthorizationVerify2"))
return
}
if !ok {
_ = conn.WriteMessage(websocket.TextMessage, ws.WsErrorConnection("null", "登录状态失效", "AuthorizationVerify2.1"))
return
}
fmt.Println("33333333333333,RecountNewMessageTotal")
conn.SetReadDeadline(time.Time{})
go cr.cache.RecountNewMessageTotal(userInfo.ID)
fmt.Println("44444444444444,ws.NewClient")
//注册ws客户端并发送clientId给ws客户端
var cli = ws.NewClient(userInfo.ID, "", conn, consts.ChatRoom)
cli.Waiter = userInfo.Role == 2
fmt.Println("55555555555555,GetUserSession")
//查询是否有历史的sessionId
cli.SessionId = cr.cache.GetUserSession(userInfo.ID)
consts.ChatRoom.Register(cli)
cr.cache.SaveUserSession(userInfo.ID, cli.SessionId)
fmt.Println("66666666666666666666666666")
go cli.WriteWait()
cli.Send <- consts.WsMessageRegisterCallback(cli.ClientId, cli.SessionId)
fmt.Println("777777777777777777777777")
// 处理websocket连接的逻辑
ctx, _ := context.WithCancel(context.Background())
cli.Reading(ctx, HandleMessage)
fmt.Println("88888888888888888888888888")
select {
case <-ctx.Done():
return
}
}
func (cr ChatHandler) NewMessage(c *gin.Context) {
var request dto.NewMessageRequest
if err := c.ShouldBindJSON(&request); err != nil {
service.Error(c, err)
return
}
if request.SessionId == "" {
service.Error(c, errors.New("sessionId不能为空"))
return
}
if request.MsgType == 0 {
service.Error(c, errors.New("msgType不能为空"))
return
}
fmt.Println("NewMessage 1111111111111111111111111111111")
//获取用户信息
chatUser, code := jwt.ParseToChatUser(c)
if code != 0 {
service.ErrWithCode(c, code)
return
}
err := logic.NewMessage(c, &cr.cache, chatUser, request)
if err != nil {
service.Error(c, err)
return
}
//fmt.Println("NewMessage 22222222222222222222222222222222222")
////存储入库
//if chatUser.NickName != "" {
// chatUser.NickName = fmt.Sprintf("未知用户(%d)", chatUser.ID)
//}
//fmt.Println("NewMessage 3333333333333333333333333333333333")
//var data = accountFiee.ChatRecordData{
// SessionId: request.SessionId,
// UserId: chatUser.ID,
// Name: chatUser.NickName,
// Avatar: "",
// MsgType: request.MsgType,
// Content: request.Message.Text,
// LocalStamp: request.LocalStamp,
// Medias: nil,
//}
//if len(request.Message.Media) > 0 {
// for _, media := range request.Message.Media {
// data.Medias = append(data.Medias, &accountFiee.ChatMediaData{
// ID: media.MediaId,
// })
// }
//}
//fmt.Println("NewMessage 4444444444444444444444444444444444")
//resp, err := service.AccountFieeProvider.CreateChatRecord(c, &data)
//if err != nil {
// service.Error(c, errors.New("创建失败"))
// return
//}
//fmt.Printf("CreateChatRecord resp:%+v\n", resp)
////录入缓存
//err = cr.cache.AddChatRecord(request.SessionId, resp.Data)
//if err != nil {
// service.Error(c, errors.New("创建失败"))
// return
//}
//fmt.Println("NewMessage 5 消息数量+1")
////新消息数量统计+1
//noticeUserId := consts.ChatRoom.GetUserIdInSession(request.SessionId, chatUser.ID)
//fmt.Println("NewMessage 5.1 消息数量配置结束")
//fmt.Printf("noticeUserId %+v\n", noticeUserId)
//for _, userId := range noticeUserId {
// fmt.Println("userId")
// cr.cache.IncreaseNewMessageTotal(userId, request.SessionId)
//}
//fmt.Println("NewMessage 6")
////发送websocket消息提醒通知
//var notice = dto.MessageListType{}
//notice.BuildMessage(resp.Data)
//fmt.Printf("ws消息提醒:%+v\n", notice)
//_, err = consts.ChatRoom.SendSessionMessage(chatUser.ID, request.SessionId, ws.NewChatMsgType, notice)
//if err != nil {
// log.Print("发送新消息通知失败", zap.Error(err), zap.Any("notice", notice))
//}
//cr.robot.Listen(&data)
//fmt.Println("NewMessage 7 -end")
////发送app推送(无横幅推送)
////go func() {
//// omitMessage := ""
//// switch request.MsgType {
//// case accountFiee.MsgType_TextMsgType:
//// runMsg := []rune(request.Text)
//// if len(runMsg) > 15 {
//// omitMessage = string(runMsg[:15]) + "..."
//// } else {
//// omitMessage = request.Text
//// }
//// case accountFiee.MsgType_ImageMsgType:
//// omitMessage = "[图片]"
//// case accountFiee.MsgType_AudioMsgType:
//// omitMessage = "[音频]"
//// case accountFiee.MsgType_VideoMsgType:
//// omitMessage = "[视频]"
//// default:
//// omitMessage = "新消息请查收"
//// }
//// for _, userId := range noticeUserId {
//// _ = asPusher.NewArtistinfoUniPush().NewChatMessageNotice(userId, omitMessage)
//// }
////}()
service.Success(c)
}
func (cr ChatHandler) MessageList(c *gin.Context) {
var request dto.MessageListRequest
if err := c.ShouldBindJSON(&request); err != nil {
service.Error(c, err)
return
}
//domain := c.GetHeader("domain")
//fmt.Println("MessageList domain:", domain)
if (request.Direction == 0 && !request.Recent) || (request.Direction > 0 && request.Recent) {
service.Error(c, errors.New("组合条件校验失败"))
return
}
if request.SessionId == "" {
service.Error(c, errors.New("sessionId不能为空"))
return
}
if request.PageSize < -1 {
service.Error(c, errors.New("pageSize校验错误"))
return
}
var resp = make([]*dto.MessageListType, 0)
if request.CurrentId == 0 && request.Direction == 1 {
service.Success(c, resp)
return
}
accessUser, code := jwt.ParseToChatUser(c)
if code != 0 {
service.ErrWithCode(c, code)
return
}
//if request.SessionId == "" {
// request.SessionId = cr.cache.GetUserSession(tokenResult.UserInfo.ID)
// if request.SessionId == "" {
// service.Success(c, resp)
// return
// }
//}
messages := cr.cache.GetChatRecord(request.SessionId)
//messages := []*accountFiee.ChatRecordData{}
var returnDataIdList = make([]int64, 0)
defer func() {
//获取最新数据时,重置新消息数量统计
if request.Direction == 1 || request.Recent {
cr.cache.ResetNewMessageTotal(accessUser.ID, request.SessionId)
}
//设置消息已被客服阅读,当客服重新通过通过websocket连接时这些消息将不被纳入新消息数量统计
if len(returnDataIdList) > 0 && accessUser.Role == 2 {
for _, hasReadId := range returnDataIdList {
for i, message := range messages {
if message.ID == hasReadId {
messages[i].WaiterRead = 1
}
}
}
err := cr.cache.CoverChatRecord(request.SessionId, messages)
if err != nil {
log.Print("设置消息已读失败", zap.Error(err))
}
for _, v := range messages {
_, err = service.AccountFieeProvider.SaveChatRecord(context.Background(), v)
if err != nil {
log.Print("设置消息已读失败", zap.Error(err))
}
}
}
}()
if len(messages) == 0 {
//从数据库获取
recordResp, err := service.AccountFieeProvider.GetChatRecordList(c, &accountFiee.GetChatRecordListRequest{
Query: &accountFiee.ChatRecordData{SessionId: request.SessionId},
Page: 1,
PageSize: -1,
//Where: fmt.Sprintf("id %s %d", utils.IfGec(request.Direction == 1, "<", ">"), request.CurrentId),
})
if err != nil {
service.Error(c, err)
return
}
messages = recordResp.List
err = cr.cache.CoverChatRecord(request.SessionId, messages)
if err != nil {
log.Print("覆盖聊天记录失败", zap.Error(err))
}
}
if request.Recent {
if int64(len(messages)) >= request.PageSize {
messages = messages[len(messages)-int(request.PageSize):]
}
var now = time.Now()
for _, message := range messages {
if request.InHour > 0 {
messageCreatedAt, _ := stime.StringToTime(message.CreatedAt)
if now.Sub(*messageCreatedAt) >= request.InHour*time.Hour {
continue
}
}
returnDataIdList = append(returnDataIdList, message.ID)
var msg = &dto.MessageListType{}
msg.BuildMessage(message)
resp = append(resp, msg)
}
} else {
sort.Slice(messages, func(i, j int) bool {
if request.Direction == 1 {
return messages[i].ID < messages[j].ID
} else {
return messages[i].ID > messages[j].ID
}
})
fmt.Printf("data is %+v\n", messages)
total := 0
for i, message := range messages {
switch request.Direction {
case 1: //向下查找找比CurrentId大的数据
if message.ID <= request.CurrentId {
continue
}
case 2: //向上查找找比CurrentId小的数据
if message.ID >= request.CurrentId {
continue
}
}
message := message
fmt.Println(i, message.ID)
if request.PageSize != -1 && int64(total+1) > request.PageSize {
continue
}
total++
returnDataIdList = append(returnDataIdList, message.ID)
var msg = &dto.MessageListType{}
msg.BuildMessage(message)
resp = append(resp, msg)
}
}
//二次排序
sort.Slice(resp, func(i, j int) bool {
return resp[i].ID < resp[j].ID
})
//优化空列表
for i, v := range resp {
if v.Message.Media == nil {
resp[i].Message.Media = []dto.MessageMedia{}
}
}
if accessUser.Role == 1 {
}
service.Success(c, resp)
}
func (cr ChatHandler) Upload(c *gin.Context) {
fmt.Println("111111111111")
//获取用户信息
chatUser, code := jwt.ParseToChatUser(c)
if code != 0 {
service.ErrWithCode(c, code)
return
}
fmt.Printf("chatUser is %#v\n", chatUser)
//获取文件对象
file, err := c.FormFile("file")
if err != nil {
log.Print("ERROR: upload file failed. ", zap.Error(err))
return
}
duration := c.PostForm("duration")
fmt.Println(duration)
ext := c.PostForm("ext")
fileExt := strings.ToLower(path.Ext(file.Filename))
if ext != "" {
fileExt = ext
}
fileType := e.DetectFileTypeByExtension(fileExt)
if fileType == e.Audio {
if !slices.Contains([]string{".mp4", ".aac", ".mp3", ".opus", ".wav"}, fileExt) {
service.Error(c, errors.New("不支持的格式"))
return
}
}
//计算md5
tmp, err := file.Open()
if err != nil {
service.Error(c, errors.New("上传失败"))
return
}
fileContent, err := io.ReadAll(tmp)
if err != nil {
service.Error(c, errors.New("文件读取失败"))
return
}
hash := md5.New()
_, err = hash.Write(fileContent)
if err != nil {
service.Error(c, errors.New("文件读取失败"))
return
}
md5Bytes := hash.Sum(nil) // 获取 MD5 字节切片
md5String := hex.EncodeToString(md5Bytes) // 转换为十六进制字符串表示
//检查文件是否存在
checkResp, err := service.AccountFieeProvider.GetChatMediaList(c, &accountFiee.GetChatMediaListRequest{Query: &accountFiee.ChatMediaData{Md5: md5String}, Page: 1, PageSize: 1})
if err != nil {
log.Print("md5查询附件失败", zap.Error(err))
}
if checkResp != nil && checkResp.Total > 0 {
service.Success(c, checkResp.List[0])
return
}
//文件不存在则上传文件
filename, _ := uuid.NewV4()
defer tmp.Close()
fileBuffer := bytes.NewBuffer(fileContent)
var bosUrl string
bosUrl, err = upload.UploadWithBuffer(fileBuffer, fmt.Sprintf("%d/%v%v", chatUser.ID, filename, fileExt))
if err != nil {
service.Error(c, err)
return
}
//存到数据库
var durationInt64, _ = strconv.ParseInt(duration, 10, 64)
var mediaData = accountFiee.ChatMediaData{
Url: bosUrl,
Md5: md5String,
Size: fmt.Sprintf("%d", file.Size),
Ext: fileExt,
Duration: durationInt64,
}
resp, err := service.AccountFieeProvider.CreateChatMedia(c, &mediaData)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, resp.Data)
}
func (cr ChatHandler) UserMessageStat(c *gin.Context) {
var request accountFiee.GetChatUserListRequest2
if err := c.ShouldBindJSON(&request); err != nil {
service.Error(c, err)
return
}
//获取用户信息
chatUser, code := jwt.ParseToChatUser(c)
if code != 0 {
service.ErrWithCode(c, code)
return
}
result := cr.cache.GetNewMessageStat(c, chatUser.ID)
if len(result) == 0 {
service.Success(c, result)
return
}
fmt.Printf("cache stat:%+v\n", result)
request.Page = 1
request.PageSize = int64(len(result))
for i, item := range result {
if item.UserId == 0 {
sessionId, _ := strconv.Atoi(item.SessionId)
item.UserId = int64(sessionId)
result[i].UserId = int64(sessionId)
}
request.UserIdIn = append(request.UserIdIn, item.UserId)
}
fmt.Printf("protoReq.UserIdIn:%+v\n", request.UserIdIn)
listRes, err := service.AccountFieeProvider.GetChatUserList2(c, &request)
if err != nil {
service.Error(c, err)
return
}
fmt.Printf("GetChatUserList:%+v\n", listRes)
for i, item := range result {
for _, user := range listRes.List {
if item.UserId == user.UserId {
user := user
result[i].Name = user.Name
//result[i].ArtistUid = user.ArtistUid
break
}
}
if result[i].Name == "" {
result[i].Name = logic.BeautifulZeroNameWithPhone(result[i].Name, result[i].UserId)
}
}
//筛选
if request.Account != "" || request.Name != "" {
newData := []dto.UserMsgStatic{}
for _, v := range listRes.List {
for _, vv := range result {
if v.UserId == vv.UserId {
vv := vv
newData = append(newData, vv)
}
}
}
result = newData
}
reverse(result)
if chatUser.Role == 1 {
userSessionId := fmt.Sprintf("%d", chatUser.ID)
newResp := []dto.UserMsgStatic{}
for _, v := range result {
if v.SessionId == userSessionId {
newResp = append(newResp, v)
service.Success(c, newResp)
return
}
}
}
service.Success(c, result)
}
func reverse(slice []dto.UserMsgStatic) {
for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
slice[i], slice[j] = slice[j], slice[i]
}
}
func (cr ChatHandler) VoiceToText(c *gin.Context) {
var req dto.VoiceToTextRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
detail, err := service.AccountFieeProvider.GetChatMediaDetail(c, &accountFiee.GetChatMediaByIdRequest{Id: req.MediaId})
if err != nil {
service.Error(c, err)
return
}
if detail.ConvText != "" {
service.Success(c, map[string]string{"convText": detail.ConvText})
return
}
voiceApi := voice.NewVoiceApi()
detail.ConvText, err = voiceApi.ToTextFromUrl(detail.Url)
if err != nil {
service.Error(c, errors.New("语音转文字失败"))
return
}
defer func() {
service.AccountFieeProvider.UpdateChatMedia(context.Background(), detail)
}()
service.Success(c, map[string]string{"convText": detail.ConvText})
}
func (cr ChatHandler) UserDetail(c *gin.Context) {
var req dto.UserDetailReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
var chatUser *accountFiee.ChatUserData
if req.ChatUserId == 0 { //不传ChatUserId则从token获取
var code e.ErrorCodeType
chatUser, code = jwt.ParseToChatUser(c)
if code != 0 {
service.ErrWithCode(c, code)
return
}
} else {
var err error
chatUser, err = service.AccountFieeProvider.GetChatUserDetail(c, &accountFiee.GetChatUserByIdRequest{
Id: req.ChatUserId,
})
if err != nil {
service.Error(c, err)
return
}
}
//fmt.Printf("chatUser:%#v\n", chatUser)
//if chatUser.Origin == "fiee" {
// chatUser.Origin = "app"
//}
resp, err := service.AccountFieeProvider.Info(c, &accountFiee.InfoRequest{ID: uint64(chatUser.OriginId), Domain: chatUser.Origin})
if err != nil {
service.Error(c, err)
return
}
var detail = dto.UserDetailResp{
UserId: resp.Id,
ChatUserId: chatUser.ID,
RnStatus: resp.Status,
SubNum: resp.SubNum,
RealName: resp.Name,
Age: "∞",
Gender: resp.Sex,
NativePlace: resp.PlaceOfResidence,
Phone: resp.TelNum,
GroupPhoto: resp.GroupPhoto,
}
service.Success(c, detail)
}
func (a *ChatHandler) UserSwitchAutoReplyStatus(c *gin.Context) {
chatUser, code := jwt.ParseToChatUser(c)
if code != 0 {
service.ErrWithCode(c, code)
return
}
var req dto.UserSwitchAutoReplyReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
enable := a.cache.GetAutoReplySwitch(c, chatUser.ID)
var resp = map[string]any{
"enableAutoReply": enable,
}
service.Success(c, resp)
}
func (a *ChatHandler) SetSwitchAutoReplyStatus(c *gin.Context) {
chatUser, code := jwt.ParseToChatUser(c)
if code != 0 {
service.ErrWithCode(c, code)
return
}
var req dto.UserSwitchAutoReplyReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
a.cache.SetAutoReplySwitch(c, chatUser.ID, req.EnableAutoReply)
msg := dto.Message{
MsgType: 1,
LocalStamp: time.Now().Unix(),
}
if req.EnableAutoReply {
msg.Text = "已退出人工"
} else {
msg.Text = "已进入人工,不会接收自动消息"
}
err := logic.NewMessage(c, &a.cache, chatUser, dto.NewMessageRequest{
Robot: true,
SessionId: fmt.Sprintf("%d", chatUser.ID),
Message: msg,
})
if err != nil {
service.Error(c, err)
return
}
service.Success(c)
}

View File

@ -0,0 +1,13 @@
// Package autoReply -----------------------------
// @file : intreface.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 16:15
// -------------------------------------------
package asChat
type IReplyRuler interface {
Name() string //规则名称
Check()
RunScript() string //运行脚本
}

View File

@ -0,0 +1,113 @@
// Package service -----------------------------
// @file : chat.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 19:04
// -------------------------------------------
package logic
import (
"context"
"errors"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/ws"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/asChat/chatCache"
"fonchain-fiee/pkg/service/asChat/consts"
"fonchain-fiee/pkg/service/asChat/dto"
"go.uber.org/zap"
"log"
"sync"
)
var cacheMap = make(map[int64]dto.NewMessageRequest)
var newMessageLocker sync.Mutex
func NewMessage(ctx context.Context, cache *chatCache.ChatCache, sender *accountFiee.ChatUserData, request dto.NewMessageRequest) (err error) {
newMessageLocker.Lock()
defer newMessageLocker.Unlock()
if request.SessionId == "" {
return errors.New("sessionId不能为空")
}
if request.MsgType == 0 {
return errors.New("msgType不能为空")
}
//短时间重复消息不发送
if request.AtUserId != 0 && request.Robot {
if msgRecord, ok := cacheMap[request.AtUserId]; ok {
if msgRecord.SessionId == "" {
cacheMap[request.AtUserId] = request
} else {
fmt.Println(request.LocalStamp - msgRecord.LocalStamp)
if msgRecord.Message.Text == request.Message.Text && request.LocalStamp-msgRecord.LocalStamp < 1 { //秒级
cacheMap[request.AtUserId] = request
return nil
} else {
cacheMap[request.AtUserId] = request
}
}
} else {
cacheMap[request.AtUserId] = request
}
}
//存储入库
if sender.NickName == "" {
//sender.NickName = fmt.Sprintf("未知用户(%d)", sender.ID)
sender.NickName = BeautifulZeroNameWithPhone(sender.NickName, sender.ID)
}
fmt.Println("NewMessage 3333333333333333333333333333333333")
var data = accountFiee.ChatRecordData{
SessionId: request.SessionId,
UserId: sender.ID,
Name: sender.NickName,
Avatar: sender.Avatar,
MsgType: request.MsgType,
Content: request.Message.Text,
LocalStamp: request.LocalStamp,
Medias: nil,
Role: sender.Role,
}
if len(request.Message.Media) > 0 {
for _, media := range request.Message.Media {
data.Medias = append(data.Medias, &accountFiee.ChatMediaData{
ID: media.MediaId,
})
}
}
fmt.Println("NewMessage 4444444444444444444444444444444444")
resp, err := service.AccountFieeProvider.CreateChatRecord(ctx, &data)
if err != nil {
return errors.New("消息发送失败")
}
fmt.Printf("CreateChatRecord resp:%+v\n", resp)
//录入缓存
err = cache.AddChatRecord(request.SessionId, resp.Data)
if err != nil {
log.Printf("cache.AddChatRecord 失败:%v", err)
return errors.New("消息发送失败")
}
fmt.Println("NewMessage 5 消息数量+1")
if sender.Role != 3 {
//新消息数量统计+1
noticeUserId := consts.ChatRoom.GetUserIdInSession(request.SessionId, sender.ID)
fmt.Println("NewMessage 5.1 消息数量配置结束")
fmt.Printf("noticeUserId %+v\n", noticeUserId)
for _, userId := range noticeUserId {
fmt.Println("userId")
_ = cache.IncreaseNewMessageTotal(userId, request.SessionId)
}
}
fmt.Println("NewMessage 6")
//发送websocket消息提醒通知
var notice = dto.MessageListType{}
notice.BuildMessage(resp.Data)
fmt.Printf("ws消息提醒:%+v\n", notice)
_, err = consts.ChatRoom.SendSessionMessage(sender, request.SessionId, ws.NewChatMsgType, notice)
if err != nil {
log.Print("发送新消息通知失败", zap.Error(err), zap.Any("notice", notice))
}
fmt.Println("NewMessage 7 -end")
return nil
}

View File

@ -0,0 +1,42 @@
package logic
import (
"context"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/utils"
)
// 对没有名字的name进行优化
func beautifulZeroName(name string, userId int64) string {
return utils.IfGec(name == "", fmt.Sprintf("未实名用户:%d", userId), name)
}
var userIdMapPhone = make(map[int64]string)
func BeautifulZeroNameWithPhone(name string, userId int64) string {
var ctx = context.Background()
if name == "" {
telNum, ok := userIdMapPhone[userId]
if ok {
return telNum
}
chatUserRes, err := service.AccountFieeProvider.GetChatUserDetail(ctx, &accountFiee.GetChatUserByIdRequest{Id: userId})
if err != nil {
return fmt.Sprintf("未实名用户:%d", userId)
} else {
if userRes, errs := service.AccountFieeProvider.Info(ctx, &accountFiee.InfoRequest{
Domain: chatUserRes.Origin,
ID: uint64(chatUserRes.OriginId),
Scene: "",
}); errs != nil {
return fmt.Sprintf("未实名用户:%d", userId)
} else {
userIdMapPhone[userId] = userRes.TelNum
return userRes.TelNum
}
}
}
return name
}

View File

@ -0,0 +1,26 @@
# asChat 客服聊天
## 聊天室主要流程与功能描述
1. 用户通过画家包登录
2. 打开客服页面。 画家宝客户端自动进行websocket连接后台会自动创建一个默认聊天室聊天室携带一个SessionId
3. 用户调用api接口发送消息。 服务端接收到消息后会通过websocket通知聊天室里面所有用户。
4. erp首次打开客服菜单时会进行websocket连接并调用一次api接口刷新消息列表。后续通过websocket接收消息推送收到消息时应主动调用一次消息列表刷新接口。
5. erp客服端发送消息时加入到此聊天室。
6. 用户端调用api接口获取新消息列表。
## 客户端应具备的其它功能
1. weboscket断开自动重连
2. 当通过websocket接收到错误类型的消息应具备对应的错误处理机制<p>
错误消息示例
```json
{"type":1,"content":"Connection error:登录状态失效","from":"0","to":"null"}
```
## 服务端应具备的功能
1. 通过redis缓存聊天消息
2. 通过redis缓存用户的sessionId避免ws断开后找不到之前的sessionId
3. 客服端由于不是画家宝用户没有userId。在websocket连接时如果找不到userId应该为其在画家宝创建一个账号。且经纪人不可见。
4. 由于没有创建聊天室的需求,所以每个用户使用一个聊天室即可。客服与之对话时,就自动加入用户端的聊天室
5. 新消息统计
- 当发送消息时,该聊天室中除了发信者以外,其它用户的新消息数都+1录入缓存。
- 当新客服人员加入时,没有新消息统计的缓存。~~他的新消息数量应该从创建时间开始计算~~,所以都是0。

View File

@ -0,0 +1,39 @@
// Package autoReply -----------------------------
// @file : KeywordsReplyRuler.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 16:21
// -------------------------------------------
package robot
import (
"time"
)
// 使用go开发一个自动回复功能
// 一个自动回复消息有多种触发条件:
// 1. 关键词触发
// 2. 进入聊天系统后直接发送
// 3. 若干秒不回复自动发送
//func (k KeywordsRuleChecker) Do(sessionId string, response string, chatRoom *ws.ChatRoom) (err error) {
// var notice = dto.MessageListType{}
// notice.BuildMessage(response)
// _, err = chatRoom.SendSessionMessage(1, sessionId, ws.NewChatMsgType, notice)
// return nil
//}
type AutoReply struct {
Response string `json:"response"`
Rules map[string]IRobotTask `json:"rules"`
}
type AutoReplyRule struct {
Enable bool `json:"enable"`
Keywords []string `json:"keywords"`
ReplyTimeout int `json:"replyTimeout"` // 回复超时时间
}
type AutoReplyManager struct {
replies []AutoReply
lastMessage time.Time
}

View File

@ -0,0 +1,31 @@
# robot 聊天机器人
web端和后端交互式时增删改查的规则配置是存放在rules对象中的。在数据库中rules字段是作为json字符串存放的。
```json
{
"title": "1",
"response": "11",
"rules": {
"keywords": {
"enable": true,
"content": "什么,为什么,怎么办,不是"
},
"joinSession": {
"enable": true
},
"noReplyAfter": {
"enable": false,
"secondDuration": 1
}
},
"status": 1
}
```
如果有新增的规则直接在rules对象中添加字段即可。然后去 [./rulerList.go](./rulerList.go) 中,增加规则的解析方法。
目前,在[./rulerList.go](./rulerList.go)定义了三种回复规则的解析方式:
- keywords :关键字回复
- joinSession用户打开聊天窗口后
- noReplyAfter客服指定时间没有回复后
## 注意
- 目前不支持用户多端登录,会导致用户收到重复消息

View File

@ -0,0 +1,29 @@
// Package robot -----------------------------
// @file : replyRuler.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 17:39
// -------------------------------------------
package robot
import (
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/ws"
)
// 回复规则
type Reply struct {
Title string
Response string
Rules []IRobotTask
}
func (r *Reply) Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, rule IRobotTask) {
for _, rule = range r.Rules {
hit = rule.Hit(event, robotInfo)
if hit {
return
}
}
return
}

View File

@ -0,0 +1,271 @@
// Package robot -----------------------------
// @file : robot.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 17:41
// -------------------------------------------
package robot
import (
"context"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/ws"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/asChat/chatCache"
"fonchain-fiee/pkg/service/asChat/consts"
"fonchain-fiee/pkg/service/asChat/dto"
"log"
"sync"
"time"
)
func NewRobot(cache *chatCache.ChatCache) *Robot {
ctx := context.Background()
robotQuery, err := service.AccountFieeProvider.GetChatUserList(ctx, &accountFiee.GetChatUserListRequest{
Query: &accountFiee.ChatUserData{Role: 3},
Page: 1, PageSize: 1,
})
if err != nil {
panic("聊天机器人初始化失败,err:" + err.Error())
}
var robotInfo *accountFiee.ChatUserData
if robotQuery.Total > 0 {
robotInfo = robotQuery.List[0]
} else {
robotInfo = &accountFiee.ChatUserData{
NickName: "阿泰",
Role: 3,
Origin: "fontree",
}
createChatUserResp, errs := service.AccountFieeProvider.CreateChatUser(ctx, robotInfo)
if errs != nil {
panic("聊天机器人创建失败,err:" + errs.Error())
}
robotInfo = createChatUserResp.Data
}
r := &Robot{
Info: robotInfo,
EventListener: &ws.EventListener{
Name: "robot1",
ListenEvents: []ws.ListenEvent{ //只监听消息推送事件
{ws.EventUserJoin, ws.EventProgressAfter},
{ws.EventChatMessage, ws.EventProgressBefore},
},
Chan: make(ws.ListenEventChan),
},
cache: cache,
}
err = r.ReloadRules(ctx)
fmt.Println("机器人规则加载完成,结果:", err)
consts.ChatRoom.RegisterEventListener(r.EventListener)
go r.Run()
return r
}
type Robot struct {
Info *accountFiee.ChatUserData //机器人信息
joinSessionRules, keywordsRules, noReplyAfterRules []IRobotTask //自动回复规则
DelayTask []IRobotTask //延时任务
ticker *time.Ticker //定时器
stopChan chan struct{} //停止管道
isRunning bool //运行状态
mu sync.Mutex
*ws.EventListener
cache *chatCache.ChatCache
}
//func (r *Robot) Listen(record *accountFiee.ChatRecordData) {
// for _, replyRules := range r.Rules {
// for _, rule := range replyRules.Rules {
// hit, runTime, function := rule.Hit(record)
// if hit && function != nil {
// if runTime.IsZero() {
// go func() {
// err := function(r.Info.ID, replyRules.Response)
// if err != nil {
// log.Printf("聊天机器人[%d]回复消息失败:%v", r.Info.ID, err)
// }
// }()
// } else {
// r.mu.Lock()
// r.DelayTask = append(r.DelayTask, RobotTask{
// RunTime: runTime,
// Run: function,
// Response: replyRules.Response,
// })
// r.mu.Unlock()
// // 添加任务后启动定时任务(如果未运行)
// if !r.isRunning {
// go r.Run()
// }
// }
// break
// }
// }
// }
//}
func (r *Robot) Run() {
r.mu.Lock()
if r.isRunning {
r.mu.Unlock()
return
}
r.isRunning = true
r.ticker = time.NewTicker(time.Second)
r.stopChan = make(chan struct{})
r.mu.Unlock()
defer func() {
r.mu.Lock()
r.isRunning = false
if r.ticker != nil {
r.ticker.Stop()
r.ticker = nil
}
r.stopChan = nil
r.mu.Unlock()
}()
for {
select {
default:
time.Sleep(200 * time.Millisecond)
case <-r.ticker.C:
r.mu.Lock()
if len(r.DelayTask) == 0 {
r.mu.Unlock()
break
//return // 没有任务时退出
}
now := time.Now()
var remainingTasks []IRobotTask
for _, task := range r.DelayTask {
if now.After(task.RunTime()) {
// 执行任务
go func() {
err := task.Run(r.cache)
if err != nil {
log.Printf("聊天机器人[%d]延时回复消息失败:%v", r.Info.ID, err)
} else {
log.Printf("聊天机器人[%d]延时回复消息成功", r.Info.ID)
}
}()
} else {
// 保留未到期的任务
remainingTasks = append(remainingTasks, task)
}
}
r.DelayTask = remainingTasks
r.mu.Unlock()
case <-r.stopChan:
return
case event := <-r.EventListener.Chan:
fmt.Printf("robot listen event:%#v\n", event)
r.mu.Lock()
//加入聊天室规则
enableAutoReply := false
if event.Client != nil {
enableAutoReply = new(chatCache.ChatCache).GetAutoReplySwitch(context.Background(), event.Client.UserId)
}
if enableAutoReply {
hasHit := false
for _, rule := range r.joinSessionRules {
hit := rule.Hit(event, r.Info)
fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
if hit {
hasHit = true
if rule.RunTime().IsZero() {
err := rule.Run(r.cache)
if err != nil {
log.Printf("robot 执行任务失败:%v\n", err)
}
} else {
r.RegisterDelayTask(rule)
}
}
}
if !hasHit {
for _, rule := range r.keywordsRules {
hit := rule.Hit(event, r.Info)
fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
if hit {
hasHit = true
fmt.Println("命中规则:", rule.GetTitle())
if rule.RunTime().IsZero() {
err := rule.Run(r.cache)
if err != nil {
log.Printf("robot 执行任务失败:%v\n", err)
}
} else {
r.RegisterDelayTask(rule)
}
}
}
}
if !hasHit {
for _, rule := range r.noReplyAfterRules {
hit := rule.Hit(event, r.Info)
fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
if hit {
hasHit = true
fmt.Println("命中规则:", rule.GetTitle())
if rule.RunTime().IsZero() {
err := rule.Run(r.cache)
if err != nil {
log.Printf("robot 执行任务失败:%v\n", err)
}
} else {
r.RegisterDelayTask(rule)
}
}
}
}
}
r.mu.Unlock()
}
}
}
// Stop 主动停止机器人的定时任务
func (r *Robot) Stop() {
r.mu.Lock()
if r.stopChan != nil {
close(r.stopChan)
}
r.mu.Unlock()
}
func (r *Robot) RegisterDelayTask(task IRobotTask) {
if task.Run == nil {
return
}
r.DelayTask = append(r.DelayTask, task)
}
// 重载回复规则
func (r *Robot) ReloadRules(ctx context.Context) error {
r.mu.Lock()
defer r.mu.Unlock()
r.joinSessionRules = []IRobotTask{}
r.keywordsRules = []IRobotTask{}
r.noReplyAfterRules = []IRobotTask{}
ruleListRes, err := service.AccountFieeProvider.GetChatAutoReplyRulerList(ctx, &accountFiee.GetChatAutoReplyRulerListRequest{
Query: &accountFiee.ChatAutoReplyRulerData{Status: 1},
Page: 1,
PageSize: -1,
})
if err != nil {
log.Printf("robot 查询回复规则失败:%v\n", err)
return fmt.Errorf("robot 查询回复规则失败:%v\n", err)
} else {
var data []*dto.ChatAutoReplyData
for _, v := range ruleListRes.List {
tmp := dto.ChatAutoReplyData{}
tmp.Parse(v)
data = append(data, &tmp)
}
r.joinSessionRules, r.keywordsRules, r.noReplyAfterRules = ParseReplyRule(data)
}
return nil
}

View File

@ -0,0 +1,64 @@
// Package autoReply -----------------------------
// @file : rulerList.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 16:16
// -------------------------------------------
package robot
import (
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/ws"
"fonchain-fiee/pkg/service/asChat/chatCache"
"fonchain-fiee/pkg/service/asChat/dto"
"strings"
"time"
)
type IRobotTask interface {
Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool)
Run(cache *chatCache.ChatCache) error
RunTime() time.Time
SetResponse(response string)
GetResponse() string
SetTitle(title string)
GetTitle() string
}
// 自动回复规则结构转换
func ParseReplyRule(data []*dto.ChatAutoReplyData) (joinSessionRules, keywordsRules, noReplyAfterRules []IRobotTask) {
for _, responseRules := range data {
responseRules := responseRules
for ruleName, v := range responseRules.Rules {
if !v.Enable {
continue
}
switch ruleName {
case "keywords": //关键字回复
var keywords []string
if v.Content == "" {
continue
} else {
keywords = strings.Split(v.Content, ",")
}
fmt.Println("ParseReplyRule 解析keywords:", keywords)
r := NewReplyWhenHitKeywords(responseRules.Title+"-keywords", keywords)
r.SetResponse(responseRules.Response)
keywordsRules = append(keywordsRules, r)
case "joinSession": //加入聊天后回复
r := NewReplyWhenUserJoinSession(responseRules.Title + "-joinSession")
r.SetResponse(responseRules.Response)
joinSessionRules = append(joinSessionRules, r)
case "noReplyAfter": //指定时间没有回复则自动回复
if v.SecondDuration == 0 {
continue
}
r := NewReplyWhenWaiterNoAction(responseRules.Title+"-noReplyAfter", v.SecondDuration)
r.SetResponse(responseRules.Response)
noReplyAfterRules = append(noReplyAfterRules, r)
}
}
}
return
}

View File

@ -0,0 +1,102 @@
// Package robot -----------------------------
// @file : ruler_ReplyWhenWaiterNoAction.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 18:02
// -------------------------------------------
package robot
import (
"context"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/ws"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/asChat/chatCache"
"fonchain-fiee/pkg/service/asChat/dto"
"fonchain-fiee/pkg/service/asChat/logic"
"time"
)
// 客服指定时间不回复则自动回复
func NewReplyWhenWaiterNoAction(title string, delaySecond time.Duration) IRobotTask {
return &RobotTaskReplyWhenWaiterNoAction{
delaySecond: delaySecond,
title: title,
}
}
type RobotTaskReplyWhenWaiterNoAction struct {
title string
runTime time.Time
Response string
Receiver *accountFiee.ChatUserData
Sender *accountFiee.ChatUserData
Msg string
Resp string
delaySecond time.Duration
}
func (r *RobotTaskReplyWhenWaiterNoAction) Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool) {
if event.Client == nil || event.EventType != ws.EventChatMessage {
return
}
//客服和机器人的的消息不需要处理
if event.ChatUser.Role != 1 {
return
}
hit = true // 立即保存SessionId的值
r.Sender = sender
r.Receiver = event.ChatUser
r.runTime = time.Now().Add(r.delaySecond * time.Second)
return
}
func (r *RobotTaskReplyWhenWaiterNoAction) Run(cache *chatCache.ChatCache) error {
clientSessionId := fmt.Sprintf("%d", r.Receiver.ID)
fmt.Println("延时回复 sessionID:", clientSessionId)
//如果客服已经回复则不发送消息
chatRecordListRes, err := service.AccountFieeProvider.GetChatRecordList(context.Background(), &accountFiee.GetChatRecordListRequest{
Query: &accountFiee.ChatRecordData{
SessionId: clientSessionId,
},
Page: 1,
PageSize: 1,
Order: "created_at desc",
})
if err != nil || chatRecordListRes.Total == 0 {
return err
}
checkUserId := chatRecordListRes.List[0].UserId
checkChatUser, err := service.AccountFieeProvider.GetChatUserDetail(context.Background(), &accountFiee.GetChatUserByIdRequest{Id: checkUserId})
if err != nil || checkChatUser.Role != 1 {
return err
}
err = logic.NewMessage(context.Background(), cache, r.Sender, dto.NewMessageRequest{
Waiter: true,
Robot: true,
AtUserId: r.Receiver.ID,
SessionId: clientSessionId,
Message: dto.Message{
MsgType: 1,
Text: r.Resp,
LocalStamp: time.Now().Unix(),
},
})
return err
}
func (r *RobotTaskReplyWhenWaiterNoAction) RunTime() time.Time {
return r.runTime
}
func (r *RobotTaskReplyWhenWaiterNoAction) SetResponse(response string) {
r.Resp = response
}
func (r *RobotTaskReplyWhenWaiterNoAction) GetResponse() string {
return r.Response
}
func (r *RobotTaskReplyWhenWaiterNoAction) SetTitle(title string) {
r.title = title
}
func (r *RobotTaskReplyWhenWaiterNoAction) GetTitle() string {
return r.title
}

View File

@ -0,0 +1,80 @@
package robot
import (
"context"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/ws"
"fonchain-fiee/pkg/service/asChat/chatCache"
"fonchain-fiee/pkg/service/asChat/dto"
"fonchain-fiee/pkg/service/asChat/logic"
"strings"
"time"
)
type RobotTaskWithKeyworkds struct {
title string
runTime time.Time
Response string
Receiver *accountFiee.ChatUserData
Sender *accountFiee.ChatUserData
Msg string
Resp string
keywords []string
}
func NewReplyWhenHitKeywords(title string, keywords []string) IRobotTask {
return &RobotTaskWithKeyworkds{title: title, keywords: keywords}
}
func (r *RobotTaskWithKeyworkds) Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool) {
if event.EventType != ws.EventChatMessage || event.Msg == "" || event.Client == nil || event.ChatUser == nil {
return
}
if event.ChatUser.Role != 1 {
return
}
r.Sender = sender
r.Receiver = event.ChatUser
for _, v := range r.keywords {
if strings.Contains(event.Msg, v) {
fmt.Printf("关键词比对:%s ----- %s : true", event.Msg, v)
hit = true
break
}
fmt.Printf("关键词比对:%s ----- %s: false", event.Msg, v)
}
return
}
func (r *RobotTaskWithKeyworkds) Run(cache *chatCache.ChatCache) (err error) {
err = logic.NewMessage(context.Background(), cache, r.Sender, dto.NewMessageRequest{
Waiter: true,
Robot: true,
AtUserId: r.Receiver.ID,
SessionId: fmt.Sprintf("%d", r.Receiver.ID),
Message: dto.Message{
MsgType: 1,
Text: r.Resp,
LocalStamp: time.Now().Unix(),
},
})
return
}
func (r *RobotTaskWithKeyworkds) RunTime() time.Time {
return time.Time{}
}
func (r *RobotTaskWithKeyworkds) SetResponse(response string) {
r.Resp = response
}
func (r *RobotTaskWithKeyworkds) GetResponse() string {
return r.Response
}
func (r *RobotTaskWithKeyworkds) SetTitle(title string) {
r.title = title
}
func (r *RobotTaskWithKeyworkds) GetTitle() string {
return r.title
}

View File

@ -0,0 +1,95 @@
package robot
import (
"context"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/ws"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/asChat/chatCache"
"fonchain-fiee/pkg/service/asChat/dto"
"fonchain-fiee/pkg/service/asChat/logic"
"strconv"
"time"
)
func NewReplyWhenUserJoinSession(title string) IRobotTask {
return &ReplyWhenUserJoinSession{title: title}
}
type ReplyWhenUserJoinSession struct {
Response string
Sender *accountFiee.ChatUserData
Msg string
Resp string
sessionId string
atUserId int
title string
}
func (r *ReplyWhenUserJoinSession) Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool) {
if event.EventType != ws.EventUserJoin {
return
}
if event.Client == nil {
return
}
ctx := context.Background()
queryRes, err := service.AccountFieeProvider.GetChatRecordList(ctx, &accountFiee.GetChatRecordListRequest{
Query: &accountFiee.ChatRecordData{
SessionId: event.Client.SessionId,
},
Page: 1,
PageSize: 1,
Order: "created_at desc",
})
if err != nil {
return
}
//如果最近一次的消息也是机器人发送的,就不再发送了
for i, v := range queryRes.List {
if i == 0 {
if v.UserId == sender.ID {
return
} else {
break
}
}
}
hit = true
r.Sender = sender
r.sessionId = event.Client.SessionId
r.atUserId, _ = strconv.Atoi(event.Client.SessionId)
return
}
func (r *ReplyWhenUserJoinSession) Run(cache *chatCache.ChatCache) (err error) {
err = logic.NewMessage(context.Background(), cache, r.Sender, dto.NewMessageRequest{
Waiter: true,
Robot: true,
AtUserId: int64(r.atUserId),
SessionId: r.sessionId,
Message: dto.Message{
MsgType: 1,
Text: r.Resp,
LocalStamp: time.Now().Unix(),
},
})
return
}
func (r *ReplyWhenUserJoinSession) RunTime() time.Time {
return time.Time{}
}
func (r *ReplyWhenUserJoinSession) SetResponse(response string) {
r.Resp = response
}
func (r *ReplyWhenUserJoinSession) GetResponse() string {
return r.Response
}
func (r *ReplyWhenUserJoinSession) SetTitle(title string) {
r.title = title
}
func (r *ReplyWhenUserJoinSession) GetTitle() string {
return r.title
}

View File

@ -0,0 +1,20 @@
// Package robot -----------------------------
// @file : task.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 18:02
// -------------------------------------------
package robot
import (
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/service/asChat/chatCache"
"time"
)
type RobotTask struct {
RunTime time.Time
Run func(msg string, cache *chatCache.ChatCache, Sender *accountFiee.ChatUserData) error
Response string
ChatUser *accountFiee.ChatUserData
}

View File

@ -0,0 +1,46 @@
// Package asChat -----------------------------
// @file : service.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2024/9/10 下午7:05
// -------------------------------------------
package asChat
import (
"encoding/json"
"fonchain-fiee/pkg/common/ws"
)
func HandleMessage(sourceData []byte, cli *ws.Client) {
var msg map[string]any
err := json.Unmarshal(sourceData, &msg)
if err != nil {
cli.Send <- ws.WsErrorInvalidDataFormat(cli.ClientId)
return
}
switch msg["type"] {
default:
cli.Send <- ws.WsErrorUnknownMessageType(cli.ClientId)
case ws.TestType:
var newMsg = ws.WsInfo{
Type: ws.TestType,
Content: msg["content"],
}
byteMsg, _ := json.Marshal(newMsg)
cli.Send <- byteMsg
//case ws.ChatType:
// var chatInfo ChatInfo
// _ = json.Unmarshal(sourceData, &chatInfo)
// //解析Content
// if clients, ok := cli.Room.clients[chatInfo.Content.TargetUserId]; ok {
// for _, targetObj := range clients {
// if targetObj != nil {
// targetObj.Send <- WsChatMessage(msg.From, chatInfo.Content.TargetClientId, chatInfo.Content.Msg)
// }
// }
// } else {
// //对方不在线
// cli.Send <- WsErrorMessage(ChatType, msg.From, e.ErrTargetOutLine, nil)
// }
}
}

View File

@ -7,8 +7,9 @@ import (
"fonchain-fiee/pkg/logic"
"fonchain-fiee/pkg/serializer"
"fonchain-fiee/pkg/service/approval/model"
"github.com/gin-gonic/gin"
"net/http"
"github.com/gin-gonic/gin"
)
const (
@ -189,3 +190,21 @@ func translateErrorMessage(c *gin.Context, message string) string {
return common.EnMessages[message]
}
}
func ErrWithCode(c *gin.Context, code e.ErrorCodeType, newMsg ...string) {
msg := e.GetCodeMsg(code)
if newMsg != nil {
msg = newMsg[0]
}
status := 1
if code == e.NotLogin {
status = e.NotLogin
}
c.JSON(e.Success, serializer.Response{
Code: code,
Status: status,
Msg: msg,
Data: nil,
})
}

View File

@ -17,10 +17,28 @@ import (
"strings"
"time"
"github.com/360EntSecGroup-Skylar/excelize"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
)
func DeleteBundleOrder(c *gin.Context) {
var req bundle.DeleteValueAddServiceRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
userInfo := login.GetUserInfoFromC(c)
req.UserID = userInfo.ID
res, err := service.BundleProvider.DeleteValueAddService(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
return
}
func CreateBundleOrderAddSignature(c *gin.Context) {
var req bundle.OrderAddRecord
@ -29,8 +47,11 @@ func CreateBundleOrderAddSignature(c *gin.Context) {
return
}
if req.Language == "" {
service.Error(c, errors.New(common.MissLanguageTypes))
return
req.Language = c.GetHeader("Accept-Language")
if req.Language == "" {
service.Error(c, errors.New(common.MissLanguageTypes))
return
}
}
if req.BundleUuid == "" {
service.Error(c, errors.New(common.MissOrderNo))
@ -66,13 +87,13 @@ func CreateBundleOrderAddSignature(c *gin.Context) {
return
}
// 获取套餐详情(待替换逻辑)
bundleDetail, err := service.BundleProvider.BundleDetail(context.Background(), &bundle.BundleDetailRequest{
Uuid: req.BundleUuid,
})
if err != nil {
service.Error(c, err)
return
}
//bundleDetail, err := service.BundleProvider.BundleDetail(context.Background(), &bundle.BundleDetailRequest{
// Uuid: req.BundleUuid,
//})
//if err != nil {
// service.Error(c, err)
// return
//}
// todo 需要判断购买的增值服务是否为可用时长 如果为可以用时长 合同截止日期为购买时长时间 否则合同截止日期为主套餐截止日期
// 处理多个增值服务
type ValueAddServiceInfo struct {
@ -81,7 +102,7 @@ func CreateBundleOrderAddSignature(c *gin.Context) {
ID int32
}
// 计算总金额和确定截止日期
var expirationDate string
//var expirationDate string
var addPriceList []*bundle.AddPriceOptionsInfo
var totalAmount float32
for _, svc := range req.AddPriceOptionsList {
@ -111,8 +132,8 @@ func CreateBundleOrderAddSignature(c *gin.Context) {
Num: svc.Num,
Unit: valueAddInfo.Unit,
})
// 如果是可用时长服务,计算新的截止日期
if valueAddInfo.ServiceType == 5 {
// 如果是可用时长服务,计算新的截止日期 todo 不需要计算到期时间 在完成支付时添加
/*if valueAddInfo.ServiceType == 5 {
endDate := orderRecordResp.OrderRecord.ExpirationTime
if endDate == "9999-12-31" {
service.Error(c, errors.New(common.ErrorPermanentPackage))
@ -126,27 +147,27 @@ func CreateBundleOrderAddSignature(c *gin.Context) {
newDeadline := calculateExpirationDate(t, svc.Num, valueAddInfo.Unit)
expirationDate = newDeadline
//}
}
}*/
}
// 如果没有可用时长服务,使用主套餐截止日期
if expirationDate == "" {
expirationDate = orderRecordResp.OrderRecord.ExpirationTime
}
//if expirationDate == "" {
// expirationDate = orderRecordResp.OrderRecord.ExpirationTime
//}
req.CustomerNum = userInfo.SubNum
req.CustomerName = userInfo.Name
req.CustomerID = strconv.FormatUint(userInfo.ID, 10)
req.Source = 2
req.SignedTime = common.GetBeijingTime()
req.ExpirationDate = expirationDate
//req.SignedTime = common.GetBeijingTime()
//req.ExpirationDate = expirationDate
req.AddPriceOptionsList = addPriceList
req.OrderUUID = orderRecordResp.OrderRecord.Uuid
// 当前 未将 签名 写入合同中
signContract, signContractErr := logic.SignContractV2(req.CustomerNum, bundleDetail.Bundle.Contract, totalAmount, expirationDate)
if signContractErr != nil {
service.Error(c, signContractErr)
return
}
req.SignContract = signContract
// 当前 未将 签名 写入合同中 todo 购买增值服务取消签约合同
//signContract, signContractErr := logic.SignContractV2(req.CustomerNum, bundleDetail.Bundle.Contract, totalAmount, expirationDate)
//if signContractErr != nil {
// service.Error(c, signContractErr)
// return
//}
//req.SignContract = signContract
// 创建增值服务订单记录
res, err := service.BundleProvider.CreateOrderAddRecord(context.Background(), &req)
if err != nil {
@ -183,8 +204,11 @@ func CreateBundleOrderSignature(c *gin.Context) {
return
}
if req.Language == "" {
service.Error(c, errors.New(common.MissLanguageTypes))
return
req.Language = c.GetHeader("Accept-Language")
if req.Language == "" {
service.Error(c, errors.New(common.MissLanguageTypes))
return
}
}
// 不去校验 签名
/*if req.Signature == "" {
@ -219,7 +243,11 @@ func CreateBundleOrderSignature(c *gin.Context) {
//有套餐并且套餐未过期
if orderRecordsList.OrderRecords != nil {
for _, orderInfo := range orderRecordsList.OrderRecords {
if orderInfo.CustomerID == strconv.FormatUint(userInfo.ID, 10) && orderInfo.ExpirationTime > time.Now().Format("2006-01-02") {
if orderInfo.CustomerID == strconv.FormatUint(userInfo.ID, 10) && orderInfo.Status == 1 {
service.Error(c, errors.New(common.ThereAreOutstandingOrders))
return
}
if orderInfo.CustomerID == strconv.FormatUint(userInfo.ID, 10) && orderInfo.ExpirationTime > time.Now().Format("2006-01-02 15:04:05") {
service.Error(c, errors.New(common.HadOrder))
return
}
@ -244,9 +272,10 @@ func CreateBundleOrderSignature(c *gin.Context) {
}
// 获取 套餐信息
bundleDetailReq := &bundle.BundleDetailRequest{
Uuid: req.BundleUuid,
Uuid: req.BundleUuid,
Language: req.Language,
}
bundleDetail, detailErr := service.BundleProvider.BundleDetail(context.Background(), bundleDetailReq)
bundleDetail, detailErr := service.BundleProvider.BundleLangDetailV2(context.Background(), bundleDetailReq)
if detailErr != nil {
service.Error(c, detailErr)
return
@ -292,7 +321,7 @@ func CreateBundleOrderSignature(c *gin.Context) {
}
}
// 当前 未将 签名 写入合同中 todo 金额和有效时间待修改
signContract, signContractErr := logic.SignContractV2(req.CustomerNum, bundleDetail.Bundle.Contract, addTotalPrice, expirationDay)
signContract, signContractErr := logic.SignContractV2(req.CustomerNum, bundleDetail.Contract, bundleDetail.Price+addTotalPrice, expirationDay)
if signContractErr != nil {
service.Error(c, signContractErr)
return
@ -300,17 +329,17 @@ func CreateBundleOrderSignature(c *gin.Context) {
req.CustomerNum = userInfo.SubNum
req.CustomerName = userInfo.Name
req.CustomerID = strconv.FormatUint(userInfo.ID, 10)
req.BundleName = bundleDetail.Bundle.Name
req.Amount = bundleDetail.Bundle.Price
req.AmountType = bundleDetail.Bundle.PriceType
req.BundleCommonUid = bundleDetail.Bundle.BundleCommonUid
req.TotalAmount = bundleDetail.Bundle.Price + addTotalPrice
req.BundleName = bundleDetail.Name
req.Amount = bundleDetail.Price
req.AmountType = bundleDetail.PriceType
//req.BundleCommonUid = bundleDetail.BundleCommonUid
req.TotalAmount = bundleDetail.Price + addTotalPrice
req.ContractNo = common.GenerateContractNo(lastContractNo)
req.SignContract = signContract
req.SignedTime = common.GetBeijingTime()
req.Status = bundleModel.OrderSigned
req.AddRecords = addRecords
req.ExpirationTime = expirationDay
//req.ExpirationTime = expirationDay //过期日期取消 在完成支付是更新
req.PayType = 1
res, err := service.BundleProvider.CreateOrderRecord(context.Background(), &req)
@ -474,12 +503,193 @@ func OrderRecordsListV2(c *gin.Context) {
if u, ok := userMap[item.CustomerId]; ok {
item.CustomerName = u.Name
item.TelNum = u.TelNum
item.SubNum = u.SubNum
}
}
}
service.Success(c, orderList)
}
func OrderRecordsListDownload(c *gin.Context) {
var req bundle.OrderRecordsRequestV2
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
res := &bundle.OrderRecordsResponseV2{}
// Step 1: 如果有姓名/电话筛选,先查用户列表
if req.CustomerName != "" {
userListResp, err := service.AccountFieeProvider.UserList(context.Background(), &accountFiee.UserListRequest{
BlurNameTel: req.CustomerName,
Domain: "app",
})
if err != nil {
service.Error(c, err)
return
}
if len(userListResp.UserList) == 0 {
// 没查到用户,直接返回空结果
res.Page = req.Page
res.PageSize = req.PageSize
res.Total = 0
service.Success(c, res)
return
}
// 提取用户ID列表
for _, u := range userListResp.UserList {
req.UserIds = append(req.UserIds, int64(u.Id))
}
}
// Step 2: 查询订单列表
orderList, err := service.BundleProvider.OrderRecordsListV2(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
// Step 3: 如果订单不为空,查一次用户信息填充(只查一次)
if len(orderList.BundleInfo) > 0 {
// 收集订单里的所有用户ID
userIdSet := make(map[int64]struct{})
for _, i := range orderList.BundleInfo {
userIdSet[i.CustomerId] = struct{}{}
}
var userIds []int64
for id := range userIdSet {
userIds = append(userIds, id)
}
userListResp, err := service.AccountFieeProvider.UserList(context.Background(), &accountFiee.UserListRequest{
Ids: userIds,
Domain: "app",
})
if err != nil {
service.Error(c, err)
return
}
// 建立用户ID -> 用户信息映射
userMap := make(map[int64]*accountFiee.UserListInfo, len(userListResp.UserList))
for _, u := range userListResp.UserList {
userMap[int64(u.Id)] = u
}
// 填充订单中的用户信息
for _, item := range orderList.BundleInfo {
if u, ok := userMap[item.CustomerId]; ok {
item.CustomerName = u.Name
item.TelNum = u.TelNum
item.SubNum = u.SubNum
}
}
}
excelFile, err := exportExcel(orderList.BundleInfo)
if err != nil {
service.Error(c, err)
return
}
// 返回 Excel 文件流给前端
c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
c.Header("Content-Disposition", "attachment; filename=order_list.xlsx")
c.Header("File-Name", "order_list.xlsx")
c.Header("Access-Control-Expose-Headers", "File-Name")
_ = excelFile.Write(c.Writer)
}
func exportExcel(orderList []*bundle.OrderBundleRecordInfo) (*excelize.File, error) {
f := excelize.NewFile()
sheetName := "Sheet1"
f.SetSheetName("Sheet1", sheetName)
headers := []string{
"套餐订单号", "套餐类型", "套餐付款状态", "艺人手机号", "用户编号", "艺人", "套餐订单创建时间", "套餐支付时间", "套餐金额",
"增值服务订单号", "增值税服务金额", "支付金额", "币种", "手续费", "增值订单创建时间", "增值付款状态",
}
for i, h := range headers {
cell := fmt.Sprintf("%s%d", string(rune('A'+i)), 1)
f.SetCellValue(sheetName, cell, h)
}
rowIndex := 2
for _, bundleInfo := range orderList {
addCount := len(bundleInfo.AddBundleInfo)
mergeRows := 1
if addCount > 1 {
mergeRows = addCount
}
// 写入主订单信息并合并单元格
for i := 0; i < 7; i++ {
col := string(rune('A' + i))
startCell := fmt.Sprintf("%s%d", col, rowIndex)
endCell := fmt.Sprintf("%s%d", col, rowIndex+mergeRows-1)
if mergeRows > 1 {
f.MergeCell(sheetName, startCell, endCell)
}
}
f.SetCellValue(sheetName, fmt.Sprintf("A%d", rowIndex), bundleInfo.OrderNo)
f.SetCellValue(sheetName, fmt.Sprintf("B%d", rowIndex), bundleInfo.BundleName)
f.SetCellValue(sheetName, fmt.Sprintf("C%d", rowIndex), GetPayStatusText(bundleInfo.PayStatus))
f.SetCellValue(sheetName, fmt.Sprintf("D%d", rowIndex), bundleInfo.TelNum)
f.SetCellValue(sheetName, fmt.Sprintf("E%d", rowIndex), bundleInfo.SubNum)
f.SetCellValue(sheetName, fmt.Sprintf("F%d", rowIndex), bundleInfo.CustomerName)
f.SetCellValue(sheetName, fmt.Sprintf("G%d", rowIndex), bundleInfo.BundleCreateAt)
f.SetCellValue(sheetName, fmt.Sprintf("H%d", rowIndex), bundleInfo.PayTime)
f.SetCellValue(sheetName, fmt.Sprintf("I%d", rowIndex), bundleInfo.Amount)
if addCount > 0 {
for i, add := range bundleInfo.AddBundleInfo {
r := rowIndex + i
f.SetCellValue(sheetName, fmt.Sprintf("J%d", r), add.OrderAddNo)
f.SetCellValue(sheetName, fmt.Sprintf("K%d", r), add.Amount)
f.SetCellValue(sheetName, fmt.Sprintf("L%d", r), add.SettlementAmount)
f.SetCellValue(sheetName, fmt.Sprintf("M%d", r), GetCurrencyTypeText(add.CurrencyType))
f.SetCellValue(sheetName, fmt.Sprintf("N%d", r), add.HandlingFee)
f.SetCellValue(sheetName, fmt.Sprintf("O%d", r), add.OrderAddCreateAt)
f.SetCellValue(sheetName, fmt.Sprintf("P%d", r), GetPayStatusText(add.AddPayStatus))
}
} else {
for i := 8; i <= 15; i++ {
col := string(rune('A' + i))
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", col, rowIndex), "")
}
}
rowIndex += mergeRows
}
return f, nil
}
func GetPayStatusText(status int32) string {
switch status {
case 1:
return "未支付"
case 2:
return "已支付"
default:
return strconv.Itoa(int(status))
}
}
// 辅助函数:获取货币类型文本
func GetCurrencyTypeText(currencyType int32) string {
switch currencyType {
case 1:
return "人民币"
case 2:
return "美元"
default:
return strconv.Itoa(int(currencyType))
}
}
func OrderRecordsList(c *gin.Context) {
var req bundle.OrderRecordsRequest

View File

@ -77,3 +77,98 @@ func BundleList(c *gin.Context) {
service.Success(c, res)
}
func SaveBundleV2(c *gin.Context) {
var req bundle.BundleProfile
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.SaveBundle(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func BundleListV2(c *gin.Context) {
var req bundle.BundleListRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.BundleListV2(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func BundleDetailV2(c *gin.Context) {
var req bundle.BundleDetailRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
language := c.GetHeader("Accept-Language")
req.Language = language
res, err := service.BundleProvider.BundleDetailV2(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func HandShelf(c *gin.Context) {
var req bundle.HandShelfRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.HandShelf(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func OnlyAddValueListByOrderNo(c *gin.Context) {
var req bundle.OnlyAddValueListByOrderNoRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.OnlyAddValueListByOrderNo(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func BundleListH5V2(c *gin.Context) {
var req bundle.BundleListRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.BundleListH5V2(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}

View File

@ -16,14 +16,21 @@ const (
NotMatchOrderInfo = "非当前用户订单信息不可操作"
InvalidOrderAmount = "订单金额错误"
HadPay = "订单已支付"
HadOrder = "您已购买过套餐,无法再次购买"
InvalidValueAddBundleNum = "套餐数量无效"
ThePackageHasExpired = "当前套餐已过期"
ErrorPermanentPackage = "永久套餐无需购买"
HadPay = "订单已支付"
ThereAreOutstandingOrders = "您还有未支付的订单,无法再次购买"
HadOrder = "您已购买过套餐,无法再次购买"
InvalidValueAddBundleNum = "套餐数量无效"
ThePackageHasExpired = "当前套餐已过期"
ErrorPermanentPackage = "永久套餐无需购买"
)
const (
OrderTypePackage = 1 // 套餐
OrderTypeAddon = 2 // 增值服务
TimeUnitDay = 1
TimeUnitMonth = 2
TimeUnitYear = 3
)
const (
ErrorExportOrderInfo = "导出订单信息失败"
)

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