Compare commits

...

415 Commits

Author SHA1 Message Date
JNG
b1e1d317ed 添加ip获取位置 2026-03-13 09:56:15 +08:00
JNG
469b0313ce 添加ip获取位置 2026-03-13 09:53:34 +08:00
JNG
c33fa06382 11 2026-03-12 16:31:35 +08:00
JNG
c982910bfb 11 2026-03-12 16:27:20 +08:00
JNG
6c7575c4ec Merge branch 'jng-QuestionnairePDF-0311' 2026-03-12 09:31:14 +08:00
JNG
ff21b6b424 Update questionnaireSurvey.go 2026-03-12 09:30:53 +08:00
JNG
dc34ad2043 Merge branch 'jng-QuestionnairePDF-0311' into feat-hjj-QuestionnaireSurvey 2026-03-11 21:11:19 +08:00
jiaji.H
8e50e029b1 Updata:去除多余代码 2026-03-11 21:05:38 +08:00
jiaji.H
cbbb5acbea Updata:转译报错 2026-03-11 20:53:42 +08:00
jiaji.H
f120cfa984 Updata:更新报错信息 2026-03-11 20:39:32 +08:00
JNG
af15840755 Update questionnaireSurvey.go 2026-03-11 20:22:16 +08:00
jiaji.H
4d9e9611ba Updata:增加新验证码接口 2026-03-11 20:19:40 +08:00
JNG
d0f87bcc76 Update questionnaireSurvey.go 2026-03-11 20:12:55 +08:00
JNG
f3df638d8d Update questionnaireSurvey.go 2026-03-11 20:03:45 +08:00
JNG
bd801656d1 修改 2026-03-11 20:01:48 +08:00
JNG
03983189f6 Update questionnaireSurvey.go 2026-03-11 19:48:44 +08:00
JNG
3e953cc04d Update questionnaireSurvey.go 2026-03-11 19:43:58 +08:00
JNG
875e987f68 111 2026-03-11 19:40:21 +08:00
JNG
c038222e16 Update questionnaireSurvey.go 2026-03-11 19:33:48 +08:00
JNG
e47bb3316c Update pdf.go 2026-03-11 19:28:31 +08:00
JNG
1ebbdece8b 修改 2026-03-11 19:06:50 +08:00
JNG
749b4bb8e9 11 2026-03-11 19:04:18 +08:00
jiaji.H
b8a34ba6aa Updata:更新pb文件 2026-03-11 18:43:19 +08:00
jiaji.H
3599e428ce Updata:调整接口路径 2026-03-11 18:12:17 +08:00
jiaji.H
d9cb1024f0 Updata:更新接口 2026-03-11 17:39:21 +08:00
jiaji.H
c4771e2255 Updata:更新pb文件 2026-03-11 17:29:28 +08:00
jiaji.H
c14ea21d82 Updata:更新pb文件 2026-03-11 17:17:54 +08:00
jiaji.H
dd173edc2f Updata:更新逻辑 2026-03-11 16:57:51 +08:00
jiaji.H
a73351c5de Updata:增加调查问卷接口路径 2026-03-11 16:28:45 +08:00
cjy
5a0d5eba3d Merge branch 'feat-cjy-addData' 2026-03-11 15:03:48 +08:00
cjy
d6022cbc5a feat: 增加艺人是否自动确定 2026-03-11 14:01:15 +08:00
cjy
b8d75df6e5 fix: 随机提交时间 2026-03-11 10:45:24 +08:00
cjy
4ac5c334bd fix:竞品报告title不要去除空格 2026-03-11 09:57:20 +08:00
cjy
51835eaa65 feat: 增加竞品报告刷数据接口 2026-03-11 09:52:18 +08:00
jiaji.H
e2b112eddd Updata:解决冲突 2026-03-11 09:47:47 +08:00
jiaji.H
030f79eabe Updata:更新发票创建逻辑 2026-03-11 09:46:04 +08:00
34d6b2fe88 fix: 有报错,暂时注掉 2026-03-11 09:26:21 +08:00
767615d649 fix: 有报错,暂时注掉 2026-03-11 09:23:42 +08:00
cjy
46cc32a4d4 feat:优化一下,按照个性化需求实现刷数据 2026-03-10 16:38:18 +08:00
cjy
7d8f129dcd fix:修复导入接口 2026-03-10 16:08:40 +08:00
cjy
bfc8c1a14c fix: 修复导入接口 2026-03-10 15:53:57 +08:00
cjy
13fec45202 fix: 小时和分钟也随机一下 2026-03-10 15:40:17 +08:00
cjy
7f9d069190 feat: 增加刷数据分析接口 2026-03-10 15:19:09 +08:00
cjy
fcddb6a732 feat: 新增一个更新数据分析链接的接口 2026-03-10 10:55:10 +08:00
cjy
789c6e5fcb update: 更新pb 2026-03-10 10:10:17 +08:00
cjy
5c4b0c8a7d 修改获取指标一个接口,获取历史某一个时刻的发布视频数和图文数 2026-03-10 10:07:04 +08:00
cjy
be2db4cf81 update: proto 2026-03-09 16:47:55 +08:00
cjy
1f3c4c0105 fix: 加上时间戳 2026-03-09 10:14:46 +08:00
cjy
2247cce068 fix:链接名字 2026-03-09 09:48:13 +08:00
cjy
aa63dec27e fix:url 2026-03-09 09:43:11 +08:00
cjy
90bbfd3a20 feat: 2026-03-09 09:42:55 +08:00
cjy
2b4ca693c8 Merge branch 'feat-cjy-report-new' 2026-03-04 15:20:16 +08:00
cjy
b1d6c68518 fix:ai生成格式不正确的时候,直接报错。 2026-03-04 15:20:01 +08:00
cjy
eab7bf3953 Revert "暂时注销主分支上ai生成数据分析的功能"
This reverts commit 32d900a735.
2026-03-04 14:05:52 +08:00
cjy
777c7dbba5 Merge branch 'feat-cjy-report-new' 2026-03-04 14:05:03 +08:00
cjy
d85ecfeeee fix:继续调整提示词 2026-03-04 13:29:09 +08:00
cjy
eb45242595 fix:增加对字数的限制 2026-03-04 13:25:55 +08:00
cjy
d3b992faba fix:修改生成数据分析概要的提示词 2026-03-04 13:17:28 +08:00
cjy
5f31c9ec08 fix:调整提示词,优化ai关于配乐亮点的回复 2026-03-04 11:47:17 +08:00
cjy
7f1fecf208 暂时注销主分支上ai生成数据分析的功能 2026-03-04 09:41:37 +08:00
cjy
4cc813de6e Merge branch 'feat-cjy-report-new' 2026-03-04 09:32:03 +08:00
cjy
919f0280bc fix:使用utf8计算长度 2026-03-04 09:15:30 +08:00
cjy
02e00f9d49 fix:增加标题长度限制要求 2026-03-03 15:53:24 +08:00
cjy
0515d2ab03 fix: 文件名增加时间戳,避免文件被覆盖 2026-03-03 15:44:06 +08:00
jiaji.H
5b6cc8ef10 Merge branch 'feat-hjj-MetricsManager' 2026-03-03 15:41:31 +08:00
jiaji.H
785c87c2a1 Updata:刷订单流程中增加创建发票逻辑 2026-03-03 15:41:04 +08:00
cjy
e90d298f98 fix: 修改生成竞品报告文件名的逻辑 2026-03-03 15:37:10 +08:00
cjy
6f5c7f219c fix: 修改字数限制 2026-03-03 15:25:47 +08:00
cjy
6af7e788d3 fix: 修改提示词 2026-03-03 14:30:27 +08:00
cjy
758a59dd2a fix: 修改提示词,约束ai的回复 2026-03-03 14:24:07 +08:00
cjy
e7a037c640 fix:批量导入的时候,图片会存入数据库 2026-03-03 14:08:56 +08:00
cjy
7898531ce1 fix: 当导入竞品报告字数过长,会自动截断 2026-03-03 14:04:41 +08:00
cjy
ce9d75ef46 fix: 修改竞品报告模板颜色的命名空间 2026-03-03 13:53:08 +08:00
cjy
76c5a9f6f3 feat: 优化pdf排版。英文符号和数字只算半个字符,并添加单元测试 2026-03-03 11:31:04 +08:00
cjy
08a70e8399 并发查询,优化接口速度 2026-03-03 10:56:46 +08:00
cjy
bbc18f56af fix:调整错误提示语,格式化代码 2026-03-03 10:33:34 +08:00
cjy
d9f8e69a11 fix: 优化提示词 2026-03-03 10:29:10 +08:00
cjy
a69815bea2 fix:修改json tag 2026-03-03 10:20:58 +08:00
cjy
51f82425c5 fix: 固定使用模板生成报告 2026-03-03 10:09:32 +08:00
cjy
7cc03c02fa fix: 优化提示词 2026-03-03 09:17:50 +08:00
cjy
ece9a964f9 feat: ai生成一个数据分析正文 2026-03-02 17:07:17 +08:00
cjy
b6fd35b2ec fix: 修改json序列化 2026-03-02 16:54:35 +08:00
cjy
8022eca1f8 fix: 竞品报告批量导入的时候添加到正文 2026-03-02 16:47:55 +08:00
cjy
9c4c4b1c66 feat: 实现新模板下的竞品报告批量导入 2026-03-02 16:25:10 +08:00
cjy
6242962b43 feat:更新竞品报告导入模板 2026-03-02 15:42:52 +08:00
cjy
c5748d673b fix: 修改生成竞品报告的请求参数 2026-03-02 15:35:06 +08:00
cjy
62ee062bc5 fix: 修改ai返回的参数 2026-03-02 15:30:13 +08:00
cjy
1b7e105164 fix:修复竞品报告json反序列化有符号导致错误 2026-03-02 14:27:43 +08:00
cjy
ad4c74639f fix:增加一点日志,用于排查 2026-03-02 14:19:28 +08:00
daiyb
fa0fa89571 Merge branch 'feature-publishLog-daiyb' 2026-03-02 14:18:43 +08:00
daiyb
8903867ab5 定时发布添加发布来源数据 2026-03-02 14:18:23 +08:00
cjy
6ef35e0852 feat: 添加竞品报告自动生成模板类型的pdf,同时和任务管理台那边同步 2026-03-02 13:53:03 +08:00
cjy
f751b37e66 feat: 竞品报告支持生成带图片的pdf,并添加测试 2026-03-02 13:32:29 +08:00
cjy
667139a610 go mod tidy 2026-03-02 13:09:31 +08:00
cjy
e1e453322a feat:优化竞品报告pdf生成效果 2026-03-02 13:07:33 +08:00
cjy
9dfb751aaf 暂时的方案 2026-03-02 11:08:31 +08:00
daiyb
38828addae Merge branch 'feature-publishLog-daiyb' 2026-03-02 09:52:44 +08:00
daiyb
71517967c8 优化导出 提示 2026-03-02 09:52:30 +08:00
cjy
264114fce8 feat: 增加竞品报告pdf模板 2026-03-02 09:20:55 +08:00
daiyb
6d3056d990 Merge branch 'feature-publishLog-daiyb' 2026-03-02 09:17:11 +08:00
daiyb
65ce2132e7 修改配置文件 2026-02-28 15:46:06 +08:00
daiyb
2d93ad6df1 Update work.go 2026-02-28 15:34:35 +08:00
daiyb
979e050108 恢复代码 2026-02-28 15:29:32 +08:00
cjy
75ba332397 fix: 优化提示词,避免ai生成的结果不是json格式 2026-02-28 15:25:58 +08:00
cjy
016f2c2459 增加一些日志打印 2026-02-28 14:58:40 +08:00
daiyb
111eeeb56f Update work.go 2026-02-28 14:55:50 +08:00
daiyb
b56763ed03 Update work.go 2026-02-28 14:54:32 +08:00
daiyb
b922b4bd88 Update work.go 2026-02-28 14:53:26 +08:00
daiyb
77248eb885 Update work.go 2026-02-28 14:49:52 +08:00
cjy
ce9edf513c feat: ai 生成竞品报告增加一个字段json,用来后续生成pdf。 2026-02-28 14:28:36 +08:00
daiyb
1791397782 测试定时检测改成1分钟 2026-02-28 14:24:34 +08:00
daiyb
37771a9b5a 添加调试日志 2026-02-28 14:21:00 +08:00
cjy
cb1345a55d feat:修改生成竞品报告的prompts,让其生成json格式的回复。 2026-02-28 14:03:29 +08:00
cjy
d2ee1c86b8 feat: 修改生成竞品报告图片的提示词 2026-02-28 09:19:03 +08:00
cjy
b2b570003e feat: 修改生成竞品报告的提示词 2026-02-28 09:16:23 +08:00
JNG
d7b56b8ea3 Merge branch 'jng' 2026-02-27 14:24:09 +08:00
JNG
63bae5ad1c Update account.go 2026-02-27 14:06:27 +08:00
daiyb
8dbe5744e5 导出 2026-02-26 15:55:33 +08:00
daiyb
d526db4c31 发布记录 2026-02-26 14:41:14 +08:00
daiyb
1608207281 1 2026-02-26 14:04:49 +08:00
daiyb
762c9640de Update work.go 2026-02-26 11:53:17 +08:00
daiyb
addd492875 Update work.go 2026-02-26 11:31:13 +08:00
daiyb
73b183a1e4 Update work.go 2026-02-26 11:18:40 +08:00
daiyb
64e52b5ec4 添加一次字段 2026-02-26 11:11:31 +08:00
daiyb
ed40212dec dm 发送log 2026-02-26 09:32:51 +08:00
daiyb
25c89523cc Update test.go 2026-02-25 16:01:43 +08:00
daiyb
f6a7e0ad8c 修改工具函数 2026-02-25 15:41:05 +08:00
bx1834938347-prog
1548e2e66a Merge branch 'main' into wwq 2026-02-25 13:46:48 +08:00
bx1834938347-prog
e172fc7c14 Update cron.go 2026-02-25 13:46:27 +08:00
bx1834938347-prog
2680b8826e Merge branch 'wwq' 2026-02-25 13:45:02 +08:00
bx1834938347-prog
406d4ef54c Update cron.go 2026-02-25 11:39:49 +08:00
daiyb
37246ed813 作品发布记录 2026-02-24 16:27:36 +08:00
cjy
10389625bf fix:正式少了代码 2026-02-13 11:41:08 +08:00
cjy
d4aebe81ba Merge branch 'feat-cjy-taskBench-new'
# Conflicts:
#	api/bundle/bundle.pb.go
#	api/bundle/bundle.validator.pb.go
#	api/cast/cast.pb.go
2026-02-13 10:15:01 +08:00
cjy
d173e86b3d fix:修改手机号错误 2026-02-12 12:00:51 +08:00
cjy
8fb59bd1b8 fix: 上传数据分析适配工作台 2026-02-12 11:50:07 +08:00
cjy
6d269744f5 fix:修复手机号传错问题 2026-02-12 10:22:39 +08:00
jiaji.H
7cb339c903 Updata:增加视频/图文确认失败原因类型 2026-02-12 10:18:25 +08:00
0adc00c5ef 限制黄反字符串长度 2026-02-11 16:08:24 +08:00
cjy
8c7c92a681 Revert "update: pb文件"
This reverts commit a162696f42.
2026-02-11 15:37:31 +08:00
cjy
7b4ec4ac6e feat:可以通过subnum查询数据分析的数据 2026-02-11 15:21:37 +08:00
cjy
a162696f42 update: pb文件 2026-02-11 14:03:47 +08:00
cjy
f4e8df6ac3 feat:增加删除竞品报告和数据分析回退任务管理台任务数量 2026-02-11 09:46:06 +08:00
cjy
81fb262830 fix:通过subnum获取艺人信息 2026-02-10 16:46:29 +08:00
jiaji.H
9d93484788 Updata:解决冲突 2026-02-10 15:37:23 +08:00
jiaji.H
56eb4ed9d0 Updata:更新金额类型 2026-02-10 14:43:20 +08:00
cjy
90a39f4d60 fix:让上传脚本逻辑保持一致 2026-02-10 14:36:23 +08:00
jiaji.H
ef9c112109 Updata:更新发票url 2026-02-10 14:33:41 +08:00
jiaji.H
9c7f340dc7 Updata 2026-02-10 14:31:52 +08:00
jiaji.H
21e64feca6 Updata:修改下载路径 2026-02-10 14:29:12 +08:00
jiaji.H
1b43fe0bf1 Updata:更新字段赋值 2026-02-10 14:21:21 +08:00
jiaji.H
758a2f5a75 Updata:增加log 2026-02-10 14:16:56 +08:00
f42eb3ba47 Merge branch 'fearture-newScript-daiyb' 2026-02-10 14:12:02 +08:00
061af70b4f 修改提示 2026-02-10 14:03:09 +08:00
jiaji.H
e5052e0e9e Updata:更新路径 2026-02-10 13:28:52 +08:00
jiaji.H
f930a1487e Merge branch 'main' of http://gitea.tools.fontree.cn:3000/fiee/fonchain-fiee 2026-02-10 13:14:27 +08:00
jiaji.H
e102a92992 Merge branch 'feat-hjj-filebrowser#Saas3' 2026-02-10 13:14:21 +08:00
cf966b182f 黄反 2026-02-10 13:14:11 +08:00
jiaji.H
2186871b1b Updata:更新路径 2026-02-10 11:44:38 +08:00
a35e0f7d69 脚本加上黄反 2026-02-10 11:36:04 +08:00
jiaji.H
ac9cb23617 Updata:增加发票下载生成行url逻辑 2026-02-10 11:32:34 +08:00
0ecdef7a4e Update work.go 2026-02-10 11:30:47 +08:00
436641a181 修改黄反提示 2026-02-10 11:27:52 +08:00
cjy
ff101141e6 feat:导出excel增加竞品报告相关字段 2026-02-10 11:17:52 +08:00
35afb07cb9 Update work.go 2026-02-10 11:13:44 +08:00
jiaji.H
00be8ca5db Updata:更新发票下载接口 2026-02-10 11:12:06 +08:00
a60f8a5d76 修改黄反提示 2026-02-10 10:45:18 +08:00
jiaji.H
9195a56892 Merge branch 'feat-hjj-BundleOrderInvoice#A225' 2026-02-10 09:46:06 +08:00
jiaji.H
df6f60c172 Updata:调整发票日期 2026-02-10 09:45:56 +08:00
0159046283 修改种子 2026-02-10 08:55:56 +08:00
cjy
1650d838d3 feat:增加带任务uuid的创建接口 2026-02-09 19:06:36 +08:00
cjy
f26897c2f4 fix:修改种子 2026-02-09 17:42:10 +08:00
b089aca290 打印容器时间 2026-02-09 16:27:03 +08:00
c692e034a6 Merge branch 'feature-special-daiyb' 2026-02-09 15:38:43 +08:00
2663a3562f 内容鉴定 2026-02-09 15:15:05 +08:00
jiaji.H
17b2b2681b Merge branch 'main' of http://gitea.tools.fontree.cn:3000/fiee/fonchain-fiee 2026-02-09 15:10:19 +08:00
ae5c3de6c4 黄反检测 2026-02-09 15:10:19 +08:00
jiaji.H
754dd62984 Updata:增加log 2026-02-09 15:10:13 +08:00
cjy
07cf4aaa15 fix:更新pb 2026-02-09 15:06:00 +08:00
e90a167f9a Merge branch 'feature-scriptApproval-daiyb' 2026-02-09 14:59:51 +08:00
ce001802ba Update task.go 2026-02-09 14:59:36 +08:00
74c66abad7 修改审批 2026-02-09 14:53:50 +08:00
cjy
d14778017e update:更新pb
# Conflicts:
#	api/cast/cast.pb.go
2026-02-09 14:47:21 +08:00
cjy
d079abbe50 feat: 增加查看指派任务的已完成的数据接口 2026-02-09 14:47:08 +08:00
2cb12418a8 Update task.go 2026-02-09 14:24:24 +08:00
372af8d0e5 审批时间 2026-02-09 14:23:50 +08:00
0ec5f1ee60 Update task.go 2026-02-09 14:16:17 +08:00
jiaji.H
295796ae1a Merge branch 'feat-hjj-BundleOrderInvoice#A225' 2026-02-09 13:30:54 +08:00
jiaji.H
255be4472b Updata:临时增加刷发票接口 2026-02-09 13:30:44 +08:00
cjy
05774fcb3b fix:修改时间戳格式化 2026-02-09 12:50:13 +08:00
cjy
7ee7bd7370 update:pb文件 2026-02-09 12:47:15 +08:00
cjy
c399689be0 fix: 避免空指针 2026-02-09 12:37:44 +08:00
cjy
cea0b741f8 fix:修改判断查询失败的逻辑 2026-02-09 12:37:26 +08:00
cjy
c941a46cee fix:续费的话,查询续费开始到现在套餐的时间所有数据
# Conflicts:
#	api/bundle/bundle.pb.go
#	api/cast/cast.pb.go
#	pkg/service/cast/analysis.go
#	pkg/service/cast/report.go
2026-02-09 12:36:51 +08:00
cjy
31a08879b6 fix:如果套餐为续费套餐直接失败
# Conflicts:
#	api/cast/cast.pb.go
2026-02-09 11:58:14 +08:00
cjy
8ec97fdcff fix:创建竞品报告时,传入订单uuid 2026-02-09 11:55:17 +08:00
cjy
063a7991ba Merge branch 'fix-cjy-baseOnjng'
# Conflicts:
#	api/cast/cast.pb.go
#	api/cast/cast.pb.validate.go
2026-02-09 11:53:30 +08:00
cjy
59ece0cb7f Merge branch 'feat-cjy-changeOperator'
# Conflicts:
#	api/cast/cast.pb.go
#	api/cast/cast.pb.validate.go
#	pkg/cron/task.go
2026-02-09 11:52:07 +08:00
jiaji.H
4530e68c11 Updata:解决冲突 2026-02-09 11:46:18 +08:00
jiaji.H
f751d84943 Updata:解决冲突 2026-02-09 11:33:38 +08:00
JNG
0a1678da58 11 2026-02-09 11:33:14 +08:00
JNG
e1a75ee420 解决冲突 2026-02-09 11:31:22 +08:00
195ac2a769 fiee5️⃣期需求
账号过期解绑
2026-02-09 11:30:22 +08:00
28d7fea3c7 修改审批时间 2026-02-09 11:11:06 +08:00
jiaji.H
99b2e125d6 Updata:更新pb文件 2026-02-09 10:59:54 +08:00
bx1834938347-prog
8eb22deb18 Merge branch 'wwq' 2026-02-09 09:41:51 +08:00
5e10fe8bb0 优化脚本导入自己不能同时导入2个 2026-02-06 19:42:39 +08:00
23cf5af6dc 修改上下文解析 2026-02-06 18:21:33 +08:00
e74bf2f911 修改种子 2026-02-06 17:24:18 +08:00
4df6706dac 兼容无token调用 2026-02-06 16:41:13 +08:00
c798ed545a 特殊补发 2026-02-06 16:15:04 +08:00
JNG
83b4e9dd9c 处理0元购 2026-02-06 15:32:57 +08:00
jiaji.H
f16a8331f3 Updata:更新发票模板 2026-02-06 15:16:38 +08:00
32af1ae5c1 Update media.go 2026-02-06 14:56:32 +08:00
a805c9c382 Update test.go 2026-02-06 14:34:53 +08:00
ccb469edda Update test.go 2026-02-06 14:33:14 +08:00
06d6eae188 创建订单的时候调用订单刷新功能 2026-02-06 14:10:21 +08:00
0cef4a573e Update test.go 2026-02-06 13:39:18 +08:00
62e25d3079 修改同步逻辑 2026-02-06 12:03:14 +08:00
JNG
93502cb589 Update signContractV2.go 2026-02-06 11:37:03 +08:00
JNG
68de4b6c54 修改订单签署 2026-02-06 11:10:30 +08:00
cjy
4c4d139b05 fix:更新也增加订单uuid 2026-02-05 19:32:00 +08:00
1186336dd3 1 2026-02-05 18:52:02 +08:00
4b9bfc15a0 1 2026-02-05 18:07:54 +08:00
6bc617ecc3 修改续费逻辑 2026-02-05 18:03:18 +08:00
cjy
d27b85a155 feat:存入订单uuid 2026-02-05 17:52:24 +08:00
JNG
41f1a807a9 Update signContractV2.go 2026-02-05 17:28:52 +08:00
cf709742b2 脚本更新 2026-02-05 17:06:24 +08:00
9fb4b01590 批量查询 2026-02-05 16:23:44 +08:00
jiaji.H
16d6d4bd29 Updata:注释0元生成发票 2026-02-05 16:19:51 +08:00
e0a5346302 完善代码 2026-02-05 15:49:55 +08:00
jiaji.H
63e3991f23 Updata:更新文件确认 2026-02-05 15:48:31 +08:00
433ec99628 套餐已过期 2026-02-05 15:44:19 +08:00
4c8789ed38 修改绑定订单 2026-02-05 15:38:12 +08:00
jiaji.H
bfd2dcd3cd Merge branch 'feat-hjj-OfficialManage#A161' 2026-02-05 14:56:53 +08:00
164b683b7d Update task.go 2026-02-05 14:39:22 +08:00
b1bde71f34 Update task.go 2026-02-05 14:38:45 +08:00
cjy
1d2ba64a22 fix:视频脚本为任务4 2026-02-05 11:36:33 +08:00
cjy
51f0d2b687 fix:视频脚本为任务4 2026-02-05 11:35:50 +08:00
cjy
748ceb5d63 feat: 增加审批通过时间 2026-02-05 11:28:01 +08:00
cjy
35bc4a04c3 feat:更新pb文件 2026-02-05 11:25:58 +08:00
cjy
d92d4199c7 fix:修改刷新定时任务的频率,并修改pageSize数量 2026-02-05 09:57:14 +08:00
cjy
c82f137ac1 fix:调用列表不再刷新审批更新状态 2026-02-05 09:56:20 +08:00
cjy
15338ca7c8 fix:更新通过审批的操作人为业务部门 2026-02-05 09:52:32 +08:00
f4c826936b 解绑取消授权记录 2026-02-04 19:02:42 +08:00
f59b434dc7 同步bundle的proto 2026-02-04 17:39:00 +08:00
jiaji.H
e6af927159 Updata:更新判别是否为新套餐还是续费套餐 2026-02-04 16:39:36 +08:00
39dc62b032 套餐续费和新购 2026-02-04 16:09:08 +08:00
jiaji.H
4e37040f9e Updata:更新pb文件 2026-02-04 14:47:18 +08:00
jiaji.H
28f1a9326d Updata:更新pb文件 2026-02-04 14:26:37 +08:00
jiaji.H
cf4af5a71a Updata:更新pb文件 2026-02-04 14:19:58 +08:00
jiaji.H
c5e36a2ae9 Updata:更新字段 2026-02-04 14:11:21 +08:00
jiaji.H
94a1c30acd Updata:更新时间获取 2026-02-04 14:09:18 +08:00
jiaji.H
e1271f7caf Updata:更新时间获取 2026-02-04 13:59:57 +08:00
d3ae7e0b85 修改默认值 2026-02-04 13:48:46 +08:00
jiaji.H
bdecb8a05f Updata:更新数据 2026-02-04 13:45:01 +08:00
jiaji.H
4a2263fba9 Updata:更新发票订单信息查询 2026-02-04 13:21:24 +08:00
jiaji.H
13ea22fae8 Updata:修改获取时间逻辑 2026-02-04 13:11:33 +08:00
48aa714706 fix: 调整创建订单的uuid 2026-02-04 13:08:30 +08:00
54b15344e0 fix: 调整创建订单的uuid 2026-02-04 12:13:27 +08:00
jiaji.H
3befb95827 Updata:更新pb文件 2026-02-04 11:17:48 +08:00
jiaji.H
b4e95bc134 Updata:增加时间格式化接口 2026-02-04 10:43:36 +08:00
jiaji.H
b047ed5056 Updata:增加log 2026-02-04 10:25:33 +08:00
jiaji.H
717ae05cc8 Updata:替换获取发票编号接口 2026-02-04 10:23:33 +08:00
573ad1b147 fix: antomReq.OutTradeNo = uuidV4.String() 2026-02-04 10:21:41 +08:00
cjy
5a89ad139f Merge branch 'feat-cjy-customerContract'
# Conflicts:
#	api/bundle/bundle.pb.go
#	api/bundle/bundle.validator.pb.go
#	api/bundle/bundle_triple.pb.go
2026-02-04 09:42:19 +08:00
5a814ab12f DM取消授权 2026-02-04 09:41:39 +08:00
JNG
a0ad992ab1 Update bundleOrder.go 2026-02-03 19:41:43 +08:00
jiaji.H
25905062f6 Updata:生成发票时间修改 2026-02-03 17:33:14 +08:00
JNG
0802c372b0 修改 2026-02-03 16:46:57 +08:00
jiaji.H
b0c725a68b Merge branch 'feat-hjj-ExportBat' 2026-02-03 16:26:49 +08:00
JNG
bb9c22e1aa Merge branch 'feature-four-daiyb' into jng 2026-02-03 16:24:16 +08:00
bbb09a08b2 修改接口 2026-02-03 16:21:13 +08:00
jiaji.H
267b0d6ab8 Updata:更新字段格式 2026-02-03 16:06:11 +08:00
7e77b6d585 发布来源 2026-02-03 15:29:36 +08:00
7f0d61b229 1 2026-02-03 15:28:12 +08:00
jiaji.H
b385b83824 Updata:增加发票地址打印换行 2026-02-03 15:08:52 +08:00
jiaji.H
59f45258eb Updata:增加间隔 2026-02-03 14:50:39 +08:00
jiaji.H
81346d611a Updata:更新发票 2026-02-03 14:24:00 +08:00
jiaji.H
6031afe227 Updata:更新金额类型 2026-02-03 14:15:27 +08:00
jiaji.H
c16c41f65c Updata:更新申请时间 2026-02-03 13:41:51 +08:00
jiaji.H
1431646900 Updata:更新发票导出 2026-02-03 13:29:50 +08:00
jiaji.H
350259c208 Updata:更新发票模板 2026-02-03 11:49:31 +08:00
jiaji.H
652e23e1e9 Merge branch 'feat-hjj-ExportBat' 2026-02-03 11:20:07 +08:00
jiaji.H
3d40d77080 Merge branch 'feat-hjj-ExportBat' 2026-02-03 10:50:21 +08:00
JNG
1096dde762 Merge branch 'feature-four-daiyb' into jng 2026-02-03 10:23:22 +08:00
JNG
71420b3c1c 11 2026-02-03 10:19:33 +08:00
544a8be9dc 解绑账号 2026-02-03 09:45:44 +08:00
jiaji.H
a1d75feb94 Updata:更新数据写入 2026-02-03 09:31:39 +08:00
jiaji.H
8941f59432 Updata:增加发票数据导出 2026-02-02 20:26:10 +08:00
jiaji.H
1a069a7136 Updata:更新pb文件 2026-02-02 20:01:50 +08:00
jiaji.H
3cd8deb84b Updata:自动创建电子发票 2026-02-02 19:43:42 +08:00
jiaji.H
91cd370d27 Updata:增加字体文件 2026-02-02 19:25:05 +08:00
jiaji.H
fa67b49c53 Updata:更新上传逻辑 2026-02-02 19:17:03 +08:00
jiaji.H
faf4a85e2e Updata:修改上传bos方法 2026-02-02 19:15:15 +08:00
jiaji.H
3c0ddfe06b Updata:更新发票生成 2026-02-02 18:14:00 +08:00
f4f75a06ca Merge branch 'feature-four-daiyb' 2026-02-02 16:50:59 +08:00
076d4d3f80 Update test.go 2026-02-02 16:50:46 +08:00
c9543cfad2 Merge branch 'feature-four-daiyb' 2026-02-02 16:46:35 +08:00
3313cb56b4 修改每个月1号等待一下1点后执行 2026-02-02 16:46:20 +08:00
jiaji.H
dbb8cd4615 Merge branch 'main' of http://gitea.tools.fontree.cn:3000/fiee/fonchain-fiee 2026-02-02 16:39:54 +08:00
jiaji.H
e85de27321 Updata:更新pb文件 2026-02-02 16:39:49 +08:00
b62d412022 Merge branch 'main' of http://gitea.tools.fontree.cn:3000/fiee/fonchain-fiee 2026-02-02 16:13:42 +08:00
7373026f48 Merge branch 'feature-four-daiyb' 2026-02-02 16:13:01 +08:00
jiaji.H
c9e7850b8a Merge branch 'feat-hjj-ExportBat' 2026-02-02 16:04:11 +08:00
jiaji.H
101dc38ed8 Updata:解决冲突 2026-02-02 15:48:09 +08:00
jiaji.H
47b103a8c4 Updata:更新pb文件 2026-02-02 15:27:40 +08:00
jiaji.H
275b94d555 Updata:更新截取长度 2026-02-02 15:26:53 +08:00
jiaji.H
3f3344ee5b Updata:更新pb文件 2026-02-02 14:11:48 +08:00
jiaji.H
4e97d3903b Updata:更新字段类型 2026-02-02 13:41:49 +08:00
jiaji.H
b64800aa49 Updata:更新pb文件 2026-02-02 11:15:44 +08:00
jiaji.H
5a8a75b8ed Updata:更新发票管理相关接口 2026-02-02 11:03:07 +08:00
bx1834938347-prog
46b9225298 feat:新增补发定时任务 2026-02-02 09:40:55 +08:00
jiaji.H
fdf6a967bf Updata:更新pb文件 2026-01-31 00:05:19 +08:00
8c18af01a8 Update work.go 2026-01-30 20:19:31 +08:00
cjy
248d8f50ef fix:修改状态映射 2026-01-30 18:31:28 +08:00
cjy
8e7a3643d2 Merge branch 'feat-cjy-report' 2026-01-30 18:20:52 +08:00
cjy
61aa8af162 Revert "fix:如果新买一个套餐,原有套餐的直接通过,不需要消耗额度"
This reverts commit 7564af8220.
2026-01-30 18:20:32 +08:00
cjy
df8fbfbc43 fix:修复批量导入的时候,始终固定报告名 2026-01-30 17:31:00 +08:00
cjy
6619c99be7 fix:修复批量导入的时候,始终固定报告名 2026-01-30 17:28:24 +08:00
jiaji.H
60a01e996a Updata:更新发票接口 2026-01-30 16:56:51 +08:00
JNG
80941aacfb Update bundleOrder.go 2026-01-30 16:19:53 +08:00
JNG
55267abc89 Update bundleOrder.go 2026-01-30 16:14:56 +08:00
cjy
2de4164875 fix: 清除空格 2026-01-30 15:56:26 +08:00
JNG
2e6c77cf88 添加购买类型 2026-01-30 15:43:27 +08:00
cjy
e57c664ec0 feat: 增加推荐人列表接口 2026-01-30 15:42:25 +08:00
jiaji.H
ab6349d438 Updata:解决冲突 2026-01-30 15:20:54 +08:00
JNG
a5ffa3e8b5 Merge branch 'jng' 2026-01-30 14:07:46 +08:00
JNG
e59c4f5487 11 2026-01-30 13:58:21 +08:00
JNG
df0df7b652 Merge branch 'main' into jng 2026-01-30 13:51:10 +08:00
jiaji.H
e4e2e303ea 美化文件名称 2026-01-30 13:43:40 +08:00
jiaji.H
973c95c76d Updata:文件名增加时间戳 2026-01-30 13:40:15 +08:00
jiaji.H
b05a300aa9 Updata:更新接口 2026-01-30 13:22:43 +08:00
jiaji.H
0e79282724 Updata:修正路由 2026-01-30 13:02:10 +08:00
jiaji.H
bc27434bed Updaya:增加导出接口 2026-01-30 12:42:47 +08:00
cjy
254d85ced3 Merge branch 'feat-cjy-report'
# Conflicts:
#	api/cast/cast.pb.go
#	api/cast/cast.pb.validate.go
#	api/cast/cast_triple.pb.go
#	pkg/service/cast/work.go
2026-01-30 12:01:23 +08:00
jiaji.H
8371c5944a Updata:增加发票相关接口 2026-01-30 11:39:46 +08:00
cjy
5bb04327d4 update: 更新pb 2026-01-30 10:06:14 +08:00
cjy
83285387e3 feat: 增加合同管理接口和路由 2026-01-30 10:05:56 +08:00
26658aaa5e 修改名称 2026-01-29 11:42:14 +08:00
dc0b639ae4 修改发布类型 2026-01-29 11:22:03 +08:00
a67adf0013 更新账号返回状态 2026-01-29 11:16:27 +08:00
03c667b6de 修改重发参数 2026-01-27 14:36:09 +08:00
c8e5ab9873 Update test.go 2026-01-27 13:37:10 +08:00
cjy
7564af8220 fix:如果新买一个套餐,原有套餐的直接通过,不需要消耗额度 2026-01-27 13:24:35 +08:00
cjy
4ce735d4de fix: 买套餐之后,旧套餐期间的数据分析和竞品报告不让看 2026-01-26 15:58:58 +08:00
cjy
c6f4385991 fix: 修改报告名 2026-01-26 15:27:32 +08:00
cjy
c0ea800511 fix: 修复套餐过期导致的错误 2026-01-26 15:01:01 +08:00
cjy
6c7e27ce78 fix: 修复检查余额的逻辑 2026-01-26 11:08:02 +08:00
cjy
7ba69a3afd fix: 修改批量导入竞品报告的模板
1.批量导入竞品报告的时候自动生成pdf
2. 增加生成pdf的检查
2026-01-26 10:44:43 +08:00
cjy
e7f90a304b fix: 移除检查 2026-01-26 10:02:51 +08:00
cjy
d20a124e14 fix: 修复逻辑 2026-01-26 09:47:21 +08:00
cjy
cccee7f86e fix:修复逻辑 2026-01-26 09:24:35 +08:00
cjy
adf3b5ee89 fix: 竞品报告需要扣减余额,以及修改错误提示语 2026-01-23 16:59:44 +08:00
cjy
ffdc047d15 fix: h5艺人确认增加校验 2026-01-23 16:30:06 +08:00
cjy
89bf59d878 fix: 修改竞品报告的prompts 2026-01-23 14:43:39 +08:00
cjy
6845ea1736 fix: 修复逻辑错误 2026-01-23 14:34:30 +08:00
cjy
351709d08e fix: 修复页面空间不足时,图片展示不完全的问题 2026-01-23 14:30:19 +08:00
cjy
11c8d63789 fix:修改生成pdf的文件名 2026-01-23 11:14:14 +08:00
b6cc081b03 账号异常 2026-01-23 10:49:17 +08:00
cjy
c8397bcfe9 fix: 修改生成竞品报告的prompts 2026-01-23 10:18:44 +08:00
cjy
91f7b54581 fix: 修改一下promps,不让ai输出markdown格式 2026-01-23 09:28:22 +08:00
ecfa719341 Update test.go 2026-01-22 16:35:09 +08:00
JNG
6381076912 11 2026-01-22 16:04:48 +08:00
JNG
bd0722bd86 修改 2026-01-22 15:57:28 +08:00
cjy
4d8e91822f update: 更新pb 2026-01-22 11:54:00 +08:00
8a9bb7d179 修改自媒体账号获取方式 2026-01-22 09:54:53 +08:00
9f9634e38e 发送日志数据 2026-01-22 09:27:39 +08:00
cjy
e9fa67ae00 fix: 修复pdf渲染图片只能渲染jpg格式的问题 2026-01-21 16:09:44 +08:00
cjy
4d82fb6f96 fix: 将ai生成的url存到阿里云上 2026-01-21 15:59:26 +08:00
cjy
445eb6a751 fix: 移除一些表情 2026-01-21 15:36:57 +08:00
cjy
ee9bbde2a7 fix: 修改报错提示语,移除一个没用的请求头 2026-01-21 14:58:41 +08:00
cjy
3180c3c476 fix:增加一个请求头 2026-01-21 14:12:18 +08:00
cjy
3c11449f6d 删除没用的接口 2026-01-20 17:15:43 +08:00
e1b9781daf 取消授权 2026-01-20 16:46:55 +08:00
abecc03b96 修改套餐过期 2026-01-20 16:26:05 +08:00
e2097a5b2c Merge branch 'main' into feature-four-daiyb 2026-01-20 10:10:16 +08:00
cjy
4f9a38693d feat: 更新pb文件 2026-01-19 11:48:46 +08:00
ed3c23724d 添加艺人编号 2026-01-19 10:36:28 +08:00
cjy
d097e9a20e feat:增加ai生成竞品报告接口 2026-01-15 16:35:47 +08:00
cjy
a2d46c4463 fix: 不通过链接分析视频文件大小 2026-01-15 15:33:11 +08:00
cjy
222b294101 feat:增加多模态ai测试接口 2026-01-15 14:13:00 +08:00
cjy
9170c77e32 feat: 增加获取url链接的文件大小的工具函数 2026-01-15 14:11:49 +08:00
jiaji.H
76a08f9ad8 Updata:解决冲突 2026-01-15 11:17:26 +08:00
jiaji.H
8688bd6abd Updata:更新pb文件 2026-01-15 11:09:17 +08:00
cjy
e9cd6876c2 feat: 增加分布式锁,防止重复提交 2026-01-14 18:56:59 +08:00
cjy
a4bff4284a update: 更新pb 2026-01-14 17:43:00 +08:00
cjy
d811235da5 fix:移除注释 2026-01-14 17:09:13 +08:00
cjy
bdf3fa6144 feat:pdf上传完之后就删除 2026-01-14 17:08:55 +08:00
cjy
dfb2e5e037 fix: 修复逻辑错误 2026-01-14 17:04:41 +08:00
cjy
6b52775913 feat:增加自动生成pdf功能 2026-01-14 16:47:52 +08:00
jiaji.H
8d36aeb751 Updata:解决冲突 2026-01-14 13:42:58 +08:00
cjy
0226b0af12 feat: 增加艺人确认竞品报告路由 2026-01-14 11:59:40 +08:00
cjy
ae76287088 feat: 把单个艺人竞品报告的接口的分开 2026-01-14 11:58:20 +08:00
cjy
13fa87ec2b feat:source固定为1 2026-01-14 09:42:46 +08:00
cjy
fbf24995b8 feat:减少前端需要传的字段 2026-01-13 16:40:25 +08:00
cjy
145935ba04 fix: 打开批量导入的接口 2026-01-13 16:22:10 +08:00
cjy
a3e617a87f feat:批量导入增加校验竞品报告的余额 2026-01-13 16:20:00 +08:00
cjy
8fa9f89db9 feat:批量导入竞品报告 2026-01-13 16:15:06 +08:00
cjy
e6ca737fb1 feat:增加一个作品列表接口 2026-01-13 15:19:13 +08:00
cjy
49caaa73c6 feat: 更新pb 2026-01-13 15:15:11 +08:00
cjy
79f37993c1 feat:增加竞品报告导入模板 2026-01-13 11:27:44 +08:00
cjy
b079b597c3 feat: 增加检验竞品报告余额 2026-01-13 11:24:50 +08:00
jiaji.H
c5f7903c6c Updata:解决冲突 2026-01-13 09:44:01 +08:00
jiaji.H
065db45cdc Updata:更新pb文件 2026-01-13 09:43:37 +08:00
jiaji.H
3d67be4e09 Updata:解决冲突 2026-01-13 09:39:13 +08:00
jiaji.H
e75e6b7ce9 Updata:增加竞品数pb 2026-01-13 09:36:01 +08:00
cjy
789af8f0db Merge branch 'main' into feat-cjy-report 2026-01-13 09:33:35 +08:00
cjy
09f598a1f4 feat: 增加自动审批 2026-01-12 18:34:56 +08:00
cjy
a6e5d38a43 feat: 增加导出excel接口 2026-01-12 14:45:52 +08:00
cjy
26c59ee54c feat: 增加竞品报告相关路由 2026-01-12 14:34:15 +08:00
cjy
17215e758b feat: 更新pb文件 2026-01-12 14:30:35 +08:00
jiaji.H
daad39d53c Updata:更新表格样式 2026-01-05 11:51:20 +08:00
jiaji.H
b52190f021 Updata:补充导出数据字段 2026-01-05 11:46:02 +08:00
jiaji.H
2a38ed44b0 Updata:增加竞品数类型数据 2026-01-04 15:04:09 +08:00
81 changed files with 34245 additions and 14825 deletions

2
.gitignore vendored
View File

@ -31,3 +31,5 @@
/cmd/logs/*.log
/cmd/runtime/log/*.log
/build/*
CLAUDE.md
.claude/settings.local.json

View File

@ -946,8 +946,8 @@ type UserListInfo struct {
DateOfBirth string `protobuf:"bytes,22,opt,name=dateOfBirth,proto3" json:"dateOfBirth"`
Age string `protobuf:"bytes,23,opt,name=age,proto3" json:"age"`
Email string `protobuf:"bytes,24,opt,name=email,proto3" json:"email"`
AbroadTelAreaCode string `protobuf:"bytes,25,opt,name=AbroadTelAreaCode,proto3" json:"AbroadTelAreaCode"`
AbroadTel string `protobuf:"bytes,26,opt,name=AbroadTel,proto3" json:"AbroadTel"`
AbroadTelAreaCode string `protobuf:"bytes,25,opt,name=abroadTelAreaCode,proto3" json:"abroadTelAreaCode"`
AbroadTel string `protobuf:"bytes,26,opt,name=abroadTel,proto3" json:"abroadTel"`
InviterName string `protobuf:"bytes,27,opt,name=inviterName,proto3" json:"inviterName"`
InviterCode string `protobuf:"bytes,28,opt,name=inviterCode,proto3" json:"inviterCode"`
unknownFields protoimpl.UnknownFields
@ -1195,6 +1195,8 @@ type UserListRequest struct {
Ids []int64 `protobuf:"varint,11,rep,packed,name=ids,proto3" json:"ids"`
Nationality string `protobuf:"bytes,12,opt,name=nationality,proto3" json:"nationality"`
NameAndNumber string `protobuf:"bytes,13,opt,name=nameAndNumber,proto3" json:"nameAndNumber"`
Email string `protobuf:"bytes,14,opt,name=email,proto3" json:"email"`
AbroadTel string `protobuf:"bytes,15,opt,name=abroadTel,proto3" json:"abroadTel"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -1320,6 +1322,20 @@ func (x *UserListRequest) GetNameAndNumber() string {
return ""
}
func (x *UserListRequest) GetEmail() string {
if x != nil {
return x.Email
}
return ""
}
func (x *UserListRequest) GetAbroadTel() string {
if x != nil {
return x.AbroadTel
}
return ""
}
type UserInfoResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Id uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id"`
@ -1344,8 +1360,8 @@ type UserInfoResponse struct {
IdNumber string `protobuf:"bytes,20,opt,name=idNumber,proto3" json:"idNumber"`
DateOfBirth string `protobuf:"bytes,21,opt,name=dateOfBirth,proto3" json:"dateOfBirth"`
Email string `protobuf:"bytes,22,opt,name=email,proto3" json:"email"`
AbroadTelAreaCode string `protobuf:"bytes,23,opt,name=AbroadTelAreaCode,proto3" json:"AbroadTelAreaCode"`
AbroadTel string `protobuf:"bytes,24,opt,name=AbroadTel,proto3" json:"AbroadTel"`
AbroadTelAreaCode string `protobuf:"bytes,23,opt,name=abroadTelAreaCode,proto3" json:"abroadTelAreaCode"`
AbroadTel string `protobuf:"bytes,24,opt,name=abroadTel,proto3" json:"abroadTel"`
InviterId uint64 `protobuf:"varint,25,opt,name=inviterId,proto3" json:"inviterId"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
@ -10374,10 +10390,10 @@ const file_api_accountFiee_accountFiee_proto_rawDesc = "" +
"\vdateOfBirth\x18\x16 \x01(\tR\vdateOfBirth\x12\x10\n" +
"\x03age\x18\x17 \x01(\tR\x03age\x12\x14\n" +
"\x05email\x18\x18 \x01(\tR\x05email\x12,\n" +
"\x11AbroadTelAreaCode\x18\x19 \x01(\tR\x11AbroadTelAreaCode\x12\x1c\n" +
"\tAbroadTel\x18\x1a \x01(\tR\tAbroadTel\x12 \n" +
"\x11abroadTelAreaCode\x18\x19 \x01(\tR\x11abroadTelAreaCode\x12\x1c\n" +
"\tabroadTel\x18\x1a \x01(\tR\tabroadTel\x12 \n" +
"\vinviterName\x18\x1b \x01(\tR\vinviterName\x12 \n" +
"\vinviterCode\x18\x1c \x01(\tR\vinviterCode\"\xff\x02\n" +
"\vinviterCode\x18\x1c \x01(\tR\vinviterCode\"\xb3\x03\n" +
"\x0fUserListRequest\x12\x16\n" +
"\x06domain\x18\x01 \x01(\tR\x06domain\x12\x16\n" +
"\x06subNum\x18\x02 \x01(\tR\x06subNum\x12$\n" +
@ -10392,7 +10408,9 @@ const file_api_accountFiee_accountFiee_proto_rawDesc = "" +
" \x01(\tR\vblurNameTel\x12\x10\n" +
"\x03ids\x18\v \x03(\x03R\x03ids\x12 \n" +
"\vnationality\x18\f \x01(\tR\vnationality\x12$\n" +
"\rnameAndNumber\x18\r \x01(\tR\rnameAndNumber\"\x92\x06\n" +
"\rnameAndNumber\x18\r \x01(\tR\rnameAndNumber\x12\x14\n" +
"\x05email\x18\x0e \x01(\tR\x05email\x12\x1c\n" +
"\tabroadTel\x18\x0f \x01(\tR\tabroadTel\"\x92\x06\n" +
"\x10UserInfoResponse\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x04R\x02id\x12\x16\n" +
"\x06status\x18\x02 \x01(\x05R\x06status\x12\x12\n" +
@ -10421,8 +10439,8 @@ const file_api_accountFiee_accountFiee_proto_rawDesc = "" +
"\bidNumber\x18\x14 \x01(\tR\bidNumber\x12 \n" +
"\vdateOfBirth\x18\x15 \x01(\tR\vdateOfBirth\x12\x14\n" +
"\x05email\x18\x16 \x01(\tR\x05email\x12,\n" +
"\x11AbroadTelAreaCode\x18\x17 \x01(\tR\x11AbroadTelAreaCode\x12\x1c\n" +
"\tAbroadTel\x18\x18 \x01(\tR\tAbroadTel\x12\x1c\n" +
"\x11abroadTelAreaCode\x18\x17 \x01(\tR\x11abroadTelAreaCode\x12\x1c\n" +
"\tabroadTel\x18\x18 \x01(\tR\tabroadTel\x12\x1c\n" +
"\tinviterId\x18\x19 \x01(\x04R\tinviterId\":\n" +
"\x10RealNameResponse\x12\x0e\n" +
"\x02id\x18\x01 \x01(\x04R\x02id\x12\x16\n" +

View File

@ -201,8 +201,8 @@ message UserListInfo{
string dateOfBirth = 22;
string age = 23;
string email = 24;
string AbroadTelAreaCode = 25;
string AbroadTel = 26;
string abroadTelAreaCode = 25;
string abroadTel = 26;
string inviterName = 27;
string inviterCode = 28;
}
@ -220,6 +220,8 @@ message UserListRequest{
repeated int64 ids = 11;
string nationality = 12;
string nameAndNumber = 13;
string email = 14;
string abroadTel = 15;
}
message UserInfoResponse{
uint64 id = 1;
@ -244,8 +246,8 @@ message UserInfoResponse{
string idNumber = 20;
string dateOfBirth = 21;
string email = 22;
string AbroadTelAreaCode = 23;
string AbroadTel = 24;
string abroadTelAreaCode = 23;
string abroadTel = 24;
uint64 inviterId = 25;
}

File diff suppressed because it is too large Load Diff

View File

@ -206,6 +206,15 @@ func (this *GenerateJWTRequest) Validate() error {
func (this *GenerateJWTResponse) Validate() error {
return nil
}
func (this *UnlinkSocialNetworkRequest) Validate() error {
if this.Platform == "" {
return github_com_mwitkow_go_proto_validators.FieldError("Platform", fmt.Errorf(`platform不能为空`))
}
return nil
}
func (this *UnlinkSocialNetworkResponse) Validate() error {
return nil
}
func (this *HistoryPostId) 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.21.1
// - protoc v6.32.0--rc2
// source: pb/ayrshare.proto
package aryshare
@ -37,6 +37,7 @@ type AyrshareClient interface {
CreateProfile(ctx context.Context, in *CreateProfileRequest, opts ...grpc_go.CallOption) (*CreateProfileResponse, common.ErrorWithAttachment)
GetProfiles(ctx context.Context, in *GetProfilesRequest, opts ...grpc_go.CallOption) (*GetProfilesResponse, common.ErrorWithAttachment)
GenerateJWT(ctx context.Context, in *GenerateJWTRequest, opts ...grpc_go.CallOption) (*GenerateJWTResponse, common.ErrorWithAttachment)
UnlinkSocialNetwork(ctx context.Context, in *UnlinkSocialNetworkRequest, opts ...grpc_go.CallOption) (*UnlinkSocialNetworkResponse, common.ErrorWithAttachment)
// 历史记录相关 api
GetHistory(ctx context.Context, in *GetHistoryRequest, opts ...grpc_go.CallOption) (*GetHistoryResponse, common.ErrorWithAttachment)
GetHistoryById(ctx context.Context, in *GetHistoryByIdRequest, opts ...grpc_go.CallOption) (*GetHistoryByIdResponse, common.ErrorWithAttachment)
@ -71,6 +72,7 @@ type AyrshareClientImpl struct {
CreateProfile func(ctx context.Context, in *CreateProfileRequest) (*CreateProfileResponse, error)
GetProfiles func(ctx context.Context, in *GetProfilesRequest) (*GetProfilesResponse, error)
GenerateJWT func(ctx context.Context, in *GenerateJWTRequest) (*GenerateJWTResponse, error)
UnlinkSocialNetwork func(ctx context.Context, in *UnlinkSocialNetworkRequest) (*UnlinkSocialNetworkResponse, error)
GetHistory func(ctx context.Context, in *GetHistoryRequest) (*GetHistoryResponse, error)
GetHistoryById func(ctx context.Context, in *GetHistoryByIdRequest) (*GetHistoryByIdResponse, error)
GetHistoryByPlatform func(ctx context.Context, in *GetHistoryByPlatformRequest) (*GetHistoryByPlatformResponse, error)
@ -137,6 +139,12 @@ func (c *ayrshareClient) GenerateJWT(ctx context.Context, in *GenerateJWTRequest
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/GenerateJWT", in, out)
}
func (c *ayrshareClient) UnlinkSocialNetwork(ctx context.Context, in *UnlinkSocialNetworkRequest, opts ...grpc_go.CallOption) (*UnlinkSocialNetworkResponse, common.ErrorWithAttachment) {
out := new(UnlinkSocialNetworkResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UnlinkSocialNetwork", in, out)
}
func (c *ayrshareClient) GetHistory(ctx context.Context, in *GetHistoryRequest, opts ...grpc_go.CallOption) (*GetHistoryResponse, common.ErrorWithAttachment) {
out := new(GetHistoryResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
@ -246,6 +254,7 @@ type AyrshareServer interface {
CreateProfile(context.Context, *CreateProfileRequest) (*CreateProfileResponse, error)
GetProfiles(context.Context, *GetProfilesRequest) (*GetProfilesResponse, error)
GenerateJWT(context.Context, *GenerateJWTRequest) (*GenerateJWTResponse, error)
UnlinkSocialNetwork(context.Context, *UnlinkSocialNetworkRequest) (*UnlinkSocialNetworkResponse, error)
// 历史记录相关 api
GetHistory(context.Context, *GetHistoryRequest) (*GetHistoryResponse, error)
GetHistoryById(context.Context, *GetHistoryByIdRequest) (*GetHistoryByIdResponse, error)
@ -293,6 +302,9 @@ func (UnimplementedAyrshareServer) GetProfiles(context.Context, *GetProfilesRequ
func (UnimplementedAyrshareServer) GenerateJWT(context.Context, *GenerateJWTRequest) (*GenerateJWTResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GenerateJWT not implemented")
}
func (UnimplementedAyrshareServer) UnlinkSocialNetwork(context.Context, *UnlinkSocialNetworkRequest) (*UnlinkSocialNetworkResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UnlinkSocialNetwork not implemented")
}
func (UnimplementedAyrshareServer) GetHistory(context.Context, *GetHistoryRequest) (*GetHistoryResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetHistory not implemented")
}
@ -543,6 +555,35 @@ func _Ayrshare_GenerateJWT_Handler(srv interface{}, ctx context.Context, dec fun
return interceptor(ctx, in, info, handler)
}
func _Ayrshare_UnlinkSocialNetwork_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UnlinkSocialNetworkRequest)
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("UnlinkSocialNetwork", 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 _Ayrshare_GetHistory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(GetHistoryRequest)
if err := dec(in); err != nil {
@ -1038,6 +1079,10 @@ var Ayrshare_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "GenerateJWT",
Handler: _Ayrshare_GenerateJWT_Handler,
},
{
MethodName: "UnlinkSocialNetwork",
Handler: _Ayrshare_UnlinkSocialNetwork_Handler,
},
{
MethodName: "GetHistory",
Handler: _Ayrshare_GetHistory_Handler,

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,9 @@ var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
func (this *GetInEffectOrderRecordRequest) Validate() error {
return nil
}
func (this *QueryTheOrderSnapshotInformationReq) Validate() error {
return nil
}
@ -484,6 +487,12 @@ func (this *GetBundleBalanceByUserIdReq) Validate() error {
func (this *GetBundleBalanceByUserIdResp) Validate() error {
return nil
}
func (this *GetBundleBalanceByOrderUUIDReq) Validate() error {
return nil
}
func (this *GetBundleBalanceByOrderUUIDResp) Validate() error {
return nil
}
func (this *OnlyAddValueListByOrderNoRequest) Validate() error {
return nil
}
@ -740,6 +749,22 @@ func (this *SetPendingTaskLayoutReq) Validate() error {
func (this *SetPendingTaskLayoutResp) Validate() error {
return nil
}
func (this *TaskWorkLogQueryRequest) Validate() error {
return nil
}
func (this *TaskWorkLogInfo) Validate() error {
return nil
}
func (this *TaskWorkLogQueryResponse) Validate() error {
for _, item := range this.Records {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Records", err)
}
}
}
return nil
}
func (this *CreateTaskWorkLogRequest) Validate() error {
return nil
}
@ -812,6 +837,218 @@ func (this *MetricsVideoSubmitExportItem) Validate() error {
func (this *MetricsBalanceDetailExportReq) Validate() error {
return nil
}
func (this *CustomerListRequest) Validate() error {
return nil
}
func (this *CustomerListResponse) 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 *CustomerDetailRequest) Validate() error {
return nil
}
func (this *CustomerDetailResponse) Validate() error {
if this.Customer != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Customer); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Customer", err)
}
}
return nil
}
func (this *CustomerUpdateRequest) Validate() error {
if this.Customer != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Customer); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Customer", err)
}
}
return nil
}
func (this *CustomerInfo) Validate() error {
return nil
}
func (this *Customer) Validate() error {
return nil
}
func (this *ReferralPersonListRequest) Validate() error {
return nil
}
func (this *ReferralPersonListResponse) Validate() error {
return nil
}
func (this *ContractUpdateRequest) Validate() error {
if this.Contract != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Contract); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Contract", err)
}
}
return nil
}
func (this *ContractListRequest) Validate() error {
return nil
}
func (this *ContractListResponse) 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 *ContractDetailRequest) Validate() error {
return nil
}
func (this *ContractDetailResponse) Validate() error {
if this.Contract != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.Contract); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Contract", err)
}
}
return nil
}
func (this *GetDevelopmentCyclesByContractUUIDRequest) Validate() error {
return nil
}
func (this *GetDevelopmentCyclesByContractUUIDResponse) 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 *GetPaymentCyclesByContractUUIDRequest) Validate() error {
return nil
}
func (this *GetPaymentCyclesByContractUUIDResponse) 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 *AttachmentItem) Validate() error {
return nil
}
func (this *ContractInfo) Validate() error {
for _, item := range this.ContractAttachments {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("ContractAttachments", err)
}
}
}
for _, item := range this.OtherAttachments {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("OtherAttachments", err)
}
}
}
return nil
}
func (this *Contract) Validate() error {
for _, item := range this.ContractAttachments {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("ContractAttachments", err)
}
}
}
for _, item := range this.OtherAttachments {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("OtherAttachments", err)
}
}
}
for _, item := range this.PaymentCycles {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("PaymentCycles", err)
}
}
}
for _, item := range this.DevelopmentCycles {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("DevelopmentCycles", err)
}
}
}
return nil
}
func (this *ContractPaymentCycle) Validate() error {
return nil
}
func (this *DevelopmentCycle) Validate() error {
for _, item := range this.Attachments {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Attachments", err)
}
}
}
return nil
}
func (this *CreateInvoiceReq) Validate() error {
return nil
}
func (this *CreateInvoiceResp) Validate() error {
return nil
}
func (this *CreatePaperInvoiceAddressReq) Validate() error {
return nil
}
func (this *CreatePaperInvoiceAddressResp) Validate() error {
return nil
}
func (this *InvoiceInfo) Validate() error {
return nil
}
func (this *GetInvoiceListReq) Validate() error {
return nil
}
func (this *GetInvoiceListResp) 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 *UpdateInvoiceExpressInfoReq) Validate() error {
return nil
}
func (this *UpdateInvoiceExpressInfoResp) Validate() error {
return nil
}
func (this *GetInvoiceExpressInfoReq) Validate() error {
return nil
}
func (this *GetInvoiceExpressInfoResp) Validate() error {
return nil
}
func (this *GetOrderInfoByOrderNoReq) Validate() error {
return nil
}
func (this *GetOrderInfoByOrderNoResp) Validate() error {
return nil
}
func (this *WorkCastInfo) Validate() error {
return nil
}
@ -828,3 +1065,92 @@ func (this *ExportWorkCastInfoResp) Validate() error {
}
return nil
}
func (this *OrderInfoByOrderUuidRequest) Validate() error {
return nil
}
func (this *GetInvoiceInfoByOrderNoReq) Validate() error {
return nil
}
func (this *InvoiceInfoByOrderNo) Validate() error {
return nil
}
func (this *GetInvoiceInfoByOrderNoResp) 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 *GetLastInvoiceNoReq) Validate() error {
return nil
}
func (this *GetLastInvoiceNoResp) Validate() error {
return nil
}
func (this *UpdataInvoiceInfoReq) Validate() error {
return nil
}
func (this *UpdataInvoiceInfoResp) Validate() error {
return nil
}
func (this *SendQuestionnaireSurveyRequest) Validate() error {
return nil
}
func (this *SendQuestionnaireSurveyResponse) Validate() error {
return nil
}
func (this *GetQuestionnaireSurveyInfoRequest) Validate() error {
return nil
}
func (this *SurveyBundleInfo) Validate() error {
return nil
}
func (this *GetQuestionnaireSurveyInfoResponse) Validate() error {
if this.BundleInfo != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.BundleInfo); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("BundleInfo", err)
}
}
return nil
}
func (this *SurveyAnswer) Validate() error {
return nil
}
func (this *SurveyFeedback) Validate() error {
return nil
}
func (this *CreateQuestionnaireSurveyAnswerRequest) Validate() error {
if this.SurveyAnswer != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.SurveyAnswer); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("SurveyAnswer", err)
}
}
if this.SurveyFeedback != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(this.SurveyFeedback); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("SurveyFeedback", err)
}
}
return nil
}
func (this *CreateQuestionnaireSurveyAnswerResponse) Validate() error {
return nil
}
func (this *GetQuestionnaireSurveyListRequest) Validate() error {
return nil
}
func (this *SurveyListInfo) Validate() error {
return nil
}
func (this *GetQuestionnaireSurveyListResponse) Validate() error {
for _, item := range this.SurveyList {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("SurveyList", err)
}
}
}
return nil
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -54,7 +54,11 @@ type CastClient interface {
RefreshWorkList(ctx context.Context, in *RefreshWorkListReq, opts ...grpc_go.CallOption) (*RefreshWorkListResp, common.ErrorWithAttachment)
WorkResource(ctx context.Context, in *WorkResourceReq, opts ...grpc_go.CallOption) (*WorkResourceResp, common.ErrorWithAttachment)
UpdateWorkResource(ctx context.Context, in *UpdateWorkResourceReq, opts ...grpc_go.CallOption) (*UpdateWorkResourceResp, common.ErrorWithAttachment)
UpdateMediaAccStatus(ctx context.Context, in *UpdateMediaAccStatusReq, opts ...grpc_go.CallOption) (*UpdateMediaAccStatusResp, common.ErrorWithAttachment)
UpdateWorkScript(ctx context.Context, in *UpdateWorkScriptReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
OAuthAccount(ctx context.Context, in *OAuthAccountReq, opts ...grpc_go.CallOption) (*OAuthAccountResp, common.ErrorWithAttachment)
UnbindMediaAuth(ctx context.Context, in *UnbindMediaAuthReq, opts ...grpc_go.CallOption) (*UnbindMediaAuthResp, common.ErrorWithAttachment)
UpdateMediaAccInfo(ctx context.Context, in *UpdateMediaAccInfoReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
OAuthAccountV2(ctx context.Context, in *OAuthAccountV2Req, opts ...grpc_go.CallOption) (*OAuthAccountV2Resp, common.ErrorWithAttachment)
OAuthCodeToToken(ctx context.Context, in *OAuthCodeToTokenReq, opts ...grpc_go.CallOption) (*OAuthCodeToTokenResp, common.ErrorWithAttachment)
UpdateOAuth(ctx context.Context, in *UpdateOAuthReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
@ -81,6 +85,7 @@ type CastClient interface {
GetArtist(ctx context.Context, in *GetArtistReq, opts ...grpc_go.CallOption) (*GetArtistResp, common.ErrorWithAttachment)
// 作品分析相关接口
CreateWorkAnalysis(ctx context.Context, in *CreateWorkAnalysisReq, opts ...grpc_go.CallOption) (*CreateWorkAnalysisResp, common.ErrorWithAttachment)
ImportWorkAnalysis(ctx context.Context, in *ImportWorkAnalysisReq, opts ...grpc_go.CallOption) (*ImportWorkAnalysisResp, common.ErrorWithAttachment)
UpdateWorkAnalysis(ctx context.Context, in *UpdateWorkAnalysisReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
UpdateWorkAnalysisStatus(ctx context.Context, in *UpdateWorkAnalysisStatusReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
GetWorkAnalysis(ctx context.Context, in *GetWorkAnalysisDetailReq, opts ...grpc_go.CallOption) (*GetWorkAnalysisDetailResp, common.ErrorWithAttachment)
@ -88,6 +93,7 @@ type CastClient interface {
ListWorkAnalysis(ctx context.Context, in *ListWorkAnalysisReq, opts ...grpc_go.CallOption) (*ListWorkAnalysisResp, common.ErrorWithAttachment)
DeleteWorkAnalysis(ctx context.Context, in *DeleteWorkAnalysisReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
UpdateWorkAnalysisApprovalID(ctx context.Context, in *UpdateWorkAnalysisApprovalIDReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
UpdateWorkAnalysisPdfUrl(ctx context.Context, in *UpdateWorkAnalysisReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
// 数据列表相关接口
ArtistDataList(ctx context.Context, in *ArtistDataListReq, opts ...grpc_go.CallOption) (*ArtistDataListResp, common.ErrorWithAttachment)
MediaDataList(ctx context.Context, in *MediaDataListReq, opts ...grpc_go.CallOption) (*MediaDataListResp, common.ErrorWithAttachment)
@ -132,6 +138,11 @@ type CastClient interface {
DeleteCompetitiveReport(ctx context.Context, in *DeleteCompetitiveReportReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
UpdateCompetitiveReportApprovalID(ctx context.Context, in *UpdateCompetitiveReportApprovalIDReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment)
CountCompetitiveReportByWorkUuids(ctx context.Context, in *CountCompetitiveReportByWorkUuidsReq, opts ...grpc_go.CallOption) (*CountCompetitiveReportByWorkUuidsResp, common.ErrorWithAttachment)
ImportCompetitiveReportHistory(ctx context.Context, in *ImportCompetitiveReportHistoryReq, opts ...grpc_go.CallOption) (*ImportCompetitiveReportHistoryResp, common.ErrorWithAttachment)
// 发布记录相关接口
ListPublishLog(ctx context.Context, in *ListPublishLogReq, opts ...grpc_go.CallOption) (*ListPublishLogResp, common.ErrorWithAttachment)
// 艺人作品统计快照接口
GetArtistWorkStats(ctx context.Context, in *GetArtistWorkStatsReq, opts ...grpc_go.CallOption) (*GetArtistWorkStatsResp, common.ErrorWithAttachment)
}
type castClient struct {
@ -164,7 +175,11 @@ type CastClientImpl struct {
RefreshWorkList func(ctx context.Context, in *RefreshWorkListReq) (*RefreshWorkListResp, error)
WorkResource func(ctx context.Context, in *WorkResourceReq) (*WorkResourceResp, error)
UpdateWorkResource func(ctx context.Context, in *UpdateWorkResourceReq) (*UpdateWorkResourceResp, error)
UpdateMediaAccStatus func(ctx context.Context, in *UpdateMediaAccStatusReq) (*UpdateMediaAccStatusResp, error)
UpdateWorkScript func(ctx context.Context, in *UpdateWorkScriptReq) (*emptypb.Empty, error)
OAuthAccount func(ctx context.Context, in *OAuthAccountReq) (*OAuthAccountResp, error)
UnbindMediaAuth func(ctx context.Context, in *UnbindMediaAuthReq) (*UnbindMediaAuthResp, error)
UpdateMediaAccInfo func(ctx context.Context, in *UpdateMediaAccInfoReq) (*emptypb.Empty, error)
OAuthAccountV2 func(ctx context.Context, in *OAuthAccountV2Req) (*OAuthAccountV2Resp, error)
OAuthCodeToToken func(ctx context.Context, in *OAuthCodeToTokenReq) (*OAuthCodeToTokenResp, error)
UpdateOAuth func(ctx context.Context, in *UpdateOAuthReq) (*emptypb.Empty, error)
@ -187,6 +202,7 @@ type CastClientImpl struct {
UpdateArtist func(ctx context.Context, in *UpdateArtistReq) (*UpdateArtistResp, error)
GetArtist func(ctx context.Context, in *GetArtistReq) (*GetArtistResp, error)
CreateWorkAnalysis func(ctx context.Context, in *CreateWorkAnalysisReq) (*CreateWorkAnalysisResp, error)
ImportWorkAnalysis func(ctx context.Context, in *ImportWorkAnalysisReq) (*ImportWorkAnalysisResp, error)
UpdateWorkAnalysis func(ctx context.Context, in *UpdateWorkAnalysisReq) (*emptypb.Empty, error)
UpdateWorkAnalysisStatus func(ctx context.Context, in *UpdateWorkAnalysisStatusReq) (*emptypb.Empty, error)
GetWorkAnalysis func(ctx context.Context, in *GetWorkAnalysisDetailReq) (*GetWorkAnalysisDetailResp, error)
@ -194,6 +210,7 @@ type CastClientImpl struct {
ListWorkAnalysis func(ctx context.Context, in *ListWorkAnalysisReq) (*ListWorkAnalysisResp, error)
DeleteWorkAnalysis func(ctx context.Context, in *DeleteWorkAnalysisReq) (*emptypb.Empty, error)
UpdateWorkAnalysisApprovalID func(ctx context.Context, in *UpdateWorkAnalysisApprovalIDReq) (*emptypb.Empty, error)
UpdateWorkAnalysisPdfUrl func(ctx context.Context, in *UpdateWorkAnalysisReq) (*emptypb.Empty, error)
ArtistDataList func(ctx context.Context, in *ArtistDataListReq) (*ArtistDataListResp, error)
MediaDataList func(ctx context.Context, in *MediaDataListReq) (*MediaDataListResp, error)
DataOverview func(ctx context.Context, in *DataOverviewReq) (*DataOverviewResp, error)
@ -227,6 +244,9 @@ type CastClientImpl struct {
DeleteCompetitiveReport func(ctx context.Context, in *DeleteCompetitiveReportReq) (*emptypb.Empty, error)
UpdateCompetitiveReportApprovalID func(ctx context.Context, in *UpdateCompetitiveReportApprovalIDReq) (*emptypb.Empty, error)
CountCompetitiveReportByWorkUuids func(ctx context.Context, in *CountCompetitiveReportByWorkUuidsReq) (*CountCompetitiveReportByWorkUuidsResp, error)
ImportCompetitiveReportHistory func(ctx context.Context, in *ImportCompetitiveReportHistoryReq) (*ImportCompetitiveReportHistoryResp, error)
ListPublishLog func(ctx context.Context, in *ListPublishLogReq) (*ListPublishLogResp, error)
GetArtistWorkStats func(ctx context.Context, in *GetArtistWorkStatsReq) (*GetArtistWorkStatsResp, error)
}
func (c *CastClientImpl) GetDubboStub(cc *triple.TripleConn) CastClient {
@ -391,12 +411,36 @@ func (c *castClient) UpdateWorkResource(ctx context.Context, in *UpdateWorkResou
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateWorkResource", in, out)
}
func (c *castClient) UpdateMediaAccStatus(ctx context.Context, in *UpdateMediaAccStatusReq, opts ...grpc_go.CallOption) (*UpdateMediaAccStatusResp, common.ErrorWithAttachment) {
out := new(UpdateMediaAccStatusResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateMediaAccStatus", in, out)
}
func (c *castClient) UpdateWorkScript(ctx context.Context, in *UpdateWorkScriptReq, 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+"/UpdateWorkScript", 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) UnbindMediaAuth(ctx context.Context, in *UnbindMediaAuthReq, opts ...grpc_go.CallOption) (*UnbindMediaAuthResp, common.ErrorWithAttachment) {
out := new(UnbindMediaAuthResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UnbindMediaAuth", in, out)
}
func (c *castClient) UpdateMediaAccInfo(ctx context.Context, in *UpdateMediaAccInfoReq, 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+"/UpdateMediaAccInfo", in, out)
}
func (c *castClient) OAuthAccountV2(ctx context.Context, in *OAuthAccountV2Req, opts ...grpc_go.CallOption) (*OAuthAccountV2Resp, common.ErrorWithAttachment) {
out := new(OAuthAccountV2Resp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
@ -529,6 +573,12 @@ func (c *castClient) CreateWorkAnalysis(ctx context.Context, in *CreateWorkAnaly
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/CreateWorkAnalysis", in, out)
}
func (c *castClient) ImportWorkAnalysis(ctx context.Context, in *ImportWorkAnalysisReq, opts ...grpc_go.CallOption) (*ImportWorkAnalysisResp, common.ErrorWithAttachment) {
out := new(ImportWorkAnalysisResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/ImportWorkAnalysis", in, out)
}
func (c *castClient) UpdateWorkAnalysis(ctx context.Context, in *UpdateWorkAnalysisReq, opts ...grpc_go.CallOption) (*emptypb.Empty, common.ErrorWithAttachment) {
out := new(emptypb.Empty)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
@ -571,6 +621,12 @@ func (c *castClient) UpdateWorkAnalysisApprovalID(ctx context.Context, in *Updat
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateWorkAnalysisApprovalID", in, out)
}
func (c *castClient) UpdateWorkAnalysisPdfUrl(ctx context.Context, in *UpdateWorkAnalysisReq, 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+"/UpdateWorkAnalysisPdfUrl", in, out)
}
func (c *castClient) ArtistDataList(ctx context.Context, in *ArtistDataListReq, opts ...grpc_go.CallOption) (*ArtistDataListResp, common.ErrorWithAttachment) {
out := new(ArtistDataListResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
@ -769,6 +825,24 @@ func (c *castClient) CountCompetitiveReportByWorkUuids(ctx context.Context, in *
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/CountCompetitiveReportByWorkUuids", in, out)
}
func (c *castClient) ImportCompetitiveReportHistory(ctx context.Context, in *ImportCompetitiveReportHistoryReq, opts ...grpc_go.CallOption) (*ImportCompetitiveReportHistoryResp, common.ErrorWithAttachment) {
out := new(ImportCompetitiveReportHistoryResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/ImportCompetitiveReportHistory", in, out)
}
func (c *castClient) ListPublishLog(ctx context.Context, in *ListPublishLogReq, opts ...grpc_go.CallOption) (*ListPublishLogResp, common.ErrorWithAttachment) {
out := new(ListPublishLogResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/ListPublishLog", in, out)
}
func (c *castClient) GetArtistWorkStats(ctx context.Context, in *GetArtistWorkStatsReq, opts ...grpc_go.CallOption) (*GetArtistWorkStatsResp, common.ErrorWithAttachment) {
out := new(GetArtistWorkStatsResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/GetArtistWorkStats", in, out)
}
// CastServer is the server API for Cast service.
// All implementations must embed UnimplementedCastServer
// for forward compatibility
@ -798,7 +872,11 @@ type CastServer interface {
RefreshWorkList(context.Context, *RefreshWorkListReq) (*RefreshWorkListResp, error)
WorkResource(context.Context, *WorkResourceReq) (*WorkResourceResp, error)
UpdateWorkResource(context.Context, *UpdateWorkResourceReq) (*UpdateWorkResourceResp, error)
UpdateMediaAccStatus(context.Context, *UpdateMediaAccStatusReq) (*UpdateMediaAccStatusResp, error)
UpdateWorkScript(context.Context, *UpdateWorkScriptReq) (*emptypb.Empty, error)
OAuthAccount(context.Context, *OAuthAccountReq) (*OAuthAccountResp, error)
UnbindMediaAuth(context.Context, *UnbindMediaAuthReq) (*UnbindMediaAuthResp, error)
UpdateMediaAccInfo(context.Context, *UpdateMediaAccInfoReq) (*emptypb.Empty, error)
OAuthAccountV2(context.Context, *OAuthAccountV2Req) (*OAuthAccountV2Resp, error)
OAuthCodeToToken(context.Context, *OAuthCodeToTokenReq) (*OAuthCodeToTokenResp, error)
UpdateOAuth(context.Context, *UpdateOAuthReq) (*emptypb.Empty, error)
@ -825,6 +903,7 @@ type CastServer interface {
GetArtist(context.Context, *GetArtistReq) (*GetArtistResp, error)
// 作品分析相关接口
CreateWorkAnalysis(context.Context, *CreateWorkAnalysisReq) (*CreateWorkAnalysisResp, error)
ImportWorkAnalysis(context.Context, *ImportWorkAnalysisReq) (*ImportWorkAnalysisResp, error)
UpdateWorkAnalysis(context.Context, *UpdateWorkAnalysisReq) (*emptypb.Empty, error)
UpdateWorkAnalysisStatus(context.Context, *UpdateWorkAnalysisStatusReq) (*emptypb.Empty, error)
GetWorkAnalysis(context.Context, *GetWorkAnalysisDetailReq) (*GetWorkAnalysisDetailResp, error)
@ -832,6 +911,7 @@ type CastServer interface {
ListWorkAnalysis(context.Context, *ListWorkAnalysisReq) (*ListWorkAnalysisResp, error)
DeleteWorkAnalysis(context.Context, *DeleteWorkAnalysisReq) (*emptypb.Empty, error)
UpdateWorkAnalysisApprovalID(context.Context, *UpdateWorkAnalysisApprovalIDReq) (*emptypb.Empty, error)
UpdateWorkAnalysisPdfUrl(context.Context, *UpdateWorkAnalysisReq) (*emptypb.Empty, error)
// 数据列表相关接口
ArtistDataList(context.Context, *ArtistDataListReq) (*ArtistDataListResp, error)
MediaDataList(context.Context, *MediaDataListReq) (*MediaDataListResp, error)
@ -876,6 +956,11 @@ type CastServer interface {
DeleteCompetitiveReport(context.Context, *DeleteCompetitiveReportReq) (*emptypb.Empty, error)
UpdateCompetitiveReportApprovalID(context.Context, *UpdateCompetitiveReportApprovalIDReq) (*emptypb.Empty, error)
CountCompetitiveReportByWorkUuids(context.Context, *CountCompetitiveReportByWorkUuidsReq) (*CountCompetitiveReportByWorkUuidsResp, error)
ImportCompetitiveReportHistory(context.Context, *ImportCompetitiveReportHistoryReq) (*ImportCompetitiveReportHistoryResp, error)
// 发布记录相关接口
ListPublishLog(context.Context, *ListPublishLogReq) (*ListPublishLogResp, error)
// 艺人作品统计快照接口
GetArtistWorkStats(context.Context, *GetArtistWorkStatsReq) (*GetArtistWorkStatsResp, error)
mustEmbedUnimplementedCastServer()
}
@ -959,9 +1044,21 @@ func (UnimplementedCastServer) WorkResource(context.Context, *WorkResourceReq) (
func (UnimplementedCastServer) UpdateWorkResource(context.Context, *UpdateWorkResourceReq) (*UpdateWorkResourceResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateWorkResource not implemented")
}
func (UnimplementedCastServer) UpdateMediaAccStatus(context.Context, *UpdateMediaAccStatusReq) (*UpdateMediaAccStatusResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateMediaAccStatus not implemented")
}
func (UnimplementedCastServer) UpdateWorkScript(context.Context, *UpdateWorkScriptReq) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateWorkScript not implemented")
}
func (UnimplementedCastServer) OAuthAccount(context.Context, *OAuthAccountReq) (*OAuthAccountResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method OAuthAccount not implemented")
}
func (UnimplementedCastServer) UnbindMediaAuth(context.Context, *UnbindMediaAuthReq) (*UnbindMediaAuthResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UnbindMediaAuth not implemented")
}
func (UnimplementedCastServer) UpdateMediaAccInfo(context.Context, *UpdateMediaAccInfoReq) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateMediaAccInfo not implemented")
}
func (UnimplementedCastServer) OAuthAccountV2(context.Context, *OAuthAccountV2Req) (*OAuthAccountV2Resp, error) {
return nil, status.Errorf(codes.Unimplemented, "method OAuthAccountV2 not implemented")
}
@ -1028,6 +1125,9 @@ func (UnimplementedCastServer) GetArtist(context.Context, *GetArtistReq) (*GetAr
func (UnimplementedCastServer) CreateWorkAnalysis(context.Context, *CreateWorkAnalysisReq) (*CreateWorkAnalysisResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateWorkAnalysis not implemented")
}
func (UnimplementedCastServer) ImportWorkAnalysis(context.Context, *ImportWorkAnalysisReq) (*ImportWorkAnalysisResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method ImportWorkAnalysis not implemented")
}
func (UnimplementedCastServer) UpdateWorkAnalysis(context.Context, *UpdateWorkAnalysisReq) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateWorkAnalysis not implemented")
}
@ -1049,6 +1149,9 @@ func (UnimplementedCastServer) DeleteWorkAnalysis(context.Context, *DeleteWorkAn
func (UnimplementedCastServer) UpdateWorkAnalysisApprovalID(context.Context, *UpdateWorkAnalysisApprovalIDReq) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateWorkAnalysisApprovalID not implemented")
}
func (UnimplementedCastServer) UpdateWorkAnalysisPdfUrl(context.Context, *UpdateWorkAnalysisReq) (*emptypb.Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateWorkAnalysisPdfUrl not implemented")
}
func (UnimplementedCastServer) ArtistDataList(context.Context, *ArtistDataListReq) (*ArtistDataListResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method ArtistDataList not implemented")
}
@ -1148,6 +1251,15 @@ func (UnimplementedCastServer) UpdateCompetitiveReportApprovalID(context.Context
func (UnimplementedCastServer) CountCompetitiveReportByWorkUuids(context.Context, *CountCompetitiveReportByWorkUuidsReq) (*CountCompetitiveReportByWorkUuidsResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method CountCompetitiveReportByWorkUuids not implemented")
}
func (UnimplementedCastServer) ImportCompetitiveReportHistory(context.Context, *ImportCompetitiveReportHistoryReq) (*ImportCompetitiveReportHistoryResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method ImportCompetitiveReportHistory not implemented")
}
func (UnimplementedCastServer) ListPublishLog(context.Context, *ListPublishLogReq) (*ListPublishLogResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListPublishLog not implemented")
}
func (UnimplementedCastServer) GetArtistWorkStats(context.Context, *GetArtistWorkStatsReq) (*GetArtistWorkStatsResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetArtistWorkStats not implemented")
}
func (s *UnimplementedCastServer) XXX_SetProxyImpl(impl protocol.Invoker) {
s.proxyImpl = impl
}
@ -1901,6 +2013,64 @@ func _Cast_UpdateWorkResource_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _Cast_UpdateMediaAccStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateMediaAccStatusReq)
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("UpdateMediaAccStatus", 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_UpdateWorkScript_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateWorkScriptReq)
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("UpdateWorkScript", 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 {
@ -1930,6 +2100,64 @@ func _Cast_OAuthAccount_Handler(srv interface{}, ctx context.Context, dec func(i
return interceptor(ctx, in, info, handler)
}
func _Cast_UnbindMediaAuth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UnbindMediaAuthReq)
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("UnbindMediaAuth", 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_UpdateMediaAccInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateMediaAccInfoReq)
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("UpdateMediaAccInfo", 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_OAuthAccountV2_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(OAuthAccountV2Req)
if err := dec(in); err != nil {
@ -2568,6 +2796,35 @@ func _Cast_CreateWorkAnalysis_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _Cast_ImportWorkAnalysis_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(ImportWorkAnalysisReq)
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("ImportWorkAnalysis", 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_UpdateWorkAnalysis_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateWorkAnalysisReq)
if err := dec(in); err != nil {
@ -2771,6 +3028,35 @@ func _Cast_UpdateWorkAnalysisApprovalID_Handler(srv interface{}, ctx context.Con
return interceptor(ctx, in, info, handler)
}
func _Cast_UpdateWorkAnalysisPdfUrl_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateWorkAnalysisReq)
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("UpdateWorkAnalysisPdfUrl", 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_ArtistDataList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(ArtistDataListReq)
if err := dec(in); err != nil {
@ -3728,6 +4014,93 @@ func _Cast_CountCompetitiveReportByWorkUuids_Handler(srv interface{}, ctx contex
return interceptor(ctx, in, info, handler)
}
func _Cast_ImportCompetitiveReportHistory_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(ImportCompetitiveReportHistoryReq)
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("ImportCompetitiveReportHistory", 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_ListPublishLog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(ListPublishLogReq)
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("ListPublishLog", 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_GetArtistWorkStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(GetArtistWorkStatsReq)
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("GetArtistWorkStats", 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)
@ -3835,10 +4208,26 @@ var Cast_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "UpdateWorkResource",
Handler: _Cast_UpdateWorkResource_Handler,
},
{
MethodName: "UpdateMediaAccStatus",
Handler: _Cast_UpdateMediaAccStatus_Handler,
},
{
MethodName: "UpdateWorkScript",
Handler: _Cast_UpdateWorkScript_Handler,
},
{
MethodName: "OAuthAccount",
Handler: _Cast_OAuthAccount_Handler,
},
{
MethodName: "UnbindMediaAuth",
Handler: _Cast_UnbindMediaAuth_Handler,
},
{
MethodName: "UpdateMediaAccInfo",
Handler: _Cast_UpdateMediaAccInfo_Handler,
},
{
MethodName: "OAuthAccountV2",
Handler: _Cast_OAuthAccountV2_Handler,
@ -3927,6 +4316,10 @@ var Cast_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "CreateWorkAnalysis",
Handler: _Cast_CreateWorkAnalysis_Handler,
},
{
MethodName: "ImportWorkAnalysis",
Handler: _Cast_ImportWorkAnalysis_Handler,
},
{
MethodName: "UpdateWorkAnalysis",
Handler: _Cast_UpdateWorkAnalysis_Handler,
@ -3955,6 +4348,10 @@ var Cast_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "UpdateWorkAnalysisApprovalID",
Handler: _Cast_UpdateWorkAnalysisApprovalID_Handler,
},
{
MethodName: "UpdateWorkAnalysisPdfUrl",
Handler: _Cast_UpdateWorkAnalysisPdfUrl_Handler,
},
{
MethodName: "ArtistDataList",
Handler: _Cast_ArtistDataList_Handler,
@ -4087,6 +4484,18 @@ var Cast_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "CountCompetitiveReportByWorkUuids",
Handler: _Cast_CountCompetitiveReportByWorkUuids_Handler,
},
{
MethodName: "ImportCompetitiveReportHistory",
Handler: _Cast_ImportCompetitiveReportHistory_Handler,
},
{
MethodName: "ListPublishLog",
Handler: _Cast_ListPublishLog_Handler,
},
{
MethodName: "GetArtistWorkStats",
Handler: _Cast_GetArtistWorkStats_Handler,
},
},
Streams: []grpc_go.StreamDesc{},
Metadata: "pb/fiee/cast.proto",

View File

@ -9,6 +9,7 @@ package cron
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
@ -2069,7 +2070,7 @@ var File_pb_cron_proto protoreflect.FileDescriptor
const file_pb_cron_proto_rawDesc = "" +
"\n" +
"\rpb/cron.proto\x12\x04cron\"!\n" +
"\rpb/cron.proto\x12\x04cron\x1a\x1bgoogle/protobuf/empty.proto\"!\n" +
"\x0fCommonIDRequest\x12\x0e\n" +
"\x02id\x18\x01 \x01(\rR\x02id\">\n" +
"\x0eCommonResponse\x12\x12\n" +
@ -2299,7 +2300,18 @@ const file_pb_cron_proto_rawDesc = "" +
"\x1dGetScheduleTaskStatusResponse\x12\x12\n" +
"\x04code\x18\x01 \x01(\x05R\x04code\x12\x18\n" +
"\amessage\x18\x02 \x01(\tR\amessage\x12$\n" +
"\x04data\x18\x03 \x03(\v2\x10.cron.TaskStatusR\x04dataB\bZ\x06./cronb\x06proto3"
"\x04data\x18\x03 \x03(\v2\x10.cron.TaskStatusR\x04data2\xd5\x06\n" +
"\x04Cron\x12Y\n" +
"\x12CreateScheduleTask\x12\x1f.cron.CreateScheduleTaskRequest\x1a .cron.CreateScheduleTaskResponse\"\x00\x12Y\n" +
"\x12UpdateScheduleTask\x12\x1f.cron.UpdateScheduleTaskRequest\x1a .cron.UpdateScheduleTaskResponse\"\x00\x12C\n" +
"\x12DeleteScheduleTask\x12\x15.cron.CommonIDRequest\x1a\x14.cron.CommonResponse\"\x00\x12\\\n" +
"\x13GetListScheduleTask\x12 .cron.GetListScheduleTaskRequest\x1a!.cron.GetListScheduleTaskResponse\"\x00\x12e\n" +
"\x16GetListExecutionRecord\x12#.cron.GetListExecutionRecordRequest\x1a$.cron.GetListExecutionRecordResponse\"\x00\x12e\n" +
"\x16GetListExecutionResult\x12#.cron.GetListExecutionResultRequest\x1a$.cron.GetListExecutionResultResponse\"\x00\x12V\n" +
"\x15GetScheduleTaskStatus\x12\x16.google.protobuf.Empty\x1a#.cron.GetScheduleTaskStatusResponse\"\x00\x12B\n" +
"\x11PauseScheduleTask\x12\x15.cron.CommonIDRequest\x1a\x14.cron.CommonResponse\"\x00\x12B\n" +
"\x11StartScheduleTask\x12\x15.cron.CommonIDRequest\x1a\x14.cron.CommonResponse\"\x00\x12F\n" +
"\x15RepublishScheduleTask\x12\x15.cron.CommonIDRequest\x1a\x14.cron.CommonResponse\"\x00B\bZ\x06./cronb\x06proto3"
var (
file_pb_cron_proto_rawDescOnce sync.Once
@ -2337,6 +2349,7 @@ var file_pb_cron_proto_goTypes = []any{
(*TaskStatus)(nil), // 19: cron.TaskStatus
(*GetScheduleTaskStatusResponse)(nil), // 20: cron.GetScheduleTaskStatusResponse
nil, // 21: cron.GetListScheduleTaskRequest.SortsEntry
(*emptypb.Empty)(nil), // 22: google.protobuf.Empty
}
var file_pb_cron_proto_depIdxs = []int32{
3, // 0: cron.ScheduleTask.task_detail:type_name -> cron.TaskDetail
@ -2354,8 +2367,28 @@ var file_pb_cron_proto_depIdxs = []int32{
5, // 12: cron.GetListExecutionRecordResponse.data:type_name -> cron.ExecutionRecord
6, // 13: cron.GetListExecutionResultResponse.data:type_name -> cron.ExecutionResult
19, // 14: cron.GetScheduleTaskStatusResponse.data:type_name -> cron.TaskStatus
15, // [15:15] is the sub-list for method output_type
15, // [15:15] is the sub-list for method input_type
7, // 15: cron.Cron.CreateScheduleTask:input_type -> cron.CreateScheduleTaskRequest
10, // 16: cron.Cron.UpdateScheduleTask:input_type -> cron.UpdateScheduleTaskRequest
0, // 17: cron.Cron.DeleteScheduleTask:input_type -> cron.CommonIDRequest
13, // 18: cron.Cron.GetListScheduleTask:input_type -> cron.GetListScheduleTaskRequest
15, // 19: cron.Cron.GetListExecutionRecord:input_type -> cron.GetListExecutionRecordRequest
17, // 20: cron.Cron.GetListExecutionResult:input_type -> cron.GetListExecutionResultRequest
22, // 21: cron.Cron.GetScheduleTaskStatus:input_type -> google.protobuf.Empty
0, // 22: cron.Cron.PauseScheduleTask:input_type -> cron.CommonIDRequest
0, // 23: cron.Cron.StartScheduleTask:input_type -> cron.CommonIDRequest
0, // 24: cron.Cron.RepublishScheduleTask:input_type -> cron.CommonIDRequest
9, // 25: cron.Cron.CreateScheduleTask:output_type -> cron.CreateScheduleTaskResponse
12, // 26: cron.Cron.UpdateScheduleTask:output_type -> cron.UpdateScheduleTaskResponse
1, // 27: cron.Cron.DeleteScheduleTask:output_type -> cron.CommonResponse
14, // 28: cron.Cron.GetListScheduleTask:output_type -> cron.GetListScheduleTaskResponse
16, // 29: cron.Cron.GetListExecutionRecord:output_type -> cron.GetListExecutionRecordResponse
18, // 30: cron.Cron.GetListExecutionResult:output_type -> cron.GetListExecutionResultResponse
20, // 31: cron.Cron.GetScheduleTaskStatus:output_type -> cron.GetScheduleTaskStatusResponse
1, // 32: cron.Cron.PauseScheduleTask:output_type -> cron.CommonResponse
1, // 33: cron.Cron.StartScheduleTask:output_type -> cron.CommonResponse
1, // 34: cron.Cron.RepublishScheduleTask:output_type -> cron.CommonResponse
25, // [25:35] is the sub-list for method output_type
15, // [15:25] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
@ -2374,7 +2407,7 @@ func file_pb_cron_proto_init() {
NumEnums: 0,
NumMessages: 22,
NumExtensions: 0,
NumServices: 0,
NumServices: 1,
},
GoTypes: file_pb_cron_proto_goTypes,
DependencyIndexes: file_pb_cron_proto_depIdxs,

View File

@ -7,6 +7,7 @@ import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
_ "google.golang.org/protobuf/types/known/emptypb"
github_com_mwitkow_go_proto_validators "github.com/mwitkow/go-proto-validators"
)

View File

@ -31,13 +31,14 @@ const _ = grpc_go.SupportPackageIsVersion7
type CronClient interface {
CreateScheduleTask(ctx context.Context, in *CreateScheduleTaskRequest, opts ...grpc_go.CallOption) (*CreateScheduleTaskResponse, common.ErrorWithAttachment)
UpdateScheduleTask(ctx context.Context, in *UpdateScheduleTaskRequest, opts ...grpc_go.CallOption) (*UpdateScheduleTaskResponse, common.ErrorWithAttachment)
DeleteScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
GetListScheduleTask(ctx context.Context, in *GetListScheduleTaskRequest, opts ...grpc_go.CallOption) (*GetListScheduleTaskResponse, common.ErrorWithAttachment)
GetListExecutionRecord(ctx context.Context, in *GetListExecutionRecordRequest, opts ...grpc_go.CallOption) (*GetListExecutionRecordResponse, common.ErrorWithAttachment)
GetListExecutionResult(ctx context.Context, in *GetListExecutionResultRequest, opts ...grpc_go.CallOption) (*GetListExecutionResultResponse, common.ErrorWithAttachment)
GetScheduleTaskStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc_go.CallOption) (*GetScheduleTaskStatusResponse, common.ErrorWithAttachment)
PauseScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
StartScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
DeleteScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
GetScheduleTaskStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc_go.CallOption) (*GetScheduleTaskStatusResponse, common.ErrorWithAttachment)
RepublishScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment)
}
type cronClient struct {
@ -47,13 +48,14 @@ type cronClient struct {
type CronClientImpl struct {
CreateScheduleTask func(ctx context.Context, in *CreateScheduleTaskRequest) (*CreateScheduleTaskResponse, error)
UpdateScheduleTask func(ctx context.Context, in *UpdateScheduleTaskRequest) (*UpdateScheduleTaskResponse, error)
DeleteScheduleTask func(ctx context.Context, in *CommonIDRequest) (*CommonResponse, error)
GetListScheduleTask func(ctx context.Context, in *GetListScheduleTaskRequest) (*GetListScheduleTaskResponse, error)
GetListExecutionRecord func(ctx context.Context, in *GetListExecutionRecordRequest) (*GetListExecutionRecordResponse, error)
GetListExecutionResult func(ctx context.Context, in *GetListExecutionResultRequest) (*GetListExecutionResultResponse, error)
GetScheduleTaskStatus func(ctx context.Context, in *emptypb.Empty) (*GetScheduleTaskStatusResponse, error)
PauseScheduleTask func(ctx context.Context, in *CommonIDRequest) (*CommonResponse, error)
StartScheduleTask func(ctx context.Context, in *CommonIDRequest) (*CommonResponse, error)
DeleteScheduleTask func(ctx context.Context, in *CommonIDRequest) (*CommonResponse, error)
GetScheduleTaskStatus func(ctx context.Context, in *emptypb.Empty) (*GetScheduleTaskStatusResponse, error)
RepublishScheduleTask func(ctx context.Context, in *CommonIDRequest) (*CommonResponse, error)
}
func (c *CronClientImpl) GetDubboStub(cc *triple.TripleConn) CronClient {
@ -80,6 +82,11 @@ func (c *cronClient) UpdateScheduleTask(ctx context.Context, in *UpdateScheduleT
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/UpdateScheduleTask", in, out)
}
func (c *cronClient) DeleteScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment) {
out := new(CommonResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/DeleteScheduleTask", in, out)
}
func (c *cronClient) GetListScheduleTask(ctx context.Context, in *GetListScheduleTaskRequest, opts ...grpc_go.CallOption) (*GetListScheduleTaskResponse, common.ErrorWithAttachment) {
out := new(GetListScheduleTaskResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
@ -98,6 +105,12 @@ func (c *cronClient) GetListExecutionResult(ctx context.Context, in *GetListExec
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/GetListExecutionResult", in, out)
}
func (c *cronClient) GetScheduleTaskStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc_go.CallOption) (*GetScheduleTaskStatusResponse, common.ErrorWithAttachment) {
out := new(GetScheduleTaskStatusResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/GetScheduleTaskStatus", in, out)
}
func (c *cronClient) PauseScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment) {
out := new(CommonResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
@ -110,16 +123,10 @@ func (c *cronClient) StartScheduleTask(ctx context.Context, in *CommonIDRequest,
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/StartScheduleTask", in, out)
}
func (c *cronClient) DeleteScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment) {
func (c *cronClient) RepublishScheduleTask(ctx context.Context, in *CommonIDRequest, opts ...grpc_go.CallOption) (*CommonResponse, common.ErrorWithAttachment) {
out := new(CommonResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/DeleteScheduleTask", in, out)
}
func (c *cronClient) GetScheduleTaskStatus(ctx context.Context, in *emptypb.Empty, opts ...grpc_go.CallOption) (*GetScheduleTaskStatusResponse, common.ErrorWithAttachment) {
out := new(GetScheduleTaskStatusResponse)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/GetScheduleTaskStatus", in, out)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/RepublishScheduleTask", in, out)
}
// CronServer is the server API for Cron service.
@ -128,13 +135,14 @@ func (c *cronClient) GetScheduleTaskStatus(ctx context.Context, in *emptypb.Empt
type CronServer interface {
CreateScheduleTask(context.Context, *CreateScheduleTaskRequest) (*CreateScheduleTaskResponse, error)
UpdateScheduleTask(context.Context, *UpdateScheduleTaskRequest) (*UpdateScheduleTaskResponse, error)
DeleteScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error)
GetListScheduleTask(context.Context, *GetListScheduleTaskRequest) (*GetListScheduleTaskResponse, error)
GetListExecutionRecord(context.Context, *GetListExecutionRecordRequest) (*GetListExecutionRecordResponse, error)
GetListExecutionResult(context.Context, *GetListExecutionResultRequest) (*GetListExecutionResultResponse, error)
GetScheduleTaskStatus(context.Context, *emptypb.Empty) (*GetScheduleTaskStatusResponse, error)
PauseScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error)
StartScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error)
DeleteScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error)
GetScheduleTaskStatus(context.Context, *emptypb.Empty) (*GetScheduleTaskStatusResponse, error)
RepublishScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error)
mustEmbedUnimplementedCronServer()
}
@ -149,6 +157,9 @@ func (UnimplementedCronServer) CreateScheduleTask(context.Context, *CreateSchedu
func (UnimplementedCronServer) UpdateScheduleTask(context.Context, *UpdateScheduleTaskRequest) (*UpdateScheduleTaskResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateScheduleTask not implemented")
}
func (UnimplementedCronServer) DeleteScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteScheduleTask not implemented")
}
func (UnimplementedCronServer) GetListScheduleTask(context.Context, *GetListScheduleTaskRequest) (*GetListScheduleTaskResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetListScheduleTask not implemented")
}
@ -158,17 +169,17 @@ func (UnimplementedCronServer) GetListExecutionRecord(context.Context, *GetListE
func (UnimplementedCronServer) GetListExecutionResult(context.Context, *GetListExecutionResultRequest) (*GetListExecutionResultResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetListExecutionResult not implemented")
}
func (UnimplementedCronServer) GetScheduleTaskStatus(context.Context, *emptypb.Empty) (*GetScheduleTaskStatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetScheduleTaskStatus not implemented")
}
func (UnimplementedCronServer) PauseScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method PauseScheduleTask not implemented")
}
func (UnimplementedCronServer) StartScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method StartScheduleTask not implemented")
}
func (UnimplementedCronServer) DeleteScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeleteScheduleTask not implemented")
}
func (UnimplementedCronServer) GetScheduleTaskStatus(context.Context, *emptypb.Empty) (*GetScheduleTaskStatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetScheduleTaskStatus not implemented")
func (UnimplementedCronServer) RepublishScheduleTask(context.Context, *CommonIDRequest) (*CommonResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RepublishScheduleTask not implemented")
}
func (s *UnimplementedCronServer) XXX_SetProxyImpl(impl protocol.Invoker) {
s.proxyImpl = impl
@ -256,6 +267,35 @@ func _Cron_UpdateScheduleTask_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler)
}
func _Cron_DeleteScheduleTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(CommonIDRequest)
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("DeleteScheduleTask", 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 _Cron_GetListScheduleTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(GetListScheduleTaskRequest)
if err := dec(in); err != nil {
@ -343,6 +383,35 @@ func _Cron_GetListExecutionResult_Handler(srv interface{}, ctx context.Context,
return interceptor(ctx, in, info, handler)
}
func _Cron_GetScheduleTaskStatus_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("GetScheduleTaskStatus", 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 _Cron_PauseScheduleTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(CommonIDRequest)
if err := dec(in); err != nil {
@ -401,7 +470,7 @@ func _Cron_StartScheduleTask_Handler(srv interface{}, ctx context.Context, dec f
return interceptor(ctx, in, info, handler)
}
func _Cron_DeleteScheduleTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
func _Cron_RepublishScheduleTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(CommonIDRequest)
if err := dec(in); err != nil {
return nil, err
@ -414,36 +483,7 @@ func _Cron_DeleteScheduleTask_Handler(srv interface{}, ctx context.Context, dec
for k, v := range md {
invAttachment[k] = v
}
invo := invocation.NewRPCInvocation("DeleteScheduleTask", 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 _Cron_GetScheduleTaskStatus_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("GetScheduleTaskStatus", args, invAttachment)
invo := invocation.NewRPCInvocation("RepublishScheduleTask", args, invAttachment)
if interceptor == nil {
result := base.XXX_GetProxyImpl().Invoke(ctx, invo)
return result, result.Error()
@ -474,6 +514,10 @@ var Cron_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "UpdateScheduleTask",
Handler: _Cron_UpdateScheduleTask_Handler,
},
{
MethodName: "DeleteScheduleTask",
Handler: _Cron_DeleteScheduleTask_Handler,
},
{
MethodName: "GetListScheduleTask",
Handler: _Cron_GetListScheduleTask_Handler,
@ -486,6 +530,10 @@ var Cron_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "GetListExecutionResult",
Handler: _Cron_GetListExecutionResult_Handler,
},
{
MethodName: "GetScheduleTaskStatus",
Handler: _Cron_GetScheduleTaskStatus_Handler,
},
{
MethodName: "PauseScheduleTask",
Handler: _Cron_PauseScheduleTask_Handler,
@ -495,12 +543,8 @@ var Cron_ServiceDesc = grpc_go.ServiceDesc{
Handler: _Cron_StartScheduleTask_Handler,
},
{
MethodName: "DeleteScheduleTask",
Handler: _Cron_DeleteScheduleTask_Handler,
},
{
MethodName: "GetScheduleTaskStatus",
Handler: _Cron_GetScheduleTaskStatus_Handler,
MethodName: "RepublishScheduleTask",
Handler: _Cron_RepublishScheduleTask_Handler,
},
},
Streams: []grpc_go.StreamDesc{},

View File

@ -2049,6 +2049,116 @@ func (x *SecurityScanResp) GetProblemTimeFrame() string {
return ""
}
type SecurityScanByTextReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text"` // 文本
}
func (x *SecurityScanByTextReq) Reset() {
*x = SecurityScanByTextReq{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[31]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SecurityScanByTextReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SecurityScanByTextReq) ProtoMessage() {}
func (x *SecurityScanByTextReq) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[31]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SecurityScanByTextReq.ProtoReflect.Descriptor instead.
func (*SecurityScanByTextReq) Descriptor() ([]byte, []int) {
return file_files_proto_rawDescGZIP(), []int{31}
}
func (x *SecurityScanByTextReq) GetText() string {
if x != nil {
return x.Text
}
return ""
}
type SecurityScanByTextResp struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
SecurityStatus string `protobuf:"bytes,1,opt,name=securityStatus,proto3" json:"securityStatus"` // 安全状态
Describe string `protobuf:"bytes,2,opt,name=describe,proto3" json:"describe"` // 描述
ProblemText string `protobuf:"bytes,3,opt,name=problemText,proto3" json:"problemText"` // 问题文本
}
func (x *SecurityScanByTextResp) Reset() {
*x = SecurityScanByTextResp{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[32]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SecurityScanByTextResp) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SecurityScanByTextResp) ProtoMessage() {}
func (x *SecurityScanByTextResp) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[32]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SecurityScanByTextResp.ProtoReflect.Descriptor instead.
func (*SecurityScanByTextResp) Descriptor() ([]byte, []int) {
return file_files_proto_rawDescGZIP(), []int{32}
}
func (x *SecurityScanByTextResp) GetSecurityStatus() string {
if x != nil {
return x.SecurityStatus
}
return ""
}
func (x *SecurityScanByTextResp) GetDescribe() string {
if x != nil {
return x.Describe
}
return ""
}
func (x *SecurityScanByTextResp) GetProblemText() string {
if x != nil {
return x.ProblemText
}
return ""
}
type UpdateFileSecurityStatusReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -2060,7 +2170,7 @@ type UpdateFileSecurityStatusReq struct {
func (x *UpdateFileSecurityStatusReq) Reset() {
*x = UpdateFileSecurityStatusReq{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[31]
mi := &file_files_proto_msgTypes[33]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2073,7 +2183,7 @@ func (x *UpdateFileSecurityStatusReq) String() string {
func (*UpdateFileSecurityStatusReq) ProtoMessage() {}
func (x *UpdateFileSecurityStatusReq) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[31]
mi := &file_files_proto_msgTypes[33]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2086,7 +2196,7 @@ func (x *UpdateFileSecurityStatusReq) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdateFileSecurityStatusReq.ProtoReflect.Descriptor instead.
func (*UpdateFileSecurityStatusReq) Descriptor() ([]byte, []int) {
return file_files_proto_rawDescGZIP(), []int{31}
return file_files_proto_rawDescGZIP(), []int{33}
}
func (x *UpdateFileSecurityStatusReq) GetSecurityStatusData() []*SecurityStatusData {
@ -2105,7 +2215,7 @@ type UpdateFileSecurityStatusResp struct {
func (x *UpdateFileSecurityStatusResp) Reset() {
*x = UpdateFileSecurityStatusResp{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[32]
mi := &file_files_proto_msgTypes[34]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2118,7 +2228,7 @@ func (x *UpdateFileSecurityStatusResp) String() string {
func (*UpdateFileSecurityStatusResp) ProtoMessage() {}
func (x *UpdateFileSecurityStatusResp) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[32]
mi := &file_files_proto_msgTypes[34]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2131,7 +2241,7 @@ func (x *UpdateFileSecurityStatusResp) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdateFileSecurityStatusResp.ProtoReflect.Descriptor instead.
func (*UpdateFileSecurityStatusResp) Descriptor() ([]byte, []int) {
return file_files_proto_rawDescGZIP(), []int{32}
return file_files_proto_rawDescGZIP(), []int{34}
}
type ManualAntiReq struct {
@ -2145,7 +2255,7 @@ type ManualAntiReq struct {
func (x *ManualAntiReq) Reset() {
*x = ManualAntiReq{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[33]
mi := &file_files_proto_msgTypes[35]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2158,7 +2268,7 @@ func (x *ManualAntiReq) String() string {
func (*ManualAntiReq) ProtoMessage() {}
func (x *ManualAntiReq) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[33]
mi := &file_files_proto_msgTypes[35]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2171,7 +2281,7 @@ func (x *ManualAntiReq) ProtoReflect() protoreflect.Message {
// Deprecated: Use ManualAntiReq.ProtoReflect.Descriptor instead.
func (*ManualAntiReq) Descriptor() ([]byte, []int) {
return file_files_proto_rawDescGZIP(), []int{33}
return file_files_proto_rawDescGZIP(), []int{35}
}
func (x *ManualAntiReq) GetSecurityStatusData() []*SecurityStatusData {
@ -2190,7 +2300,7 @@ type ManualAntiResp struct {
func (x *ManualAntiResp) Reset() {
*x = ManualAntiResp{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[34]
mi := &file_files_proto_msgTypes[36]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2203,7 +2313,7 @@ func (x *ManualAntiResp) String() string {
func (*ManualAntiResp) ProtoMessage() {}
func (x *ManualAntiResp) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[34]
mi := &file_files_proto_msgTypes[36]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2216,7 +2326,7 @@ func (x *ManualAntiResp) ProtoReflect() protoreflect.Message {
// Deprecated: Use ManualAntiResp.ProtoReflect.Descriptor instead.
func (*ManualAntiResp) Descriptor() ([]byte, []int) {
return file_files_proto_rawDescGZIP(), []int{34}
return file_files_proto_rawDescGZIP(), []int{36}
}
type GetFileSecurityStatusReq struct {
@ -2231,7 +2341,7 @@ type GetFileSecurityStatusReq struct {
func (x *GetFileSecurityStatusReq) Reset() {
*x = GetFileSecurityStatusReq{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[35]
mi := &file_files_proto_msgTypes[37]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2244,7 +2354,7 @@ func (x *GetFileSecurityStatusReq) String() string {
func (*GetFileSecurityStatusReq) ProtoMessage() {}
func (x *GetFileSecurityStatusReq) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[35]
mi := &file_files_proto_msgTypes[37]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2257,7 +2367,7 @@ func (x *GetFileSecurityStatusReq) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetFileSecurityStatusReq.ProtoReflect.Descriptor instead.
func (*GetFileSecurityStatusReq) Descriptor() ([]byte, []int) {
return file_files_proto_rawDescGZIP(), []int{35}
return file_files_proto_rawDescGZIP(), []int{37}
}
func (x *GetFileSecurityStatusReq) GetUrl() string {
@ -2287,7 +2397,7 @@ type GetFileSecurityStatusResp struct {
func (x *GetFileSecurityStatusResp) Reset() {
*x = GetFileSecurityStatusResp{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[36]
mi := &file_files_proto_msgTypes[38]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2300,7 +2410,7 @@ func (x *GetFileSecurityStatusResp) String() string {
func (*GetFileSecurityStatusResp) ProtoMessage() {}
func (x *GetFileSecurityStatusResp) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[36]
mi := &file_files_proto_msgTypes[38]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2313,7 +2423,7 @@ func (x *GetFileSecurityStatusResp) ProtoReflect() protoreflect.Message {
// Deprecated: Use GetFileSecurityStatusResp.ProtoReflect.Descriptor instead.
func (*GetFileSecurityStatusResp) Descriptor() ([]byte, []int) {
return file_files_proto_rawDescGZIP(), []int{36}
return file_files_proto_rawDescGZIP(), []int{38}
}
func (x *GetFileSecurityStatusResp) GetSecurityStatus() string {
@ -2352,7 +2462,7 @@ type SearchResp_Nested struct {
func (x *SearchResp_Nested) Reset() {
*x = SearchResp_Nested{}
if protoimpl.UnsafeEnabled {
mi := &file_files_proto_msgTypes[37]
mi := &file_files_proto_msgTypes[39]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@ -2365,7 +2475,7 @@ func (x *SearchResp_Nested) String() string {
func (*SearchResp_Nested) ProtoMessage() {}
func (x *SearchResp_Nested) ProtoReflect() protoreflect.Message {
mi := &file_files_proto_msgTypes[37]
mi := &file_files_proto_msgTypes[39]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@ -2632,102 +2742,118 @@ var file_files_proto_rawDesc = []byte{
0x08, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x70, 0x72, 0x6f,
0x62, 0x6c, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x22, 0x68, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46,
0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x65, 0x71, 0x12, 0x49, 0x0a, 0x12, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x19, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x52, 0x12, 0x73, 0x65, 0x63,
0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x22,
0x1e, 0x0a, 0x1c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63,
0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22,
0x5a, 0x0a, 0x0d, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69, 0x52, 0x65, 0x71,
0x12, 0x49, 0x0a, 0x12, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x52, 0x12, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x22, 0x10, 0x0a, 0x0e, 0x4d,
0x61, 0x6e, 0x75, 0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69, 0x52, 0x65, 0x73, 0x70, 0x22, 0x48, 0x0a,
0x18, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x66,
0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66,
0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x46,
0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73,
0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a,
0x08, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x70, 0x72, 0x6f,
0x62, 0x6c, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x32, 0x90, 0x08, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x31,
0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x12, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x46,
0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x66, 0x69, 0x6c,
0x65, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22,
0x00, 0x12, 0x31, 0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65,
0x73, 0x70, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x10,
0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71,
0x1a, 0x11, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52,
0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12,
0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65,
0x71, 0x1a, 0x11, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
0x12, 0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52,
0x65, 0x71, 0x1a, 0x11, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63,
0x68, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x55, 0x70, 0x6c, 0x6f, 0x61,
0x64, 0x12, 0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64,
0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x6c, 0x6f,
0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x09, 0x54, 0x75, 0x73, 0x43,
0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x54, 0x75,
0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x66, 0x69, 0x6c,
0x65, 0x73, 0x2e, 0x54, 0x75, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
0x22, 0x00, 0x12, 0x38, 0x0a, 0x09, 0x54, 0x75, 0x73, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12,
0x13, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x73, 0x55, 0x70, 0x6c, 0x6f, 0x61,
0x64, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x73,
0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x11,
0x52, 0x65, 0x73, 0x75, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65,
0x72, 0x12, 0x1b, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x1c,
0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x61, 0x62, 0x6c, 0x65,
0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x32,
0x0a, 0x07, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x12, 0x11, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70,
0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x2e, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x11,
0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73,
0x70, 0x22, 0x00, 0x12, 0x40, 0x0a, 0x0b, 0x44, 0x69, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f,
0x61, 0x64, 0x12, 0x15, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x44, 0x6f,
0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x2e, 0x44, 0x69, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73,
0x70, 0x22, 0x00, 0x30, 0x01, 0x12, 0x2c, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0f,
0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x1a,
0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73,
0x70, 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53,
0x63, 0x61, 0x6e, 0x12, 0x16, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75,
0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x61, 0x6e,
0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x12, 0x22, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x3b, 0x0a,
0x0a, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69, 0x12, 0x14, 0x2e, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69, 0x52, 0x65,
0x71, 0x1a, 0x15, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c,
0x41, 0x6e, 0x74, 0x69, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x15, 0x47, 0x65,
0x46, 0x72, 0x61, 0x6d, 0x65, 0x22, 0x2b, 0x0a, 0x15, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x53, 0x63, 0x61, 0x6e, 0x42, 0x79, 0x54, 0x65, 0x78, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12,
0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65,
0x78, 0x74, 0x22, 0x7e, 0x0a, 0x16, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63,
0x61, 0x6e, 0x42, 0x79, 0x54, 0x65, 0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x26, 0x0a, 0x0e,
0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65,
0x12, 0x20, 0x0a, 0x0b, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x54, 0x65, 0x78, 0x74, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x54, 0x65,
0x78, 0x74, 0x22, 0x68, 0x0a, 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65,
0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65,
0x71, 0x12, 0x49, 0x0a, 0x12, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x52, 0x12, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69,
0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x22, 0x1e, 0x0a, 0x1c,
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69,
0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x5a, 0x0a, 0x0d,
0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69, 0x52, 0x65, 0x71, 0x12, 0x49, 0x0a,
0x12, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44,
0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
0x44, 0x61, 0x74, 0x61, 0x52, 0x12, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x22, 0x10, 0x0a, 0x0e, 0x4d, 0x61, 0x6e, 0x75,
0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69, 0x52, 0x65, 0x73, 0x70, 0x22, 0x48, 0x0a, 0x18, 0x47, 0x65,
0x74, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x46,
0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x52, 0x65, 0x71, 0x1a, 0x20, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x47, 0x65, 0x74,
0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x3b, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65,
0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65,
0x4e, 0x61, 0x6d, 0x65, 0x22, 0x8b, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65,
0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65,
0x73, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x63, 0x75,
0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65,
0x6d, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x72, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
0x52, 0x10, 0x70, 0x72, 0x6f, 0x62, 0x6c, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x46, 0x72, 0x61,
0x6d, 0x65, 0x32, 0xe5, 0x08, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x31, 0x0a, 0x04, 0x4c,
0x69, 0x73, 0x74, 0x12, 0x12, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65,
0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e,
0x46, 0x69, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x31,
0x0a, 0x04, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x46,
0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x66, 0x69, 0x6c,
0x65, 0x73, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x22,
0x00, 0x12, 0x2f, 0x0a, 0x06, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x10, 0x2e, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70,
0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x10, 0x2e, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x11,
0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73,
0x70, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x10, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x71, 0x1a,
0x11, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
0x73, 0x70, 0x22, 0x00, 0x12, 0x2f, 0x0a, 0x06, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x10,
0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71,
0x1a, 0x11, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52,
0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x09, 0x54, 0x75, 0x73, 0x43, 0x72, 0x65, 0x61,
0x74, 0x65, 0x12, 0x13, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x73, 0x43, 0x72,
0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e,
0x54, 0x75, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12,
0x38, 0x0a, 0x09, 0x54, 0x75, 0x73, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x13, 0x2e, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x73, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65,
0x71, 0x1a, 0x14, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x73, 0x55, 0x70, 0x6c,
0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x11, 0x52, 0x65, 0x73,
0x75, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x1b,
0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x61, 0x62, 0x6c, 0x65,
0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x72, 0x61,
0x6e, 0x73, 0x66, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x32, 0x0a, 0x07, 0x50,
0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x12, 0x11, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x50,
0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x2e, 0x50, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12,
0x2f, 0x0a, 0x06, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x11, 0x2e, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00,
0x12, 0x40, 0x0a, 0x0b, 0x44, 0x69, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12,
0x15, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x44, 0x69, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c,
0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x44,
0x69, 0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00,
0x30, 0x01, 0x12, 0x2c, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x0f, 0x2e, 0x66, 0x69,
0x6c, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x10, 0x2e, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00,
0x12, 0x41, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x61, 0x6e,
0x12, 0x16, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74,
0x79, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73,
0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x61, 0x6e, 0x52, 0x65, 0x73,
0x70, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x12, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53,
0x63, 0x61, 0x6e, 0x42, 0x79, 0x54, 0x65, 0x78, 0x74, 0x12, 0x1c, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x61, 0x6e, 0x42, 0x79,
0x54, 0x65, 0x78, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x1d, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e,
0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x63, 0x61, 0x6e, 0x42, 0x79, 0x54, 0x65,
0x78, 0x74, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x12, 0x22, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x55, 0x70, 0x64,
0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53,
0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x23, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72,
0x69, 0x74, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12,
0x3b, 0x0a, 0x0a, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69, 0x12, 0x14, 0x2e,
0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69,
0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x6e, 0x75,
0x61, 0x6c, 0x41, 0x6e, 0x74, 0x69, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x15,
0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53,
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x47, 0x65,
0x74, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x20, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0x47,
0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f,
0x3b, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -2742,7 +2868,7 @@ func file_files_proto_rawDescGZIP() []byte {
return file_files_proto_rawDescData
}
var file_files_proto_msgTypes = make([]protoimpl.MessageInfo, 38)
var file_files_proto_msgTypes = make([]protoimpl.MessageInfo, 40)
var file_files_proto_goTypes = []interface{}{
(*FileListReq)(nil), // 0: files.FileListReq
(*Items)(nil), // 1: files.Items
@ -2775,19 +2901,21 @@ var file_files_proto_goTypes = []interface{}{
(*SecurityStatusData)(nil), // 28: files.SecurityStatusData
(*SecurityScanReq)(nil), // 29: files.SecurityScanReq
(*SecurityScanResp)(nil), // 30: files.SecurityScanResp
(*UpdateFileSecurityStatusReq)(nil), // 31: files.UpdateFileSecurityStatusReq
(*UpdateFileSecurityStatusResp)(nil), // 32: files.UpdateFileSecurityStatusResp
(*ManualAntiReq)(nil), // 33: files.ManualAntiReq
(*ManualAntiResp)(nil), // 34: files.ManualAntiResp
(*GetFileSecurityStatusReq)(nil), // 35: files.GetFileSecurityStatusReq
(*GetFileSecurityStatusResp)(nil), // 36: files.GetFileSecurityStatusResp
(*SearchResp_Nested)(nil), // 37: files.searchResp.Nested
(*SecurityScanByTextReq)(nil), // 31: files.SecurityScanByTextReq
(*SecurityScanByTextResp)(nil), // 32: files.SecurityScanByTextResp
(*UpdateFileSecurityStatusReq)(nil), // 33: files.UpdateFileSecurityStatusReq
(*UpdateFileSecurityStatusResp)(nil), // 34: files.UpdateFileSecurityStatusResp
(*ManualAntiReq)(nil), // 35: files.ManualAntiReq
(*ManualAntiResp)(nil), // 36: files.ManualAntiResp
(*GetFileSecurityStatusReq)(nil), // 37: files.GetFileSecurityStatusReq
(*GetFileSecurityStatusResp)(nil), // 38: files.GetFileSecurityStatusResp
(*SearchResp_Nested)(nil), // 39: files.searchResp.Nested
}
var file_files_proto_depIdxs = []int32{
2, // 0: files.FileListReq.sorting:type_name -> files.Sorting
1, // 1: files.FileListResp.items:type_name -> files.Items
2, // 2: files.FileListResp.sorting:type_name -> files.Sorting
37, // 3: files.searchResp.items:type_name -> files.searchResp.Nested
39, // 3: files.searchResp.items:type_name -> files.searchResp.Nested
28, // 4: files.UpdateFileSecurityStatusReq.securityStatusData:type_name -> files.SecurityStatusData
28, // 5: files.ManualAntiReq.securityStatusData:type_name -> files.SecurityStatusData
0, // 6: files.File.List:input_type -> files.FileListReq
@ -2804,28 +2932,30 @@ var file_files_proto_depIdxs = []int32{
24, // 17: files.File.DirDownload:input_type -> files.DirDownloadReq
26, // 18: files.File.Usage:input_type -> files.UsageReq
29, // 19: files.File.SecurityScan:input_type -> files.SecurityScanReq
31, // 20: files.File.UpdateFileSecurityStatus:input_type -> files.UpdateFileSecurityStatusReq
33, // 21: files.File.ManualAnti:input_type -> files.ManualAntiReq
35, // 22: files.File.GetFileSecurityStatus:input_type -> files.GetFileSecurityStatusReq
3, // 23: files.File.List:output_type -> files.FileListResp
19, // 24: files.File.Info:output_type -> files.FileInfoResp
5, // 25: files.File.Create:output_type -> files.CreateResp
7, // 26: files.File.Delete:output_type -> files.DeleteResp
11, // 27: files.File.Search:output_type -> files.searchResp
9, // 28: files.File.Upload:output_type -> files.UploadResp
13, // 29: files.File.TusCreate:output_type -> files.TusCreateResp
15, // 30: files.File.TusUpload:output_type -> files.TusUploadResp
17, // 31: files.File.ResumableTransfer:output_type -> files.ResumableTransferResp
21, // 32: files.File.Preview:output_type -> files.PreviewResp
23, // 33: files.File.Action:output_type -> files.ActionResp
25, // 34: files.File.DirDownload:output_type -> files.DirDownloadResp
27, // 35: files.File.Usage:output_type -> files.UsageResp
30, // 36: files.File.SecurityScan:output_type -> files.SecurityScanResp
32, // 37: files.File.UpdateFileSecurityStatus:output_type -> files.UpdateFileSecurityStatusResp
34, // 38: files.File.ManualAnti:output_type -> files.ManualAntiResp
36, // 39: files.File.GetFileSecurityStatus:output_type -> files.GetFileSecurityStatusResp
23, // [23:40] is the sub-list for method output_type
6, // [6:23] is the sub-list for method input_type
31, // 20: files.File.SecurityScanByText:input_type -> files.SecurityScanByTextReq
33, // 21: files.File.UpdateFileSecurityStatus:input_type -> files.UpdateFileSecurityStatusReq
35, // 22: files.File.ManualAnti:input_type -> files.ManualAntiReq
37, // 23: files.File.GetFileSecurityStatus:input_type -> files.GetFileSecurityStatusReq
3, // 24: files.File.List:output_type -> files.FileListResp
19, // 25: files.File.Info:output_type -> files.FileInfoResp
5, // 26: files.File.Create:output_type -> files.CreateResp
7, // 27: files.File.Delete:output_type -> files.DeleteResp
11, // 28: files.File.Search:output_type -> files.searchResp
9, // 29: files.File.Upload:output_type -> files.UploadResp
13, // 30: files.File.TusCreate:output_type -> files.TusCreateResp
15, // 31: files.File.TusUpload:output_type -> files.TusUploadResp
17, // 32: files.File.ResumableTransfer:output_type -> files.ResumableTransferResp
21, // 33: files.File.Preview:output_type -> files.PreviewResp
23, // 34: files.File.Action:output_type -> files.ActionResp
25, // 35: files.File.DirDownload:output_type -> files.DirDownloadResp
27, // 36: files.File.Usage:output_type -> files.UsageResp
30, // 37: files.File.SecurityScan:output_type -> files.SecurityScanResp
32, // 38: files.File.SecurityScanByText:output_type -> files.SecurityScanByTextResp
34, // 39: files.File.UpdateFileSecurityStatus:output_type -> files.UpdateFileSecurityStatusResp
36, // 40: files.File.ManualAnti:output_type -> files.ManualAntiResp
38, // 41: files.File.GetFileSecurityStatus:output_type -> files.GetFileSecurityStatusResp
24, // [24:42] is the sub-list for method output_type
6, // [6:24] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
@ -3210,7 +3340,7 @@ func file_files_proto_init() {
}
}
file_files_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateFileSecurityStatusReq); i {
switch v := v.(*SecurityScanByTextReq); i {
case 0:
return &v.state
case 1:
@ -3222,7 +3352,7 @@ func file_files_proto_init() {
}
}
file_files_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateFileSecurityStatusResp); i {
switch v := v.(*SecurityScanByTextResp); i {
case 0:
return &v.state
case 1:
@ -3234,7 +3364,7 @@ func file_files_proto_init() {
}
}
file_files_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ManualAntiReq); i {
switch v := v.(*UpdateFileSecurityStatusReq); i {
case 0:
return &v.state
case 1:
@ -3246,7 +3376,7 @@ func file_files_proto_init() {
}
}
file_files_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ManualAntiResp); i {
switch v := v.(*UpdateFileSecurityStatusResp); i {
case 0:
return &v.state
case 1:
@ -3258,7 +3388,7 @@ func file_files_proto_init() {
}
}
file_files_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetFileSecurityStatusReq); i {
switch v := v.(*ManualAntiReq); i {
case 0:
return &v.state
case 1:
@ -3270,7 +3400,7 @@ func file_files_proto_init() {
}
}
file_files_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetFileSecurityStatusResp); i {
switch v := v.(*ManualAntiResp); i {
case 0:
return &v.state
case 1:
@ -3282,6 +3412,30 @@ func file_files_proto_init() {
}
}
file_files_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetFileSecurityStatusReq); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_files_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*GetFileSecurityStatusResp); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_files_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SearchResp_Nested); i {
case 0:
return &v.state
@ -3300,7 +3454,7 @@ func file_files_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_files_proto_rawDesc,
NumEnums: 0,
NumMessages: 38,
NumMessages: 40,
NumExtensions: 0,
NumServices: 1,
},

View File

@ -135,6 +135,12 @@ func (this *SecurityScanReq) Validate() error {
func (this *SecurityScanResp) Validate() error {
return nil
}
func (this *SecurityScanByTextReq) Validate() error {
return nil
}
func (this *SecurityScanByTextResp) Validate() error {
return nil
}
func (this *UpdateFileSecurityStatusReq) Validate() error {
for _, item := range this.SecurityStatusData {
if item != nil {

View File

@ -43,6 +43,7 @@ type FileClient interface {
DirDownload(ctx context.Context, in *DirDownloadReq, opts ...grpc_go.CallOption) (File_DirDownloadClient, error)
Usage(ctx context.Context, in *UsageReq, opts ...grpc_go.CallOption) (*UsageResp, common.ErrorWithAttachment)
SecurityScan(ctx context.Context, in *SecurityScanReq, opts ...grpc_go.CallOption) (*SecurityScanResp, common.ErrorWithAttachment)
SecurityScanByText(ctx context.Context, in *SecurityScanByTextReq, opts ...grpc_go.CallOption) (*SecurityScanByTextResp, common.ErrorWithAttachment)
UpdateFileSecurityStatus(ctx context.Context, in *UpdateFileSecurityStatusReq, opts ...grpc_go.CallOption) (*UpdateFileSecurityStatusResp, common.ErrorWithAttachment)
ManualAnti(ctx context.Context, in *ManualAntiReq, opts ...grpc_go.CallOption) (*ManualAntiResp, common.ErrorWithAttachment)
GetFileSecurityStatus(ctx context.Context, in *GetFileSecurityStatusReq, opts ...grpc_go.CallOption) (*GetFileSecurityStatusResp, common.ErrorWithAttachment)
@ -67,6 +68,7 @@ type FileClientImpl struct {
DirDownload func(ctx context.Context, in *DirDownloadReq) (File_DirDownloadClient, error)
Usage func(ctx context.Context, in *UsageReq) (*UsageResp, error)
SecurityScan func(ctx context.Context, in *SecurityScanReq) (*SecurityScanResp, error)
SecurityScanByText func(ctx context.Context, in *SecurityScanByTextReq) (*SecurityScanByTextResp, error)
UpdateFileSecurityStatus func(ctx context.Context, in *UpdateFileSecurityStatusReq) (*UpdateFileSecurityStatusResp, error)
ManualAnti func(ctx context.Context, in *ManualAntiReq) (*ManualAntiResp, error)
GetFileSecurityStatus func(ctx context.Context, in *GetFileSecurityStatusReq) (*GetFileSecurityStatusResp, error)
@ -195,6 +197,12 @@ func (c *fileClient) SecurityScan(ctx context.Context, in *SecurityScanReq, opts
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/SecurityScan", in, out)
}
func (c *fileClient) SecurityScanByText(ctx context.Context, in *SecurityScanByTextReq, opts ...grpc_go.CallOption) (*SecurityScanByTextResp, common.ErrorWithAttachment) {
out := new(SecurityScanByTextResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
return out, c.cc.Invoke(ctx, "/"+interfaceKey+"/SecurityScanByText", in, out)
}
func (c *fileClient) UpdateFileSecurityStatus(ctx context.Context, in *UpdateFileSecurityStatusReq, opts ...grpc_go.CallOption) (*UpdateFileSecurityStatusResp, common.ErrorWithAttachment) {
out := new(UpdateFileSecurityStatusResp)
interfaceKey := ctx.Value(constant.InterfaceKey).(string)
@ -231,6 +239,7 @@ type FileServer interface {
DirDownload(*DirDownloadReq, File_DirDownloadServer) error
Usage(context.Context, *UsageReq) (*UsageResp, error)
SecurityScan(context.Context, *SecurityScanReq) (*SecurityScanResp, error)
SecurityScanByText(context.Context, *SecurityScanByTextReq) (*SecurityScanByTextResp, error)
UpdateFileSecurityStatus(context.Context, *UpdateFileSecurityStatusReq) (*UpdateFileSecurityStatusResp, error)
ManualAnti(context.Context, *ManualAntiReq) (*ManualAntiResp, error)
GetFileSecurityStatus(context.Context, *GetFileSecurityStatusReq) (*GetFileSecurityStatusResp, error)
@ -284,6 +293,9 @@ func (UnimplementedFileServer) Usage(context.Context, *UsageReq) (*UsageResp, er
func (UnimplementedFileServer) SecurityScan(context.Context, *SecurityScanReq) (*SecurityScanResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method SecurityScan not implemented")
}
func (UnimplementedFileServer) SecurityScanByText(context.Context, *SecurityScanByTextReq) (*SecurityScanByTextResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method SecurityScanByText not implemented")
}
func (UnimplementedFileServer) UpdateFileSecurityStatus(context.Context, *UpdateFileSecurityStatusReq) (*UpdateFileSecurityStatusResp, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateFileSecurityStatus not implemented")
}
@ -725,6 +737,35 @@ func _File_SecurityScan_Handler(srv interface{}, ctx context.Context, dec func(i
return interceptor(ctx, in, info, handler)
}
func _File_SecurityScanByText_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(SecurityScanByTextReq)
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("SecurityScanByText", 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 _File_UpdateFileSecurityStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc_go.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateFileSecurityStatusReq)
if err := dec(in); err != nil {
@ -871,6 +912,10 @@ var File_ServiceDesc = grpc_go.ServiceDesc{
MethodName: "SecurityScan",
Handler: _File_SecurityScan_Handler,
},
{
MethodName: "SecurityScanByText",
Handler: _File_SecurityScanByText_Handler,
},
{
MethodName: "UpdateFileSecurityStatus",
Handler: _File_UpdateFileSecurityStatus_Handler,

File diff suppressed because it is too large Load Diff

View File

@ -29,9 +29,23 @@ func (this *PressReleasesData) Validate() error {
}
}
}
for _, item := range this.Files {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Files", err)
}
}
}
return nil
}
func (this *DisplayItem) Validate() error {
for _, item := range this.Files {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Files", err)
}
}
}
return nil
}
func (this *ListReq) Validate() error {
@ -64,6 +78,13 @@ func (this *InfoResp) Validate() error {
}
}
}
for _, item := range this.Files {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Files", err)
}
}
}
return nil
}
func (this *DisplayReq) Validate() error {
@ -79,6 +100,9 @@ func (this *DisplayResp) Validate() error {
}
return nil
}
func (this *Files) Validate() error {
return nil
}
func (this *EditReq) Validate() error {
for _, item := range this.DataByLang {
if item != nil {
@ -87,6 +111,13 @@ func (this *EditReq) Validate() error {
}
}
}
for _, item := range this.Files {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Files", err)
}
}
}
return nil
}
func (this *EditResp) Validate() error {
@ -100,6 +131,13 @@ func (this *CreateReq) Validate() error {
}
}
}
for _, item := range this.Files {
if item != nil {
if err := github_com_mwitkow_go_proto_validators.CallValidatorIfExists(item); err != nil {
return github_com_mwitkow_go_proto_validators.FieldError("Files", err)
}
}
}
return nil
}
func (this *CreateResp) Validate() error {

View File

@ -39,3 +39,10 @@ Password = "Gy.123456"
[service]
IsHTTPS = false
[zapLog]
level = "info"
filename = "logs/fiee_zap.log"
maxsize = 5
maxage = 30
maxbackups = 30

BIN
data/SourceHanSansSC-VF.ttf Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -43,6 +43,6 @@ Webhookkey = "whsec_uOQpG6IZTqtfLuePIDtfLCGJPqedSCCN"
[zapLog]
level = "info"
filename = "logs/fiee_zap.log"
max_size = 5
max_age = 30
max_backups = 30
maxsize = 5
maxage = 30
maxbackups = 30

View File

@ -43,6 +43,6 @@ Webhookkey = "whsec_Mol32WD1KcKHUdYsSwap0LR03q2g9qNY"
[zapLog]
level = "info"
filename = "logs/fiee_zap.log"
max_size = 5
max_age = 30
max_backups = 30
maxsize = 5
maxage = 30
maxbackups = 30

View File

@ -44,6 +44,6 @@ Webhookkey = "whsec_uOQpG6IZTqtfLuePIDtfLCGJPqedSCCN"
[zapLog]
level = "info"
filename = "logs/fiee_zap.log"
max_size = 5
max_age = 30
max_backups = 30
maxsize = 5
maxage = 30
maxbackups = 30

6
go.mod
View File

@ -106,7 +106,6 @@ require (
github.com/BurntSushi/toml v1.2.1
github.com/PuerkitoBio/goquery v1.8.1
github.com/disintegration/imaging v1.6.2
github.com/duke-git/lancet/v2 v2.3.8
github.com/envoyproxy/protoc-gen-validate v0.1.0
github.com/fonchain/utils/security v0.0.0-00010101000000-000000000000
github.com/fonchain/utils/voice v0.0.0-00010101000000-000000000000
@ -114,8 +113,10 @@ require (
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/google/uuid v1.6.0
github.com/mholt/archiver v3.1.1+incompatible
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/phpdave11/gofpdf v1.4.3
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd
github.com/samber/lo v1.52.0
github.com/shopspring/decimal v1.4.0
@ -165,7 +166,6 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-resty/resty/v2 v2.7.0 // indirect
github.com/golang/mock v1.5.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@ -180,7 +180,7 @@ require (
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/phpdave11/gofpdi v1.0.15 // 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

11
go.sum
View File

@ -168,6 +168,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA=
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
@ -257,8 +258,6 @@ github.com/dubbogo/net v0.0.4/go.mod h1:1CGOnM7X3he+qgGNqjeADuE5vKZQx/eMSeUkpU3u
github.com/dubbogo/triple v1.0.9/go.mod h1:1t9me4j4CTvNDcsMZy6/OGarbRyAUSY0tFXGXHCp7Iw=
github.com/dubbogo/triple v1.1.8 h1:yE+J3W1NTZCEPa1FoX+VWZH6UF1c0+A2MGfERlU2zbI=
github.com/dubbogo/triple v1.1.8/go.mod h1:9pgEahtmsY/avYJp3dzUQE8CMMVe1NtGBmUhfICKLJk=
github.com/duke-git/lancet/v2 v2.3.8 h1:dlkqn6Nj2LRWFuObNxttkMHxrFeaV6T26JR8jbEVbPg=
github.com/duke-git/lancet/v2 v2.3.8/go.mod h1:zGa2R4xswg6EG9I6WnyubDbFO/+A/RROxIbXcwryTsc=
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@ -583,6 +582,7 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
@ -747,8 +747,11 @@ github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZO
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 h1:zyWXQ6vu27ETMpYsEMAsisQ+GqJ4e1TPvSNfdOPF0no=
github.com/phpdave11/gofpdf v1.4.3 h1:M/zHvS8FO3zh9tUd2RCOPEjyuVcs281FCyF22Qlz/IA=
github.com/phpdave11/gofpdf v1.4.3/go.mod h1:MAwzoUIgD3J55u0rxIG2eu37c+XWhBtXSpPAhnQXf/o=
github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/phpdave11/gofpdi v1.0.15 h1:iJazY1BQ07I9s7N5EWjBO1YbhmKfHGxNligUv/Rw4Lc=
github.com/phpdave11/gofpdi v1.0.15/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
@ -827,6 +830,7 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK3dcGsnCnO41eRBOnY12zwkn5qVwgc=
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
@ -1081,6 +1085,7 @@ 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-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
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=

109
pkg/common/qwen/qwen_vl.go Normal file
View File

@ -0,0 +1,109 @@
package qwen
import (
"encoding/json"
"errors"
"fmt"
modelQwen "fonchain-fiee/pkg/model/qwen"
"fonchain-fiee/pkg/utils"
"go.uber.org/zap"
)
// VL 调用通义千问视觉多模态API支持多个视频、多张图片和文本
func VL(videoURLs []string, imageURLs []string, text string, model string) (resp *modelQwen.VLResponse, err error) {
// 设置默认模型
if model == "" {
model = "qwen3-vl-plus"
}
// 构建内容列表
content := make([]modelQwen.VLContent, 0)
// 添加视频内容支持自定义fps
for _, videoURL := range videoURLs {
fps := 2 // 默认fps为2
content = append(content, modelQwen.VLContent{
Type: "video_url",
VideoURL: &modelQwen.VideoURL{
URL: videoURL,
},
FPS: fps,
})
}
// 添加图片内容
for _, imageURL := range imageURLs {
content = append(content, modelQwen.VLContent{
Type: "image_url",
ImageURL: &modelQwen.ImageURL{
URL: imageURL,
},
})
}
// 添加文本内容
if text != "" {
content = append(content, modelQwen.VLContent{
Type: "text",
Text: text,
})
}
// 构建请求
req := modelQwen.VLRequest{
Model: model,
Messages: []modelQwen.VLMessage{
{
Role: "user",
Content: content,
},
},
}
// 序列化请求
jsonData, err := json.Marshal(req)
if err != nil {
zap.L().Error("VL Marshal failed", zap.Error(err))
return nil, errors.New("序列化请求失败")
}
// 发送请求使用PostBytesHeader获取状态码和响应体
statusCode, body, err := utils.PostBytesHeader(modelQwen.DashscopeVLURL, map[string]interface{}{
"Authorization": "Bearer " + modelQwen.DashscopeAPIKey,
"Content-Type": "application/json",
// "X-DashScope-OssResourceResolve": "enable", // 启用OSS资源解析
}, jsonData)
if err != nil {
zap.L().Error("VL Post failed", zap.Error(err))
return nil, errors.New("请求视觉AI失败")
}
// 检查状态码如果不是200尝试解析错误响应
if statusCode != 200 {
// 尝试解析错误响应
var errorResp struct {
Error struct {
Message string `json:"message"`
Type string `json:"type"`
Code string `json:"code"`
} `json:"error"`
}
if err := json.Unmarshal(body, &errorResp); err == nil && errorResp.Error.Message != "" {
zap.L().Error("VL API error", zap.Int("status", statusCode), zap.String("message", errorResp.Error.Message))
return nil, fmt.Errorf("%s", errorResp.Error.Message)
}
// 如果无法解析错误响应,返回通用错误
zap.L().Error("VL API error", zap.Int("status", statusCode), zap.String("body", string(body)))
return nil, fmt.Errorf("接口返回错误")
}
// 解析响应
var result modelQwen.VLResponse
if err = json.Unmarshal(body, &result); err != nil {
zap.L().Error("VL Unmarshal failed", zap.Error(err), zap.String("body", string(body)))
return nil, fmt.Errorf("解析响应失败: %v", err)
}
return &result, nil
}

View File

@ -14,6 +14,7 @@ import (
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/bundle/common"
serverCast "fonchain-fiee/pkg/service/cast"
"fonchain-fiee/pkg/utils/stime"
"log"
"math/rand"
"strconv"
@ -27,14 +28,16 @@ import (
// InitTasks 初始化定时任务
func InitTasks() error {
cm := GetCronManager()
err := cm.AddTask("refreshWorkApprovalStatus", "0 */1 * * * *", RefreshWorkApprovalStatusTask)
err := cm.AddTask("refreshWorkApprovalStatus", "0 */5 * * * *", RefreshApprovalStatusTask)
err = cm.AddTask("artistAutoConfirm", "0 */1 * * * *", ArtistAutoConfirmTask)
err = cm.AddTask("refreshPublishStatus", "0 */1 * * * *", PublishTask)
err = cm.AddTask("scheduledPublish", "0 */10 * * * *", ScheduledPublishTask)
err = cm.AddTask("refreshPublishStatus", "0 */5 * * * *", PublishTask)
err = cm.AddTask("scheduledPublish", "0 */1 * * * *", ScheduledPublishTask) //FIXME
err = cm.AddTask("artistAutoConfirmAnalysis", "0 */1 * * * *", ArtistAutoConfirmAnalysisTask)
err = cm.AddTask("refreshWorkAnalysisApprovalStatus", "0 */1 * * * *", RefreshWorkAnalysisApprovalStatusTask)
err = cm.AddTask("refreshArtistOrder", "0 */30 * * * *", RefreshArtistOrderTask)
err = cm.AddTask("refreshWorkAnalysisApprovalStatus", "0 */5 * * * *", RefreshWorkAnalysisApprovalStatusTask)
err = cm.AddTask("artistAutoConfirmReport", "0 */1 * * * *", ArtistAutoConfirmReportTask)
err = cm.AddTask("refreshCompetitiveReportApprovalStatus", "0 */5 * * * *", RefreshCompetitiveReportApprovalStatusTask)
err = cm.AddTask("refreshArtistOrder", "0 */5 * * * *", RefreshArtistOrderTask)
// 每天 00:30 和 12:30 执行 Ayrshare 指标采集任务
// err = cm.AddTask("ayrshareMetricsCollector", "0 30 0,12 * * *", AyrshareMetricsCollectorTask)
@ -56,6 +59,12 @@ func InitTasks() error {
return nil
}
func RefreshApprovalStatusTask() {
go RefreshWorkApprovalStatusTask()
go RefreshScriptApprovalStatusTask()
}
// RefreshWorkApprovalStatusTask 刷新作品审批状态任务
func RefreshWorkApprovalStatusTask() {
resp, err := service.CastProvider.WorkList(context.Background(), &cast.WorkListReq{
Page: 1,
@ -72,6 +81,50 @@ func RefreshWorkApprovalStatusTask() {
serverCast.RefreshWorkApproval(nil, resp.Data)
}
// RefreshScriptApprovalStatusTask 刷新脚本审批状态任务
func RefreshScriptApprovalStatusTask() {
resp, err := service.CastProvider.ListVideoScripts(context.Background(), &cast.ListVideoScriptsReq{
Status: 2,
Page: 1,
PageSize: 9999,
})
if err != nil {
log.Printf("获取工作列表失败: %v", err)
return
}
if resp.Data == nil || len(resp.Data) == 0 {
return
}
var approvalIds []int
for _, v := range resp.Data {
if v.ApprovalID == "" {
continue
}
id, _ := strconv.ParseInt(v.ApprovalID, 10, 64)
approvalIds = append(approvalIds, int(id))
}
var data map[int]modelCast.Item
castService := new(serverCast.CastService)
data, err = castService.ApprovalDetail(approvalIds)
if err != nil {
return
}
for approvalID, v := range data {
var scriptReq cast.UpdateScriptStatusReq
scriptReq.ApprovalID = fmt.Sprint(approvalID)
uTimes, _ := stime.DatetimeToTimes(v.UpdatedAt, "2006-01-02 15:04:05")
if v.Status == 2 && int64(uTimes) <= time.Now().Unix() {
scriptReq.WorkAction = cast.WorkActionENUM_APPROVAL_PASS
}
if v.Status == 3 {
scriptReq.WorkAction = cast.WorkActionENUM_APPROVAL_REJECT
}
scriptReq.ApprovalReply = v.Reply
scriptReq.ApprovalTime = v.UpdatedAt
_, _ = service.CastProvider.UpdateScriptStatus(context.Background(), &scriptReq)
}
}
// AutoManuallyConfirmWorkTaskWithRandomInterval 以随机间隔3-7分钟执行自动确认任务
func AutoManuallyConfirmWorkTaskWithRandomInterval() {
@ -146,10 +199,11 @@ func AutoManuallyConfirmWorkTask() {
if balanceInfoRes.BundleStatus == common.BundleExpired {
_, err = service.CastProvider.UpdateStatus(context.Background(), &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_EXPIRED,
})
log.Printf("套餐已过期,作品uuid:"+req.WorkUuid, zap.Error(err))
continue
@ -161,6 +215,24 @@ func AutoManuallyConfirmWorkTask() {
if err != nil {
continue
}
if balanceInfoRes.PurchaseType == 1 {
//判断作品对应订单是否相同
if wordInfoRes.BundleOrderUuid != balanceInfoRes.OrderUUID {
//订单号不相同
//新购买的,直接扣除失败
_, err = service.CastProvider.UpdateStatus(context.Background(), &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_EXPIRED,
})
log.Printf("订单号不相同,作品uuid:"+req.WorkUuid, zap.Error(err))
continue
}
//相同着正常走流程
}
if wordInfoRes.WorkStatus != 4 {
continue
}
@ -174,10 +246,11 @@ func AutoManuallyConfirmWorkTask() {
{
if balanceInfoRes.ImageExtendConsumptionNumber >= balanceInfoRes.ImageExtendNumber { // 图文余量不足
_, err = service.CastProvider.UpdateStatus(context.Background(), &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_NOTENOUGH,
})
log.Printf("图文余量不足,作品uuid:"+req.WorkUuid, zap.Error(err))
continue
@ -188,10 +261,11 @@ func AutoManuallyConfirmWorkTask() {
{
if balanceInfoRes.VideoExtendConsumptionNumber >= balanceInfoRes.VideoExtendNumber { // 视频余量不足
_, err = service.CastProvider.UpdateStatus(context.Background(), &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_NOTENOUGH,
})
log.Printf("视频余量不足,作品uuid:"+req.WorkUuid, zap.Error(err))
continue
@ -225,7 +299,7 @@ func RefreshWorkAnalysisApprovalStatusTask() {
resp, err := service.CastProvider.ListWorkAnalysis(context.Background(), &cast.ListWorkAnalysisReq{
Page: 1,
StatusList: []uint32{2}, // 状态为2表示待审批
PageSize: 999999,
PageSize: 9999,
})
if err != nil {
log.Printf("获取数据分析列表失败: %v", err)
@ -238,6 +312,7 @@ func RefreshWorkAnalysisApprovalStatusTask() {
}
func ArtistAutoConfirmTask() {
//FIXME 再加一个定时确认 不完全依赖于队列
now := float64(time.Now().Unix())
opt := redis.ZRangeBy{
Min: fmt.Sprintf("%d", 0),
@ -386,7 +461,8 @@ func ScheduledPublishTask() {
if len(publishBatch) > 0 {
zap.L().Info("批量发布剩余作品", zap.Int("batch_size", len(publishBatch)), zap.Strings("work_uuids", publishBatch))
_ = serverCast.PublishWork(context.Background(), &cast.PublishReq{
WorkUuids: publishBatch,
WorkUuids: publishBatch,
PublishSource: cast.PublishSourceENUM_RePublishType_SCHEDULED,
})
zap.L().Info("剩余批次发布完成", zap.Int("published", len(publishBatch)))
}
@ -570,12 +646,53 @@ func ArtistAutoConfirmAnalysisTask() {
}
}
func ArtistAutoConfirmReportTask() {
now := float64(time.Now().Unix())
opt := redis.ZRangeBy{
Min: fmt.Sprintf("%d", 0),
Max: fmt.Sprintf("%f", now),
}
reportUuids, err := cache.RedisClient.ZRangeByScore(modelCast.AutoConfirmReportQueueKey, opt).Result()
if err != nil {
zap.L().Error("获取到期竞品报告任务失败", zap.Error(err))
return
}
if len(reportUuids) == 0 {
zap.L().Debug("没有到期的竞品报告任务")
return
}
zap.L().Info("发现到期竞品报告任务", zap.Int("count", len(reportUuids)))
for _, reportUuid := range reportUuids {
serverCast.ProcessReportTask(context.Background(), reportUuid)
}
}
func RefreshCompetitiveReportApprovalStatusTask() {
resp, err := service.CastProvider.ListCompetitiveReport(context.Background(), &cast.ListCompetitiveReportReq{
Page: 1,
StatusList: []uint32{2}, // 状态为2表示待审批
PageSize: 9999,
})
if err != nil {
log.Printf("获取竞品报告列表失败: %v", err)
return
}
if resp.Data == nil || len(resp.Data) == 0 {
return
}
serverCast.RefreshCompetitiveReportApproval(nil, resp.Data)
}
// AyrshareMetricsCollectorTask Ayrshare 指标采集定时任务(每天 00:30 和 12:30 执行)
func AyrshareMetricsCollectorTask() {
serverCast.ExecuteAyrshareMetricsCollector()
}
func RefreshArtistOrderTask() {
now := time.Now()
if now.Day() == 1 && now.Hour() < 1 {
return
}
_, _ = service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: "artistOrderInfo"})
}

View File

@ -1,6 +1,7 @@
package cast
import (
"fmt"
"fonchain-fiee/api/cast"
modelCast "fonchain-fiee/pkg/model/cast"
"strings"
@ -102,3 +103,44 @@ func (w *Work) ExportExcelWorkList(data []*cast.WorkListResp_Info) (*excelize.Fi
return f, nil
}
func (w *Work) ExportPublishLogList(data []*cast.PublishLogInfo, savePath string) error {
f := excelize.NewFile()
defer f.Close()
sheetName := "Sheet1"
f.SetSheetName("Sheet1", sheetName)
headers := []string{
"状态", "失败原因", "提交发布时间", "发布平台", "发布方式", "作品类型", "作品标题", "艺人", "用户编号",
}
for col, h := range headers {
cell, _ := excelize.CoordinatesToCellName(col+1, 1)
f.SetCellValue(sheetName, cell, h)
}
for rowIndex, info := range data {
row := rowIndex + 2
platformName := modelCast.PlatformNameKv[info.PlatformID]
if platformName == "" {
platformName = fmt.Sprintf("%d", info.PlatformID)
}
values := []interface{}{
modelCast.PublishStatusMM[int(info.PublishMediaStatus)],
info.Detail,
info.CreatedAt,
modelCast.PlatformNameKv[info.PlatformID],
modelCast.PublishSourceMM[int(info.PublishSource)],
modelCast.WorkCategoryMM[int(info.WorkCategory)],
info.Title,
info.ArtistName,
info.ArtistSubNum,
}
for col, v := range values {
cell, _ := excelize.CoordinatesToCellName(col+1, row)
f.SetCellValue(sheetName, cell, v)
}
}
return f.SaveAs(savePath)
}

View File

@ -13,7 +13,6 @@ type UserWorkAnalysisConfirmReq struct {
}
type GetBundleBalanceListResp struct {
Total int64 `protobuf:"varint,1,opt,name=total,proto3" json:"total"`
Data []*BundleBalanceItem `protobuf:"bytes,2,rep,name=data,proto3" json:"data"`
}
@ -33,6 +32,8 @@ type BundleBalanceItem struct {
ImageConsumptionNumber int32 `protobuf:"varint,12,opt,name=imageConsumptionNumber,proto3" json:"imageConsumptionNumber"`
DataAnalysisNumber int32 `protobuf:"varint,13,opt,name=dataAnalysisNumber,proto3" json:"dataAnalysisNumber"`
DataAnalysisConsumptionNumber int32 `protobuf:"varint,14,opt,name=dataAnalysisConsumptionNumber,proto3" json:"dataAnalysisConsumptionNumber"`
ExpansionPacksNumber int32 `protobuf:"varint,15,opt,name=expansionPacksNumber,proto3" json:"expansionPacksNumber"`
Bought int32 `protobuf:"varint,16,opt,name=bought,proto3" json:"bought"`
CompetitiveNumber int32 `protobuf:"varint,15,opt,name=competitiveNumber,proto3" json:"competitiveNumber"`
CompetitiveConsumptionNumber int32 `protobuf:"varint,16,opt,name=competitiveConsumptionNumber,proto3" json:"competitiveConsumptionNumber"`
ExpansionPacksNumber int32 `protobuf:"varint,17,opt,name=expansionPacksNumber,proto3" json:"expansionPacksNumber"`
Bought int32 `protobuf:"varint,18,opt,name=bought,proto3" json:"bought"`
}

View File

@ -8,10 +8,11 @@ type SyncAsProfileReq struct {
// 定义枚举值
const (
BalanceTypeAccountValue BalanceTypeEnum = 1
BalanceTypeImageValue BalanceTypeEnum = 2
BalanceTypeVideoValue BalanceTypeEnum = 3
BalanceTypeDataValue BalanceTypeEnum = 4
BalanceTypeAccountValue BalanceTypeEnum = 1 //账号
BalanceTypeImageValue BalanceTypeEnum = 2 //图文
BalanceTypeVideoValue BalanceTypeEnum = 3 //视频
BalanceTypeDataValue BalanceTypeEnum = 4 //数据分析
BalanceTypeCompetitiveValue BalanceTypeEnum = 5 //竞品数
)
var PlatformNameKv = map[uint32]string{
@ -29,3 +30,7 @@ var NamePlatformIDKv = map[string]uint32{
"DM": 4,
"bluesky": 5,
}
type UnbindAccountReq struct {
MediaAccountUuids []string `json:"mediaAccountUuids"`
}

View File

@ -21,6 +21,9 @@ const (
AutoConfirmAnalysisQueueKey = "auto_confirm:analysis:queue"
AutoConfirmAnalysisLockKey = "auto_confirm:analysis:lock:%s"
AutoConfirmReportQueueKey = "auto_confirm:report:queue"
AutoConfirmReportLockKey = "auto_confirm:report:lock:%s"
// AyrshareMetricsCollectorLockKey Ayrshare 指标采集任务锁
AyrshareMetricsCollectorLockKey = "ayrshare:metrics:collector:lock"
)
@ -29,6 +32,18 @@ var WorkCategoryMM = map[int]string{
1: "图文",
2: "视频",
}
var PublishSourceMM = map[int]string{
1: "手动发布",
2: "定时任务",
3: "手动发布",
}
var PublishStatusMM = map[int]string{
1: "进行中",
2: "发布成功",
3: "发布失败",
4: "发布异常",
}
var WorkCostTypeMM = map[int]string{
1: "套餐",
@ -43,13 +58,6 @@ var PlatformPublishStatusMM = map[cast.PublishStatusENUM]string{
cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION: "异常",
}
var PlatformIDMM = map[int]string{
1: "TIKTOK",
2: "YouTube",
3: "Ins",
4: "DM",
}
var WorkStatusMM = map[int]string{
1: "草稿",
2: "审核中",

View File

@ -4,6 +4,7 @@ const (
DashscopeAPIKey string = "sk-5ae9df5d3bcf4755ad5d12012058a2e7"
DashscopeText2ImageURL string = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis"
DashscopeEditImageURL string = "https://dashscope.aliyuncs.com/api/v1/services/aigc/image2image/image-synthesis"
DashscopeVLURL string = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"
)
// QwenImageRequest 通义千问文生图请求

47
pkg/model/qwen/qwen_vl.go Normal file
View File

@ -0,0 +1,47 @@
package qwen
// VLContent 视觉多模态内容结构,支持文本、图片和视频
type VLContent struct {
Type string `json:"type"` // text, image_url, video_url
Text string `json:"text,omitempty"` // type=text 时使用
ImageURL *ImageURL `json:"image_url,omitempty"` // type=image_url 时使用
VideoURL *VideoURL `json:"video_url,omitempty"` // type=video_url 时使用
FPS int `json:"fps,omitempty"` // type=video_url 时可选,视频帧率
}
// VideoURL 视频URL结构
type VideoURL struct {
URL string `json:"url"`
}
// VLRequest 视觉多模态请求结构
type VLRequest struct {
Model string `json:"model"` // 模型名称,如 qwen3-vl-plus
Messages []VLMessage `json:"messages"` // 消息列表
Seed int64 `json:"seed,omitempty"` // 随机种子
EnableSearch bool `json:"enable_search,omitempty"` // 是否启用搜索
}
// VLMessage 视觉多模态消息结构
type VLMessage struct {
Role string `json:"role"` // user, assistant, system
Content []VLContent `json:"content"` // 内容列表,可包含文本、图片、视频
}
// VLResponse 视觉多模态响应结构
type VLResponse struct {
Choices []VLChoice `json:"choices"`
Model string `json:"model,omitempty"`
ID string `json:"id,omitempty"`
}
// VLChoice 视觉多模态选择结果
type VLChoice struct {
Message struct {
Content string `json:"content"`
ReasoningContent string `json:"reasoning_content"`
Role string `json:"role"`
} `json:"message"`
FinishReason string `json:"finish_reason"`
Index int `json:"index,omitempty"`
}

View File

@ -31,20 +31,51 @@ func AnalysisRouter(r *gin.RouterGroup) {
analysis.POST("artist-metrics-single", serviceCast.ArtistMetricsDailyWindow) // 艺人指标日窗口
analysis.POST("tobe-confirmed-list", serviceCast.TobeConfirmedList) // 待确认数据列表
analysis.POST("update-approval-id", serviceCast.UpdateWorkAnalysisApprovalID) // 更新作品分析审批ID
analysis.POST("update-pdf-url", serviceCast.UpdateWorkAnalysisPdfUrl) // 更新作品分析PDF链接
// 刷数据专用的导入接口
analysis.POST("import-batch", serviceCast.ImportWorkAnalysisBatch) // Excel 批量导入数据分析
analysis.POST("trigger-ayrshare-metrics", serviceCast.TriggerAyrshareMetricsCollector) // 手动触发 Ayrshare 指标采集任务
}
competitiveReport := r.Group("report")
competitiveReport.Use(middleware.CheckWebLogin(service.AccountProvider))
{
competitiveReport.POST("create", serviceCast.CreateCompetitiveReport) // 创建竞品报告
competitiveReport.POST("import-batch", serviceCast.ImportCompetitiveReportBatch) // 批量导入竞品报告
competitiveReport.POST("update-status", serviceCast.UpdateCompetitiveReportStatus) // 更新竞品报告状态
competitiveReport.POST("detail", serviceCast.GetCompetitiveReport) // 获取竞品报告详情
competitiveReport.POST("list", serviceCast.ListCompetitiveReport) // 获取竞品报告列表
competitiveReport.POST("single-list", serviceCast.ListCompetitiveReportByArtistUuid) // 根据艺人UUID获取竞品报告列表
competitiveReport.POST("delete", serviceCast.DeleteCompetitiveReport) // 删除竞品报告
competitiveReport.POST("update-approval-id", serviceCast.UpdateCompetitiveReportApprovalID) // 更新竞品报告审批ID
competitiveReport.POST("count-by-work-uuids", serviceCast.CountCompetitiveReportByWorkUuids) // 根据作品UUID统计竞品报告数量
competitiveReport.POST("export-list", serviceCast.ListCompetitiveReportExport) // 竞品报告列表导出
competitiveReport.POST("export-single-list", serviceCast.ListCompetitiveReportSingleExport) // 竞品报告单个列表导出
competitiveReport.POST("import-pdf-batch", serviceCast.ImportPdfBatch) // 批量导入PDF下载、重命名、上传
// 刷竞品报告专用的导入接口
competitiveReport.POST("import-history-batch", serviceCast.ImportCompetitiveReportHistoryBatch) // Excel 批量刷写竞品报告历史数据
}
// 员工任务相关路由需要App登录验证
analysisAppRoute := r.Group("app/analysis")
analysisAppRoute.Use(middleware.CheckLogin(service.AccountFieeProvider))
{
analysisAppRoute.POST("list", serviceCast.ListWorkAnalysis) // 作品列表
analysisAppRoute.POST("list", serviceCast.ListWorkAnalysisForApp) // 作品列表
analysisAppRoute.POST("detail", serviceCast.GetWorkAnalysis) // 作品分析详情
analysisAppRoute.POST("update-status", serviceCast.UpdateWorkAnalysisStatus) // 用户确认
analysisAppRoute.POST("check-balance", serviceCast.CheckBundleBalance) // 检查套餐余量
analysisAppRoute.POST("tobe-confirmed-list", serviceCast.TobeConfirmedList) // 待确认数据列表
analysisAppRoute.POST("work-analysis-confirm", bundle.WorkAnalysisConfirm)
}
competitiveReportAppRoute := r.Group("app/report")
competitiveReportAppRoute.Use(middleware.CheckLogin(service.AccountFieeProvider))
{
competitiveReportAppRoute.POST("detail", serviceCast.GetCompetitiveReportForApp) // 获取竞品报告详情App端
competitiveReportAppRoute.POST("list", serviceCast.ListReportByArtistUuidForApp) // 根据艺人UUID获取竞品报告列表App端
competitiveReportAppRoute.POST("update-status", serviceCast.UpdateCompetitiveReportStatus) // 更新竞品报告状态App端
}
}

View File

@ -14,12 +14,15 @@ func BundleRouter(r *gin.RouterGroup) {
bundleAppRoute := r.Group("bundle")
bundleAppNoAuthRoute := r.Group("bundle")
bundleAppRoute.Use(middleware.CheckLogin(service.AccountFieeProvider))
bundleClientNoAuthRoute := r.Group("bundle/no-auth")
// 套餐
{
bundleClientNoAuthRoute := bundleRoute.Group("system/no-auth")
{
bundleClientNoAuthRoute.POST("export/work-cast-info", bundle.ExportWorkCastInfo)
bundleClientNoAuthRoute.POST("export/bundle-price-info", bundle.ExportBundlePriceInfo)
bundleClientNoAuthRoute.POST("survey/is-send", bundle.IsSendSurvey)
bundleClientNoAuthRoute.POST("survey/bundleInfo", bundle.QuestionnaireSurveyBundleInfo)
bundleClientNoAuthRoute.POST("survey/create", bundle.QuestionnaireSurveyCreate)
}
bundleClientRoute := bundleRoute.Group("system")
{
@ -55,6 +58,10 @@ func BundleRouter(r *gin.RouterGroup) {
metrics.POST("export/balance-detail", bundle.MetricsBalanceDetailExport)
metrics.POST("export/balance-metrics", bundle.BalanceMetricsExport)
}
survey := bundleClientRoute.Group("survey")
{
survey.POST("list", bundle.QuestionnaireSurveyList)
}
}
bundleClientRouteV2 := bundleRoute.Group("system/v2")

View File

@ -16,11 +16,13 @@ func BundleOrderRouter(r *gin.RouterGroup) {
bundleOrderRoute := r.Group("bundle-order")
bundleOrderRoute.Use(middleware.CheckLogin(service.AccountFieeProvider))
bundleOrderWebRoute := r.Group("bundle-order")
bundleOrderWebRoute.POST("password-free/bundle-order-list-download", bundle.OrderRecordsListPasswordFreeDownload)
bundleOrderWebRoute.Use(middleware.CheckWebLogin(service.AccountProvider))
bundleOrderNoAuthRoute := r.Group("bundle-order")
// 套餐
{
bundleOrderNoAuthRoute.POST("common/web/no-auth/reconciliation-list-download", bundle.GetReconciliationListDownload)
bundleOrderNoAuthRoute.POST("common/web/no-auth/creat-invoice", bundle.CreatInvoice)
bundleOrderClientWebRoute := bundleOrderWebRoute.Group("common/web")
{
bundleOrderClientWebRoute.POST("bundle-order-list", bundle.OrderRecordsList)
@ -31,10 +33,22 @@ func BundleOrderRouter(r *gin.RouterGroup) {
bundleOrderClientWebRoute.POST("query-order-snapshot-information", bundle.QueryTheOrderSnapshotInformation)
// 自动创建用户和订单
bundleOrderClientWebRoute.POST("auto-create-user-order", bundle.AutoCreateUserAndOrder)
// 发票管理相关接口
bundleOrderClientWebRoute.POST("invoice-list", bundle.GetBundleInvoiceList)
bundleOrderClientWebRoute.POST("invoice-express-info", bundle.GetInvoiceExpressInfo)
bundleOrderClientWebRoute.POST("updata-invoice-express-info", bundle.UpdateInvoiceExpressInfo)
bundleOrderClientWebRoute.GET("country-list", bundle.GetCountryList)
bundleOrderClientWebRoute.POST("export-invoice", bundle.ExportInvoice)
}
bundleOrderClientAppRoute := bundleOrderRoute.Group("common/app")
{
bundleOrderClientAppRoute.POST("bundle-order-list", bundle.OrderRecordsList)
//发票管理
bundleOrderClientAppRoute.POST("creat-paper-invoice", bundle.CreatePaperInvoiceAddress)
bundleOrderClientAppRoute.POST("invoice-express-info", bundle.GetInvoiceExpressInfo)
bundleOrderClientAppRoute.POST("invoice-list", bundle.GetInvoiceList)
bundleOrderClientAppRoute.GET("country-list", bundle.GetCountryList)
bundleOrderClientAppRoute.POST("download-invoice", bundle.CreateDownloadInvoice)
}
//bundleOrderWebRoute := bundleOrderRoute.Group("web")

View File

@ -17,6 +17,7 @@ func cronRouter(r *gin.RouterGroup) {
cron.POST("updateScheduleTask", cronService.UpdateScheduleTask)
cron.POST("pauseScheduleTask", cronService.PauseScheduleTask)
cron.POST("startScheduleTask", cronService.StartScheduleTask)
cron.POST("republishScheduleTask", cronService.RepublishScheduleTask)
cron.POST("deleteScheduleTask", cronService.DeleteScheduleTask)
cron.POST("getListScheduleTask", cronService.GetListScheduleTask)
cron.POST("getListExecutionResult", cronService.GetListExecutionResult)

View File

@ -0,0 +1,35 @@
package router
import (
"fonchain-fiee/pkg/middleware"
"fonchain-fiee/pkg/service"
serviceCustomerContract "fonchain-fiee/pkg/service/customerContract"
"github.com/gin-gonic/gin"
)
// CustomerContractRouter 客户与合同管理路由,参考 MediaRouter 实现
func CustomerContractRouter(r *gin.RouterGroup) {
auth := r.Group("")
auth.Use(middleware.CheckWebLogin(service.AccountProvider))
// 客户管理
customer := auth.Group("customer")
{
customer.POST("list", serviceCustomerContract.GetCustomerList)
customer.POST("detail", serviceCustomerContract.GetCustomerDetail)
customer.POST("update", serviceCustomerContract.UpdateCustomer)
customer.POST("list/referral-person", serviceCustomerContract.GetReferralPersonList)
}
// 合同管理
contract := auth.Group("contract")
{
contract.POST("list", serviceCustomerContract.GetContractList)
contract.POST("detail", serviceCustomerContract.GetContractDetail)
contract.POST("update", serviceCustomerContract.UpdateContract)
contract.POST("development-cycles", serviceCustomerContract.GetDevelopmentCyclesByContractUUID)
contract.POST("payment-cycles", serviceCustomerContract.GetPaymentCyclesByContractUUID)
contract.POST("upload-attachment", serviceCustomerContract.UploadContractAttachment)
}
}

View File

@ -24,6 +24,7 @@ func MediaRouter(r *gin.RouterGroup) {
media.POST("artist-info", serviceCast.ArtistInfo)
media.POST("sync-as-profile", serviceCast.SyncAsProfile)
media.POST("import-media-account", serviceCast.ImportMediaAccount)
media.POST("unbind-auth", serviceCast.UnbindAuth)
}
mediaNoLogin := r.Group("media")
{
@ -47,6 +48,15 @@ func MediaRouter(r *gin.RouterGroup) {
work.POST("remind", serviceCast.Remind)
work.POST("publish-info", serviceCast.PublishInfo)
work.POST("import-batch", serviceCast.ImportWorkBatch)
work.POST("list-published", serviceCast.WorkListPublished)
work.POST("update-work-script", serviceCast.UpdateWorkScript)
work.POST("publish-log-list", serviceCast.PublishLogList)
work.Any("publish-log-list-export", serviceCast.PublishLogListExport)
}
workNoAuth := noAuth.Group("work")
{
workNoAuth.POST("cron-republish", serviceCast.CronRePublish)
}
script := auth.Group("script")
@ -98,11 +108,13 @@ func MediaRouter(r *gin.RouterGroup) {
{
aiNoAuth.POST("image-generate", serviceAI.AIImageGenerate)
aiNoAuth.POST("text-generate", serviceAI.AIChat)
aiNoAuth.POST("video-vl", serviceAI.AIVideoVL)
}
aiAuth := auth.Group("ai")
{
aiAuth.POST("one-text", serviceAI.OneText)
aiAuth.POST("more-text", serviceAI.MoreText)
aiAuth.POST("generate-report", serviceAI.AICompetitorReport)
}
social := noAuth.Group("social")

View File

@ -57,6 +57,7 @@ func NewRouter() *gin.Engine {
ValueAddBundleRouter(privateGroup)
TaskBenchRouter(privateGroup) // 新增任务台路由
MediaRouter(privateGroup)
CustomerContractRouter(privateGroup)
AnalysisRouter(privateGroup)
SecFilingRouter(privateGroup)
app.MediaAppRouter(privateGroup)
@ -67,14 +68,15 @@ func NewRouter() *gin.Engine {
}
//账号模块
{
privateGroup.POST("user/register", account.UserRegister) //h5注册登录
privateGroup.POST("user/login", account.UserLogin) //后台登录
privateGroup.POST("user/send", account.SendMsg) //发送验证码
privateGroup.POST("user/logout", account.UserLogout) //登出
privateGroup.POST("user/check/msg", account.CheckMsg) //校验验证码
privateGroup.POST("generate/captcha", account.GenerateCaptcha) //生成滑块验证码
privateGroup.POST("validate/captcha", account.ValidateCaptcha) //验证滑块验证码
privateGroup.POST("check/register", account.CheckRegister) //校验是否注册
privateGroup.POST("user/register", account.UserRegister) //h5注册登录
privateGroup.POST("user/login", account.UserLogin) //后台登录
privateGroup.POST("user/send", account.SendMsg) //发送验证码
privateGroup.POST("user/send/no-slider", account.SendMsgNoSlider) //发送验证码(不验证滑块)
privateGroup.POST("user/logout", account.UserLogout) //登出
privateGroup.POST("user/check/msg", account.CheckMsg) //校验验证码
privateGroup.POST("generate/captcha", account.GenerateCaptcha) //生成滑块验证码
privateGroup.POST("validate/captcha", account.ValidateCaptcha) //验证滑块验证码
privateGroup.POST("check/register", account.CheckRegister) //校验是否注册
acRoute := privateGroup.Group("/user")
acRoute.Use(middleware.CheckLogin(service.AccountFieeProvider))
{

View File

@ -16,28 +16,22 @@ func TaskBenchRouter(r *gin.RouterGroup) {
taskBenchRoute.Use(middleware.CheckWebLogin(service.AccountProvider))
// 任务台管理
{
// 查询待指派任务记录
taskBenchRoute.POST("pending-task-list", taskbench.GetPendingTaskList)
// 待指派任务布局
taskBenchRoute.POST("pending-task-layout", taskbench.GetPendingTaskLayout)
taskBenchRoute.POST("set-pending-task-layout", taskbench.SetPendingTaskLayout)
// 指派某位员工完成某个艺人的任务
// 指派
taskBenchRoute.POST("assign-task", taskbench.AssignTask)
// 批量指派任务
// 批量指派
taskBenchRoute.POST("batch-assign-task", taskbench.BatchAssignTask)
// 中止指派任务根据任务指派记录UUID
// 中止指派
taskBenchRoute.POST("terminate-task-by-uuid", taskbench.TerminateTaskByUUID)
// 批量中止指派任务根据多个任务指派记录UUID
// 批量中止指派
taskBenchRoute.POST("batch-terminate-task", taskbench.BatchTerminateTask)
// 修改待发数量
taskBenchRoute.POST("update-pending-count", taskbench.UpdatePendingCount)
// 查询最近被指派记录
taskBenchRoute.POST("recent-assign-records", taskbench.GetRecentAssignRecords)
@ -56,18 +50,15 @@ func TaskBenchRouter(r *gin.RouterGroup) {
// 员工完成视频脚本带任务UUID
taskBenchRoute.POST("update-script-with-task-uuid", taskbench.UpdateVideoScriptWithUUID)
taskBenchRoute.POST("create-analysis-with-task-uuid", taskbench.CreateWorkAnalysisWithTaskUUID)
taskBenchRoute.POST("create-report-with-task-uuid", taskbench.CreateCompetitiveReportWithTaskUUID)
// 根据登录人信息查询被指派给该员工的任务
taskBenchRoute.POST("assigned-tasks", taskbench.GetEmployeeAssignedTasks)
// 员工手动点击完成任务
taskBenchRoute.POST("complete-manually", taskbench.CompleteTaskManually)
// 查询艺人套餐剩余数量
taskBenchRoute.POST("artist-bundle-balance", taskbench.GetArtistBundleBalance)
// 批量查询艺人待上传数量
taskBenchRoute.POST("batch-get-pending-upload", taskbench.GetPendingUploadBreakdown)
// 查询艺人待上传列表
taskBenchRoute.POST("pending-upload-list", taskbench.GetArtistUploadStatsList)
@ -79,14 +70,9 @@ func TaskBenchRouter(r *gin.RouterGroup) {
// 查询待指派数据
taskBenchRoute.POST("pending-data-list", taskbench.GetPendingAssign)
// 查询指派任务中已完成任务
taskBenchRoute.POST("completed-list", taskbench.GetTaskWorkLogListItems)
}
// 员工任务相关路由需要App登录验证
taskBenchAppRoute := r.Group("task-bench")
taskBenchAppRoute.Use(middleware.CheckLogin(service.AccountFieeProvider))
{
// 员工实际完成任务状态更新
taskBenchAppRoute.POST("update-progress", taskbench.UpdateTaskProgress)
}
}

View File

@ -15,6 +15,7 @@ import (
"fonchain-fiee/pkg/utils"
"io/ioutil"
"net/http"
"strings"
"time"
"github.com/fonchain_enterprise/utils/baidu"
@ -36,7 +37,7 @@ func UserExcelDownload(c *gin.Context) {
return
}
titleList := []string{
"用户编号", "姓名", "性别", "国籍", "手机号", "证件类型", "有效期至", "证件号码", "出生日期", "年龄", "现所在地", "注册时间", "审核时间", "审核状态", "不通过备注",
"用户编号", "姓名", "性别", "国籍", "手机号", "证件类型", "有效期至", "证件号码", "出生日期", "年龄", "现所在地", "注册时间", "审核时间", "审核状态", "不通过备注", "非大陆手机号", "邮箱",
}
var dataList []interface{}
@ -59,6 +60,8 @@ func UserExcelDownload(c *gin.Context) {
i.AuditTime,
Status,
i.NotPassRemarks,
i.AbroadTelAreaCode + i.AbroadTel,
i.Email,
}
dataList = append(dataList, &data)
}
@ -275,6 +278,40 @@ func dd(dateStr string) string {
}
func isValidMainlandID(id string) bool {
id = strings.TrimSpace(strings.ToUpper(id))
if len(id) != 18 {
return false
}
for i := 0; i < 17; i++ {
if id[i] < '0' || id[i] > '9' {
return false
}
}
last := id[17]
if (last < '0' || last > '9') && last != 'X' {
return false
}
birthday := id[6:14]
birthTime, err := time.Parse("20060102", birthday)
if err != nil {
return false
}
if birthTime.After(time.Now()) {
return false
}
weights := []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
checkMap := "10X98765432"
sum := 0
for i := 0; i < 17; i++ {
sum += int(id[i]-'0') * weights[i]
}
checkCode := checkMap[sum%11]
return byte(checkCode) == last
}
// SendMsg 用户发送验证码
func SendMsg(c *gin.Context) {
var req account.SendMsgRequest
@ -376,6 +413,54 @@ func SendMsg(c *gin.Context) {
//}
}
// 用户发送验证码(不验证滑块)
func SendMsgNoSlider(c *gin.Context) {
var req account.SendMsgRequest
if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
service.Error(c, err)
return
}
req.Project = "fiee"
req.TelNum = req.Zone + req.TelNum
//todo 审核使用账号
if req.TelNum == "8618888888888" {
service.Success1(c, "发送成功", &account.SendMsgStatusResponse{})
return
}
if req.Zone != e.ZoneCn && req.Zone != "" {
// ============================== redis检查ip开始
ip := c.ClientIP()
fmt.Println("当前ip", ip, ";手机号:", req.TelNum, ";domain", req.Domain)
tempReq := &account.SendNationMsgRequest{
Domain: req.Domain,
TelNum: req.TelNum,
Project: req.Project,
SignNo: req.SignNo,
MId: req.MId,
Scope: req.Scope,
}
res, err := service.AccountFieeProvider.SendNationMsg(context.Background(), tempReq)
if err != nil {
service.Error(c, err)
return
}
service.Success1(c, "发送成功", res)
return
} else {
res, err := service.AccountFieeProvider.SendMsg(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success1(c, "发送成功", res)
return
}
}
func RealName(c *gin.Context) {
var req account.RealNameRequest
@ -386,12 +471,14 @@ func RealName(c *gin.Context) {
user := login.GetUserInfoFromC(c)
req.Id = user.ID
if req.DocumentType == 2 {
if len(req.IdNumber) != 18 {
service.Error(c, errors.New("身份证号格式错误"))
return
if req.Nationality == "中国大陆" {
if !isValidMainlandID(req.IdNumber) {
service.Error(c, errors.New("身份证号格式错误"))
return
}
}
} else {
if req.IdNumber == "" {
if strings.TrimSpace(req.IdNumber) == "" {
service.Error(c, errors.New("证件号码不能为空"))
return
}
@ -418,7 +505,8 @@ func CheckMsg(c *gin.Context) {
req.TelNum = req.Zone + req.TelNum
res, err := service.AccountFieeProvider.CheckMsg(context.Background(), &req)
if err != nil {
service.Error(c, err)
fmt.Println("CheckMsg error:", err)
service.Error(c, errors.New("验证码错误"))
return
}

514
pkg/service/ai/video_vl.go Normal file
View File

@ -0,0 +1,514 @@
package ai
import (
"encoding/json"
"errors"
"fmt"
"fonchain-fiee/pkg/common/qwen"
"fonchain-fiee/pkg/service"
"strings"
"github.com/gin-gonic/gin"
)
// VideoVLRequest 视频/图片理解请求参数
type VideoVLRequest struct {
Videos []string `json:"videos"` // 视频URL列表
Images []string `json:"images"` // 图片URL列表
Text string `json:"text"` // 可选的文本提示
Model string `json:"model"` // 可选的模型名称,默认使用 qwen3-vl-plus
}
// AIVideoVL AI理解视频/图片接口
func AIVideoVL(ctx *gin.Context) {
var req VideoVLRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
service.Error(ctx, errors.New("参数错误"))
return
}
// 检查是否至少提供了视频或图片
if len(req.Videos) == 0 && len(req.Images) == 0 {
service.Error(ctx, errors.New("至少需要提供一个视频或图片"))
return
}
if len(req.Videos) > 1 {
service.Error(ctx, errors.New("当前只能选一个视频"))
return
}
Prompt := "请你详细描述视频和图片中的内容分别是什么,包括画面内容、人物动作、场景等。如果有配乐或背景音乐,请详细描述配乐的节奏、风格和情感特点"
// 调用VL函数进行AI理解
result, err := qwen.VL(req.Videos, req.Images, Prompt, req.Model)
if err != nil {
// 检查是否是文件下载超时错误(内容过大)
errMsg := err.Error()
if contains(errMsg, "Download multimodal file timed out") || contains(errMsg, "timed out") {
service.Error(ctx, errors.New("内容过大,请重新选择"))
} else {
service.Error(ctx, errors.New("ai分析帖子内容失败"))
}
return
}
// 返回AI返回的数据
service.Success(ctx, result)
}
// contains 检查字符串是否包含子字符串(不区分大小写)
func contains(s, substr string) bool {
return strings.Contains(strings.ToLower(s), strings.ToLower(substr))
}
// CompetitorReportRequest 竞品报告请求参数
type CompetitorReportRequest struct {
Videos []string `json:"videos"` // 视频URL列表
Images []string `json:"images"` // 图片URL列表
TextPrompt string `json:"textPrompt"` // 竞品报告要求文本
ImagePrompt string `json:"imagePrompt"` // 图片URL
Model string `json:"model"` // 可选的模型名称,默认使用 qwen3-vl-plus
}
// CompetitorReportData 竞品报告数据(用于返回给前端)
type CompetitorReportData struct {
HighlightAnalysis HighlightAnalysisData `json:"highlight_analysis"`
DataPerformance DataPerformanceData `json:"data_performance_analysis"`
OverallSummary string `json:"overall_summary_and_optimization"`
}
type HighlightAnalysisData struct {
Summary string `json:"summary"`
Points PointsData `json:"points"`
}
type PointsData struct {
Theme string `json:"theme"`
Narrative string `json:"narrative"`
Content string `json:"content"`
Copywriting string `json:"copywriting"`
Data string `json:"data"`
Music string `json:"music,omitempty"`
}
type DataPerformanceData struct {
Views string `json:"views"`
Completion string `json:"completion_rate,omitempty"`
Engagement string `json:"engagement"`
}
// CompetitorReportResponse 竞品报告响应数据
type CompetitorReportResponse struct {
ImageURL string `json:"image_url,omitempty"` // 生成的图片URL1024*1024非必须返回
Text string `json:"text,omitempty"` // 竞品报告文本内容,非必须返回
JsonData *CompetitorReportData `json:"json_data,omitempty"` // 竞品报告JSON数据
}
// CompetitorReportJSON AI返回的JSON结构
type CompetitorReportJSON struct {
HighlightAnalysis HighlightAnalysis `json:"highlight_analysis"`
DataPerformance DataPerformance `json:"data_performance_analysis"`
OverallSummary string `json:"overall_summary_and_optimization"`
}
type HighlightAnalysis struct {
Summary string `json:"summary"`
Points Points `json:"points"`
}
type Points struct {
Theme string `json:"theme"`
Narrative string `json:"narrative"`
Content string `json:"content"`
Copywriting string `json:"copywriting"`
Data string `json:"data"`
Music string `json:"music,omitempty"`
}
type DataPerformance struct {
Views string `json:"views"`
Completion string `json:"completion_rate,omitempty"`
Engagement string `json:"engagement"`
}
// convertJSONToText 将 JSON 转换为纯文本格式
func convertJSONToText(data CompetitorReportJSON, isVideo bool) string {
var sb strings.Builder
// 一、亮点表现分析
sb.WriteString("一、亮点表现分析\n")
sb.WriteString(data.HighlightAnalysis.Summary)
sb.WriteString("\n\n")
sb.WriteString("1. 标题亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Theme)
sb.WriteString("\n")
sb.WriteString("2. 题材亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Narrative)
sb.WriteString("\n")
sb.WriteString("3. 内容亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Content)
sb.WriteString("\n")
sb.WriteString("4. 文案亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Copywriting)
sb.WriteString("\n")
sb.WriteString("5. 数据亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Data)
sb.WriteString("\n")
if isVideo && data.HighlightAnalysis.Points.Music != "" {
sb.WriteString("6. 配乐亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Music)
sb.WriteString("\n")
}
// 二、数据表现分析
sb.WriteString("\n二、数据表现分析\n")
sb.WriteString("1. 浏览量表现:")
sb.WriteString(data.DataPerformance.Views)
sb.WriteString("\n")
if isVideo && data.DataPerformance.Completion != "" {
sb.WriteString("2. 完播率表现:")
sb.WriteString(data.DataPerformance.Completion)
sb.WriteString("\n")
sb.WriteString("3. 点赞/分享/评论表现:")
} else {
sb.WriteString("2. 点赞/分享/评论表现:")
}
sb.WriteString(data.DataPerformance.Engagement)
sb.WriteString("\n")
// 三、整体总结及可优化建议
sb.WriteString("\n三、整体总结及可优化建议\n")
sb.WriteString(data.OverallSummary)
return sb.String()
}
// convertJSONToTextFromData 将 JSON 转换为纯文本格式(使用新的 CompetitorReportData 结构)
func convertJSONToTextFromData(data CompetitorReportData, isVideo bool) string {
var sb strings.Builder
// 一、亮点表现分析
sb.WriteString("一、亮点表现分析\n")
sb.WriteString(data.HighlightAnalysis.Summary)
sb.WriteString("\n\n")
sb.WriteString("1. 标题亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Theme)
sb.WriteString("\n")
sb.WriteString("2. 题材亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Narrative)
sb.WriteString("\n")
sb.WriteString("3. 内容亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Content)
sb.WriteString("\n")
sb.WriteString("4. 文案亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Copywriting)
sb.WriteString("\n")
sb.WriteString("5. 数据亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Data)
sb.WriteString("\n")
if isVideo && data.HighlightAnalysis.Points.Music != "" {
sb.WriteString("6. 配乐亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Music)
sb.WriteString("\n")
}
// 二、数据表现分析
sb.WriteString("\n二、数据表现分析\n")
sb.WriteString("1. 浏览量表现:")
sb.WriteString(data.DataPerformance.Views)
sb.WriteString("\n")
if isVideo && data.DataPerformance.Completion != "" {
sb.WriteString("2. 完播率表现:")
sb.WriteString(data.DataPerformance.Completion)
sb.WriteString("\n")
sb.WriteString("3. 点赞/分享/评论表现:")
} else {
sb.WriteString("2. 点赞/分享/评论表现:")
}
sb.WriteString(data.DataPerformance.Engagement)
sb.WriteString("\n")
// 三、整体总结及可优化建议
sb.WriteString("\n三、整体总结及可优化建议\n")
sb.WriteString(data.OverallSummary)
return sb.String()
}
// AICompetitorReport 生成竞品报告接口
func AICompetitorReport(ctx *gin.Context) {
var req CompetitorReportRequest
if err := ctx.ShouldBindJSON(&req); err != nil {
service.Error(ctx, errors.New("参数错误"))
return
}
if req.TextPrompt == "" && req.ImagePrompt == "" {
service.Error(ctx, errors.New("文本和图片提示词不能同时为空"))
return
}
// 检查是否至少提供了视频或图片
if len(req.Videos) == 0 && len(req.Images) == 0 {
service.Error(ctx, errors.New("至少需要提供一个视频或图片"))
return
}
if len(req.Videos) > 1 {
service.Error(ctx, errors.New("当前只能选一个视频"))
return
}
// 第一步调用AI理解视频/图片内容
vlPrompt := "请你详细描述这些视频或者这些图片中的内容分别是什么,请详细描述,不要遗漏任何细节。如果有配乐或背景音乐,请详细描述配乐的节奏、风格和情感特点"
vlResult, err := qwen.VL(req.Videos, req.Images, vlPrompt, req.Model)
if err != nil {
// 检查是否是文件下载超时错误(内容过大)
errMsg := err.Error()
if contains(errMsg, "Download multimodal file timed out") || contains(errMsg, "timed out") {
service.Error(ctx, errors.New("内容过大,请重新选择"))
} else {
service.Error(ctx, fmt.Errorf("AI理解视频图片失败: %v", err))
}
return
}
// 获取理解后的内容
if len(vlResult.Choices) == 0 {
service.Error(ctx, errors.New("AI理解返回结果为空"))
return
}
vlContent := vlResult.Choices[0].Message.Content
// 定义协程结果结构
type textResult struct {
text string
err error
}
type imageResult struct {
imageURL string
err error
}
// 根据 TextPrompt 和 ImagePrompt 是否为空决定启动哪些协程
needText := req.TextPrompt != ""
needImage := req.ImagePrompt != ""
var textChan chan textResult
var imageChan chan imageResult
// 如果需要生成文本,启动文本生成协程
if needText {
textChan = make(chan textResult, 1)
go func() {
// 根据是否有视频来判断作品类型
isVideo := len(req.Videos) > 0
// 构建文本生成提示词:理解内容 + 用户要求JSON格式
// 重要必须明确要求使用英文标点符号确保返回的JSON符合规范
// 重要:必须基于内容给出分析性回复,即使没有提供具体数据
var textPrompt string
if isVideo {
textPrompt = fmt.Sprintf(`你必须严格输出以下JSON格式不要输出任何其他内容输出必须以 { 开头并以 } 结束
重要提示
1. 所有字符串值必须使用英文标点符号包括英文逗号, 英文句号. 英文冒号: 英文引号" 禁止使用中文标点符号
2. 即使没有提供具体数据也要基于视频和图片内容给出分析性回复禁止回复"未提供数据""暂无数据"等类似内容而应该根据内容分析数据表现如根据时长分析完播率潜力根据内容质量分析互动潜力等
3. 配乐亮点(music字段)禁止回复"未提供配乐信息""没有配乐信息"等类似内容即使没有识别到配乐也要根据视频整体风格和内容特点编写合理的配乐分析根据视频风格推断适合的配乐类型根据内容节奏分析配乐潜力等
基于以下视频和图片的内容描述
%s
用户要求仅作为内容参考不会改变JSON结构
%s
JSON结构是固定的请将内容填充到对应的value中禁止修改key禁止添加额外字段禁止输出任何说明文字
{"highlight_analysis":{"summary":"[78字以内的概述]","points":{"theme":"[标题亮点最多60字]","narrative":"[题材亮点最多60字]","content":"[内容亮点最多60字]","copywriting":"[文案亮点最多60字]","data":"[数据亮点最多60字]","music":"[配乐亮点仅视频最多60字]"}},"data_performance_analysis":{"views":"[浏览量表现最多60字]","completion_rate":"[完播率表现仅视频最多60字]","engagement":"[点赞/分享/评论表现最多60字]"},"overall_summary_and_optimization":"[整体总结及可优化建议最多300字]"}`, vlContent, req.TextPrompt)
} else {
textPrompt = fmt.Sprintf(`你必须严格输出以下JSON格式不要输出任何其他内容输出开头并以 }必须以 { 结束
重要提示
1. 所有字符串值必须使用英文标点符号包括英文逗号, 英文句号. 英文冒号: 英文引号" 禁止使用中文标点符号
2. 即使没有提供具体数据也要基于视频和图片内容给出分析性回复禁止回复"未提供数据""暂无数据"等类似内容而应该根据内容分析数据表现如根据内容质量分析互动潜力等
基于以下视频和图片的内容描述
%s
用户要求仅作为内容参考不会改变JSON结构
%s
JSON结构是固定的请将内容填充到对应的value中禁止修改key禁止添加额外字段禁止输出任何说明文字
{"highlight_analysis":{"summary":"[100字以内的概述]","points":{"theme":"[标题亮点最多60字]","narrative":"[题材亮点最多60字]","content":"[内容亮点最多60字]","copywriting":"[文案亮点最多60字]","data":"[数据亮点最多60字]"}},"data_performance_analysis":{"views":"[浏览量表现最多60字]","engagement":"[点赞/分享/评论表现最多60字]"},"overall_summary_and_optimization":"[整体总结及可优化建议最多300字]"}`, vlContent, req.TextPrompt)
}
chatReq, err := buildChatRequest(textPrompt, nil)
if err != nil {
textChan <- textResult{err: err}
return
}
chatResp, err := qwen.Chat(*chatReq)
if err != nil {
textChan <- textResult{err: err}
return
}
if len(chatResp.Choices) == 0 {
textChan <- textResult{err: errors.New("文本生成返回结果为空")}
return
}
// 打印 AI 返回的原始内容(用于调试)
aiText := chatResp.Choices[0].Message.Content
fmt.Println("========== AI 返回的原始内容 ==========")
fmt.Println(aiText)
fmt.Println("=========================================")
textChan <- textResult{text: aiText}
}()
}
// 如果需要生成图片,启动图片生成协程
if needImage {
imageChan = make(chan imageResult, 1)
go func() {
// 先请求聊天获取图片提示词
imagePromptText := fmt.Sprintf("基于以下视频和图片的内容描述:\n%s\n\n请根据以下要求生成竞品报告图片的提示词\n%s\n\n重要提示生成的图片内容中不要包含任何文字仅仅是根据内容生成一张配图即可", vlContent, req.ImagePrompt)
chatReq, err := buildChatRequest(imagePromptText, nil)
if err != nil {
imageChan <- imageResult{err: err}
return
}
chatResp, err := qwen.Chat(*chatReq)
if err != nil {
imageChan <- imageResult{err: err}
return
}
if len(chatResp.Choices) == 0 {
imageChan <- imageResult{err: errors.New("图片提示词生成返回结果为空")}
return
}
imagePrompt := chatResp.Choices[0].Message.Content
// 生成图片1024*1024基于理解后的内容使用文生图
size := "1024*1024"
resultTask, err := qwen.GenerateTextImage(imagePrompt, size)
if err != nil {
imageChan <- imageResult{err: err}
return
}
if resultTask.Code != "" {
imageChan <- imageResult{err: errors.New("文生图失败: " + resultTask.Message)}
return
}
// 等待图片生成完成
result, err := qwen.ImgTaskResult(resultTask.Output.TaskID)
if err != nil {
imageChan <- imageResult{err: err}
return
}
if result == nil || len(result.Output.Results) == 0 {
imageChan <- imageResult{err: errors.New("图片生成失败")}
return
}
// 返回第一张图片的URL
imageChan <- imageResult{imageURL: result.Output.Results[0].URL}
}()
}
// 等待所有启动的协程完成
var textRes textResult
var imageRes imageResult
// 根据实际启动的协程数量等待结果
if needText && needImage {
// 两个协程都启动了,使用循环等待两个都完成
completed := 0
for completed < 2 {
select {
case textRes = <-textChan:
completed++
case imageRes = <-imageChan:
completed++
}
}
} else if needText {
// 只启动文本生成协程
textRes = <-textChan
} else if needImage {
// 只启动图片生成协程
imageRes = <-imageChan
}
// 处理文本结果(如果生成了文本)
if needText {
if textRes.err != nil {
service.Error(ctx, fmt.Errorf("生成竞品报告文本失败: %v", textRes.err))
return
}
}
// 处理图片结果(如果生成了图片)
if needImage {
if imageRes.err != nil {
service.Error(ctx, fmt.Errorf("生成竞品报告图片失败: %v", imageRes.err))
return
}
}
// 返回结果(只返回实际生成的内容)
result := CompetitorReportResponse{}
if needText {
// 将 JSON 解析为结构化数据
fmt.Println("========== 开始解析 JSON ==========")
fmt.Println("原始内容是否以 { 开头:", strings.HasPrefix(strings.TrimSpace(textRes.text), "{"))
fmt.Println("原始内容前100字符:", strings.TrimSpace(textRes.text)[:min(100, len(strings.TrimSpace(textRes.text)))])
var jsonData CompetitorReportData
if err := json.Unmarshal([]byte(textRes.text), &jsonData); err != nil {
// 如果解析失败,直接报错
fmt.Println("========== JSON 解析失败 ==========")
fmt.Println("解析错误:", err)
fmt.Println("===================================")
service.Error(ctx, errors.New("AI生成格式错误请重试"))
return
} else {
fmt.Println("========== JSON 解析成功 ==========")
fmt.Println("Summary:", jsonData.HighlightAnalysis.Summary)
fmt.Println("==================================")
// 赋值结构体到 JsonData 中
result.JsonData = &jsonData
result.Text = convertJSONToTextFromData(jsonData, len(req.Videos) > 0)
}
}
if needImage {
result.ImageURL = imageRes.imageURL
}
service.Success(ctx, result)
}

View File

@ -1,11 +1,13 @@
package cast
import (
"context"
"fmt"
"fonchain-fiee/api/cast"
"fonchain-fiee/cmd/config"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
"github.com/gin-gonic/gin"
)
@ -16,9 +18,11 @@ func UserAccounts(ctx *gin.Context) {
userInfo := login.GetUserInfoFromC(ctx)
req.ArtistUuid = fmt.Sprint(userInfo.ID)
} else {
req.ArtistUuid = "61"
req.ArtistUuid = "1234"
}
go func() {
_, _ = service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: "artistOrderInfo", ArtistUuid: req.ArtistUuid})
}()
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return

View File

@ -0,0 +1,387 @@
package bundle
import (
"context"
"errors"
"fmt"
"fonchain-fiee/api/bundle"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/bundle/common"
"fonchain-fiee/pkg/utils"
"strconv"
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/xuri/excelize/v2"
)
// 创建发票
func CreateBundleInvoice(c *gin.Context) {
var req bundle.CreateInvoiceReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.CreateInvoice(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// 创建纸质发票地址
func CreatePaperInvoiceAddress(c *gin.Context) {
var req bundle.CreatePaperInvoiceAddressReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
userInfo := login.GetUserInfoFromC(c)
req.UserId = strconv.FormatInt(int64(userInfo.ID), 10)
req.ApplyTime = time.Now().Format("2006-01-02 15:04:05")
res, err := service.BundleProvider.CreatePaperInvoiceAddress(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// 获取发票列表
func GetBundleInvoiceList(c *gin.Context) {
var req bundle.GetInvoiceListReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.GetInvoiceList(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// 获取用户信息
func GetUserInfo(c *gin.Context) {
userInfo := login.GetUserInfoFromC(c)
service.Success(c, userInfo)
}
// 获取纸质发票地址列表
func GetInvoiceExpressInfo(c *gin.Context) {
var req bundle.GetInvoiceExpressInfoReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.GetInvoiceExpressInfo(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// 更新纸质发票地址
func UpdateInvoiceExpressInfo(c *gin.Context) {
var req bundle.UpdateInvoiceExpressInfoReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.UpdateInvoiceExpressInfo(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// H5获取用户的发票列表
func GetInvoiceList(c *gin.Context) {
var req bundle.GetInvoiceInfoByOrderNoReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
userInfo := login.GetUserInfoFromC(c)
req.UserId = strconv.FormatInt(int64(userInfo.ID), 10)
res, err := service.BundleProvider.GetInvoiceInfoByOrderNo(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func ExportInvoice(c *gin.Context) {
var req bundle.GetInvoiceListReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
exportFileName := "FIEE订单发票列表_" + time.Now().Format("20060102150405") + ".xlsx"
userInfo := login.GetUserInfoFromC(c)
filePath := fmt.Sprintf("./runtime/%d/%s", userInfo.ID, exportFileName)
utils.CheckDirPath("./runtime/"+fmt.Sprint(userInfo.ID), true)
res, err := service.BundleProvider.GetInvoiceList(context.Background(), &req)
if err != nil {
service.Error(c, errors.New(common.ExportInvoiceFailed))
return
}
fmt.Println("开始写入Excel:", filePath)
if err := writeToExcelInvoiceInfo(filePath, res.Data); err != nil {
fmt.Println("写入Excel失败:", err)
service.Error(c, errors.New(common.ExportInvoiceFailed))
return
}
var scheme string
if c.GetHeader("X-Forwarded-Proto") == "https" {
scheme = "https"
} else {
scheme = "http"
}
var exportUrl string = fmt.Sprintf("%s://%s/api/fiee/static/%s", scheme, c.Request.Host, strings.Replace(filePath, "./runtime/", "", 1))
service.Success(c, gin.H{
"url": exportUrl,
})
}
func writeToExcelInvoiceInfo(filePath string, data []*bundle.InvoiceInfo) error {
f := excelize.NewFile()
sheet := "Sheet1"
// 手动表头(顺序与写入字段顺序必须一致)
headers := []string{
"是否申请纸质发票", "是否寄出", "姓名", "手机号", "国家",
"详细地址", "申请时间", "操作艺人", "艺人编号",
}
// 写表头
for i, h := range headers {
col, _ := excelize.ColumnNumberToName(i + 1)
cell := col + "1"
if err := f.SetCellValue(sheet, cell, h); err != nil {
return err
}
}
// 从第2行开始写数据
for r, it := range data {
row := r + 2
// 逐列写入(注意顺序必须和 headers 一致)
write := func(colIdx int, v interface{}) error {
col, _ := excelize.ColumnNumberToName(colIdx)
cell := fmt.Sprintf("%s%d", col, row)
return f.SetCellValue(sheet, cell, v)
}
isApplyPaperInvoice := ""
isExpress := ""
if it.PaperInvocieStatus == 1 {
isApplyPaperInvoice = "未申请"
isExpress = "未寄出"
} else if it.PaperInvocieStatus == 2 {
isApplyPaperInvoice = "已申请"
isExpress = "未寄出"
} else if it.PaperInvocieStatus == 3 {
isApplyPaperInvoice = "已申请"
isExpress = "已寄出"
}
_ = write(1, isApplyPaperInvoice)
_ = write(2, isExpress)
_ = write(3, it.Name)
_ = write(4, it.Phone)
_ = write(5, it.Country)
_ = write(6, it.Address)
_ = write(7, formatApplyTime(it.ApplyTime))
_ = write(8, it.UserName)
_ = write(9, it.UserNum)
}
// 可选:设置列宽,使表格更美观
_ = f.SetColWidth(sheet, "A", "AZ", 15)
// 保存文件
if err := f.SaveAs(filePath); err != nil {
return err
}
return nil
}
// 获取国家列表
func GetCountryList(c *gin.Context) {
list := getCountryList()
service.Success(c, map[string]interface{}{"data": list})
}
func getCountryList() []struct {
Code string `json:"code"`
Name string `json:"name"`
} {
return []struct {
Code string `json:"code"`
Name string `json:"name"`
}{
{Code: "CN", Name: "中国"},
{Code: "JP", Name: "日本"},
{Code: "US", Name: "美国"},
{Code: "HK", Name: "中国香港"},
{Code: "MO", Name: "中国澳门"},
{Code: "TW", Name: "中国台湾"},
{Code: "GB", Name: "英国"},
{Code: "KR", Name: "韩国"},
{Code: "SG", Name: "新加坡"},
{Code: "DE", Name: "德国"},
{Code: "FR", Name: "法国"},
{Code: "AU", Name: "澳大利亚"},
{Code: "CA", Name: "加拿大"},
{Code: "IT", Name: "意大利"},
{Code: "ES", Name: "西班牙"},
{Code: "NL", Name: "荷兰"},
{Code: "BE", Name: "比利时"},
{Code: "CH", Name: "瑞士"},
{Code: "AT", Name: "奥地利"},
{Code: "SE", Name: "瑞典"},
{Code: "NO", Name: "挪威"},
{Code: "DK", Name: "丹麦"},
{Code: "FI", Name: "芬兰"},
{Code: "IE", Name: "爱尔兰"},
{Code: "PT", Name: "葡萄牙"},
{Code: "GR", Name: "希腊"},
{Code: "PL", Name: "波兰"},
{Code: "CZ", Name: "捷克"},
{Code: "HU", Name: "匈牙利"},
{Code: "RO", Name: "罗马尼亚"},
{Code: "RU", Name: "俄罗斯"},
{Code: "UA", Name: "乌克兰"},
{Code: "TR", Name: "土耳其"},
{Code: "IL", Name: "以色列"},
{Code: "AE", Name: "阿联酋"},
{Code: "SA", Name: "沙特阿拉伯"},
{Code: "IN", Name: "印度"},
{Code: "MY", Name: "马来西亚"},
{Code: "TH", Name: "泰国"},
{Code: "VN", Name: "越南"},
{Code: "PH", Name: "菲律宾"},
{Code: "ID", Name: "印度尼西亚"},
{Code: "NZ", Name: "新西兰"},
{Code: "ZA", Name: "南非"},
{Code: "EG", Name: "埃及"},
{Code: "NG", Name: "尼日利亚"},
{Code: "KE", Name: "肯尼亚"},
{Code: "AR", Name: "阿根廷"},
{Code: "BR", Name: "巴西"},
{Code: "MX", Name: "墨西哥"},
{Code: "CL", Name: "智利"},
{Code: "CO", Name: "哥伦比亚"},
{Code: "PE", Name: "秘鲁"},
{Code: "LU", Name: "卢森堡"},
{Code: "SK", Name: "斯洛伐克"},
{Code: "BG", Name: "保加利亚"},
{Code: "HR", Name: "克罗地亚"},
{Code: "SI", Name: "斯洛文尼亚"},
{Code: "LT", Name: "立陶宛"},
{Code: "LV", Name: "拉脱维亚"},
{Code: "EE", Name: "爱沙尼亚"},
{Code: "RS", Name: "塞尔维亚"},
{Code: "PK", Name: "巴基斯坦"},
{Code: "BD", Name: "孟加拉国"},
{Code: "LK", Name: "斯里兰卡"},
{Code: "QA", Name: "卡塔尔"},
{Code: "KW", Name: "科威特"},
{Code: "BH", Name: "巴林"},
{Code: "OM", Name: "阿曼"},
{Code: "JO", Name: "约旦"},
{Code: "LB", Name: "黎巴嫩"},
{Code: "IR", Name: "伊朗"},
{Code: "IQ", Name: "伊拉克"},
{Code: "KZ", Name: "哈萨克斯坦"},
{Code: "UZ", Name: "乌兹别克斯坦"},
{Code: "GE", Name: "格鲁吉亚"},
{Code: "AZ", Name: "阿塞拜疆"},
{Code: "AM", Name: "亚美尼亚"},
{Code: "MN", Name: "蒙古"},
{Code: "MM", Name: "缅甸"},
{Code: "KH", Name: "柬埔寨"},
{Code: "LA", Name: "老挝"},
{Code: "BN", Name: "文莱"},
{Code: "NP", Name: "尼泊尔"},
{Code: "AF", Name: "阿富汗"},
{Code: "ET", Name: "埃塞俄比亚"},
{Code: "GH", Name: "加纳"},
{Code: "TZ", Name: "坦桑尼亚"},
{Code: "UG", Name: "乌干达"},
{Code: "MA", Name: "摩洛哥"},
{Code: "TN", Name: "突尼斯"},
{Code: "AL", Name: "阿尔巴尼亚"},
{Code: "MK", Name: "北马其顿"},
{Code: "BA", Name: "波黑"},
{Code: "ME", Name: "黑山"},
{Code: "CY", Name: "塞浦路斯"},
{Code: "MT", Name: "马耳他"},
{Code: "IS", Name: "冰岛"},
{Code: "EC", Name: "厄瓜多尔"},
{Code: "VE", Name: "委内瑞拉"},
{Code: "CR", Name: "哥斯达黎加"},
{Code: "PA", Name: "巴拿马"},
{Code: "GT", Name: "危地马拉"},
{Code: "CU", Name: "古巴"},
{Code: "DO", Name: "多米尼加"},
{Code: "JM", Name: "牙买加"},
{Code: "PR", Name: "波多黎各"},
{Code: "UY", Name: "乌拉圭"},
{Code: "BO", Name: "玻利维亚"},
{Code: "PY", Name: "巴拉圭"},
{Code: "SV", Name: "萨尔瓦多"},
{Code: "HN", Name: "洪都拉斯"},
{Code: "NI", Name: "尼加拉瓜"},
{Code: "TT", Name: "特立尼达和多巴哥"},
{Code: "BS", Name: "巴哈马"},
{Code: "BB", Name: "巴巴多斯"},
{Code: "GY", Name: "圭亚那"},
{Code: "SR", Name: "苏里南"},
{Code: "BW", Name: "博茨瓦纳"},
{Code: "ZW", Name: "津巴布韦"},
{Code: "MZ", Name: "莫桑比克"},
{Code: "AO", Name: "安哥拉"},
{Code: "CM", Name: "喀麦隆"},
{Code: "CI", Name: "科特迪瓦"},
{Code: "SN", Name: "塞内加尔"},
{Code: "LY", Name: "利比亚"},
{Code: "SD", Name: "苏丹"},
{Code: "DZ", Name: "阿尔及利亚"},
{Code: "BY", Name: "白俄罗斯"},
{Code: "MD", Name: "摩尔多瓦"},
}
}
// 时间格式化函数
func formatApplyTime(s string) string {
if s == "" {
return s
}
beijing, err := time.LoadLocation("Asia/Shanghai")
if err != nil {
return s
}
layouts := []string{
time.RFC3339, // 2026-02-03T23:01:29+08:00
"2006-01-02 15:04:05",
"2006-01-02T15:04:05Z07:00",
}
for _, layout := range layouts {
if t, err := time.Parse(layout, s); err == nil {
return t.In(beijing).Format("2006-01-02 15:04:05")
}
}
return s
}

View File

@ -200,15 +200,34 @@ func WorkConfirm(c *gin.Context) { // 确认作品并扣除余量
if balanceInfoRes.BundleStatus == common.BundleExpired {
_, err = service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_EXPIRED,
})
service.Error(c, errors.New("套餐已过期"))
return
}
if balanceInfoRes.PurchaseType == 1 {
//判断作品对应订单是否相同
if wordInfoRes.BundleOrderUuid != balanceInfoRes.OrderUUID {
//订单号不相同
//新购买的,直接扣除失败
_, err = service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_EXPIRED,
})
service.Error(c, errors.New("套餐为新套餐,确认失败"))
return
}
//相同着正常走流程
}
if wordInfoRes.WorkStatus != 4 {
service.Error(c, errors.New("作品不是待确认状态"))
return
@ -222,10 +241,11 @@ func WorkConfirm(c *gin.Context) { // 确认作品并扣除余量
{
if balanceInfoRes.ImageExtendConsumptionNumber >= balanceInfoRes.ImageExtendNumber { // 图文余量不足
_, err = service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_EXPIRED,
})
service.Error(c, errors.New("图文余量不足"))
return
@ -236,10 +256,11 @@ func WorkConfirm(c *gin.Context) { // 确认作品并扣除余量
{
if balanceInfoRes.VideoExtendConsumptionNumber >= balanceInfoRes.VideoExtendNumber { // 视频余量不足
_, err = service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
WorkAction: cast.WorkActionENUM_CONFIRM,
WorkUuid: req.WorkUuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_EXPIRED,
})
service.Error(c, errors.New("视频余量不足"))
return
@ -287,7 +308,7 @@ func WorkAnalysisConfirm(c *gin.Context) { // 确认数据分析并扣除余量
fmt.Println("res:", res)
fmt.Println("err:", err)
if err != nil {
service.Error(c, errors.New(common.UpdateWorkStatusFailed))
service.Error(c, errors.New("驳回失败"))
return
}
service.Success(c, res)
@ -309,10 +330,56 @@ func WorkAnalysisConfirm(c *gin.Context) { // 确认数据分析并扣除余量
service.Error(c, errors.New(common.GetWorkDetailFailed))
return
}
if analysisInfoRes == nil {
service.Error(c, errors.New("数据分析不存在"))
}
if balanceInfoRes.BundleStatus == common.BundleExpired {
// 套餐过期的话直接失败
_, err := service.CastProvider.UpdateWorkAnalysisStatus(c, &cast.UpdateWorkAnalysisStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
Uuid: req.Uuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
})
if err != nil {
service.Error(c, errors.New(common.UpdateWorkStatusFailed))
return
}
service.Error(c, errors.New("套餐已过期"))
return
}
if analysisInfoRes.WorkAnalysisStatus != 4 {
service.Error(c, errors.New("数据分析不是待确认状态"))
return
}
artistID, _ := strconv.ParseUint(analysisInfoRes.ArtistID, 10, 64)
if artistID != uint64(userInfo.ID) {
service.Error(c, errors.New("非本人数据分析,无法操作"))
return
}
if balanceInfoRes.PurchaseType == 1 {
// 判断数据分析对应订单是否相同
if analysisInfoRes.BundleOrderUuid != balanceInfoRes.OrderUUID {
// 订单号不同
// 说明是新购买的,直接扣除失败
_, err := service.CastProvider.UpdateWorkAnalysisStatus(c, &cast.UpdateWorkAnalysisStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
Uuid: req.Uuid,
ConfirmRemark: req.ConfirmRemark,
ConfirmStatus: 3,
})
if err != nil {
service.Error(c, errors.New(common.UpdateWorkStatusFailed))
return
}
service.Error(c, errors.New("套餐为新套餐,确认失败"))
return
}
}
var addBalanceReq bundle.AddBundleBalanceReq
addBalanceReq.UserId = int32(userInfo.ID)
@ -338,7 +405,7 @@ func WorkAnalysisConfirm(c *gin.Context) { // 确认数据分析并扣除余量
fmt.Println("res:", res)
fmt.Println("err:", err)
if err != nil {
service.Error(c, errors.New(common.UpdateWorkStatusFailed))
service.Error(c, errors.New("确认失败"))
return
}
// 如果是艺人手动确认,确认操作后,自动标记为待阅读状态
@ -457,7 +524,8 @@ func writeToExcel(filename string, items []*bundle.BundleBalanceExportItem) erro
"当前可用套餐视频数", "当前可用增值视频数", "当前已用套餐视频数", "当前已用增值视频数", "当前作废套餐视频数", "当前作废增值视频数", "当月新增可用套餐视频数", "当月新增可用增值视频数", "当月使用套餐视频数", "当月使用增值视频数", "当月作废套餐视频数", "当月作废增值视频数",
"当前可用套餐图文数", "当前可用增值图文数", "当前已用套餐图文数", "当前已用增值图文数", "当前作废套餐图文数", "当前作废增值图文数", "当月新增可用套餐图文数", "当月新增可用增值图文数", "当月使用套餐图文数", "当月使用增值图文数", "当月作废套餐图文数", "当月作废增值图文数",
"当前可用套餐数据分析数", "当前可用增值数据分析数", "当前已用套餐数据分析数", "当前已用增值数据分析数", "当前作废套餐数据分析数", "当前作废增值数据分析数", "当月新增可用套餐数据分析数", "当月新增可用增值数据分析数", "当月使用套餐数据分析数", "当月使用增值数据分析数", "当月作废套餐数据分析数", "当月作废增值数据分析数",
"当月手动扩展账号新增数", "当月手动扩展视频新增数", "当月手动扩展图文新增数", "当月手动扩展数据分析新增数", "当月新增手动扩展时长(天)", "当月手动扩展账号使用数", "当月手动扩展视频使用数", "当月手动扩展图文使用数", "当月手动扩展数据分析使用数",
"当前可用套餐竞品数", "当前可用增值竞品数", "当前已用套餐竞品数", "当前已用增值竞品数", "当前作废套餐竞品数", "当前作废增值竞品数", "当月新增可用套餐竞品数", "当月新增可用增值竞品数", "当月使用套餐竞品数", "当月使用增值竞品数", "当月作废套餐竞品数", "当月作废增值竞品数",
"当月手动扩展账号新增数", "当月手动扩展视频新增数", "当月手动扩展图文新增数", "当月手动扩展数据分析新增数", "当月新增手动扩展时长(天)", "当月手动扩展账号使用数", "当月手动扩展视频使用数", "当月手动扩展图文使用数", "当月手动扩展数据分析使用数", "当月手动扩展竞品数", "当月手动扩展竞品使用数",
}
// 写表头
@ -555,21 +623,37 @@ func writeToExcel(filename string, items []*bundle.BundleBalanceExportItem) erro
_ = write(55, int(it.MonthlyInvalidBundleDataAnalysisNumber))
_ = write(56, int(it.MonthlyInvalidIncreaseDataAnalysisNumber))
// 竞品数
_ = write(57, int(it.MonthlyBundleCompetitiveNumber))
_ = write(58, int(it.MonthlyIncreaseCompetitiveNumber))
_ = write(59, int(it.BundleCompetitiveConsumptionNumber))
_ = write(60, int(it.IncreaseCompetitiveConsumptionNumber))
_ = write(61, int(it.InvalidBundleCompetitiveNumber))
_ = write(62, int(it.InvalidIncreaseCompetitiveNumber))
_ = write(63, int(it.MonthlyNewBundleCompetitiveNumber))
_ = write(64, int(it.MonthlyNewIncreaseCompetitiveNumber))
_ = write(65, int(it.MonthlyBundleCompetitiveConsumptionNumber))
_ = write(66, int(it.MonthlyIncreaseCompetitiveConsumptionNumber))
_ = write(67, int(it.MonthlyInvalidBundleCompetitiveNumber))
_ = write(68, int(it.MonthlyInvalidIncreaseCompetitiveNumber))
// 手动扩展类
_ = write(57, int(it.MonthlyNewManualAccountNumber))
_ = write(58, int(it.MonthlyNewManualVideoNumber))
_ = write(59, int(it.MonthlyNewManualImageNumber))
_ = write(60, int(it.MonthlyNewManualDataAnalysisNumber))
_ = write(61, int(it.MonthlyNewDurationNumber))
_ = write(62, int(it.MonthlyManualAccountConsumptionNumber))
_ = write(63, int(it.MonthlyManualVideoConsumptionNumber))
_ = write(64, int(it.MonthlyManualImageConsumptionNumber))
_ = write(65, int(it.MonthlyManualDataAnalysisConsumptionNumber))
_ = write(69, int(it.MonthlyNewManualAccountNumber))
_ = write(70, int(it.MonthlyNewManualVideoNumber))
_ = write(71, int(it.MonthlyNewManualImageNumber))
_ = write(72, int(it.MonthlyNewManualDataAnalysisNumber))
_ = write(73, int(it.MonthlyNewDurationNumber))
_ = write(74, int(it.MonthlyManualAccountConsumptionNumber))
_ = write(75, int(it.MonthlyManualVideoConsumptionNumber))
_ = write(76, int(it.MonthlyManualImageConsumptionNumber))
_ = write(77, int(it.MonthlyManualDataAnalysisConsumptionNumber))
_ = write(78, int(it.MonthlyNewManualCompetitiveNumber))
_ = write(79, int(it.MonthlyManualCompetitiveConsumptionNumber))
}
// 可选:设置列宽,使表格更美观
_ = f.SetColWidth(sheet, "A", "AZ", 15)
_ = f.SetColWidth(sheet, "A", "BZ", 15)
// 保存文件
if err := f.SaveAs(filename); err != nil {
@ -609,6 +693,8 @@ func GetAccountBundleBalance(c *gin.Context) {
ImageConsumptionNumber: item.BundleImageConsumptionNumber + item.IncreaseImageConsumptionNumber + item.ManualImageNumber,
DataAnalysisNumber: item.BundleDataAnalysisNumber + item.IncreaseDataAnalysisNumber + item.ManualDataAnalysisNumber,
DataAnalysisConsumptionNumber: item.BundleDataAnalysisConsumptionNumber + item.IncreaseDataAnalysisConsumptionNumber + item.ManualDataAnalysisNumber,
CompetitiveNumber: item.BundleCompetitiveNumber + item.IncreaseCompetitiveNumber + item.ManualCompetitiveNumber,
CompetitiveConsumptionNumber: item.BundleCompetitiveConsumptionNumber + item.IncreaseCompetitiveConsumptionNumber + item.ManualCompetitiveConsumptionNumber,
Bought: item.Bought,
}
})
@ -657,10 +743,12 @@ func writeToExcelCast(filename string, items []*bundle.WorkCastInfo) error {
workCategory = "视频"
}
confirmType := ""
if it.ConfirmType == "系统自动确定" {
if it.ConfirmType == 2 {
confirmType = "系统确认"
} else {
} else if it.ConfirmType == 1 {
confirmType = "艺人确认"
} else {
confirmType = "未确认"
}
_ = write(1, it.CustomerName)
_ = write(2, it.CustomerNum)

View File

@ -708,17 +708,15 @@ func tsToStr(ts int64, layout string) string {
func ExportWorkCastInfo(ctx *gin.Context) {
var req bundle.ExportWorkCastInfoReq
if err := ctx.ShouldBindJSON(&req); err != nil {
service.Error(ctx, err)
return
}
req.StartTime = "2025-01-01 00:00:00"
req.EndTime = "2025-12-31 23:59:59"
resp, err := service.BundleProvider.ExportWorkCastInfo(ctx, &req)
if err != nil {
service.Error(ctx, err)
return
}
exportFileName := "作品上传数据_2025-12-31" + ".xlsx"
exportFileName := "作品上传数据_2025-12-31_" + time.Now().Format("20060102150405") + ".xlsx"
filePath := fmt.Sprintf("./runtime/%d/%s", 9999, exportFileName)
utils.CheckDirPath("./runtime/"+fmt.Sprint(9999), true)
@ -740,13 +738,10 @@ func ExportWorkCastInfo(ctx *gin.Context) {
func ExportBundlePriceInfo(ctx *gin.Context) {
var req bundle.BundleBalanceExportReq
if err := ctx.ShouldBindJSON(&req); err != nil {
service.Error(ctx, err)
return
}
exportFileName := "业务收入大表2025.1.1-2025.12.31" + ".xlsx"
exportFileName := "业务收入大表2025.1.1-2025.12.31_" + time.Now().Format("20060102150405") + ".xlsx"
filePath := fmt.Sprintf("./runtime/%d/%s", 9999, exportFileName)
utils.CheckDirPath("./runtime/"+fmt.Sprint(9999), true)
req.Month = []string{"2025-03", "2025-04", "2025-05", "2025-06", "2025-07", "2025-08", "2025-09", "2025-10", "2025-11", "2025-12"}
res, err := service.BundleProvider.BundleBalanceExport(context.Background(), &req)
if err != nil {
service.Error(ctx, errors.New(common.BalanceMetricsExportFailed))

View File

@ -7,10 +7,12 @@ import (
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/api/bundle"
"fonchain-fiee/api/order"
"fonchain-fiee/pkg/cache"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/bundle/common"
"fonchain-fiee/pkg/service/bundle/logic"
"fonchain-fiee/pkg/service/bundle/model"
bundleModel "fonchain-fiee/pkg/service/bundle/model"
"fonchain-fiee/pkg/service/upload"
"strconv"
@ -213,6 +215,14 @@ func CreateBundleOrderSignature(c *gin.Context) {
return
}
// Redis 防重复提交同一用户5秒内只能提交一次订单
lockKey := fmt.Sprintf("create_bundle_order_%d", userInfo.ID)
reply := cache.RedisClient.SetNX(lockKey, 1, 5*time.Second)
if !reply.Val() {
service.Error(c, errors.New("请勿重复提交订单,请稍后再试"))
return
}
// 校验套餐是否已购买
if err := logic.CheckUserOrder(userInfo.ID); err != nil {
service.Error(c, err)
@ -239,9 +249,9 @@ func CreateBundleOrderSignature(c *gin.Context) {
service.Error(c, err)
return
}
startDate := time.Now().Format("2006-01-02")
// 签合同(金额 + 有效期)
signContract, err := logic.SignContractV2(req.CustomerNum, bundleDetail.Contract, bundleDetail.Price+addTotalPrice, expirationDay, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence)
signContract, err := logic.SignContractV2(req.CustomerNum, bundleDetail.Contract, bundleDetail.Price+addTotalPrice, expirationDay, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence, startDate)
if err != nil {
service.Error(c, err)
return
@ -250,8 +260,10 @@ func CreateBundleOrderSignature(c *gin.Context) {
req.InviterId = userInfo.InviterID
}
// 组装订单信息
req = logic.BuildOrderRequest(req, userInfo, bundleDetail, addRecords, addTotalPrice, lastContractNo, signContract)
if err := logic.BuildOrderRequest(&req, userInfo, bundleDetail, addRecords, addTotalPrice, lastContractNo, signContract); err != nil {
service.Error(c, err)
return
}
// 校验发布平台
if len(req.PlatformIds) == 0 {
req.PlatformIds = []uint32{1, 4, 5}
@ -312,6 +324,11 @@ func VerificationSignature(c *gin.Context) {
service.Success(c, res)
return
}
payTime, err := time.Parse("2006-01-02 15:04:05", order.PayTime)
if err != nil {
service.Success(c, res)
return
}
if expirationTime.Before(time.Now()) {
service.Success(c, res)
return
@ -320,7 +337,8 @@ func VerificationSignature(c *gin.Context) {
res.Signature = true
contract := ContractUrl
expirationDate := expirationTime.Format("2006-01-02")
signContract, err := logic.SignContractV2(userInfo.SubNum, contract, 0, expirationDate, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence)
payDate := payTime.Format("2006-01-02")
signContract, err := logic.SignContractV2(userInfo.SubNum, contract, 0, expirationDate, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence, payDate)
if err != nil {
service.Error(c, err)
return
@ -354,11 +372,17 @@ func RestartSignature(c *gin.Context) {
return
}
payTime, err := time.Parse("2006-01-02 15:04:05", order.PayTime)
if err != nil {
service.Error(c, errors.New("获取订单支付日期错误"))
return
}
if expirationTime.Before(time.Now()) {
service.Error(c, errors.New("订单已过期"))
return
}
expirationDate := expirationTime.Format("2006-01-02")
payDate := payTime.Format("2006-01-02")
if order.ReSignature == 2 {
service.Error(c, errors.New("订单无需重新签署"))
@ -371,7 +395,7 @@ func RestartSignature(c *gin.Context) {
return
}
contract := ContractUrl
signContract, err := logic.SignContractV2(userInfo.SubNum, contract, 0, expirationDate, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence)
signContract, err := logic.SignContractV2(userInfo.SubNum, contract, 0, expirationDate, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence, payDate)
if err != nil {
service.Error(c, err)
return
@ -648,13 +672,136 @@ func OrderRecordsListDownload(c *gin.Context) {
_ = excelFile.Write(c.Writer)
}
func OrderRecordsListPasswordFreeDownload(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 {
// 先过滤掉 InviterId == 0 的记录
var filtered []*bundle.OrderBundleRecordInfo
for _, item := range orderList.BundleInfo {
if item.InviterId != 0 {
filtered = append(filtered, item)
}
}
// 如果过滤后为空,直接导出空结果
if len(filtered) == 0 {
excelFile, err := exportExcel(filtered)
if err != nil {
service.Error(c, err)
return
}
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)
return
}
// 收集订单里的所有用户ID仅限过滤后的
userIdSet := make(map[int64]struct{})
for _, i := range filtered {
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 filtered {
if u, ok := userMap[item.CustomerId]; ok {
item.CustomerName = u.Name
item.TelNum = u.TelNum
item.SubNum = u.SubNum
if item.InviterId != 0 {
item.InviterCode = u.InviterCode
item.InviterName = u.InviterName
}
}
}
// 用过滤后的数据覆盖原数据用于导出
orderList.BundleInfo = filtered
}
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 {
@ -682,26 +829,27 @@ func exportExcel(orderList []*bundle.OrderBundleRecordInfo) (*excelize.File, err
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)
f.SetCellValue(sheetName, fmt.Sprintf("Q%d", rowIndex), bundleInfo.InviterCode)
f.SetCellValue(sheetName, fmt.Sprintf("R%d", rowIndex), bundleInfo.InviterName)
f.SetCellValue(sheetName, fmt.Sprintf("C%d", rowIndex), GetPurchaseType(bundleInfo.PurchaseType))
f.SetCellValue(sheetName, fmt.Sprintf("D%d", rowIndex), GetPayStatusText(bundleInfo.PayStatus))
f.SetCellValue(sheetName, fmt.Sprintf("E%d", rowIndex), bundleInfo.TelNum)
f.SetCellValue(sheetName, fmt.Sprintf("F%d", rowIndex), bundleInfo.SubNum)
f.SetCellValue(sheetName, fmt.Sprintf("G%d", rowIndex), bundleInfo.CustomerName)
f.SetCellValue(sheetName, fmt.Sprintf("H%d", rowIndex), bundleInfo.BundleCreateAt)
f.SetCellValue(sheetName, fmt.Sprintf("I%d", rowIndex), bundleInfo.PayTime)
f.SetCellValue(sheetName, fmt.Sprintf("J%d", rowIndex), bundleInfo.Amount)
f.SetCellValue(sheetName, fmt.Sprintf("R%d", rowIndex), bundleInfo.InviterCode)
f.SetCellValue(sheetName, fmt.Sprintf("S%d", rowIndex), bundleInfo.InviterName)
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))
f.SetCellValue(sheetName, fmt.Sprintf("K%d", r), add.OrderAddNo)
f.SetCellValue(sheetName, fmt.Sprintf("L%d", r), add.Amount)
f.SetCellValue(sheetName, fmt.Sprintf("M%d", r), add.SettlementAmount)
f.SetCellValue(sheetName, fmt.Sprintf("N%d", r), GetCurrencyTypeText(add.CurrencyType))
f.SetCellValue(sheetName, fmt.Sprintf("O%d", r), add.HandlingFee)
f.SetCellValue(sheetName, fmt.Sprintf("P%d", r), add.OrderAddCreateAt)
f.SetCellValue(sheetName, fmt.Sprintf("Q%d", r), GetPayStatusText(add.AddPayStatus))
}
} else {
for i := 8; i <= 15; i++ {
@ -725,6 +873,16 @@ func GetPayStatusText(status int32) string {
return strconv.Itoa(int(status))
}
}
func GetPurchaseType(status uint64) string {
switch status {
case 1:
return "新购"
case 2:
return "续费"
default:
return strconv.Itoa(int(status))
}
}
// 辅助函数:获取货币类型文本
func GetCurrencyTypeText(currencyType int32) string {
@ -1054,3 +1212,63 @@ func ExportOrderInfoOss(c *gin.Context) {
service.Success(c, &bundleModel.ExportResponse{ExportUrl: exportUrl})
}
func CreatInvoice(c *gin.Context) {
var orderInof model.InvoiceInfo
if err := c.ShouldBindBodyWith(&orderInof, binding.JSON); err != nil {
service.Error(c, err)
return
}
//生成发票
orderRecord, err := service.BundleProvider.GetOrderInfoByOrderNo(context.Background(), &bundle.GetOrderInfoByOrderNoReq{
Uuid: orderInof.OrderUUID,
})
if err != nil {
service.Error(c, err)
return
}
amountType := strconv.FormatInt(orderRecord.AmountType, 10)
applyTime := orderInof.ApplyTime
payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
payTimeString := payTime.Format("20060102")
fmt.Println("发票payTimeString :", payTimeString, "发票applyTime :", applyTime, "发票payTime :", payTime)
fmt.Println("发票时间数据获取完成")
err = createInvoice(orderRecord.UserId, orderRecord.UserNum, orderRecord.UserName, orderRecord.Address, orderRecord.Phone, orderRecord.BundleName, orderRecord.OrderNo, "1", amountType, orderRecord.TotalAmount, payTimeString, payTimeString, applyTime)
if err != nil {
fmt.Println("生成发票失败:", err)
service.Error(c, errors.New("生成发票失败:"+err.Error()))
return
}
service.Success(c, "生成发票成功")
}
func CreateDownloadInvoice(c *gin.Context) {
var orderInof model.InvoiceDownloadInfo
if err := c.ShouldBindBodyWith(&orderInof, binding.JSON); err != nil {
service.Error(c, err)
return
}
fmt.Println("下载对应发票订单编号 :", orderInof.OrderNo)
//生成发票
orderRecord, err := service.BundleProvider.GetOrderInfoByOrderNo(context.Background(), &bundle.GetOrderInfoByOrderNoReq{
OrderNo: orderInof.OrderNo,
})
if err != nil {
service.Error(c, err)
return
}
amountType := strconv.FormatInt(orderRecord.AmountType, 10)
applyTime := orderRecord.PayTime
payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
payTimeString := payTime.Format("20060102")
fmt.Println("发票payTimeString :", payTimeString, "发票applyTime :", applyTime, "发票payTime :", payTime)
fmt.Println("发票时间数据获取完成")
invoiceUrl, err := createDownloadInvoice(orderRecord.UserId, orderRecord.UserNum, orderRecord.UserName, orderRecord.Address, orderRecord.Phone, orderRecord.BundleName, orderRecord.OrderNo, "1", amountType, orderRecord.TotalAmount, payTimeString, payTimeString, applyTime)
if err != nil {
fmt.Println("生成发票失败:", err)
service.Error(c, errors.New("生成发票失败:"+err.Error()))
return
}
service.Success(c, &bundleModel.ExportResponse{ExportUrl: invoiceUrl})
}

View File

@ -21,7 +21,7 @@ const (
OnlyAddValueListByOrderNoFailed = "根据订单号查询增值套餐失败"
)
//官网报告
// 官网报告
const (
ErrorCreateReportFailed = "创建官网报告失败"
ErrorDeleteReportFailed = "删除官网报告失败"
@ -30,7 +30,7 @@ const (
ErrorDisplayReportFailed = "显示官网报告失败"
)
//官网成员管理
// 官网成员管理
const (
ErrorCreateMemberFailed = "创建官网成员失败"
ErrorDeleteMemberFailed = "删除官网成员失败"
@ -45,7 +45,7 @@ const (
ErrorDisplayBoardOfDirectorsFailed = "显示董事会成员失败"
)
//官网邮箱通知
// 官网邮箱通知
const (
ErrorEmailAlertSubmitFailed = "提交邮箱通知失败"
ErrorGetEmailInformationListFailed = "获取邮箱通知列表失败"
@ -66,6 +66,7 @@ const (
InvalidValueAddBundleNum = "套餐数量无效"
ThePackageHasExpired = "当前套餐已过期"
ErrorPermanentPackage = "永久套餐无需购买"
ErrPurchaseType = "购买类型错误"
)
const (
OrderTypePackage = 1 // 套餐
@ -75,6 +76,10 @@ const (
TimeUnitMonth = 2
TimeUnitYear = 3
)
const (
NewPurchaseOrder = 1 //新购
RenewalOrder = 2 //续费
)
const (
ErrorExportOrderInfo = "导出订单信息失败"
)
@ -124,7 +129,7 @@ const (
InsufficientBalance = "余量不足"
)
//用户套餐状态
// 用户套餐状态
const (
BundleExpired = 1 //已过期
BundleNotExpired = 0 //未过期
@ -141,6 +146,11 @@ const (
BalanceMetricsExportFailed = "服务使用明细数据导出失败"
)
// 发票管理
const (
ExportInvoiceFailed = "发票导出失败"
)
// 素材库
const (
FileListFailed = "素材库列表查询失败"

View File

@ -25,6 +25,9 @@ func ValidateRequest(c *gin.Context, req *bundle.OrderCreateRecord) error {
return errors.New(common.MissLanguageTypes)
}
}
if req.PurchaseType != common.NewPurchaseOrder && req.PurchaseType != common.RenewalOrder {
return errors.New(common.ErrPurchaseType)
}
return nil
}
@ -200,9 +203,9 @@ func buildAddRecord(addService *bundle.ValueAddServiceLang, uid string, price fl
}
// 组装订单请求
func BuildOrderRequest(req bundle.OrderCreateRecord, userInfo login.Info,
func BuildOrderRequest(req *bundle.OrderCreateRecord, userInfo login.Info,
bundleDetail *bundle.BundleProfileLang, addRecords []*bundle.OrderCreateAddRecord,
addTotalPrice float32, lastContractNo, signContract string) bundle.OrderCreateRecord {
addTotalPrice float32, lastContractNo, signContract string) error {
req.CustomerNum = userInfo.SubNum
req.CustomerName = userInfo.Name
@ -217,7 +220,18 @@ func BuildOrderRequest(req bundle.OrderCreateRecord, userInfo login.Info,
req.Status = bundleModel.OrderSigned
req.AddRecords = addRecords
req.PayType = 1
return req
//确认购买类型
if req.PurchaseType == common.RenewalOrder {
currentOrder, err := service.BundleProvider.GetInEffectOrderRecord(context.Background(), &bundle.GetInEffectOrderRecordRequest{
UserID: userInfo.ID,
})
if err != nil {
return err
}
req.RenewalOrderUUID = currentOrder.Uuid
}
return nil
}
func calculateExpirationDate(startDate time.Time, num int32, unit string) string {
//now := time.Now()

View File

@ -10,11 +10,12 @@ import (
"os"
"time"
"github.com/google/uuid"
"github.com/signintech/gopdf"
"go.uber.org/zap"
)
func SignContractV2(customerNum, contract string, price float32, expirationDate string, nickName string, idCard string, address string) (outputUrl string, err error) {
func SignContractV2(customerNum, contract string, price float32, expirationDate string, nickName string, idCard string, address string, startDate string) (outputUrl string, err error) {
filePath := model.MediaPath + customerNum + time.Now().Format("20060102150405") + ".pdf"
downloadFileErr := DownloadFile(filePath, contract)
if downloadFileErr != nil {
@ -23,7 +24,7 @@ func SignContractV2(customerNum, contract string, price float32, expirationDate
return outputUrl, errors.New(common.ErrorDownloadFile)
}
signFile := model.MediaPath + customerNum + "signed" + time.Now().Format("20060102150405") + ".pdf"
signFile := model.MediaPath + customerNum + "signed" + uuid.New().String() + ".pdf"
/*signErr := InsertSignature(filePath, signFile, signImgPath, contractNo, idNo, telNum, address, price)
if signErr != nil {
@ -31,7 +32,7 @@ func SignContractV2(customerNum, contract string, price float32, expirationDate
return outputUrl, errors.New(common.ErrorInsertSignature)
}*/
signErr := InsertSignatureV2(filePath, signFile, price, expirationDate, nickName, idCard, address)
signErr := InsertSignatureV2(filePath, signFile, price, expirationDate, nickName, idCard, address, startDate)
if signErr != nil {
zap.L().Error("insert signature error: ", zap.Error(signErr))
return outputUrl, errors.New(common.ErrorInsertSignature)
@ -46,7 +47,7 @@ func SignContractV2(customerNum, contract string, price float32, expirationDate
return outputUrl, nil
}
func InsertSignatureV2(templatePath, outputPath string, price float32, expirationDate string, nickName string, idCard string, address string) error {
func InsertSignatureV2(templatePath, outputPath string, price float32, expirationDate string, nickName string, idCard string, address string, startDate string) error {
fmt.Println("================================templatePath:", templatePath)
fmt.Println("================================outputPath:", outputPath)
fmt.Println("================================price:", price)
@ -84,24 +85,30 @@ func InsertSignatureV2(templatePath, outputPath string, price float32, expiratio
// 英文格式的时间
parsedTime, err := time.Parse("2006-01-02", expirationDate)
if err != nil {
fmt.Println("时间解析错误: %v", err)
fmt.Println(expirationDate)
return errors.New("时间解析错误")
}
// 英文格式的时间
startTime, err := time.Parse("2006-01-02", startDate)
if err != nil {
return errors.New("时间解析错误")
}
year := parsedTime.Format("2006") // "2006"
month := parsedTime.Format("01") // "01"
day := parsedTime.Format("02") // "02"
startYear := startTime.Format("2006")
startMonth := startTime.Format("01")
startDay := startTime.Format("02")
// 填 第一页 日期-姓名-身份证号
pdf.SetPage(onePage)
pdf.SetX(232)
pdf.SetY(152)
pdf.Cell(nil, year)
pdf.Cell(nil, startYear)
pdf.SetX(279)
pdf.SetY(152)
pdf.Cell(nil, month)
pdf.Cell(nil, startMonth)
pdf.SetX(313)
pdf.SetY(152)
pdf.Cell(nil, day)
pdf.Cell(nil, startDay)
pdf.SetX(370)
pdf.SetY(152)
pdf.Cell(nil, nickName)

View File

@ -13,3 +13,12 @@ const (
type ExportResponse struct {
ExportUrl string `json:"exportUrl"`
}
type InvoiceInfo struct {
ApplyTime string `json:"applyTime"`
OrderUUID string `json:"orderUuid"`
}
type InvoiceDownloadInfo struct {
OrderNo string `json:"orderNo"`
}

View File

@ -0,0 +1,35 @@
package model
type QuestionnairePDFData struct {
// 基本信息
CustomerNum string `json:"customerNum"`
CustomerName string `json:"customerName"`
BundleName string `json:"bundleName"`
BundleStartDate string `json:"bundleStartDate"`
BundleEndDate string `json:"bundleEndDate"`
VideoNum string `json:"videoNum"`
AccountNum string `json:"accountNum"`
ImagesNum string `json:"imagesNum"`
DataAnalysisNum string `json:"dataAnalysisNum"`
CompetitiveNum string `json:"competitiveNum"`
ValueAddVideoNum string `json:"valueAddVideoNum"`
// 评分1-5
Score1 int `json:"score1"`
Score2 int `json:"score2"`
Score3 int `json:"score3"`
Score4 int `json:"score4"`
Score5 int `json:"score5"`
Score6 int `json:"score6"`
Score7 int `json:"score7"`
// 意见
Opinion1 string `json:"opinion1"`
Opinion2 string `json:"opinion2"`
Opinion3 string `json:"opinion3"`
// 提交信息
Submitter string `json:"submitter"`
SubmissionDate string `json:"submissionDate"`
Address string `json:"address"`
}

View File

@ -7,6 +7,8 @@ import (
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/api/bundle"
"fonchain-fiee/api/cast"
castProto "fonchain-fiee/api/cast"
"fonchain-fiee/api/order"
"fonchain-fiee/api/payment"
"fonchain-fiee/pkg/cache"
@ -15,6 +17,7 @@ import (
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/bundle/common"
bundleModel "fonchain-fiee/pkg/service/bundle/model"
"fonchain-fiee/pkg/service/invoice"
"io"
"math"
"net/http"
@ -329,7 +332,9 @@ func CreateAntomPay(c *gin.Context) {
}
}
}
go func() {
_, _ = service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: "artistOrderInfo", ArtistUuid: fmt.Sprint(orderLimit.UserId)})
}()
if req.ProductAllPrice == 0 {
////创建对账单 todo 待修改
_, err = service.BundleProvider.CreateReconciliation(context.Background(), &bundle.ReconciliationInfo{
@ -351,7 +356,11 @@ func CreateAntomPay(c *gin.Context) {
service.Error(c, err)
return
}
//获取上一笔订单信息:如果没有查询到代表首次购买 需要判断异常情况
lastOrderInfo, _ := service.BundleProvider.OrderRecordsDetail(context.Background(), &bundle.OrderRecordsDetailRequest{
CustomerID: strconv.FormatUint(orderLimit.UserId, 10),
Status: 2,
})
_, updateStatusErr := service.BundleProvider.UpdateOrderRecordByOrderNo(context.Background(), &bundle.OrderRecord{
OrderNo: req.OutTradeNo,
PayTime: common.GetBeijingTime(),
@ -363,6 +372,25 @@ func CreateAntomPay(c *gin.Context) {
service.Error(c, updateStatusErr)
return
}
// //生成发票
// fmt.Println("开始生成发票")
// orderRecord, err := service.BundleProvider.GetOrderInfoByOrderNo(context.Background(), &bundle.GetOrderInfoByOrderNoReq{
// Uuid: req.OutTradeNo, //因为需求更新实际传入的是订单的uuid
// })
// if err != nil {
// service.Error(c, err)
// return
// }
// amountType := strconv.FormatInt(orderRecord.AmountType, 10)
// // 将当前时间转换为北京时间
// applyTime := common.GetBeijingTime()
// payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
// payTimeString := payTime.Format("20060102")
// fmt.Println("发票payTimeString :", payTimeString, "发票applyTime :", applyTime, "发票payTime :", payTime)
// fmt.Println("发票时间数据获取完成")
// err = createInvoice(orderRecord.UserId, orderRecord.UserNum, orderRecord.UserName, orderRecord.Address, orderRecord.Phone, orderRecord.BundleName, orderRecord.OrderNo, "1", amountType, orderRecord.TotalAmount, payTimeString, payTimeString, applyTime)
switch orderLimit.Type {
case common.OrderTypePackage:
@ -434,6 +462,7 @@ func CreateAntomPay(c *gin.Context) {
service.Error(c, err)
return
}
handleMediaAccountBinding(orderLimit.UserId, orderLimit.PurchaseType, int(orderLimit.AccountNumber), lastOrderInfo)
service.Success(c)
return
@ -448,7 +477,15 @@ func CreateAntomPay(c *gin.Context) {
antomReq.Domain = "fiee"
antomReq.Amount = req.ProductAllPrice
antomReq.Currency = req.ProductPriceCurrency
antomReq.OutTradeNo = req.OutTradeNo
//antomReq.OutTradeNo = req.OutTradeNo
//uuidV4, err := uuid.NewV4()
//if err != nil {
// fmt.Println("生成错误", err)
// service.Error(c, errors.New("订单编号生成失败"))
// return
//}
//antomReq.OutTradeNo = uuidV4.String()
antomReq.OutTradeNo = orderLimit.OrderUUID
antomReq.ReturnUrl = req.SuccessUrl
//调用微服务获取支付地址
@ -491,7 +528,7 @@ func CreateAntomPay(c *gin.Context) {
CurrencyType: int32(currencyType),
PayStatus: 1,
UserID: userInfo.ID,
SerialNumber: result.CheckoutSessionId,
SerialNumber: req.OutTradeNo,
})
if err != nil {
fmt.Println("=============== antom创建支付创建对账单报错", err)
@ -581,6 +618,7 @@ func AntomWebhook(c *gin.Context) {
fmt.Println("支付时间:", paymentTime)
fmt.Println("支付结果状态:", resultStatus)
fmt.Println("支付结果消息:", resultMessage)
/*
* S: notifyType 为PAYMENT_RESULT时表示支付成功 notifyType 为PAYMENT_PENDING时表示支付处理中
* F: 表示支付失败
@ -602,9 +640,23 @@ func AntomWebhook(c *gin.Context) {
}
fmt.Println("resp.Status:", resp.Status)
if resp.Status == "paid" {
//添加余额
orderLimit, err := service.BundleProvider.OrderListByOrderUuid(context.Background(), &bundle.OrderInfoByOrderUuidRequest{
OrderUuid: resp.OutTradeNo,
})
if err != nil {
service.Error(c, err)
return
}
//获取上一笔订单信息:如果没有查询到代表首次购买 需要判断异常情况
lastOrderInfo, _ := service.BundleProvider.OrderRecordsDetail(context.Background(), &bundle.OrderRecordsDetailRequest{
CustomerID: strconv.FormatUint(orderLimit.UserId, 10),
Status: 2,
})
//支付成功
_, updateStatusErr := service.BundleProvider.UpdateOrderRecordByOrderNo(context.Background(), &bundle.OrderRecord{
OrderNo: resp.OutTradeNo,
_, updateStatusErr := service.BundleProvider.UpdateOrderRecordByOrderUuid(context.Background(), &bundle.OrderRecord{
Uuid: resp.OutTradeNo,
PayTime: common.GetBeijingTime(),
Status: bundleModel.OrderPaid,
})
@ -614,9 +666,9 @@ func AntomWebhook(c *gin.Context) {
}
// 更新对账单
_, err = service.BundleProvider.UpdateReconciliationStatusBySerialNumber(context.Background(), &bundle.UpdateStatusAndPayTimeBySerialNumber{
PayTime: paymentTime,
PayTime: common.GetBeijingTime(),
PaymentStatus: 2,
SerialNumber: requestId,
SerialNumber: resp.OutTradeNo,
})
if err != nil {
fmt.Println("=============== antom回调更新对账单报错", err)
@ -626,13 +678,34 @@ func AntomWebhook(c *gin.Context) {
}
//添加余额
orderLimit, err := service.BundleProvider.OrderListByOrderNo(context.Background(), &bundle.OrderInfoByOrderNoRequest{
OrderNo: resp.OutTradeNo,
// orderLimit, err = service.BundleProvider.OrderListByOrderUuid(context.Background(), &bundle.OrderInfoByOrderUuidRequest{
// OrderUuid: resp.OutTradeNo,
// })
// if err != nil {
// service.Error(c, err)
// return
// }
//生成发票
orderRecord, err := service.BundleProvider.GetOrderInfoByOrderNo(context.Background(), &bundle.GetOrderInfoByOrderNoReq{
Uuid: resp.OutTradeNo, //因为需求更新实际传入的是订单的uuid
})
if err != nil {
service.Error(c, err)
return
}
amountType := strconv.FormatInt(orderRecord.AmountType, 10)
applyTime := common.GetBeijingTime()
payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
payTimeString := payTime.Format("20060102")
fmt.Println("发票payTimeString :", payTimeString, "发票applyTime :", applyTime, "发票payTime :", payTime)
fmt.Println("发票时间数据获取完成")
err = createInvoice(orderRecord.UserId, orderRecord.UserNum, orderRecord.UserName, orderRecord.Address, orderRecord.Phone, orderRecord.BundleName, orderRecord.OrderNo, "1", amountType, orderRecord.TotalAmount, payTimeString, payTimeString, applyTime)
if err != nil {
service.Error(c, errors.New("生成发票失败"))
return
}
//购买套餐
switch orderLimit.Type {
case common.OrderTypePackage:
@ -669,6 +742,9 @@ func AntomWebhook(c *gin.Context) {
service.Error(c, errors.New("无效的订单类型"))
return
}
go func() {
_, _ = service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: "artistOrderInfo", ArtistUuid: fmt.Sprint(orderLimit.UserId)})
}()
var timeUnit uint32
switch orderLimit.Unit {
case "天":
@ -692,11 +768,15 @@ func AntomWebhook(c *gin.Context) {
Type: 2, //自行购买
OperatorName: orderLimit.UserName,
OperatorId: orderLimit.UserId,
CompetitiveAdditional: uint32(orderLimit.CompetitiveAdditional), //添加竞品数
})
if err != nil {
service.Error(c, err)
return
}
// 处理媒体账号绑定逻辑
handleMediaAccountBinding(orderLimit.UserId, orderLimit.PurchaseType, int(orderLimit.AccountNumber), lastOrderInfo)
}
service.Success(c)
}
@ -759,3 +839,291 @@ func HomePageRoll(c *gin.Context) {
service.Success(c, roll)
return
}
func createInvoice(userId, userNum, userName, address, phone, bundleName, orderNo, spec, priceType, totalAmount, transactionDate, invoiceDate, applyTime string) error {
// InvoiceInfo 发票信息
InvoiceResp, err := service.BundleProvider.GetLastInvoiceNo(context.Background(), &bundle.GetLastInvoiceNoReq{})
if err != nil {
fmt.Println("获取最后一张发票号码失败:", err)
return err
}
lastestInvoiceNo := ""
if InvoiceResp.LastNo != "" {
lastestInvoiceNo = InvoiceResp.LastNo
}
currentInvoiceNo := ""
// 获取 lastestInvoiceNo CNY-ART-202501010001的 长度
if priceType == "1" {
priceType = "CNY"
//人民币
if lastestInvoiceNo == "" {
currentInvoiceNo = fmt.Sprintf("CNY-MDA-%s0001", transactionDate)
} else {
lastestSeq := lastestInvoiceNo[16:]
var seqNum int
_, err = fmt.Sscanf(lastestSeq, "%d", &seqNum)
if err != nil {
return err
}
seqNum++
currentInvoiceNo = fmt.Sprintf("CNY-MDA-%s%04d", transactionDate, seqNum)
}
} else if priceType == "2" {
priceType = "USD"
//美元
if lastestInvoiceNo == "" {
currentInvoiceNo = fmt.Sprintf("USD-MDA-%s0001", transactionDate)
} else {
lastestSeq := lastestInvoiceNo[16:]
var seqNum int
_, err = fmt.Sscanf(lastestSeq, "%d", &seqNum)
if err != nil {
return err
}
seqNum++
currentInvoiceNo = fmt.Sprintf("USD-MDA-%s%04d", transactionDate, seqNum)
}
} else {
//默认美元
priceType = "USD"
if lastestInvoiceNo == "" {
currentInvoiceNo = fmt.Sprintf("USD-MDA-%s0001", transactionDate)
} else {
lastestSeq := lastestInvoiceNo[16:]
var seqNum int
_, err = fmt.Sscanf(lastestSeq, "%d", &seqNum)
if err != nil {
return err
}
seqNum++
currentInvoiceNo = fmt.Sprintf("USD-MDA-%s%04d", transactionDate, seqNum)
}
}
fmt.Println("当前发票号码:", currentInvoiceNo)
payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
transactionDate = payTime.Format("2006-01-02")
invoiceUrl, err := invoice.MakeInvoice(currentInvoiceNo, userName, address, phone, bundleName, spec, priceType, totalAmount, transactionDate, "")
if err != nil {
return err
}
fmt.Println("发票生成成功URL:", invoiceUrl)
_, err = service.BundleProvider.CreateInvoice(context.Background(), &bundle.CreateInvoiceReq{
UserId: userId,
UserNum: userNum,
UserName: userName,
OrderNo: orderNo,
ApplyTime: applyTime,
InvoiceType: 1,
InvoiceNo: currentInvoiceNo,
InvoiceUrl: invoiceUrl,
PaperInvocieStatus: 1,
Remark: "系统自动生成发票",
})
if err != nil {
return err
}
return nil
}
// MediaAccount 媒体账号信息
type MediaAccount struct {
UUID string
PlatformID uint32
}
// handleMediaAccountBinding 处理媒体账号绑定逻辑(统一解绑方法)
// userId: 用户ID
// purchaseType: 购买类型(新购/续费)
// currentAccountNum: 本次购买的账号数
// lastOrderInfo: 上次订单信息
func handleMediaAccountBinding(userId uint64, purchaseType int32, currentAccountNum int, lastOrderInfo *bundle.OrderRecordsDetailResponse) {
// 1. 获取用户的媒体账号列表
MediaList, err := service.CastProvider.MediaUserList(context.Background(), &castProto.MediaUserListReq{
Page: 1,
PageSize: 999,
ArtistUuid: strconv.FormatUint(userId, 10),
})
if err != nil {
logger.Warnf("Failed to get media list for user %d: %v", userId, err)
return
}
if MediaList == nil || len(MediaList.Data) == 0 {
logger.Infof("No media accounts found for user %d", userId)
return
}
// 2. 收集过期的媒体账号信息包含平台ID
var expiredAccounts []MediaAccount
for _, media := range MediaList.Data {
if media.Expired == 1 {
expiredAccounts = append(expiredAccounts, MediaAccount{
UUID: media.MediaAccountUuid,
PlatformID: media.PlatformID,
})
}
}
if len(expiredAccounts) == 0 {
logger.Infof("No expired media accounts found for user %d", userId)
return
}
// 3. 判断是否首次购买
isFirstPurchase := lastOrderInfo == nil || lastOrderInfo.OrderRecord == nil || len(lastOrderInfo.OrderRecord.AddInfos) == 0
// 4. 根据购买类型处理解绑逻辑
var accountsToUnbind []string
if purchaseType == common.NewPurchaseOrder {
// 新购订单
if isFirstPurchase {
logger.Infof("First time purchase for user %d, no need to unbind accounts", userId)
return
}
// 非首次购买的新购:解绑所有过期账号
for _, account := range expiredAccounts {
accountsToUnbind = append(accountsToUnbind, account.UUID)
}
logger.Infof("New purchase for user %d, will unbind all %d expired accounts", userId, len(accountsToUnbind))
} else if purchaseType == common.RenewalOrder {
// 续费订单
if isFirstPurchase {
logger.Infof("No previous order found for renewal user %d, no need to unbind accounts", userId)
return
}
// 获取上次购买的账号数
var lastAccountNum int
for _, addInfo := range lastOrderInfo.OrderRecord.AddInfos {
if addInfo.ServiceType == 4 { // ServiceType 4 表示账号服务
lastAccountNum += int(addInfo.Num)
}
}
logger.Infof("Renewal order for user %d: current=%d, last=%d, expired=%d",
userId, currentAccountNum, lastAccountNum, len(expiredAccounts))
// 如果当前购买数量 >= 上次购买数量,不需要解绑
if currentAccountNum >= lastAccountNum {
logger.Infof("No need to unbind accounts for renewal user %d: current(%d) >= last(%d)",
userId, currentAccountNum, lastAccountNum)
return
}
// 当前购买数量 < 上次购买数量,按优先级解绑差额部分
needUnbindCount := lastAccountNum - currentAccountNum
// 定义平台优先级(数字越小优先级越高,优先保留)
// TikTok(1) > DM(4) > Bluesky(5) > Instagram(3) > YouTube(2)
platformPriority := map[uint32]int{
1: 1, // TikTok - 最高优先级,最后解绑
4: 2, // DM
5: 3, // Bluesky
3: 4, // Instagram
2: 5, // YouTube - 最低优先级,最先解绑
}
// 按优先级排序(优先级低的排在前面,先解绑)
sortedAccounts := make([]MediaAccount, len(expiredAccounts))
copy(sortedAccounts, expiredAccounts)
for i := 0; i < len(sortedAccounts)-1; i++ {
for j := 0; j < len(sortedAccounts)-i-1; j++ {
priority1 := platformPriority[sortedAccounts[j].PlatformID]
priority2 := platformPriority[sortedAccounts[j+1].PlatformID]
if priority1 == 0 {
priority1 = 999
}
if priority2 == 0 {
priority2 = 999
}
// 降序排列:优先级数字大的排在前面(先解绑)
if priority1 < priority2 {
sortedAccounts[j], sortedAccounts[j+1] = sortedAccounts[j+1], sortedAccounts[j]
}
}
}
// 取前needUnbindCount个账号进行解绑
if needUnbindCount > len(sortedAccounts) {
needUnbindCount = len(sortedAccounts)
}
for i := 0; i < needUnbindCount; i++ {
accountsToUnbind = append(accountsToUnbind, sortedAccounts[i].UUID)
}
logger.Infof("Renewal downgrade for user %d, will unbind %d accounts by priority", userId, len(accountsToUnbind))
}
// 5. 执行解绑操作
if len(accountsToUnbind) > 0 {
successCount := 0
failCount := 0
for _, accountUUID := range accountsToUnbind {
if _, err := service.CastProvider.UpdateMediaAccInfo(context.Background(), &castProto.UpdateMediaAccInfoReq{
MediaAccountUuid: accountUUID,
Expired: 2,
ExpiredSource: castProto.ExpiredMediaSourceENUM_UpdateMediaSource_CHARGE,
}); err != nil {
logger.Errorf("Failed to unbind account %s for user %d: %v", accountUUID, userId, err)
failCount++
} else {
successCount++
}
}
logger.Infof("Unbind completed for user %d: success=%d, fail=%d", userId, successCount, failCount)
}
}
func createDownloadInvoice(userId, userNum, userName, address, phone, bundleName, orderNo, spec, priceType, totalAmount, transactionDate, invoiceDate, applyTime string) (string, error) {
// InvoiceInfo 发票信息
currentInvoiceNo := ""
// 获取 lastestInvoiceNo CNY-ART-202501010001的 长度
InvoiceInfo, err := service.BundleProvider.GetInvoiceInfoByOrderNo(context.Background(), &bundle.GetInvoiceInfoByOrderNoReq{
UserId: userId,
OrderNo: orderNo,
})
if err != nil {
return "", err
}
if InvoiceInfo.Data[0].InvoiceNo != "" {
currentInvoiceNo = InvoiceInfo.Data[0].InvoiceNo
} else {
fmt.Println("获取发票号码失败:没有找到发票号码")
return "", errors.New("获取发票号码失败:没有找到发票号码")
}
if priceType == "1" {
priceType = "CNY"
} else if priceType == "2" {
priceType = "USD"
} else {
priceType = "USD"
}
fmt.Println("当前发票号码:", currentInvoiceNo)
payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
transactionDate = payTime.Format("2006-01-02")
invoiceDate = time.Now().Format("2006-01-02")
invoiceUrl, err := invoice.MakeInvoice(currentInvoiceNo, userName, address, phone, bundleName, spec, priceType, totalAmount, transactionDate, invoiceDate)
if err != nil {
return "", err
}
fmt.Println("发票生成成功URL:", invoiceUrl)
return invoiceUrl, nil
}

View File

@ -0,0 +1,136 @@
package bundle
import (
"context"
"errors"
"fonchain-fiee/api/bundle"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/bundle/model"
"fonchain-fiee/pkg/service/upload"
"fonchain-fiee/pkg/utils"
"strconv"
"time"
m "fonchain-fiee/pkg/model"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
)
func IsSendSurvey(c *gin.Context) {
var req bundle.SendQuestionnaireSurveyRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.SendQuestionnaireSurvey(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func QuestionnaireSurveyList(c *gin.Context) {
var req bundle.GetQuestionnaireSurveyListRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.GetQuestionnaireSurveyList(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func QuestionnaireSurveyBundleInfo(c *gin.Context) {
var req bundle.GetQuestionnaireSurveyInfoRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.GetQuestionnaireSurveyInfo(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
func QuestionnaireSurveyCreate(c *gin.Context) {
var req bundle.CreateQuestionnaireSurveyAnswerRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
ip := c.ClientIP()
address, err := utils.GetAddressByIP(ip)
if err != nil {
service.Error(c, errors.New("获取地址失败"))
return
}
//if req.Longitude == "" || req.Latitude == "" {
// service.Error(c, errors.New("获取定位失败"))
// return
//}
//address, err := utils.ReverseGeo(req.Longitude, req.Latitude, "ZhCN")
//if err != nil {
// service.Error(c, errors.New("获取地址失败"))
// return
//}
surveyInfo, err := service.BundleProvider.GetQuestionnaireSurveyInfo(c, &bundle.GetQuestionnaireSurveyInfoRequest{UserTel: req.UserTel})
if err != nil {
service.Error(c, err)
return
}
templateDir := "./data/满意度调成报告模板.pdf"
outputPath := m.MediaPath + "questionnaire_" + uuid.NewString() + ".pdf"
err = utils.QuestionnaireSurveyPDF(templateDir, outputPath, &model.QuestionnairePDFData{
//CustomerNum: surveyInfo.BundleInfo.,
CustomerName: surveyInfo.UserName,
BundleName: surveyInfo.BundleInfo.BundleName,
BundleStartDate: surveyInfo.BundleInfo.StartAt,
BundleEndDate: surveyInfo.BundleInfo.ExpiredAt,
VideoNum: strconv.FormatInt(int64(surveyInfo.BundleInfo.BundleVideoNumber), 10),
AccountNum: strconv.FormatInt(int64(surveyInfo.BundleInfo.BundleAccountNumber), 10),
ImagesNum: strconv.FormatInt(int64(surveyInfo.BundleInfo.BundleImageNumber), 10),
DataAnalysisNum: strconv.FormatInt(int64(surveyInfo.BundleInfo.BundleDataNumber), 10),
CompetitiveNum: strconv.FormatInt(int64(surveyInfo.BundleInfo.BundleCompetitiveNumber), 10),
ValueAddVideoNum: strconv.FormatInt(int64(surveyInfo.BundleInfo.IncreaseVideoNumber), 10),
Score1: int(req.SurveyAnswer.BundleAccountScore),
Score2: int(req.SurveyAnswer.BundleAccountScore),
Score3: int(req.SurveyAnswer.BundleImageScore),
Score4: int(req.SurveyAnswer.BundleDataScore),
Score5: int(req.SurveyAnswer.IncreaseVideoScore),
Score6: int(req.SurveyAnswer.ServiceResponseSpeed),
Score7: int(req.SurveyAnswer.ServiceStaffProfessionalism),
Opinion1: req.SurveyFeedback.MeritsReview,
Opinion2: req.SurveyFeedback.SuggestionsorImprovements,
Opinion3: req.SurveyFeedback.AdditionalComments,
Submitter: surveyInfo.UserName,
SubmissionDate: time.Now().Format(time.DateOnly),
Address: address,
})
if err != nil {
service.Error(c, err)
return
}
outputUrl, ossErr := upload.PutBos(outputPath, upload.PdfType, true)
if ossErr != nil {
service.Error(c, err)
return
}
//service.Success(c, outputUrl)
//return
req.SurveyUrl = outputUrl
res, err := service.BundleProvider.CreateQuestionnaireSurveyAnswer(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}

View File

@ -390,8 +390,8 @@ func AutoCreateUserAndOrder(c *gin.Context) {
// 当前 未将 签名 写入合同中 todo 金额和有效时间待修改
contract := ContractUrl
expirationDay = t.AddDate(1, 0, 0).Format("2006-01-02")
signContract, signContractErr := logic.SignContractV2(userReq.UserNum, contract, TotalPrice, expirationDay, unfinishInfo.UserName, unfinishInfo.CardNum, unfinishInfo.PlaceOfResidence)
startDate := t.Format("2006-01-02")
signContract, signContractErr := logic.SignContractV2(userReq.UserNum, contract, TotalPrice, expirationDay, unfinishInfo.UserName, unfinishInfo.CardNum, unfinishInfo.PlaceOfResidence, startDate)
if signContractErr != nil {
service.Error(c, signContractErr)
return
@ -419,6 +419,7 @@ func AutoCreateUserAndOrder(c *gin.Context) {
//expirationTime := t.AddDate(10, 0, 0).Format("2006-01-02 15:04:05")
//orderReq.ExpirationTime = expirationTime
orderReq.PlatformIds = []uint32{1, 4, 5}
orderReq.PurchaseType = common.NewPurchaseOrder
_, err = service.BundleProvider.CreateOrderRecord(context.Background(), &orderReq)
if err != nil {
service.Error(c, err)
@ -491,6 +492,26 @@ func AutoCreateUserAndOrder(c *gin.Context) {
return
}
//生成发票
orderRecord, err := service.BundleProvider.GetOrderInfoByOrderNo(context.Background(), &bundle.GetOrderInfoByOrderNoReq{
OrderNo: unfinishInfo.OrderNo, //因为需求更新实际传入的是订单的uuid
})
if err != nil {
service.Error(c, err)
return
}
amountType := strconv.FormatInt(orderRecord.AmountType, 10)
applyTime := unfinishInfo.PayTime
payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
payTimeString := payTime.Format("20060102")
fmt.Println("发票payTimeString :", payTimeString, "发票applyTime :", applyTime, "发票payTime :", payTime)
fmt.Println("发票时间数据获取完成")
err = createInvoice(orderRecord.UserId, orderRecord.UserNum, orderRecord.UserName, orderRecord.Address, orderRecord.Phone, orderRecord.BundleName, orderRecord.OrderNo, "1", amountType, orderRecord.TotalAmount, payTimeString, payTimeString, applyTime)
if err != nil {
service.Error(c, errors.New("生成发票失败"))
return
}
//如果是购买套餐 1:创建新的余量信息CreateBundleBalance 2 添加扩展记录BundleExtend
_, err = service.BundleProvider.CreateBundleBalance(context.Background(), &bundle.CreateBundleBalanceReq{
UserId: int32(userResp.UserId),

View File

@ -1,26 +1,37 @@
package cast
package cast
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/api/aryshare"
"fonchain-fiee/api/bundle"
"fonchain-fiee/api/cast"
"fonchain-fiee/pkg/cache"
"fonchain-fiee/pkg/common/qwen"
"fonchain-fiee/pkg/e"
modelCast "fonchain-fiee/pkg/model/cast"
"fonchain-fiee/pkg/model/login"
modelQwen "fonchain-fiee/pkg/model/qwen"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/bundle/common"
"fonchain-fiee/pkg/utils"
"fonchain-fiee/pkg/utils/stime"
"path/filepath"
"strconv"
"strings"
"sync"
"time"
"math/rand"
"dubbo.apache.org/dubbo-go/v3/common/constant"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
"github.com/xuri/excelize/v2"
"go.uber.org/zap"
)
@ -32,17 +43,7 @@ func CreateWorkAnalysis(ctx *gin.Context) {
service.Error(ctx, err)
return
}
newCtx := NewCtxWithUserInfo(ctx)
artistID, _ := strconv.ParseUint(req.ArtistID, 10, 64)
if _, err = CheckUserBundleBalance(int32(artistID), modelCast.BalanceTypeDataValue); err != nil {
if err != nil && err.Error() == e.ErrorBalanceInsufficient {
service.Error(ctx, errors.New("该艺人数据可用次数为0"))
return
}
service.Error(ctx, err)
return
}
resp, err := service.CastProvider.CreateWorkAnalysis(newCtx, req)
resp, err := CreateWorkAnalysisCore(ctx, req)
if err != nil {
service.Error(ctx, err)
return
@ -51,6 +52,350 @@ func CreateWorkAnalysis(ctx *gin.Context) {
return
}
func CreateWorkAnalysisCore(ctx *gin.Context, req *cast.CreateWorkAnalysisReq) (*cast.CreateWorkAnalysisResp, error) {
newCtx := NewCtxWithUserInfo(ctx)
if req.SubNum == "" {
return nil, errors.New("艺人编号不能为空")
}
// 根据 subNum 查询艺人 artistUuid
subInfoResp, err := service.AccountFieeProvider.SubNumGetInfo(context.Background(), &accountFiee.SubNumGetInfoRequest{
SubNum: req.SubNum,
Domain: "app",
})
if err != nil {
zap.L().Error("AccountFieeProvider.SubNumGetInfo", zap.Error(err), zap.String("subNum", req.SubNum))
return nil, errors.New("自媒体用户查询失败")
}
if subInfoResp == nil || subInfoResp.Id == 0 {
return nil, errors.New("自媒体用户不存在")
}
req.ArtistID = fmt.Sprint(subInfoResp.Id)
req.ArtistName = subInfoResp.Name
req.ArtistPhone = subInfoResp.TelNum
artistID := uint64(subInfoResp.Id)
if _, err = CheckUserBundleBalance(int32(artistID), modelCast.BalanceTypeDataValue); err != nil {
if err.Error() == e.ErrorBalanceInsufficient {
return nil, errors.New("该艺人数据可用次数为0")
}
return nil, err
}
resp1, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{UserId: int32(artistID)})
if err != nil {
zap.L().Error("GetBundleBalanceByUserId", zap.Error(err), zap.Uint64("artistID", artistID))
return nil, errors.New("获取套餐订单失败")
}
if resp1.OrderUUID == "" {
return nil, errors.New("订单不存在")
}
req.BundleOrderUuid = resp1.OrderUUID
resp, err := service.CastProvider.CreateWorkAnalysis(newCtx, req)
if err != nil {
return nil, err
}
return resp, nil
}
// ImportWorkAnalysisBatch 通过 Excel 批量导入数据分析
// Excel 列顺序SubNum | ArtistName | SubmitTime | PeriodTypeFans | PeriodTypeViews | PeriodTypeLikes | PeriodTypeComments | PeriodTypeShares | IsRefreshData(1=false,2=true)
func ImportWorkAnalysisBatch(ctx *gin.Context) {
excelFile, err := ctx.FormFile("file")
if err != nil {
service.Error(ctx, err)
return
}
loginInfo := login.GetUserInfoFromC(ctx)
lockKey := fmt.Sprintf("import_work_analysis_batch:%d", loginInfo.ID)
replay := cache.RedisClient.SetNX(lockKey, time.Now().Format("20060102150405"), 5*time.Minute)
if !replay.Val() {
service.Error(ctx, errors.New("有导入任务正在进行,请稍后再试"))
return
}
defer cache.RedisClient.Del(lockKey)
tempDir := "./runtime/report_pdf"
_, err = utils.CheckDirPath(tempDir, true)
if err != nil {
service.Error(ctx, err)
return
}
fileName := fmt.Sprintf("%d_work_analysis.xlsx", time.Now().UnixMicro())
excelPath := filepath.Join(tempDir, fileName)
if err = ctx.SaveUploadedFile(excelFile, excelPath); err != nil {
service.Error(ctx, err)
return
}
excelData, err := excelize.OpenFile(excelPath)
if err != nil {
service.Error(ctx, err)
return
}
defer excelData.Close()
rows, err := excelData.GetRows("Sheet1")
if err != nil {
service.Error(ctx, err)
return
}
newCtx := NewCtxWithUserInfo(ctx)
// 写入表头
_ = excelData.SetCellValue("Sheet1", "J1", "DateInt")
_ = excelData.SetCellValue("Sheet1", "K1", "ConfirmType")
_ = excelData.SetCellValue("Sheet1", "L1", "结果")
successCount := 0
for line, row := range rows {
if line == 0 {
continue // 跳过表头
}
if len(row) == 0 {
continue
}
// Excel 行号1-basedline=1 → 行号 2
cellL := fmt.Sprintf("L%d", line+1)
// 第一列SubNum
subNum := ""
if len(row) > 0 {
subNum = utils.CleanString(row[0])
}
if subNum == "" {
_ = excelData.SetCellValue("Sheet1", cellL, "SubNum 不能为空")
continue
}
// 第二列ArtistName
artistName := ""
if len(row) > 1 {
artistName = utils.CleanString(row[1])
}
// 第三列SubmitTime
submitTime := ""
if len(row) > 2 {
submitTime = row[2]
}
// 第四列PeriodTypeFans
var periodTypeFans uint32
if len(row) > 3 && utils.CleanString(row[3]) != "" {
v, _ := strconv.ParseUint(utils.CleanString(row[3]), 10, 32)
periodTypeFans = uint32(v)
}
// 第五列PeriodTypeViews
var periodTypeViews uint32
if len(row) > 4 && utils.CleanString(row[4]) != "" {
v, _ := strconv.ParseUint(utils.CleanString(row[4]), 10, 32)
periodTypeViews = uint32(v)
}
// 第六列PeriodTypeLikes
var periodTypeLikes uint32
if len(row) > 5 && utils.CleanString(row[5]) != "" {
v, _ := strconv.ParseUint(utils.CleanString(row[5]), 10, 32)
periodTypeLikes = uint32(v)
}
// 第七列PeriodTypeComments
var periodTypeComments uint32
if len(row) > 6 && utils.CleanString(row[6]) != "" {
v, _ := strconv.ParseUint(utils.CleanString(row[6]), 10, 32)
periodTypeComments = uint32(v)
}
// 第八列PeriodTypeShares
var periodTypeShares uint32
if len(row) > 7 && utils.CleanString(row[7]) != "" {
v, _ := strconv.ParseUint(utils.CleanString(row[7]), 10, 32)
periodTypeShares = uint32(v)
}
// 第九列IsRefreshData1 → false, 2 → true
isRefreshData := false
if len(row) > 8 && utils.CleanString(row[8]) == "2" {
isRefreshData = true
}
// 第十列DateIntYYYYMMDD 格式,直接从 Excel 读取)
var dateInt int32
if len(row) > 9 && utils.CleanString(row[9]) != "" {
v, _ := strconv.ParseInt(utils.CleanString(row[9]), 10, 32)
dateInt = int32(v)
}
// 第十一列ConfirmType1 艺人确认2 系统自动确认)
var confirmType int32
if len(row) > 10 && utils.CleanString(row[10]) != "" {
v, _ := strconv.ParseInt(utils.CleanString(row[10]), 10, 32)
confirmType = int32(v)
}
// 根据 subNum 查询艺人信息
subInfoResp, err := service.AccountFieeProvider.SubNumGetInfo(context.Background(), &accountFiee.SubNumGetInfoRequest{
SubNum: subNum,
Domain: "app",
})
if err != nil {
zap.L().Error("ImportWorkAnalysisBatch SubNumGetInfo", zap.Error(err), zap.String("subNum", subNum))
_ = excelData.SetCellValue("Sheet1", cellL, fmt.Sprintf("自媒体用户查询失败:%s", err.Error()))
continue
}
if subInfoResp == nil || subInfoResp.Id == 0 {
_ = excelData.SetCellValue("Sheet1", cellL, "自媒体用户不存在")
continue
}
artistID := uint64(subInfoResp.Id)
// 查询艺人套餐订单
balanceResp, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
UserId: int32(artistID),
})
if err != nil {
zap.L().Error("ImportWorkAnalysisBatch GetBundleBalanceByUserId", zap.Error(err), zap.Uint64("artistID", artistID))
_ = excelData.SetCellValue("Sheet1", cellL, fmt.Sprintf("获取套餐订单失败:%s", err.Error()))
continue
}
if balanceResp.OrderUUID == "" {
_ = excelData.SetCellValue("Sheet1", cellL, "订单不存在")
continue
}
// 若 artistName 为空则使用账号服务中的姓名
if artistName == "" {
artistName = subInfoResp.Name
}
// 将 submitTimeYYYY-MM-DD 00:00:00加随机 9~15 小时、0~59 分钟、0~59 秒,使提交时间更真实
if submitTime != "" {
if parsedTime, parseErr := time.Parse("2006-01-02 15:04:05", submitTime); parseErr == nil {
randomDuration := time.Duration(rand.Intn(7)+9)*time.Hour +
time.Duration(rand.Intn(60))*time.Minute +
time.Duration(rand.Intn(60))*time.Second
submitTime = parsedTime.Add(randomDuration).Format("2006-01-02 15:04:05")
}
}
// 提升到外部作用域,供 importReq 使用
var aiAnalysis string
var mediaAccountCount int32
var workVideoCount, workImageCount int32
// 调用 ArtistMetricsSeries 获取艺人指标数据并写入 Analysis
metricsReq := &cast.ArtistMetricsSeriesReq{
ArtistUUID: fmt.Sprint(subInfoResp.Id),
Date: dateInt,
PeriodTypeFans: periodTypeFans,
PeriodTypeViews: periodTypeViews,
PeriodTypeLikes: periodTypeLikes,
PeriodTypeComments: periodTypeComments,
PeriodTypeShares: periodTypeShares,
}
// 并行调用 ArtistMetricsSeries 和 GetArtistWorkStats
var metricsResp *cast.ArtistMetricsSeriesResp
var workStatsResp *cast.GetArtistWorkStatsResp
var metricsErr, workStatsErr error
wg := sync.WaitGroup{}
wg.Add(2)
go func() {
defer wg.Done()
metricsResp, metricsErr = service.CastProvider.ArtistMetricsSeries(context.Background(), metricsReq)
}()
go func() {
defer wg.Done()
workStatsResp, workStatsErr = service.CastProvider.GetArtistWorkStats(newCtx, &cast.GetArtistWorkStatsReq{
ArtistUuid: fmt.Sprint(subInfoResp.Id),
StatusUpdateTime: submitTime,
})
}()
wg.Wait()
if workStatsErr == nil && workStatsResp != nil {
mediaAccountCount = int32(workStatsResp.AccountCount)
workVideoCount = int32(workStatsResp.VideoCount)
workImageCount = int32(workStatsResp.ImageCount)
} else if workStatsErr != nil {
zap.L().Warn("ImportWorkAnalysisBatch GetArtistWorkStats failed", zap.Error(workStatsErr), zap.String("subNum", subNum))
}
if metricsErr != nil {
zap.L().Warn("ImportWorkAnalysisBatch ArtistMetricsSeries failed", zap.Error(metricsErr), zap.String("subNum", subNum))
} else if metricsResp != nil {
// 构建与 ArtistMetricsSeries HTTP 接口相同的 respMap
raw, _ := json.Marshal(metricsResp)
respMap := make(map[string]interface{})
_ = json.Unmarshal(raw, &respMap)
respMap["accountConsumptionNumber"] = mediaAccountCount
respMap["videoCount"] = workVideoCount
respMap["imageCount"] = workImageCount
// 调用 AI 生成分析文本
aiAnalysis, _ = generateArtistMetricsAnalysis(metricsResp)
if aiAnalysis == "" {
zap.L().Warn("ImportWorkAnalysisBatch generateArtistMetricsAnalysis returned empty", zap.String("subNum", subNum))
}
respMap["analysis"] = aiAnalysis
}
importReq := &cast.ImportWorkAnalysisReq{
SubNum: subNum,
ArtistID: fmt.Sprint(subInfoResp.Id),
ArtistName: artistName,
ArtistPhone: subInfoResp.TelNum,
BundleOrderUuid: balanceResp.OrderUUID,
SubmitTime: submitTime,
PeriodTypeFans: periodTypeFans,
PeriodTypeViews: periodTypeViews,
PeriodTypeLikes: periodTypeLikes,
PeriodTypeComments: periodTypeComments,
PeriodTypeShares: periodTypeShares,
IsRefreshData: isRefreshData,
Analysis: aiAnalysis,
MediaAccountCount: mediaAccountCount,
WorkVideoCount: workVideoCount,
WorkImageCount: workImageCount,
Views: 1,
Likes: 1,
Comments: 1,
Shares: 1,
FansCount: 1,
MostActiveDay: 1,
BestPostTime: 1,
Date: dateInt,
ConfirmType: confirmType,
}
importResp, err := service.CastProvider.ImportWorkAnalysis(newCtx, importReq)
if err != nil {
zap.L().Error("ImportWorkAnalysisBatch ImportWorkAnalysis", zap.Error(err), zap.String("subNum", subNum))
_ = excelData.SetCellValue("Sheet1", cellL, fmt.Sprintf("导入失败:%s", err.Error()))
continue
}
// 导入成功,将返回的 UUID 写入 L 列
_ = excelData.SetCellValue("Sheet1", cellL, importResp.Uuid)
successCount++
}
// 将修改后的 Excel 写入 buffer 并返回给客户端下载
buf, err := excelData.WriteToBuffer()
if err != nil {
service.Error(ctx, err)
return
}
utils.ResponseXls(ctx, bytes.NewReader(buf.Bytes()), fmt.Sprintf("数据分析导入结果_%d成功", successCount))
}
// UpdateWorkAnalysis 更新作品分析
func UpdateWorkAnalysis(ctx *gin.Context) {
var req *cast.UpdateWorkAnalysisReq
@ -60,6 +405,17 @@ func UpdateWorkAnalysis(ctx *gin.Context) {
return
}
newCtx := NewCtxWithUserInfo(ctx)
artistID, _ := strconv.ParseUint(req.ArtistUUID, 10, 64)
resp1, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{UserId: int32(artistID)})
if err != nil {
service.Error(ctx, err)
return
}
if resp1.OrderUUID == "" {
service.Error(ctx, errors.New("订单不存在"))
return
}
req.BundleOrderUuid = resp1.OrderUUID
_, err = service.CastProvider.UpdateWorkAnalysis(newCtx, req)
if err != nil {
service.Error(ctx, err)
@ -138,7 +494,59 @@ func ListWorkAnalysis(ctx *gin.Context) {
service.Error(ctx, err)
return
}
RefreshWorkAnalysisApproval(ctx, resp.Data)
// RefreshWorkAnalysisApproval(ctx, resp.Data)
service.Success(ctx, resp)
return
}
// ListWorkAnalysis 获取作品分析列表
func ListWorkAnalysisForApp(ctx *gin.Context) {
var req *cast.ListWorkAnalysisReq
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
newCtx := NewCtxWithUserInfo(ctx)
loginInfo := login.GetUserInfoFromC(ctx)
// 查询用户套餐有没有过期
balanceInfoRes, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
UserId: int32(loginInfo.ID),
})
if err != nil {
zap.L().Error("ListWorkAnalysisForApp GetBundleBalanceByUserId", zap.Any("err", err))
service.Error(ctx, errors.New(common.GetUserBalanceFailed))
return
}
// 套餐未过期的话,传入 subNum ,只获取该套餐的有效期内数据
if balanceInfoRes.BundleStatus == common.BundleNotExpired {
zap.L().Info("ListWorkAnalysisForApp BundleNotExpired", zap.Any("loginInfo", loginInfo))
// 调用GetBundleBalanceByOrderUUID接口
resp1, err := service.BundleProvider.GetBundleBalanceByOrderUUID(context.Background(), &bundle.GetBundleBalanceByOrderUUIDReq{OrderUUID: balanceInfoRes.OrderUUID})
if err != nil {
err = errors.New("获取最初非续费订单失败")
service.Error(ctx, err)
return
}
fmt.Println("resp1", resp1)
req.SubmitStartTime = time.Unix(resp1.StartTime, 0).Format("2006-01-02 15:04:05")
req.SubmitEndTime = time.UnixMilli(balanceInfoRes.ExpiredTime).Format("2006-01-02 15:04:05")
if resp1.Status == 1 {
// 说明查询失败,采用当前套餐的开始时间
req.SubmitStartTime = time.UnixMilli(balanceInfoRes.StartTime).Format("2006-01-02 15:04:05")
}
}
if balanceInfoRes.BundleStatus == common.BundleExpired {
req.SubmitStartTime = time.UnixMilli(balanceInfoRes.StartTime).Format("2006-01-02 15:04:05")
req.SubmitEndTime = time.UnixMilli(balanceInfoRes.ExpiredTime).Format("2006-01-02 15:04:05")
}
resp, err := service.CastProvider.ListWorkAnalysis(newCtx, req)
if err != nil {
zap.L().Error("ListWorkAnalysisForApp ListWorkAnalysis", zap.Any("err", err))
service.Error(ctx, err)
return
}
// RefreshWorkAnalysisApproval(ctx, resp.Data)
service.Success(ctx, resp)
return
}
@ -181,7 +589,7 @@ func RefreshWorkAnalysisApprovalStatus(ctx *gin.Context, approvalIDAnalysisUuidM
for _, v := range approvalIDs {
newData[v] = data[v]
}
newCtx := NewCtxWithUserInfo(ctx)
newCtx := NewCtxWithUserInfo(ctx, "业务部门")
if len(newData) > 0 {
for approvalId, v := range newData {
if v.ID == 0 {
@ -190,11 +598,13 @@ func RefreshWorkAnalysisApprovalStatus(ctx *gin.Context, approvalIDAnalysisUuidM
Uuid: approvalIDAnalysisUuidMap[approvalId],
ApprovalID: fmt.Sprint(approvalId),
ApprovalReply: "",
ApprovalTime: v.UpdatedAt,
})
continue
}
var workAction cast.WorkActionENUM
if v.Status == 2 {
uTimes, _ := stime.DatetimeToTimes(v.UpdatedAt, "2006-01-02 15:04:05")
if v.Status == 2 && int64(uTimes) <= time.Now().Unix() {
workAction = cast.WorkActionENUM_APPROVAL_PASS
} else if v.Status == 3 {
workAction = cast.WorkActionENUM_APPROVAL_REJECT
@ -206,6 +616,7 @@ func RefreshWorkAnalysisApprovalStatus(ctx *gin.Context, approvalIDAnalysisUuidM
Uuid: approvalIDAnalysisUuidMap[approvalId],
ApprovalID: fmt.Sprint(approvalId),
ApprovalReply: v.Reply,
ApprovalTime: v.UpdatedAt,
})
}
}
@ -227,6 +638,13 @@ func DeleteWorkAnalysis(ctx *gin.Context) {
service.Error(ctx, err)
return
}
if service.BundleProvider != nil {
if _, e := service.BundleProvider.RevertTaskCompletionByUUIDItem(context.Background(), &bundle.RevertTaskCompletionByUUIDItemRequest{Uuid: req.Uuid}); e != nil {
zap.L().Error("回撤数量失败", zap.Error(e))
}
} else {
zap.L().Warn("BundleProvider is nil, skipping RevertTaskCompletionByUUIDItem")
}
service.Success(ctx, nil)
return
}
@ -420,16 +838,204 @@ func ArtistMetricsSeries(ctx *gin.Context) {
service.Error(ctx, err)
return
}
newCtx := NewCtxWithUserInfo(ctx)
resp, err := service.CastProvider.ArtistMetricsSeries(newCtx, req)
if err != nil {
service.Error(ctx, err)
if req.ArtistUUID == "" {
service.Error(ctx, errors.New("参数错误"))
return
}
service.Success(ctx, resp)
subNum := ""
if strings.HasPrefix(strings.ToUpper(req.ArtistUUID), "FE") {
subNum = req.ArtistUUID
} else {
artistID, err := strconv.ParseUint(req.ArtistUUID, 10, 64)
if err != nil {
service.Error(ctx, errors.New("艺人编号格式不正确"))
return
}
infoResp, err := service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
ID: artistID,
Domain: "app",
})
if err != nil {
service.Error(ctx, errors.New("自媒体用户查询失败"))
return
}
if infoResp == nil || infoResp.SubNum == "" {
service.Error(ctx, errors.New("自媒体用户不存在"))
return
}
subNum = infoResp.SubNum
}
var subInfoResp *accountFiee.UserInfoResponse
var subInfoErr error
var workStatsResp *cast.GetArtistWorkStatsResp
var metricsResp *cast.ArtistMetricsSeriesResp
var workStatsErr, metricsErr error
wg := sync.WaitGroup{}
wg.Add(2)
// 并行调用 SubNumGetInfo、ArtistMetricsSeries
go func() {
defer wg.Done()
subInfoResp, subInfoErr = service.AccountFieeProvider.SubNumGetInfo(context.Background(), &accountFiee.SubNumGetInfoRequest{
SubNum: subNum,
Domain: "app",
})
}()
go func() {
defer wg.Done()
metricsResp, metricsErr = service.CastProvider.ArtistMetricsSeries(context.Background(), req)
}()
wg.Wait()
if subInfoErr != nil {
service.Error(ctx, errors.New("自媒体用户查询失败"))
return
}
if subInfoResp == nil || subInfoResp.Id == 0 {
service.Error(ctx, errors.New("自媒体用户不存在"))
return
}
req.ArtistUUID = fmt.Sprint(subInfoResp.Id)
// 将 ArtistMetricsSeriesReq 中 int 类型日期YYYYMMDD格式化为时间字符串作为快照截止时间
statusUpdateTime := ""
if req.Date > 0 {
parsedDate, parseErr := time.Parse("20060102", strconv.Itoa(int(req.Date)))
if parseErr == nil {
statusUpdateTime = parsedDate.Add(17 * time.Hour).Format("2006-01-02 15:04:05")
}
}
newCtx := NewCtxWithUserInfo(ctx)
workStatsResp, workStatsErr = service.CastProvider.GetArtistWorkStats(newCtx, &cast.GetArtistWorkStatsReq{
ArtistUuid: req.ArtistUUID,
StatusUpdateTime: statusUpdateTime,
})
var accountConsumptionNumber int32
var videoCount int64
var imageCount int64
if workStatsErr == nil && workStatsResp != nil {
accountConsumptionNumber = int32(workStatsResp.AccountCount)
videoCount = workStatsResp.VideoCount
imageCount = workStatsResp.ImageCount
} else if workStatsErr != nil {
zap.L().Warn("GetArtistWorkStats failed", zap.Error(workStatsErr), zap.String("artistUUID", req.ArtistUUID), zap.String("statusUpdateTime", statusUpdateTime))
}
if metricsErr != nil {
service.Error(ctx, errors.New("查询失败"))
return
}
resp := metricsResp
raw, _ := json.Marshal(resp)
respMap := make(map[string]interface{})
_ = json.Unmarshal(raw, &respMap)
respMap["accountConsumptionNumber"] = accountConsumptionNumber
respMap["videoCount"] = videoCount
respMap["imageCount"] = imageCount
// 调用 AI 分析数据
analysis, err := generateArtistMetricsAnalysis(resp)
if err != nil {
zap.L().Error("生成艺人指标分析失败", zap.Error(err))
// AI 分析失败不影响主业务,返回空字符串
respMap["analysis"] = ""
} else {
respMap["analysis"] = analysis
}
service.Success(ctx, respMap)
return
}
// generateArtistMetricsAnalysis 调用 AI 分析艺人指标数据
func generateArtistMetricsAnalysis(resp *cast.ArtistMetricsSeriesResp) (string, error) {
if resp == nil {
return "", errors.New("数据为空")
}
// 构建分析用的数据摘要
var dataSummary strings.Builder
dataSummary.WriteString("艺人各平台数据表现如下:\n")
// 粉丝数
if resp.FansSeries != nil {
dataSummary.WriteString(fmt.Sprintf("粉丝数总数: %d (周期类型: %d, 开始日期: %d, 结束日期: %d)\n",
resp.FansSeries.FansCount, resp.FansSeries.PeriodType, resp.FansSeries.StartDate, resp.FansSeries.EndDate))
}
// 播放量
if resp.ViewsSeries != nil {
dataSummary.WriteString(fmt.Sprintf("播放量总数: %d (周期类型: %d, 开始日期: %d, 结束日期: %d)\n",
resp.ViewsSeries.ViewsCount, resp.ViewsSeries.PeriodType, resp.ViewsSeries.StartDate, resp.ViewsSeries.EndDate))
}
// 点赞数
if resp.LikesSeries != nil {
dataSummary.WriteString(fmt.Sprintf("点赞数总数: %d (周期类型: %d, 开始日期: %d, 结束日期: %d)\n",
resp.LikesSeries.LikesCount, resp.LikesSeries.PeriodType, resp.LikesSeries.StartDate, resp.LikesSeries.EndDate))
}
// 评论数
if resp.CommentsSeries != nil {
dataSummary.WriteString(fmt.Sprintf("评论数总数: %d (周期类型: %d, 开始日期: %d, 结束日期: %d)\n",
resp.CommentsSeries.CommentsCount, resp.CommentsSeries.PeriodType, resp.CommentsSeries.StartDate, resp.CommentsSeries.EndDate))
}
// 分享数
if resp.SharesSeries != nil {
dataSummary.WriteString(fmt.Sprintf("分享数总数: %d (周期类型: %d, 开始日期: %d, 结束日期: %d)\n",
resp.SharesSeries.SharesCount, resp.SharesSeries.PeriodType, resp.SharesSeries.StartDate, resp.SharesSeries.EndDate))
}
// 最佳发布时间
if resp.BestPostTime != nil {
dataSummary.WriteString(fmt.Sprintf("最佳发布时间: %s\n", resp.BestPostTime.DetailJSON))
}
// 最活跃日期
if resp.MostActiveDay != nil {
dataSummary.WriteString(fmt.Sprintf("最活跃日期: %s\n", resp.MostActiveDay.DetailJSON))
}
// 构建 prompt
prompt := fmt.Sprintf(`根据以下艺人各平台运营数据分析各平台数据表现结合相关数据简要表述优点文字内容在150-200字之间标点符号不计入字数回复时不需要返回具体字数。注意回复时请使用平台名称如TIKTOK、INS等而非数字。重要不要逐一列举所有平台名称只需提及有亮点的平台即可\n%s`, dataSummary.String())
// 调用 AI
req := modelQwen.ChatRequest{
Model: "qwen-plus",
Messages: []modelQwen.Message{
{
Role: "user",
Content: []modelQwen.Content{
{
Type: "text",
Text: prompt,
},
},
},
},
}
respAI, err := qwen.Chat(req)
if err != nil {
return "", err
}
if respAI == nil || len(respAI.Choices) == 0 {
return "", errors.New("AI 返回结果为空")
}
return respAI.Choices[0].Message.Content, nil
}
// ArtistMetricsDailyWindow 艺人指标日窗口
func ArtistMetricsDailyWindow(ctx *gin.Context) {
var req *cast.ArtistMetricsDailyWindowReq
@ -459,6 +1065,39 @@ func TobeConfirmedList(ctx *gin.Context) {
userInfo := login.GetUserInfoFromC(ctx)
req.ArtistUuid = strconv.Itoa(int(userInfo.ID))
newCtx := NewCtxWithUserInfo(ctx)
loginInfo := login.GetUserInfoFromC(ctx)
// 查询用户套餐有没有过期
balanceInfoRes, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
UserId: int32(loginInfo.ID),
})
if err != nil {
zap.L().Error("TobeConfirmedList GetBundleBalanceByUserId", zap.Any("err", err))
service.Error(ctx, errors.New(common.GetUserBalanceFailed))
return
}
// 套餐未过期的话,获取套餐的开始时间和结束时间
if balanceInfoRes.BundleStatus == common.BundleNotExpired {
zap.L().Info("TobeConfirmedList BundleNotExpired", zap.Any("loginInfo", loginInfo))
// 调用GetBundleBalanceByOrderUUID接口
resp1, err := service.BundleProvider.GetBundleBalanceByOrderUUID(context.Background(), &bundle.GetBundleBalanceByOrderUUIDReq{OrderUUID: balanceInfoRes.OrderUUID})
if err != nil {
err = errors.New("获取最初非续费订单失败")
service.Error(ctx, err)
return
}
fmt.Println("resp1", resp1)
req.StartAt = time.Unix(resp1.StartTime, 0).Format("2006-01-02 15:04:05")
req.ExpiredAt = time.UnixMilli(balanceInfoRes.ExpiredTime).Format("2006-01-02 15:04:05")
if resp1.Status == 1 {
// 说明查询失败,采用当前套餐的开始时间的前两天时间
req.StartAt = time.UnixMilli(balanceInfoRes.StartTime - 2*24*60*60*1000).Format("2006-01-02 15:04:05")
}
}
// 如果过期的话,获取套餐的开始时间和结束时间
if balanceInfoRes.BundleStatus == common.BundleExpired {
req.StartAt = time.UnixMilli(balanceInfoRes.StartTime).Format("2006-01-02 15:04:05")
req.ExpiredAt = time.UnixMilli(balanceInfoRes.ExpiredTime).Format("2006-01-02 15:04:05")
}
resp, err := service.CastProvider.TobeConfirmedList(newCtx, req)
if err != nil {
service.Error(ctx, err)
@ -486,6 +1125,24 @@ func UpdateWorkAnalysisApprovalID(ctx *gin.Context) {
return
}
// UpdateWorkAnalysisPdfUrl 更新作品分析PDF链接
func UpdateWorkAnalysisPdfUrl(ctx *gin.Context) {
var req *cast.UpdateWorkAnalysisReq
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
newCtx := NewCtxWithUserInfo(ctx)
_, err = service.CastProvider.UpdateWorkAnalysisPdfUrl(newCtx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, nil)
return
}
type CheckBundleBalanceReq struct {
ArtistID string `protobuf:"bytes,4,opt,name=artistID,proto3" json:"artistID"` // 艺人ID
BalanceType modelCast.BalanceTypeEnum `json:"balanceType"` // 套餐类型
@ -538,6 +1195,12 @@ func CheckBundleBalance(ctx *gin.Context) {
service.Error(ctx, err)
return
}
case modelCast.BalanceTypeCompetitiveValue:
if resp.CompetitiveExtendNumber-resp.CompetitiveExtendConsumptionNumber <= 0 {
err = errors.New(e.ErrorBalanceInsufficient)
service.Error(ctx, err)
return
}
}
service.Success(ctx, resp)
@ -590,6 +1253,11 @@ func autoConfirmAnalysis(ctx context.Context, analysisUuid string) (err error) {
isFailed = true
}
if infoResp == nil {
zap.L().Error("autoConfirmAnalysis GetWorkAnalysis返回nil")
return
}
if infoResp.WorkAnalysisStatus != 4 { // 4是待确认状态需要根据实际情况调整
return
}
@ -603,6 +1271,41 @@ func autoConfirmAnalysis(ctx context.Context, analysisUuid string) (err error) {
isFailed = true
}
if balanceInfoRes.BundleStatus == common.BundleExpired {
confirmRemark = "套餐已过期"
// 直接提交
_, err = service.CastProvider.UpdateWorkAnalysisStatus(context.Background(), &cast.UpdateWorkAnalysisStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
Uuid: analysisUuid,
ConfirmRemark: confirmRemark,
ConfirmStatus: 3,
})
if err != nil {
zap.L().Error("autoConfirmAnalysis UpdateWorkAnalysisStatus", zap.Any("err", err))
return
}
return
}
if balanceInfoRes.PurchaseType == 1 {
// 判断数据分析对应订单是否相同
if infoResp.BundleOrderUuid != balanceInfoRes.OrderUUID {
// 订单号不同
// 说明是新购买的,直接扣除失败
_, err = service.CastProvider.UpdateWorkAnalysisStatus(context.Background(), &cast.UpdateWorkAnalysisStatusReq{
WorkAction: cast.WorkActionENUM_CONFIRM,
Uuid: analysisUuid,
ConfirmRemark: "套餐为新套餐,确认失败",
ConfirmStatus: 3,
})
if err != nil {
return
zap.L().Error("autoConfirmAnalysis UpdateWorkAnalysisStatus", zap.Any("err", err))
}
return
}
}
var addBalanceReq bundle.AddBundleBalanceReq
addBalanceReq.UserId = int32(userID)
// 检查数据分析余量
@ -992,6 +1695,10 @@ func processMediaMetricsTask(ctx context.Context, task mediaMetricsTask) *cast.M
}
socialResp, err := service.AyrshareProvider.GetSocialAnalytics(ctx, socialReq)
if err != nil {
// 传送账号错误,用来判断是不是被封了
go func(task mediaMetricsTask) {
UpdateAccStatus(task.artistInfo.ArtistUuid, task.platformID, err.Error())
}(task)
// 构建失败记录
return buildFailedMediaMetricsItem(task.artistInfo, task.dateCN, 3, "获取社交分析数据失败", task.platformID, mediaInfoResp.Info)
}
@ -2681,3 +3388,19 @@ func retryFailedWorkMetrics(ctx context.Context, dateCN int) {
fmt.Printf("[%s] [INFO] 没有需要重试的作品指标\n", time.Now().Format("2006-01-02 15:04:05"))
}
}
func UpdateAccStatus(artistUuid string, platformID uint32, resp string) {
accResp, _err := service.CastProvider.UpdateMediaAccStatus(context.Background(), &cast.UpdateMediaAccStatusReq{
ArtistUuid: artistUuid,
PlatformID: platformID,
InfoResp: resp,
})
if _err != nil {
zap.L().Error("更新媒体账号状态失败", zap.Error(_err),
zap.String("artistUuid", artistUuid), zap.Uint32("platformID", platformID), zap.Error(_err))
return
}
if accResp != nil && accResp.ExceptionStatus == 2 {
_ = UnbindAyr([]string{accResp.MediaAccUserID})
}
}

View File

@ -14,6 +14,7 @@ import (
modelCast "fonchain-fiee/pkg/model/cast"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/upload"
"fonchain-fiee/pkg/utils"
"net/http"
"net/url"
@ -39,11 +40,33 @@ func MediaUserList(ctx *gin.Context) {
service.Error(ctx, err)
return
}
resp, err := service.CastProvider.MediaUserList(ctx, req)
resp, err := MediaListCombine(req)
if err != nil {
service.Error(ctx, err)
return
}
go func() {
seen := make(map[string]struct{})
for _, v := range resp.Data {
if v.ArtistUuid == "" {
continue
}
if _, ok := seen[v.ArtistUuid]; ok {
continue
}
seen[v.ArtistUuid] = struct{}{}
_ = SyncAsAuth(v.ArtistUuid)
}
}()
service.Success(ctx, resp)
return
}
func MediaListCombine(req *cast.MediaUserListReq) (*cast.MediaUserListResp, error) {
resp, err := service.CastProvider.MediaUserList(context.Background(), req)
if err != nil {
return nil, err
}
if req.NeedStats {
var statResp *bundle.ArtistUploadStatsResponse
zap.L().Info("MediaUserList 1")
@ -63,8 +86,7 @@ func MediaUserList(ctx *gin.Context) {
})
zap.L().Info("MediaUserList 2")
if err != nil {
service.Error(ctx, err)
return
return nil, err
}
for _, v := range resp.Data {
for _, vv := range statResp.Items {
@ -82,14 +104,7 @@ func MediaUserList(ctx *gin.Context) {
}
}
}
zap.L().Info("MediaUserList 3")
go func() {
for _, v := range resp.Data {
_ = SyncAsAuth(v.ArtistUuid)
}
}()
service.Success(ctx, resp)
return
return resp, nil
}
func UnbindManager(ctx *gin.Context) {
@ -228,6 +243,9 @@ func UpdateMediaAccount(ctx *gin.Context) {
}
return
}
go func() {
_, _ = service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: "artistOrderInfo", ArtistUuid: req.ArtistUuid})
}()
service.Success(ctx, resp)
return
}
@ -337,7 +355,6 @@ func OAuth2Callback(ctx *gin.Context) {
ctx.Redirect(http.StatusFound, fmt.Sprintf("%s?%s", config.AppConfig.System.AuthRedirectUrl, "status=1"))
return
}
// TODO 跳转到前端页面
ctx.Redirect(http.StatusFound, fmt.Sprintf("%s?%s", config.AppConfig.System.AuthRedirectUrl, "status=0"))
//service.Success(ctx, map[string]interface{}{
// "req": req,
@ -772,3 +789,201 @@ func updateMediaAccount(platformName string, platformId cast.PlatformIDENUM, sub
//}
return err
}
func UnbindAuth(ctx *gin.Context) {
var req modelCast.UnbindAccountReq
var UpsertTaskListResp *cast.UpsertTaskListResp
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
if len(req.MediaAccountUuids) == 0 {
service.Error(ctx, errors.New("参数错误"))
return
}
loginInfo := login.GetUserInfoFromC(ctx)
extraBytes, _ := json.Marshal(req.MediaAccountUuids)
UpsertTaskListResp, err = service.CastProvider.UpsertTaskList(context.Background(), &cast.UpsertTaskListReq{
Action: "unbindAuth",
Url: "",
Status: 1,
OperatorID: fmt.Sprint(loginInfo.ID),
OperatorName: loginInfo.Name,
ExtraData: string(extraBytes),
})
if err != nil {
service.Error(ctx, err)
return
}
err = UnbindAyr(req.MediaAccountUuids)
go func() {
err = RefreshTaskUnBindAuth(UpsertTaskListResp.Uuid)
if err != nil {
zap.L().Error("RefreshTaskUnBindAuth err", zap.Error(err))
return
}
}()
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, nil)
return
}
func UnbindAyr(MediaAccountUuids []string) error {
for _, mediaAccountUuid := range MediaAccountUuids {
mediaResp, err := service.CastProvider.MediaUserList(context.Background(), &cast.MediaUserListReq{
MediaUserID: mediaAccountUuid,
Page: 1,
PageSize: 1,
})
if err != nil {
return err
}
if mediaResp == nil || len(mediaResp.Data) == 0 {
return errors.New("未找到该账号")
}
// DM直接更新数据库
if cast.PlatformIDENUM(mediaResp.Data[0].PlatformID) == cast.PlatformIDENUM_DM {
_, err = service.CastProvider.UpdateMediaAccInfo(context.Background(), &cast.UpdateMediaAccInfoReq{
MediaAccountUuid: mediaResp.Data[0].MediaAccountUuid,
AuthStatus: cast.AuthStatusENUM_AuthNo,
})
if err != nil {
return err
}
continue
}
asArtistResp, _err := service.CastProvider.GetArtist(context.Background(), &cast.GetArtistReq{
ArtistUuid: fmt.Sprint(mediaResp.Data[0].ArtistUuid),
})
if _err != nil {
return errors.New("未找到该艺人")
}
_, err = service.AyrshareProvider.UnlinkSocialNetwork(context.Background(), &aryshare.UnlinkSocialNetworkRequest{
Platform: modelCast.PlatformNameKv[mediaResp.Data[0].PlatformID],
ProfileKey: asArtistResp.ArtistInfo.ProfileKey,
})
if err != nil {
zap.L().Error("UnlinkSocialNetwork err", zap.Error(err))
return errors.New("解除授权失败")
}
_ = SyncAsAuth(mediaResp.Data[0].ArtistUuid)
}
return nil
}
// RefreshTaskUnBindAuth 刷新解绑授权任务状态
func RefreshTaskUnBindAuth(taskUuid string) error {
listResp, err := service.CastProvider.GetTaskList(context.Background(), &cast.GetTaskListReq{Uuid: taskUuid})
if err != nil {
zap.L().Error("GetTaskList err", zap.Error(err))
return err
}
if listResp == nil || listResp.Data.Status != 1 {
return nil
}
var mediaAccountUuids []string
err = json.Unmarshal([]byte(listResp.Data.ExtraData), &mediaAccountUuids)
if err != nil {
zap.L().Error("Unmarshal err", zap.Error(err))
return err
}
// 创建Excel文件
excelFile := excelize.NewFile()
sheetName := "Sheet1"
// 设置表头
headers := []string{"所属艺人", "账号", "所属平台", "授权结果", "备注"}
for i, header := range headers {
cell := fmt.Sprintf("%c1", 'A'+i)
excelFile.SetCellValue(sheetName, cell, header)
}
// 收集账号信息并写入Excel
rowIndex := 2
for _, mediaAccountUuid := range mediaAccountUuids {
mediaResp, err := service.CastProvider.MediaUserList(context.Background(), &cast.MediaUserListReq{
MediaUserID: mediaAccountUuid,
Page: 1,
PageSize: 1,
})
if err != nil {
zap.L().Error("MediaUserList err", zap.Error(err))
continue
}
if mediaResp == nil || len(mediaResp.Data) == 0 {
continue
}
mediaData := mediaResp.Data[0]
// 获取平台名字
platformName := modelCast.PlatformNameKv[mediaData.PlatformID]
if platformName == "" {
platformName = "未知平台"
}
// 获取授权状态
authStatusText := ""
switch mediaData.AuthStatus {
case cast.AuthStatusENUM_AuthOk:
authStatusText = "已授权"
case cast.AuthStatusENUM_AuthNo:
authStatusText = "未授权"
default:
authStatusText = "未知"
}
// 写入Excel
excelFile.SetCellValue(sheetName, fmt.Sprintf("A%d", rowIndex), mediaData.ArtistName) // 艺人名字
excelFile.SetCellValue(sheetName, fmt.Sprintf("B%d", rowIndex), mediaData.PlatformUserName) // 账号名字
excelFile.SetCellValue(sheetName, fmt.Sprintf("C%d", rowIndex), platformName) // 平台名字
excelFile.SetCellValue(sheetName, fmt.Sprintf("D%d", rowIndex), authStatusText) // 授权状态
excelFile.SetCellValue(sheetName, fmt.Sprintf("E%d", rowIndex), "") // 备注
rowIndex++
}
// 创建临时目录
tempDir := "./runtime/unbind_auth"
_, err = utils.CheckDirPath(tempDir, true)
if err != nil {
zap.L().Error("CheckDirPath err", zap.Error(err))
return err
}
// 保存Excel到本地
fileName := fmt.Sprintf("unbind_auth_%d.xlsx", time.Now().UnixMicro())
localPath := filepath.Join(tempDir, fileName)
if err = excelFile.SaveAs(localPath); err != nil {
zap.L().Error("SaveAs err", zap.Error(err))
return err
}
// Linux系统下需要显式设置文件权限
if err = os.Chmod(localPath, 0666); err != nil {
zap.L().Warn("设置文件权限失败", zap.Error(err))
}
// 上传到OSS
exportUrl, err := upload.PutBos(localPath, "excel", true)
if err != nil {
zap.L().Error("uploadExcelToOSS err", zap.Error(err))
return err
}
// 更新任务状态为完成
_, err = service.CastProvider.UpsertTaskList(context.Background(), &cast.UpsertTaskListReq{
Uuid: taskUuid,
Status: 3, // 3-处理完成
Url: exportUrl,
})
if err != nil {
zap.L().Error("UpsertTaskList err", zap.Error(err))
return err
}
return nil
}

View File

@ -0,0 +1,126 @@
package cast
import (
"context"
"errors"
"fmt"
"strings"
"time"
"fonchain-fiee/api/cast"
"fonchain-fiee/pkg/cache"
logicCast "fonchain-fiee/pkg/logic/cast"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/utils"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// PublishLogList 查询发布记录列表
func PublishLogList(ctx *gin.Context) {
var req cast.ListPublishLogReq
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
resp, err := service.CastProvider.ListPublishLog(context.Background(), &req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// PublishLogListExport 导出发布记录列表 Excel
func PublishLogListExport(ctx *gin.Context) {
var req cast.ListPublishLogReq
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, errors.New("绑定参数失败"))
return
}
loginInfo := login.GetUserInfoFromC(ctx)
newCtx := NewCtxWithUserInfo(ctx)
lockKey := "PublishLogListExport" + fmt.Sprint(loginInfo.ID)
replay := cache.RedisClient.SetNX(lockKey, time.Now().Unix(), time.Minute*30)
if !replay.Val() {
service.Error(ctx, errors.New("已有导出任务在进行中,请稍后再试"))
return
}
defer cache.RedisClient.Del(lockKey)
const batchSize = 5000
var allData []*cast.PublishLogInfo
page := int32(1)
if req.Page > 0 {
page = req.Page
}
originalPageSize := req.PageSize
req.PageSize = batchSize
zap.L().Info("开始分批导出发布记录列表", zap.Int32("batchSize", batchSize))
for {
req.Page = page
zap.L().Info("获取第 N 页数据", zap.Int32("page", page), zap.Int32("pageSize", req.PageSize))
resp, err := service.CastProvider.ListPublishLog(newCtx, &req)
if err != nil {
zap.L().Error("获取发布记录失败", zap.Error(err), zap.Int32("page", page))
service.Error(ctx, errors.New("获取发布记录失败"))
return
}
if resp == nil || len(resp.Data) == 0 {
zap.L().Info("没有更多数据", zap.Int32("page", page))
break
}
allData = append(allData, resp.Data...)
zap.L().Info("获取数据成功",
zap.Int32("page", page),
zap.Int("本批次数量", len(resp.Data)),
zap.Int("累计总数", len(allData)))
if len(resp.Data) < batchSize {
zap.L().Info("已到最后一页", zap.Int32("page", page))
break
}
page++
}
req.PageSize = originalPageSize
zap.L().Info("数据获取完成开始生成Excel", zap.Int("总数据量", len(allData)))
if len(allData) == 0 {
service.Error(ctx, errors.New("没有数据可导出"))
return
}
fileName := fmt.Sprintf("发布记录_%s.xlsx", time.Now().Format("20060102150405"))
filePath := fmt.Sprintf("./runtime/%d/%s", loginInfo.ID, fileName)
utils.CheckDirPath("./runtime/"+fmt.Sprint(loginInfo.ID), true)
var logicWork = new(logicCast.Work)
if err := logicWork.ExportPublishLogList(allData, filePath); err != nil {
zap.L().Error("生成Excel失败", zap.Error(err))
service.Error(ctx, err)
return
}
scheme := "http"
if ctx.GetHeader("X-Forwarded-Proto") == "https" {
scheme = "https"
}
exportUrl := fmt.Sprintf("%s://%s/api/fiee/static/%s", scheme, ctx.Request.Host, strings.Replace(filePath, "./runtime/", "", 1))
zap.L().Info("Excel导出成功", zap.String("文件名", fileName), zap.Int("记录数", len(allData)))
service.Success(ctx, map[string]interface{}{
"url": exportUrl,
})
}

1662
pkg/service/cast/report.go Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,7 @@ import (
"fonchain-fiee/api/bundle"
"fonchain-fiee/api/cast"
"fonchain-fiee/cmd/config"
"fonchain-fiee/pkg/cache"
"fonchain-fiee/pkg/e"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
@ -23,14 +24,30 @@ import (
"go.uber.org/zap"
)
// UpdateVideoScript 更新视频脚本
func UpdateVideoScript(ctx *gin.Context) {
var req *cast.UpdateVideoScriptReq
const (
// scriptImportLockKey Redis分布式锁的key
scriptImportLockKey = "script:import:lock"
// scriptImportLockExpire 锁的过期时间(秒),防止死锁
scriptImportLockExpire = 600 // 10分钟根据实际导入时长调整
)
func UpdateVideoScriptCore(ctx *gin.Context, req *cast.UpdateVideoScriptReq) (*cast.UpdateVideoScriptResp, error) {
var infoResp *accountFiee.UserInfoResponse
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
// 检查并截取 title 和 content 长度(支持中文)
titleRunes := []rune(req.Title)
if len(titleRunes) > 600 {
req.Title = string(titleRunes[:600])
}
contentRunes := []rune(req.Content)
if len(contentRunes) > 600 {
req.Content = string(contentRunes[:600])
}
if err = SecurityText(req.Title); err != nil {
return nil, errors.New(fmt.Sprintf("标题未通过黄反,原因:%s", err.Error()))
}
if err = SecurityText(req.Content); err != nil {
return nil, errors.New(fmt.Sprintf("内容未通过黄反,原因:%s", err.Error()))
}
newCtx := NewCtxWithUserInfo(ctx)
artistId, _ := strconv.ParseUint(req.ArtistUuid, 10, 64)
@ -39,17 +56,30 @@ func UpdateVideoScript(ctx *gin.Context) {
Domain: "app",
})
if err != nil {
service.Error(ctx, err)
return
return nil, err
}
if infoResp.Id == 0 {
service.Error(ctx, errors.New(e.GetMsg(e.NOTDATA)))
return
return nil, errors.New(e.GetMsg(e.NOTDATA))
}
req.ArtistName = infoResp.Name
req.ArtistPhone = infoResp.TelNum
req.ArtistNum = infoResp.SubNum
resp, err := service.CastProvider.UpdateVideoScript(newCtx, req)
if err != nil {
return nil, err
}
return resp, nil
}
// UpdateVideoScript 更新视频脚本
func UpdateVideoScript(ctx *gin.Context) {
var req *cast.UpdateVideoScriptReq
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
resp, err := UpdateVideoScriptCore(ctx, req)
if err != nil {
service.Error(ctx, err)
return
@ -120,7 +150,29 @@ func DeleteVideoScript(ctx *gin.Context) {
}
func ImportBatch(ctx *gin.Context) {
//接收form表单的Excel保存到本地进行解析
loginInfo := login.GetUserInfoFromC(ctx)
lockValue := fmt.Sprintf("%d", loginInfo.ID)
locked, err := cache.RedisClient.SetNX(scriptImportLockKey, lockValue, scriptImportLockExpire*time.Second).Result()
if err != nil {
zap.L().Error("获取导入锁失败", zap.Error(err))
service.Error(ctx, errors.New("系统繁忙,请稍后再试"))
return
}
if !locked {
zap.L().Warn("当前有导入任务正在进行中,本次请求被拒绝")
service.Error(ctx, errors.New("当前有导入任务正在进行中,请稍后再试"))
return
}
defer func() {
// 只有当锁的值匹配时才删除,防止误删其他请求的锁
val, err := cache.RedisClient.Get(scriptImportLockKey).Result()
if err == nil && val == lockValue {
cache.RedisClient.Del(scriptImportLockKey)
zap.L().Info("导入任务结束,释放分布式锁")
}
}()
zap.L().Info("开始执行导入任务", zap.String("lockValue", lockValue))
excelFile, err := ctx.FormFile("file")
if err != nil {
service.Error(ctx, err)
@ -181,6 +233,17 @@ func ImportBatch(ctx *gin.Context) {
req.Data = append(req.Data, &temp)
continue
}
// 检查并截取 title 和 content 长度(支持中文)
titleRunes := []rune(temp.Title)
if len(titleRunes) > 600 {
temp.Title = string(titleRunes[:600])
}
contentRunes := []rune(temp.Content)
if len(contentRunes) > 600 {
temp.Content = string(contentRunes[:600])
}
if utf8.RuneCountInString(temp.Title) > 50 {
temp.Remark = "脚本标题过长限制50字以内"
req.Data = append(req.Data, &temp)
@ -191,6 +254,18 @@ func ImportBatch(ctx *gin.Context) {
req.Data = append(req.Data, &temp)
continue
}
err = SecurityText(temp.Title)
if err != nil {
temp.Remark = fmt.Sprintf("标题未通过黄反,原因:%s", err.Error())
req.Data = append(req.Data, &temp)
continue
}
err = SecurityText(temp.Content)
if err != nil {
temp.Remark = fmt.Sprintf("内容未通过黄反,原因:%s", err.Error())
req.Data = append(req.Data, &temp)
continue
}
var subInfoResp *accountFiee.UserInfoResponse
subInfoResp, err = service.AccountFieeProvider.SubNumGetInfo(context.Background(), &accountFiee.SubNumGetInfoRequest{
SubNum: row[2],

View File

@ -10,6 +10,7 @@ import (
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/check"
"fonchain-fiee/pkg/utils"
"time"
"github.com/gin-gonic/gin"
)
@ -17,13 +18,9 @@ import (
func Test(ctx *gin.Context) {
action := ctx.PostForm("action")
if action == "" {
workUuid := ctx.PostForm("workUuid")
err := CheckImage(workUuid)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, nil)
service.Success(ctx, map[string]interface{}{
"now": time.Now().Unix(),
})
return
}
@ -123,10 +120,28 @@ func Test(ctx *gin.Context) {
service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: action})
return
}
//刷新订单
if action == "artistOrderInfo" {
service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: action})
return
}
//刷新审批状态
if action == "refreshApprovalStatus" {
/* resp, err := service.CastProvider.WorkList(context.Background(), &cast.WorkListReq{
Page: 1,
WorkStatus: uint32(cast.WorkActionENUM_APPROVAL),
PageSize: 9999,
})
if err != nil {
return
}
if resp.Data == nil || len(resp.Data) == 0 {
return
}
serverCast.RefreshWorkApproval(nil, resp.Data)
service.Success(ctx, resp.Data)
return*/
}
if action == "SecurityText" {
val := ctx.PostForm("val")
ok, err := check.SecurityFile(val)
@ -174,6 +189,14 @@ func Test(ctx *gin.Context) {
return
}
if action == "addDecodoProxies" {
service.CastProvider.Tools(context.Background(), &cast.ToolsReq{Action: action, CfgLinks: []string{
"http://spd7b09ho0:sqx_1MlQ1rN5gfm2Dx@isp.decodo.com:10001",
"http://spd7b09ho0:sqx_1MlQ1rN5gfm2Dx@isp.decodo.com:10002",
"http://spd7b09ho0:sqx_1MlQ1rN5gfm2Dx@isp.decodo.com:10003",
}})
}
service.Success(ctx, "unknow")
return
}

View File

@ -12,7 +12,7 @@ import (
"github.com/gin-gonic/gin"
)
func NewCtxWithUserInfo(ctx *gin.Context) (newCtx context.Context) {
func NewCtxWithUserInfo(ctx *gin.Context, customVals ...string) (newCtx context.Context) {
var userInfo = login.Info{}
if config.AppConfig.System.AppMode == "prod" || config.AppConfig.System.AppMode == "test" {
//_, ok := ctx.Get("jwtInfo")
@ -37,6 +37,9 @@ func NewCtxWithUserInfo(ctx *gin.Context) (newCtx context.Context) {
mm["userid"] = fmt.Sprintf("%d", userInfo.ID)
mm["name"] = userInfo.Name
mm["phone"] = userInfo.TelNum
if len(customVals) > 0 {
mm["name"] = customVals[0]
}
newCtx = context.WithValue(context.Background(), constant.DubboCtxKey("attachment"), mm)
return
}

View File

@ -64,6 +64,21 @@ func UpdateWorkImageCore(ctx *gin.Context, req *cast.UpdateWorkImageReq) (*cast.
cache.RedisClient.Del(lockKey)
}()
fmt.Println(ok)
// 检查并截取 title 和 content 长度(支持中文)
titleRunes := []rune(req.Title)
if len(titleRunes) > 600 {
req.Title = string(titleRunes[:600])
}
contentRunes := []rune(req.Content)
if len(contentRunes) > 600 {
req.Content = string(contentRunes[:600])
}
if err = SecurityText(req.Title); err != nil {
return nil, errors.New(fmt.Sprintf("标题未通过黄反,原因:%s", err.Error()))
}
if err = SecurityText(req.Content); err != nil {
return nil, errors.New(fmt.Sprintf("内容未通过黄反,原因:%s", err.Error()))
}
// 图片鉴定
/*for _, v := range req.Images {
ok, err = check.SecurityFile(v)
@ -277,7 +292,6 @@ func processContentAndAutoTags(ctx *gin.Context, content string) (string, error)
func UpdateWorkVideoCore(ctx *gin.Context, req *cast.UpdateWorkVideoReq) (*cast.UpdateWorkVideoResp, error) {
var infoResp *accountFiee.UserInfoResponse
var err error
var ok bool
if req.CoverUrl != "" {
if filepath.Ext(req.CoverUrl) != ".jpg" && filepath.Ext(req.CoverUrl) != ".jpeg" {
return nil, errors.New("图片格式只支持jpg")
@ -292,7 +306,21 @@ func UpdateWorkVideoCore(ctx *gin.Context, req *cast.UpdateWorkVideoReq) (*cast.
defer func() {
cache.RedisClient.Del(lockKey)
}()
fmt.Println(ok)
// 检查并截取 title 和 content 长度(支持中文)
titleRunes := []rune(req.Title)
if len(titleRunes) > 600 {
req.Title = string(titleRunes[:600])
}
contentRunes := []rune(req.Content)
if len(contentRunes) > 600 {
req.Content = string(contentRunes[:600])
}
if err = SecurityText(req.Title); err != nil {
return nil, errors.New(fmt.Sprintf("标题未通过黄反,原因:%s", err.Error()))
}
if err = SecurityText(req.Content); err != nil {
return nil, errors.New(fmt.Sprintf("内容未通过黄反,原因:%s", err.Error()))
}
/* ok, err = check.SecurityText(req.Title)
if err != nil {
return nil, err
@ -314,19 +342,6 @@ func UpdateWorkVideoCore(ctx *gin.Context, req *cast.UpdateWorkVideoReq) (*cast.
if !ok {
return nil, errors.New("图片鉴定未通过")
}*/
if req.VideoUrl != "" && false {
//请求接口判断
fileResp, errs := service.FilesProvider.GetFileSecurityStatus(ctx, &files.GetFileSecurityStatusReq{
Url: req.VideoUrl,
FileName: "",
})
if errs != nil {
return nil, errs
}
if fileResp.SecurityStatus == "high" {
return nil, errors.New("视频鉴定未通过")
}
}
if config.AppConfig.System.AppMode != "dev" {
artistId, _ := strconv.ParseUint(req.ArtistUuid, 10, 64)
infoResp, err = service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
@ -491,7 +506,8 @@ func WorkDetail(ctx *gin.Context) {
}
// 检查用户套餐余量
func CheckUserBundleBalance(userID int32, balanceType modelCast.BalanceTypeEnum) (confirmFailType cast.ConfirmFailENUM, err error) {
// otherFields 补充的字段 第一个是workUuid 第二个是orderUuid
func CheckUserBundleBalance(userID int32, balanceType modelCast.BalanceTypeEnum, otherFields ...string) (confirmFailType cast.ConfirmFailENUM, err error) {
zap.L().Info("CheckUserBundleBalance", zap.Any("userID", userID))
confirmFailType = cast.ConfirmFailENUM_ConfirmFailENUM_NO
resp, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{UserId: userID})
@ -505,7 +521,6 @@ func CheckUserBundleBalance(userID int32, balanceType modelCast.BalanceTypeEnum)
err = errors.New("套餐已过期")
return
}
fmt.Println("CheckUserBundleBalance resp", resp)
switch balanceType {
case modelCast.BalanceTypeAccountValue:
if resp.AccountConsumptionNumber >= resp.AccountNumber {
@ -514,12 +529,26 @@ func CheckUserBundleBalance(userID int32, balanceType modelCast.BalanceTypeEnum)
return
}
case modelCast.BalanceTypeImageValue:
//判断用户是新购还是续费,新购就提示验收失败,套餐已过期,续费就继续扣减
if len(otherFields) >= 2 {
confirmFailType, err = CheckOrderRenewal(otherFields[1], resp)
if err != nil {
return
}
}
if resp.ImageExtendConsumptionNumber >= resp.ImageExtendNumber {
confirmFailType = cast.ConfirmFailENUM_ConfirmFailENUM_NOTENOUGH
err = errors.New(e.ErrorBalanceInsufficient)
return
}
case modelCast.BalanceTypeVideoValue:
if len(otherFields) >= 2 {
//判断用户是新购还是续费,新购就提示验收失败,套餐已过期,续费就继续扣减
confirmFailType, err = CheckOrderRenewal(otherFields[1], resp)
if err != nil {
return
}
}
if resp.VideoExtendConsumptionNumber >= resp.VideoExtendNumber {
confirmFailType = cast.ConfirmFailENUM_ConfirmFailENUM_NOTENOUGH
err = errors.New(e.ErrorBalanceInsufficient)
@ -531,10 +560,30 @@ func CheckUserBundleBalance(userID int32, balanceType modelCast.BalanceTypeEnum)
// err = errors.New(e.ErrorBalanceInsufficient)
return
}
case modelCast.BalanceTypeCompetitiveValue:
if resp.CompetitiveExtendNumber-resp.CompetitiveExtendConsumptionNumber <= 0 {
err = errors.New("该艺人竞品数可用次数为0")
// err = errors.New(e.ErrorBalanceInsufficient)
return
}
}
return
}
func CheckOrderRenewal(workBindOrderUuid string, resp *bundle.GetBundleBalanceByUserIdResp) (cast.ConfirmFailENUM, error) {
if resp.PurchaseType == 2 {
return cast.ConfirmFailENUM_ConfirmFailENUM_NO, nil
}
if resp.PurchaseType == 1 {
// 证明是新购套餐
if resp.OrderUUID != workBindOrderUuid {
return cast.ConfirmFailENUM_ConfirmFailENUM_EXPIRED, errors.New("套餐已过期")
}
return cast.ConfirmFailENUM_ConfirmFailENUM_NO, nil
}
return cast.ConfirmFailENUM_ConfirmFailENUM_NO, nil
}
func Publish(ctx *gin.Context) {
var (
req *cast.PublishReq
@ -618,7 +667,7 @@ func PublishWork(ctx context.Context, req *cast.PublishReq) error {
go func() {
defer wg.Done()
for workUuid := range jobs {
if err := PostAS(ctx, workUuid); err != nil {
if err := PostAS(ctx, workUuid, req.PublishSource); err != nil {
errsMu.Lock()
errs = append(errs, err)
errsMu.Unlock()
@ -657,11 +706,11 @@ func PublishWork(ctx context.Context, req *cast.PublishReq) error {
return nil
}
func PostAS(ctx context.Context, workUuid string) error {
func PostAS(ctx context.Context, workUuid string, publishSource cast.PublishSourceENUM) error {
var err error
//检查封面
_ = CheckImage(workUuid)
_, err = service.CastProvider.Publish(ctx, &cast.PublishReq{WorkUuids: []string{workUuid}})
_, err = service.CastProvider.Publish(ctx, &cast.PublishReq{WorkUuids: []string{workUuid}, PublishSource: publishSource})
if err != nil {
zap.L().Error("Publish err", zap.String("workUuid", workUuid), zap.Error(err))
return err
@ -686,11 +735,10 @@ func PostAS(ctx context.Context, workUuid string) error {
return nil
//return errors.New("作品无发布平台")
}
zap.L().Info("post 2", zap.Any("workUuid", workUuid))
zap.L().Info("post 2", zap.Any("workUuid", workUuid), zap.Any("needPlatformIDs", needPlatformIDs))
var mediaUrls []string
var isVideo bool
var urlResp *UploadMediaResponse
fmt.Println(urlResp)
//var urlResp *UploadMediaResponse
if workDetail.WorkCategory == 1 {
isVideo = false
// 先用服务器上的文件,不上传到第三方
@ -845,10 +893,12 @@ func PostAS(ctx context.Context, workUuid string) error {
}
if _err != nil {
_, errS := service.CastProvider.UpdateWorkPublishLog(context.Background(), &cast.UpdateWorkPublishLogReq{
WorkUuid: workUuid,
PlatformID: cast.PlatformIDENUM(platformID),
Action: "post",
Detail: _err.Error(),
WorkUuid: workUuid,
PlatformID: cast.PlatformIDENUM(platformID),
Action: "post",
Detail: _err.Error(),
PublishSource: publishSource,
PublishMediaStatus: cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION,
})
if errS != nil {
zap.L().Error("PostAs UpdateWorkPublishLog err", zap.Error(errS), zap.Any("WorkUuid", workDetail.WorkUuid))
@ -863,9 +913,11 @@ func PostAS(ctx context.Context, workUuid string) error {
PublishMediaId: "",
PublishMediaStatus: cast.PublishStatusENUM_PublishMediaStatus_EXCEPTION,
Remark: "",
PublishSource: publishSource,
})
zap.L().Info("UpdateWorkPlatformInfo", zap.Any("infoReq", infoReq))
_, errS = service.CastProvider.UpdateWorkPlatformInfo(context.Background(), infoReq)
go UpdateAccStatus(workDetail.ArtistUuid, uint32(platformID), _err.Error())
if errS != nil {
zap.L().Error("PostAs UpdateWorkPlatformInfo err", zap.Error(errS), zap.Any("WorkUuid", workDetail.WorkUuid))
}
@ -877,10 +929,11 @@ func PostAS(ctx context.Context, workUuid string) error {
zap.L().Info("post 8", zap.Any("workUuid", workUuid), zap.Any("platformID", platformID))
postBytes, _ := json.Marshal(postResp)
_, _ = service.CastProvider.UpdateWorkPublishLog(context.Background(), &cast.UpdateWorkPublishLogReq{
PlatformID: cast.PlatformIDENUM(platformID),
WorkUuid: workUuid,
Action: "post",
Detail: string(postBytes),
PlatformID: cast.PlatformIDENUM(platformID),
WorkUuid: workUuid,
Action: "post",
Detail: string(postBytes),
PublishSource: publishSource,
})
zap.L().Info("post 9", zap.Any("workUuid", workUuid), zap.Any("platformID", platformID))
zap.L().Info("PostAs", zap.Any("postResp", postResp), zap.Any("workDetail", workDetail))
@ -924,6 +977,16 @@ func PostAS(ctx context.Context, workUuid string) error {
PublishMediaId: postResp.Posts[0].Id,
PublishMediaStatus: publishStatus,
Remark: string(postData),
PublishSource: publishSource,
})
_, _ = service.CastProvider.UpdateWorkPublishLog(context.Background(), &cast.UpdateWorkPublishLogReq{
PlatformID: cast.PlatformIDENUM(platformID),
WorkUuid: workUuid,
Action: "post",
Detail: string(postData),
PublishSource: publishSource,
PublishMediaStatus: publishStatus,
PublishMediaID: postResp.Posts[0].Id,
})
}
zap.L().Info("post 10", zap.Any("workUuid", workUuid), zap.Any("platformID", platformID))
@ -931,6 +994,7 @@ func PostAS(ctx context.Context, workUuid string) error {
if err != nil {
zap.L().Error("Publish UpdateWorkPlatformInfo failed", zap.String("workUuid", workUuid), zap.Error(err))
}
zap.L().Info("Publish Ayrshare PostResp", zap.Any("postResp", postResp))
}
zap.L().Info("post 5.1", zap.Any("workUuid", workUuid))
@ -939,8 +1003,7 @@ func PostAS(ctx context.Context, workUuid string) error {
func RePublish(ctx *gin.Context) {
var (
req *cast.RePublishReq
resp *cast.RePublishResp
req *cast.RePublishReq
//workInfoResp *cast.WorkInfoResp
)
var err error
@ -948,40 +1011,59 @@ func RePublish(ctx *gin.Context) {
service.Error(ctx, err)
return
}
if req.PublishSource == cast.PublishSourceENUM_RePublishType_UNKNOW {
req.PublishSource = cast.PublishSourceENUM_RePublishType_MANUAL
}
newCtx := NewCtxWithUserInfo(ctx)
/* workInfoResp, err = service.CastProvider.WorkInfo(context.Background(), &cast.WorkInfoReq{
WorkUuid: req.WorkUuid,
})
if err != nil {
service.Error(ctx, err)
return
}
fmt.Println(workInfoResp)*/
/*artistID, _ := strconv.ParseInt(workInfoResp.ArtistUuid, 10, 64)
if err = CheckUserBundleBalance(int32(artistID), modelCast.BalanceTypeVideoValue); err != nil {
service.Error(ctx, err)
return
}
balanceReq := &bundle.AddBundleBalanceReq{
UserId: int32(artistID),
}
if workInfoResp.WorkCategory == 1 {
balanceReq.ImageConsumptionNumber = 1
}
if workInfoResp.WorkCategory == 2 {
balanceReq.VideoConsumptionNumber = 1
}
_, err = service.BundleProvider.AddBundleBalance(context.Background(), balanceReq)
err = republishCore(ctx, newCtx, req)
if err != nil {
service.Error(ctx, err)
return
}*/
}
service.Success(ctx, req)
return
}
func republishCore(gCtx *gin.Context, newCtx context.Context, req *cast.RePublishReq) error {
zap.L().Info("republishCore", zap.Any("req", req))
var resp *cast.RePublishResp
var err error
if len(req.PlatformIDs) == 0 && len(req.MediaAccountUuids) == 0 {
return errors.New("请选择发布平台或账号")
}
if len(req.MediaAccountUuids) == 0 {
if len(req.WorkUuids) != 1 {
return errors.New("只选择平台时只能单个作品重发")
}
workInfo, _err := service.CastProvider.WorkInfo(context.Background(), &cast.WorkInfoReq{WorkUuid: req.WorkUuids[0]})
if _err != nil {
return _err
}
accountResp, _err := service.CastProvider.MediaAccounts(context.Background(), &cast.MediaAccountsReq{
ArtistUuid: workInfo.ArtistUuid,
})
if _err != nil {
return _err
}
if accountResp == nil || len(accountResp.Data) == 0 {
return errors.New("该艺人无可用媒体账号")
}
for _, platformId := range req.PlatformIDs {
for _, v := range accountResp.Data {
if v.PlatformID == uint32(platformId) {
req.MediaAccountUuids = append(req.MediaAccountUuids, v.MediaAccountUuid)
}
}
}
}
resp, err = service.CastProvider.RePublish(newCtx, req)
if err != nil {
service.Error(ctx, err)
return
return err
}
var loginInfo login.Info
if gCtx != nil {
loginInfo = login.GetUserInfoFromC(gCtx)
}
loginInfo := login.GetUserInfoFromC(ctx)
var extraBytes []byte
extraBytes, _ = json.Marshal(req)
_, err = service.CastProvider.UpsertTaskList(newCtx, &cast.UpsertTaskListReq{
@ -994,14 +1076,57 @@ func RePublish(ctx *gin.Context) {
})
if err != nil {
zap.L().Error("RePublish UpsertTaskList failed", zap.Error(err))
service.Error(ctx, err)
return
return err
}
if err = PublishWork(newCtx, &cast.PublishReq{WorkUuids: resp.WorkUuids}); err != nil {
return err
}
return nil
}
// CronRePublish 定时重发布接口不走登录校验通过header校验
func CronRePublish(ctx *gin.Context) {
// 从 header 中获取 API Key
apiNoAuthKey := ctx.GetHeader("X-Api-Key")
if apiNoAuthKey == "" {
service.Error(ctx, errors.New("非法请求!"))
return
}
// 从配置文件中获取预设的 API Key
expectedKey := "c8a2512cea2274a0f3d34520d82d51b3b149e7edc571e5f46854b8c6c0575920"
if apiNoAuthKey != expectedKey {
service.Error(ctx, errors.New("非法请求!!"))
return
}
// 校验通过,调用 RePublish 逻辑
var (
req *cast.RePublishReq
)
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, req)
// 设置发布源为定时任务
if req.PublishSource == cast.PublishSourceENUM_RePublishType_UNKNOW {
req.PublishSource = cast.PublishSourceENUM_RePublishType_SCHEDULED_RETRY
}
// 创建系统用户上下文(因为没有登录用户信息)
var mm = make(map[string]interface{}, 3)
mm["userid"] = ""
mm["name"] = "定时任务补发"
mm["phone"] = ""
newCtx := context.WithValue(context.Background(), constant.DubboCtxKey("attachment"), mm)
// 调用重发布服务
err = republishCore(nil, newCtx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, nil)
return
}
@ -1029,7 +1154,7 @@ func RefreshWorkApprovalStatus(ctx *gin.Context, approvalIDWorkUuidMap map[int]s
for _, v := range approvalIDs {
newData[v] = data[v]
}
newCtx := NewCtxWithUserInfo(ctx)
newCtx := NewCtxWithUserInfo(ctx, "业务部门")
if len(newData) > 0 {
for approvalId, v := range newData {
if v.ID == 0 {
@ -1168,7 +1293,7 @@ func WorkListExport(ctx *gin.Context) {
)
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
//service.Error(ctx, err)
return
}
loginInfo := login.GetUserInfoFromC(ctx)
@ -1176,7 +1301,7 @@ func WorkListExport(ctx *gin.Context) {
lockKey := "WorkListExport" + fmt.Sprint(loginInfo.ID)
replay := cache.RedisClient.SetNX(lockKey, time.Now().Unix(), time.Minute*30)
if !replay.Val() {
service.Error(ctx, errors.New("请勿重复导出"))
//service.Error(ctx, errors.New("请勿重复导出"))
return
}
defer cache.RedisClient.Del(lockKey)
@ -1201,7 +1326,7 @@ func WorkListExport(ctx *gin.Context) {
resp, err := service.CastProvider.WorkList(newCtx, req)
if err != nil {
zap.L().Error("获取作品列表失败", zap.Error(err), zap.Int32("page", page))
service.Error(ctx, errors.New("获取数据失败"))
//service.Error(ctx, errors.New("获取数据失败"))
return
}
@ -1226,7 +1351,7 @@ func WorkListExport(ctx *gin.Context) {
req.PageSize = originalPageSize
zap.L().Info("数据获取完成开始生成Excel", zap.Int("总数据量", len(allData)))
if len(allData) == 0 {
service.Error(ctx, errors.New("没有可导出的数据"))
//service.Error(ctx, errors.New("没有可导出的数据"))
return
}
@ -1234,7 +1359,7 @@ func WorkListExport(ctx *gin.Context) {
excelFile, err := logicCastWork.ExportExcelWorkList(allData)
if err != nil {
zap.L().Error("生成Excel失败", zap.Error(err))
service.Error(ctx, err)
//service.Error(ctx, err)
return
}
@ -1314,7 +1439,7 @@ func autoConfirm(ctx context.Context, workUuid string) (err error) {
}
var resp *bundle.AddBundleBalanceResp = nil
var confirmFailType cast.ConfirmFailENUM
confirmFailType, err = CheckUserBundleBalance(int32(userID), checkType)
confirmFailType, err = CheckUserBundleBalance(int32(userID), checkType, []string{workUuid, infoResp.BundleOrderUuid}...)
if err != nil {
isFailed = true
confirmRemark = err.Error()
@ -1497,9 +1622,15 @@ func ImportWorkBatch(ctx *gin.Context) {
temp.ArtistName = subInfoResp.Name
temp.ArtistPhone = subInfoResp.TelNum
temp.ArtistPhoneAreaCode = subInfoResp.TelAreaCode
temp.ArtistSubNum = subInfoResp.SubNum
}
if len(row) > 7 {
temp.Title = utils.CleanString(row[7])
// 检查并截取 title 长度(支持中文)
titleRunes := []rune(temp.Title)
if len(titleRunes) > 600 {
temp.Title = string(titleRunes[:600])
}
ok, _err := check.SecurityText(temp.Title)
if _err != nil {
temp.Remark = _err.Error()
@ -1515,6 +1646,11 @@ func ImportWorkBatch(ctx *gin.Context) {
if len(row) > 8 {
temp.Content = utils.CleanString(row[8])
if temp.Content != "" {
// 检查并截取 content 长度(支持中文)
contentRunes := []rune(temp.Content)
if len(contentRunes) > 600 {
temp.Content = string(contentRunes[:600])
}
ok, _err := check.SecurityText(temp.Content)
if _err != nil {
temp.Remark = _err.Error()
@ -1849,6 +1985,15 @@ func RefreshPublish() error {
PlatformUuid: platformInfo.PlatformUuid,
})
_, _ = service.CastProvider.UpdateWorkPlatformInfo(context.Background(), infoReq)
go func(work *cast.RefreshWorkListResp_Info, platform *cast.RefreshWorkListResp_Info_PlatformInfo, postResult string) {
_, _ = service.CastProvider.UpdateWorkPublishLog(context.Background(), &cast.UpdateWorkPublishLogReq{
PlatformID: platform.PlatformID,
WorkUuid: work.WorkUuid,
Action: "getPost",
Detail: postResult,
PublishMediaID: platform.PublishMediaID,
})
}(workInfo, platformInfo, string(dmData))
} else {
// 未发布的先不管,不能标记失败
/*infoReq.PlatformInfoData = append(infoReq.PlatformInfoData, &cast.PlatformInfo{
@ -1871,15 +2016,16 @@ func RefreshPublish() error {
ProfileKey: workInfo.ProfileKey,
})
go func() {
postBytes, _ := json.Marshal(postResp)
go func(work *cast.RefreshWorkListResp_Info, platform *cast.RefreshWorkListResp_Info_PlatformInfo, post *aryshare.GetPostResponse) {
postBytes, _ := json.Marshal(post)
_, _ = service.CastProvider.UpdateWorkPublishLog(context.Background(), &cast.UpdateWorkPublishLogReq{
PlatformID: platformInfo.PlatformID,
WorkUuid: workInfo.WorkUuid,
Action: "getPost",
Detail: string(postBytes),
PlatformID: platform.PlatformID,
WorkUuid: work.WorkUuid,
Action: "getPost",
Detail: string(postBytes),
PublishMediaID: platform.PublishMediaID,
})
}()
}(workInfo, platformInfo, postResp)
if _err != nil {
zap.L().Error("GetPost err", zap.Error(_err))
@ -1984,7 +2130,6 @@ func checkAndReuploadImage(imageUrl string, mediaType string) (string, error) {
if err != nil {
return "", errors.New("图片解码失败")
}
fmt.Println("原始图片格式:", format)
newFilePath := "./runtime/work/" + uuid.New().String() + ".jpg"
// 如果不是 jpg则转换
if format != "jpeg" {
@ -1998,7 +2143,6 @@ func checkAndReuploadImage(imageUrl string, mediaType string) (string, error) {
if err != nil {
return "", errors.New("打开文件失败")
}
fmt.Println("已转换为 JPG: output.jpg")
} else {
fmt.Println("本身就是 JPG无需转换")
}
@ -2043,3 +2187,79 @@ func ProcessImg(imgs []string) ([]string, error) {
}
return newImgs, nil
}
// WorkListPublished 获取已发布的作品列表
func WorkListPublished(ctx *gin.Context) {
var (
req *cast.WorkListPublishedReq
resp *cast.WorkListPublishedResp
)
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
newCtx := NewCtxWithUserInfo(ctx)
if req.ArtistUuid != "" && strings.HasPrefix(strings.ToUpper(req.ArtistUuid), "FE") {
subInfoResp, err := service.AccountFieeProvider.SubNumGetInfo(context.Background(), &accountFiee.SubNumGetInfoRequest{
SubNum: req.ArtistUuid,
Domain: "app",
})
if err != nil {
service.Error(ctx, errors.New("自媒体用户查询失败"))
return
}
if subInfoResp == nil || subInfoResp.Id == 0 {
service.Error(ctx, errors.New("自媒体用户不存在"))
return
}
req.ArtistUuid = fmt.Sprint(subInfoResp.Id)
}
resp, err = service.CastProvider.WorkListPublished(newCtx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
return
}
func UpdateWorkScript(ctx *gin.Context) {
var (
req *cast.UpdateWorkScriptReq
)
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
newCtx := NewCtxWithUserInfo(ctx)
_, err = service.CastProvider.UpdateWorkScript(newCtx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, nil)
return
}
func SecurityText(keywords string) error {
if keywords == "" {
return nil
}
secResp, err := service.FilesProvider.SecurityScanByText(context.Background(), &files.SecurityScanByTextReq{
Text: keywords,
})
if err != nil {
return errors.New("内容安全检测服务异常")
}
if secResp.SecurityStatus == "high" {
problemText := secResp.ProblemText
runes := []rune(problemText)
if len(runes) > 10 {
problemText = string(runes[:10]) + "..."
}
return errors.New(problemText)
}
return nil
}

View File

@ -131,11 +131,12 @@ func ExportExcelExecutionResult(c *gin.Context) {
}
titleList := []string{
"任务标题", "艺人编号", "艺人姓名", "内容类型", "内容标题", "执行结果", "原因", "TIKTOK", "YOUTUBE", "INS", "DM", "BULESKY",
"开始时间", "任务标题", "艺人编号", "艺人姓名", "内容类型", "内容标题", "执行结果", "原因", "TIKTOK", "YOUTUBE", "INS", "DM", "BULESKY",
}
var dataList []interface{}
for _, task := range res.Data {
data := []interface{}{
task.StartTime,
task.TaskTitle,
idFindSubName[uint64(task.ArtistId)],
task.ArtistName,
@ -178,6 +179,23 @@ func StartScheduleTask(c *gin.Context) {
}
service.Success(c, res)
}
func RepublishScheduleTask(c *gin.Context) {
var req cron.CommonIDRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, errors.New("参数错误"))
return
}
res, err := service.CronProvider.RepublishScheduleTask(context.Background(), &req)
if err != nil {
service.Error(c, errors.New("网络超时,请重试"))
return
}
if res.Code != 200 {
service.Error(c, errors.New(res.Message))
return
}
service.Success(c, res)
}
func PauseScheduleTask(c *gin.Context) {
var req cron.CommonIDRequest

View File

@ -0,0 +1,238 @@
package customerContract
import (
"errors"
"fmt"
"fonchain-fiee/api/bundle"
"fonchain-fiee/pkg/model"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
"fonchain-fiee/pkg/service/upload"
"fonchain-fiee/pkg/utils"
"path"
"strconv"
"strings"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
)
// GetCustomerList 客户列表
func GetCustomerList(ctx *gin.Context) {
var req *bundle.CustomerListRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
// 如果客户名称不为空,就清除前后空格
if req.CustomerName != "" {
req.CustomerName = strings.TrimSpace(req.CustomerName)
}
if req.ReferralPerson != "" {
req.ReferralPerson = strings.TrimSpace(req.ReferralPerson)
}
resp, err := service.BundleProvider.GetCustomerList(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// GetCustomerDetail 客户详情
func GetCustomerDetail(ctx *gin.Context) {
var req *bundle.CustomerDetailRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
resp, err := service.BundleProvider.GetCustomerDetail(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// UpdateCustomer 更新客户
func UpdateCustomer(ctx *gin.Context) {
var req *bundle.CustomerUpdateRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
// 从token中获取用户信息
user := login.GetUserInfoFromC(ctx)
req.Customer.Operator = user.Name
req.Customer.OperatorID = strconv.FormatUint(uint64(user.ID), 10)
req.Customer.OperatorNum = user.TelNum
resp, err := service.BundleProvider.UpdateCustomer(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// GetReferralPersonList 获取推荐人列表,支持关键字模糊查询
func GetReferralPersonList(ctx *gin.Context) {
var req *bundle.ReferralPersonListRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
if req.Keyword != "" {
req.Keyword = strings.TrimSpace(req.Keyword)
}
resp, err := service.BundleProvider.GetReferralPersonList(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// GetContractList 合同列表
func GetContractList(ctx *gin.Context) {
var req *bundle.ContractListRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
if req.ContractName != "" {
req.ContractName = strings.TrimSpace(req.ContractName)
}
if req.ProjectName != "" {
req.ProjectName = strings.TrimSpace(req.ProjectName)
}
if req.CustomerName != "" {
req.CustomerName = strings.TrimSpace(req.CustomerName)
}
resp, err := service.BundleProvider.GetContractList(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// GetContractDetail 合同详情
func GetContractDetail(ctx *gin.Context) {
var req *bundle.ContractDetailRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
resp, err := service.BundleProvider.GetContractDetail(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// UpdateContract 更新合同
func UpdateContract(ctx *gin.Context) {
var req *bundle.ContractUpdateRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
// 从token中获取用户信息
user := login.GetUserInfoFromC(ctx)
req.Contract.Operator = user.Name
req.Contract.OperatorID = strconv.FormatUint(uint64(user.ID), 10)
req.Contract.OperatorNum = user.TelNum
resp, err := service.BundleProvider.UpdateContract(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// GetDevelopmentCyclesByContractUUID 根据合同UUID获取开发周期列表
func GetDevelopmentCyclesByContractUUID(ctx *gin.Context) {
var req *bundle.GetDevelopmentCyclesByContractUUIDRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
resp, err := service.BundleProvider.GetDevelopmentCyclesByContractUUID(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// GetPaymentCyclesByContractUUID 根据合同UUID获取付款周期列表
func GetPaymentCyclesByContractUUID(ctx *gin.Context) {
var req *bundle.GetPaymentCyclesByContractUUIDRequest
if err := ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
resp, err := service.BundleProvider.GetPaymentCyclesByContractUUID(ctx, req)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, resp)
}
// 合同附件允许的扩展名word、pdf、excel
var allowedAttachmentExt = map[string]bool{
".doc": true, ".docx": true,
".pdf": true,
".xls": true, ".xlsx": true,
}
const maxAttachmentSize = 50 * 1024 * 1024 // 50M
// UploadContractAttachment 上传合同附件,仅支持 word/pdf/excel单文件不超过 50M上传后写入 OSS 并返回访问 URL
func UploadContractAttachment(ctx *gin.Context) {
file, err := ctx.FormFile("file")
if err != nil {
service.Error(ctx, errors.New("请选择要上传的文件"))
return
}
// 校验大小:不超过 50M
if file.Size > maxAttachmentSize {
service.Error(ctx, errors.New("单个文件大小不超过50M"))
return
}
ext := strings.ToLower(path.Ext(file.Filename))
if !allowedAttachmentExt[ext] {
service.Error(ctx, errors.New("仅支持 Word、PDF、Excel 格式"))
return
}
// 本地临时目录runtime/contract/attachment/(使用 / 以与 PutBos 内 model.MediaPath 替换一致)
basePath := model.MediaPath + "contract/attachment"
if _, err = utils.CheckDirPath(basePath, true); err != nil {
service.Error(ctx, err)
return
}
// 对象名上传的文件名_UUID.扩展名,便于识别且不重名
originalBase := path.Base(file.Filename)
nameWithoutExt := strings.TrimSuffix(originalBase, ext)
nameWithoutExt = strings.ReplaceAll(strings.ReplaceAll(nameWithoutExt, "/", "_"), "\\", "_")
newUuid, _ := uuid.NewV4()
var filename string
if nameWithoutExt == "" {
filename = fmt.Sprintf("%s%s", newUuid.String(), ext)
} else {
filename = fmt.Sprintf("%s_%s%s", nameWithoutExt, newUuid.String(), ext)
}
dst := basePath + "/" + filename
if err = ctx.SaveUploadedFile(file, dst); err != nil {
service.Error(ctx, err)
return
}
url, err := upload.PutBos(dst, "attachment", true)
if err != nil {
service.Error(ctx, err)
return
}
service.Success(ctx, gin.H{"url": url})
}

View File

@ -0,0 +1,137 @@
package invoice
import (
"errors"
"fmt"
"time"
"fonchain-fiee/pkg/service/upload"
"dubbo.apache.org/dubbo-go/v3/common/logger"
"github.com/signintech/gopdf"
)
func MakeInvoice(invoiceNo, customerName, address, phone, bundleName, spec, priceType, totalAmount, transactionDate, invoiceDate string) (string, error) {
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
templatePath := "./data/invoice.pdf"
// 导入模板文件中的页面
err := pdf.ImportPagesFromSource(templatePath, "/MediaBox")
if err != nil {
logger.Fatalf("无法导入页面: %v", err)
return "", errors.New("error loading template PDF")
}
// 获取模板文件的总页数
totalPages := pdf.GetNumberOfPages()
fmt.Printf("模板文件的总页数: %d\n", totalPages)
customerPage := 1
// 生成 发票编号
// JP-ART- + time.Now().Format("20060102") + 7 位随机数
//invoiceNo := fmt.Sprintf("JP-ART-%s%s", time.Now().Format("20060102"))
tffErr := pdf.AddTTFFont("SourceHanSansSC-VF", "./data/SourceHanSansSC-VF.ttf")
if tffErr != nil {
logger.Fatalf("加载中文字体失败: %v", tffErr)
return "", errors.New("error loading font")
}
// 设置字体和字号
err = pdf.SetFont("SourceHanSansSC-VF", "", 12)
if err != nil {
logger.Fatalf("设置字体失败: %v", err)
return "", errors.New("error setting font")
}
// 填 用户信息
pdf.SetPage(customerPage)
pdf.SetX(443)
pdf.SetY(95)
pdf.Cell(nil, invoiceNo)
pdf.SetX(80)
pdf.SetY(162)
pdf.Cell(nil, customerName)
const (
addressX = 90
addressStartY = 182
addressLineH = 20 // 行高,按模板微调
maxAddressRunes = 16 // 每行最多字符数,按模板宽度调
)
lines := splitStringByRune(address, maxAddressRunes)
for i, line := range lines {
pdf.SetX(addressX)
pdf.SetY(addressStartY + float64(i)*addressLineH)
pdf.Cell(nil, line)
}
pdf.SetX(70)
pdf.SetY(268)
pdf.Cell(nil, phone)
pdf.SetX(80)
pdf.SetY(345)
pdf.Cell(nil, bundleName)
pdf.SetX(310)
pdf.SetY(345)
pdf.Cell(nil, spec)
pdf.SetX(410)
pdf.SetY(345)
pdf.Cell(nil, priceType+" "+totalAmount)
pdf.SetX(437)
pdf.SetY(388)
pdf.Cell(nil, priceType+" "+totalAmount)
pdf.SetX(125)
pdf.SetY(772)
pdf.Cell(nil, transactionDate)
pdf.SetX(495)
pdf.SetY(772)
pdf.Cell(nil, invoiceDate)
outputPath := fmt.Sprintf("./data/invoice_%s_%s.pdf", invoiceNo, time.Now().Format("20060102150405"))
// 生成新的 PDF
if err = pdf.WritePdf(outputPath); err != nil {
//zap.L().Error("WritePdf err", zap.Error(err))
return "", errors.New("error writing final PDF")
}
fmt.Println("生成发票成功开始上传oss")
// 上传 至 oss
ossUrl, err := upload.PutBos(outputPath, "fieeInvoice", true)
if err != nil {
//zap.L().Error("UploadFileToOss err", zap.Error(err))
return "", errors.New("error uploading PDF to OSS")
}
logger.Infof("Agreement uploaded to OSS: %s", ossUrl)
return ossUrl, nil
}
// 按每行最大字符数拆分,中文、英文都按 1 个 rune 计
func splitStringByRune(s string, maxRunesPerLine int) []string {
runes := []rune(s)
if len(runes) <= maxRunesPerLine {
return []string{s}
}
var lines []string
for i := 0; i < len(runes); i += maxRunesPerLine {
end := i + maxRunesPerLine
if end > len(runes) {
end = len(runes)
}
lines = append(lines, string(runes[i:end]))
}
return lines
}

View File

@ -9,7 +9,6 @@ import (
"fonchain-fiee/api/bundle"
"fonchain-fiee/api/cast"
"fonchain-fiee/cmd/config"
"fonchain-fiee/pkg/e"
"fonchain-fiee/pkg/model/login"
"fonchain-fiee/pkg/service"
castService "fonchain-fiee/pkg/service/cast"
@ -22,21 +21,25 @@ import (
"go.uber.org/zap"
)
// GetPendingTaskList 查询待指派任务记录
func GetPendingTaskList(c *gin.Context) {
var req bundle.TaskQueryRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
type TaskWorkLogListHTTPReq struct {
AssignRecordsUUID string `json:"assignRecordsUUID" binding:"required"`
TaskType int32 `json:"taskType" binding:"required"`
Page int32 `json:"page" binding:"required"`
PageSize int32 `json:"pageSize" binding:"required"`
}
res, err := service.BundleProvider.GetPendingTaskList(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
type CompletedItem struct {
Uuid string `json:"uuid"`
Title string `json:"title"`
ScriptUuid string `json:"scriptUuid,omitempty"`
ScriptTitle string `json:"scriptTitle,omitempty"`
SubmitTime string `json:"submitTime"`
PdfUrl string `json:"pdfUrl,omitempty"`
}
service.Success(c, res)
type CompletedListResp struct {
Data []*CompletedItem `json:"data"`
Count int64 `json:"count"`
}
func GetPendingTaskLayout(c *gin.Context) {
@ -71,6 +74,32 @@ func AssignTask(c *gin.Context) {
service.Error(c, err)
return
}
if req.SubNum == "" {
err2 := errors.New("艺人编号不能为空")
service.Error(c, err2)
return
}
// 根据 subNum 查询艺人 artistUuid
subInfoResp, err1 := service.AccountFieeProvider.SubNumGetInfo(context.Background(), &accountFiee.SubNumGetInfoRequest{
SubNum: req.SubNum,
Domain: "app",
})
if err1 != nil {
fmt.Println("SubNumGetInfo err")
fmt.Println(err1)
err1 = errors.New("自媒体用户查询失败")
service.Error(c, err1)
return
}
if subInfoResp == nil || subInfoResp.Id == 0 {
err1 = errors.New("自媒体用户不存在")
service.Error(c, err1)
return
}
req.UserID = int32(subInfoResp.Id)
req.ArtistName = subInfoResp.Name
req.TelNum = subInfoResp.TelNum
res, err := service.BundleProvider.AssignTask(context.Background(), &req)
if err != nil {
@ -98,6 +127,32 @@ func BatchAssignTask(c *gin.Context) {
item.Operator = userInfo.Name
item.OperatorNum = userInfo.TelNum
if item.SubNum == "" {
err2 := errors.New("艺人编号不能为空")
service.Error(c, err2)
return
}
subInfoResp, err1 := service.AccountFieeProvider.SubNumGetInfo(context.Background(), &accountFiee.SubNumGetInfoRequest{
SubNum: item.SubNum,
Domain: "app",
})
if err1 != nil {
fmt.Println("SubNumGetInfo err")
fmt.Println(err1)
err1 = errors.New("自媒体用户查询失败")
service.Error(c, err1)
return
}
if subInfoResp == nil || subInfoResp.Id == 0 {
err1 = errors.New("自媒体用户不存在")
service.Error(c, err1)
return
}
item.UserID = int32(subInfoResp.Id)
item.ArtistName = subInfoResp.Name
item.TelNum = subInfoResp.TelNum
}
@ -144,26 +199,6 @@ func BatchTerminateTask(c *gin.Context) {
service.Success(c, res)
}
// UpdatePendingCount 修改待发数量
func UpdatePendingCount(c *gin.Context) {
var req bundle.UpdatePendingCountRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
userInfo := login.GetUserInfoFromC(c)
req.OperatorNum = userInfo.TelNum
req.Operator = userInfo.Name
res, err := service.BundleProvider.UpdatePendingCount(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// GetRecentAssignRecords 查询最近被指派记录
func GetRecentAssignRecords(c *gin.Context) {
var req bundle.RecentAssignRecordsRequest
@ -238,23 +273,6 @@ func CompleteTaskManually(c *gin.Context) {
service.Success(c, res)
}
// UpdateTaskProgress 员工实际完成任务状态更新
func UpdateTaskProgress(c *gin.Context) {
var req bundle.UpdateTaskProgressRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.UpdateTaskProgress(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// GetTaskAssignRecordsList 多条件查询操作记录表
func GetTaskAssignRecordsList(c *gin.Context) {
var req bundle.TaskAssignRecordsQueryRequest
@ -280,7 +298,7 @@ func GetTaskAssignRecordsListDownload(c *gin.Context) {
return
}
req.Page = 1
req.PageSize = 999999999
req.PageSize = 999999
detail, detailErr := service.BundleProvider.GetTaskAssignRecordsList(context.Background(), &req)
if detailErr != nil {
@ -289,7 +307,7 @@ func GetTaskAssignRecordsListDownload(c *gin.Context) {
}
titleList := []string{
"用户编号", "艺人", "艺人手机号", "任务批次", "状态", "实际完成状态", "待上传视频脚本数", "待上传视频数", "待上传图文数", "待上传数据数", "实际上传视频脚本数", "实际上传视频数", "实际上传图文数", "实际上传数据数", "指派人", "操作人账号", "操作人", "操作时间",
"用户编号", "艺人", "艺人手机号", "任务批次", "状态", "实际完成状态", "待上传视频脚本数", "待上传视频数", "待上传图文数", "待上传数据数", "待上传竞品报告数", "实际上传视频脚本数", "实际上传视频数", "实际上传图文数", "实际上传数据数", "实际上传竞品报告数", "指派人", "操作人账号", "操作人", "操作时间",
}
var dataList []interface{}
@ -307,10 +325,12 @@ func GetTaskAssignRecordsListDownload(c *gin.Context) {
i.PendingVideoCount,
i.PendingPostCount,
i.PendingDataCount,
i.PendingReportCount,
i.CompleteVideoScriptCount,
i.CompleteVideoCount,
i.CompletePostCount,
i.CompleteDataCount,
i.CompleteReportCount,
i.TaskAssignee,
i.OperatorNum,
i.Operator,
@ -356,6 +376,17 @@ type UpdateVideoScriptWithTaskUUIDReq struct {
AssignRecordsUUID string `json:"assignRecordsUUID"`
}
type CreateWorkAnalysisWithTaskUUIDReq struct {
*cast.CreateWorkAnalysisReq
AssignRecordsUUID string `json:"assignRecordsUUID"`
}
type CreateCompetitiveReportWithTaskUUIDReq struct {
*cast.CreateCompetitiveReportReq
AssignRecordsUUID string `json:"assignRecordsUUID"`
ReportData utils.CompetitorReportData `json:"json_data"` // AI生成的竞品报告数据
}
func UpdateWorkImageWithTaskUUID(ctx *gin.Context) {
var req UpdateWorkImageWithTaskUUIDReq
var infoResp *accountFiee.UserInfoResponse
@ -444,6 +475,170 @@ func UpdateWorkImageWithTaskUUID(ctx *gin.Context) {
return
}
func CreateWorkAnalysisWithTaskUUID(ctx *gin.Context) {
var req CreateWorkAnalysisWithTaskUUIDReq
var infoResp *accountFiee.UserInfoResponse
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
res, err := service.BundleProvider.GetTaskActualStatusByUUID(context.Background(), &bundle.GetTaskActualStatusByUUIDRequest{
AssignRecordsUUID: req.AssignRecordsUUID,
})
if err != nil {
service.Error(ctx, err)
return
}
if res.ActualStatus == 3 {
service.Error(ctx, errors.New("任务已中止"))
return
}
resp, err := castService.CreateWorkAnalysisCore(ctx, req.CreateWorkAnalysisReq)
if err != nil {
service.Error(ctx, err)
return
}
if config.AppConfig.System.AppMode != "dev" {
artistId, _ := strconv.ParseUint(req.ArtistID, 10, 64)
infoResp, err = service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
ID: artistId,
Domain: "app",
})
if err != nil {
service.Error(ctx, err)
return
}
} else {
infoResp = &accountFiee.UserInfoResponse{
Name: "小波",
TelNum: "18288888888",
TelAreaCode: "86",
}
}
userInfo := login.GetUserInfoFromC(ctx)
resp1, err := service.BundleProvider.UpdateTaskProgress(context.Background(), &bundle.UpdateTaskProgressRequest{
AssignRecordsUUID: req.AssignRecordsUUID,
EmployeeName: userInfo.Name,
EmployeeNum: userInfo.TelNum,
TaskType: "data",
CompleteCount: 1,
Uuid: resp.Uuid,
})
if err != nil {
service.Error(ctx, err)
return
}
zap.L().Info("UpdateTaskProgress", zap.Any("resp", resp1))
logReq := &bundle.CreateTaskWorkLogRequest{
AssignRecordsUUID: req.AssignRecordsUUID,
WorkUUID: resp.Uuid,
Title: req.Title,
ArtistUUID: req.ArtistID,
SubNum: infoResp.SubNum,
TelNum: infoResp.TelNum,
ArtistName: infoResp.Name,
OperationType: 3, // 完成任务
TaskType: 3, // 数据分析
TaskCount: 1,
OperatorName: userInfo.Name,
OperatorNum: userInfo.TelNum,
}
zap.L().Info("CreateTaskWorkLog request", zap.Any("req", logReq))
logResp, err := service.BundleProvider.CreateTaskWorkLog(context.Background(), logReq)
if err != nil {
zap.L().Error("CreateTaskWorkLog failed", zap.Error(err), zap.Any("req", logReq))
} else {
zap.L().Info("CreateTaskWorkLog success", zap.Any("resp", logResp))
}
service.Success(ctx, resp)
return
}
func CreateCompetitiveReportWithTaskUUID(ctx *gin.Context) {
var req CreateCompetitiveReportWithTaskUUIDReq
var infoResp *accountFiee.UserInfoResponse
var err error
if err = ctx.ShouldBind(&req); err != nil {
service.Error(ctx, err)
return
}
res, err := service.BundleProvider.GetTaskActualStatusByUUID(context.Background(), &bundle.GetTaskActualStatusByUUIDRequest{
AssignRecordsUUID: req.AssignRecordsUUID,
})
if err != nil {
service.Error(ctx, err)
return
}
if res.ActualStatus == 3 {
service.Error(ctx, errors.New("任务已中止"))
return
}
resp, err := castService.CreateCompetitiveReportCore(ctx, req.CreateCompetitiveReportReq, req.ReportData)
if err != nil {
service.Error(ctx, err)
return
}
if config.AppConfig.System.AppMode != "dev" {
artistId, _ := strconv.ParseUint(req.ArtistID, 10, 64)
infoResp, err = service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
ID: artistId,
Domain: "app",
})
if err != nil {
service.Error(ctx, err)
return
}
} else {
infoResp = &accountFiee.UserInfoResponse{
Name: "小波",
TelNum: "18288888888",
TelAreaCode: "86",
}
}
userInfo := login.GetUserInfoFromC(ctx)
resp1, err := service.BundleProvider.UpdateTaskProgress(context.Background(), &bundle.UpdateTaskProgressRequest{
AssignRecordsUUID: req.AssignRecordsUUID,
EmployeeName: userInfo.Name,
EmployeeNum: userInfo.TelNum,
TaskType: "report",
CompleteCount: 1,
Uuid: resp.Uuid,
})
if err != nil {
service.Error(ctx, err)
return
}
zap.L().Info("UpdateTaskProgress", zap.Any("resp", resp1))
logReq := &bundle.CreateTaskWorkLogRequest{
AssignRecordsUUID: req.AssignRecordsUUID,
WorkUUID: resp.Uuid,
Title: req.Title,
ArtistUUID: req.ArtistID,
SubNum: infoResp.SubNum,
TelNum: infoResp.TelNum,
ArtistName: infoResp.Name,
OperationType: 3,
TaskType: 5,
TaskCount: 1,
OperatorName: userInfo.Name,
OperatorNum: userInfo.TelNum,
}
zap.L().Info("CreateTaskWorkLog request", zap.Any("req", logReq))
logResp, err := service.BundleProvider.CreateTaskWorkLog(context.Background(), logReq)
if err != nil {
zap.L().Error("CreateTaskWorkLog failed", zap.Error(err), zap.Any("req", logReq))
} else {
zap.L().Info("CreateTaskWorkLog success", zap.Any("resp", logResp))
}
service.Success(ctx, resp)
return
}
func UpdateWorkVideoWithUUID(ctx *gin.Context) {
var req UpdateWorkVideoWithUUIDReq
var infoResp *accountFiee.UserInfoResponse
@ -532,23 +727,6 @@ func UpdateWorkVideoWithUUID(ctx *gin.Context) {
return
}
// GetArtistBundleBalance 查询艺人套餐剩余数量
func GetArtistBundleBalance(c *gin.Context) {
var req bundle.ArtistBundleBalanceRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.GetArtistBundleBalance(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// GetArtistUploadStatsList 查询艺人待上传列表
func GetArtistUploadStatsList(c *gin.Context) {
var req bundle.TaskQueryRequest
@ -566,22 +744,6 @@ func GetArtistUploadStatsList(c *gin.Context) {
service.Success(c, res)
}
func GetPendingUploadBreakdown(c *gin.Context) {
var req bundle.PendingUploadBreakdownRequest
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
res, err := service.BundleProvider.GetPendingUploadBreakdown(context.Background(), &req)
if err != nil {
service.Error(c, err)
return
}
service.Success(c, res)
}
// GetArtistUploadStatsListDownload 导出艺人待上传列表为Excel
func GetArtistUploadStatsListDownload(c *gin.Context) {
var req bundle.TaskQueryRequest
@ -591,7 +753,7 @@ func GetArtistUploadStatsListDownload(c *gin.Context) {
}
// 拉取所有数据
req.Page = 1
req.PageSize = 999999999
req.PageSize = 999999
detail, detailErr := service.BundleProvider.GetArtistUploadStatsList(context.Background(), &req)
if detailErr != nil {
@ -600,7 +762,7 @@ func GetArtistUploadStatsListDownload(c *gin.Context) {
}
titleList := []string{
"用户编号", "艺人", "手机号", "最近一次指派人", "可指派视频脚本数", "可上传视频脚本数", "已上传视频脚本数", "可指派视频数", "可上传视频数", "已上传视频数", "已释放视频额度", "套餐视频总数", "增值视频总数", "可指派图文数", "可上传图文数", "已上传图文数", "已释放图文额度", "套餐图文总数", "增值图文总数", "可指派数据数", "可上传数据数", "已上传数据数", "已释放数据额度", "套餐数据总数", "增值数据总数", "进行中任务数", "已完成任务数",
"用户编号", "艺人", "手机号", "最近一次指派人", "可指派视频脚本数", "可上传视频脚本数", "已上传视频脚本数", "可指派视频数", "可上传视频数", "已上传视频数", "已释放视频额度", "套餐视频总数", "增值视频总数", "可指派图文数", "可上传图文数", "已上传图文数", "已释放图文额度", "套餐图文总数", "增值图文总数", "可指派数据数", "可上传数据数", "已上传数据数", "已释放数据额度", "套餐数据总数", "增值数据总数", "可指派竞品报告数", "可上传竞品报告数", "已上传竞品报告数", "已释放竞品报告额度", "套餐竞品报告总数", "增值竞品报告总数", "进行中任务数", "已完成任务数",
}
var dataList []interface{}
@ -631,6 +793,12 @@ func GetArtistUploadStatsListDownload(c *gin.Context) {
i.ReleasedDataAnalysisTotal,
i.BundleDataAnalysisTotal,
i.IncreaseDataAnalysisTotal,
i.AllowReportCount,
i.PendingReportCount,
i.UploadedReportCount,
i.ReleasedReportTotal,
i.BundleReportTotal,
i.IncreaseReportTotal,
i.ProgressTaskCount,
i.CompleteTaskCount,
}
@ -669,27 +837,27 @@ func UpdateVideoScriptWithUUID(ctx *gin.Context) {
return
}
newCtx := castService.NewCtxWithUserInfo(ctx)
artistId, _ := strconv.ParseUint(req.ArtistUuid, 10, 64)
infoResp, err = service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
ID: artistId,
Domain: "app",
})
resp, err := castService.UpdateVideoScriptCore(ctx, req.UpdateVideoScriptReq)
if err != nil {
service.Error(ctx, err)
return
}
if infoResp.Id == 0 {
service.Error(ctx, errors.New(e.GetMsg(e.NOTDATA)))
return
}
req.ArtistName = infoResp.Name
req.ArtistPhone = infoResp.TelNum
req.ArtistNum = infoResp.SubNum
resp, err := service.CastProvider.UpdateVideoScript(newCtx, req.UpdateVideoScriptReq)
if err != nil {
service.Error(ctx, err)
return
if config.AppConfig.System.AppMode != "dev" {
artistId, _ := strconv.ParseUint(req.ArtistUuid, 10, 64)
infoResp, err = service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
ID: artistId,
Domain: "app",
})
if err != nil {
service.Error(ctx, err)
return
}
} else {
infoResp = &accountFiee.UserInfoResponse{
Name: "小波",
TelNum: "18288888888",
TelAreaCode: "86",
}
}
// EmployeeName 和 EmployeeNum 从 toekn 里面拿
userInfo := login.GetUserInfoFromC(ctx)
@ -718,7 +886,7 @@ func UpdateVideoScriptWithUUID(ctx *gin.Context) {
TelNum: infoResp.TelNum,
ArtistName: infoResp.Name,
OperationType: 3, // 3:完成任务
TaskType: 1, // 1:视频(脚本属于视频类型)
TaskType: 4, // 4:视频脚本
TaskCount: 1,
OperatorName: userInfo.Name,
OperatorNum: userInfo.TelNum,
@ -752,3 +920,195 @@ func GetPendingAssign(c *gin.Context) {
service.Success(c, res)
}
func GetTaskWorkLogListItems(c *gin.Context) {
var req TaskWorkLogListHTTPReq
if err := c.ShouldBindJSON(&req); err != nil {
service.Error(c, err)
return
}
if req.AssignRecordsUUID == "" {
err := errors.New("参数错误")
service.Error(c, err)
return
}
if req.TaskType == 0 {
err := errors.New("参数错误")
service.Error(c, err)
return
}
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
workLogResp, err := service.BundleProvider.GetTaskWorkLogList(context.Background(), &bundle.TaskWorkLogQueryRequest{
AssignRecordsUUID: req.AssignRecordsUUID,
OperationType: 3, // 类型,完成任务
TaskType: req.TaskType,
Page: 1,
PageSize: 9999,
})
if err != nil {
err := errors.New("查询失败")
service.Error(c, err)
return
}
uuidMap := make(map[string]struct{})
var uuids []string
for _, r := range workLogResp.Records {
if r == nil || r.WorkUUID == "" {
continue
}
if _, ok := uuidMap[r.WorkUUID]; ok {
continue
}
uuidMap[r.WorkUUID] = struct{}{}
uuids = append(uuids, r.WorkUUID)
}
items := make([]*CompletedItem, 0)
ctx := castService.NewCtxWithUserInfo(c)
switch req.TaskType {
case 1, 2:
if len(uuids) == 0 {
service.Success(c, &CompletedListResp{Data: items, Count: int64(len(items))})
return
}
resp, err := service.CastProvider.WorkList(ctx, &cast.WorkListReq{
WorkUuids: uuids,
Page: req.Page,
PageSize: int32(req.PageSize),
})
if err != nil {
err := errors.New("查询失败")
service.Error(c, err)
return
}
workMap := make(map[string]*cast.WorkListResp_Info)
for _, w := range resp.Data {
if w == nil {
continue
}
workMap[w.WorkUuid] = w
}
for _, uuid := range uuids {
w, ok := workMap[uuid]
if !ok {
continue
}
items = append(items, &CompletedItem{
Uuid: w.WorkUuid,
Title: w.Title,
ScriptUuid: w.ScriptUuid,
ScriptTitle: w.ScriptTitle,
SubmitTime: w.SubmitTime,
})
}
case 3:
if len(uuids) == 0 {
service.Success(c, &CompletedListResp{Data: items, Count: int64(len(items))})
return
}
resp, err := service.CastProvider.ListWorkAnalysis(ctx, &cast.ListWorkAnalysisReq{
UuidList: uuids,
Page: req.Page,
PageSize: int32(req.PageSize),
})
if err != nil {
err := errors.New("查询失败")
service.Error(c, err)
return
}
analysisMap := make(map[string]*cast.WorkAnalysisInfo)
for _, a := range resp.Data {
if a == nil {
continue
}
analysisMap[a.Uuid] = a
}
for _, uuid := range uuids {
a, ok := analysisMap[uuid]
if !ok {
continue
}
items = append(items, &CompletedItem{
Uuid: a.Uuid,
Title: a.Title,
SubmitTime: a.SubmitTime,
PdfUrl: a.PdfUrl,
})
}
case 4:
if len(uuids) == 0 {
service.Success(c, &CompletedListResp{Data: items, Count: int64(len(items))})
return
}
resp, err := service.CastProvider.ListVideoScripts(ctx, &cast.ListVideoScriptsReq{
ScriptUuids: uuids,
Page: req.Page,
PageSize: int32(req.PageSize),
})
if err != nil {
err := errors.New("查询失败")
service.Error(c, err)
return
}
scriptMap := make(map[string]*cast.VideoScriptInfo)
for _, s := range resp.Data {
if s == nil {
continue
}
scriptMap[s.Uuid] = s
}
for _, uuid := range uuids {
s, ok := scriptMap[uuid]
if !ok {
continue
}
items = append(items, &CompletedItem{
Uuid: s.Uuid,
Title: s.Title,
SubmitTime: s.CreatedDate,
})
}
case 5:
if len(uuids) == 0 {
service.Success(c, &CompletedListResp{Data: items, Count: int64(len(items))})
return
}
resp, err := service.CastProvider.ListCompetitiveReport(ctx, &cast.ListCompetitiveReportReq{
UuidList: uuids,
Page: req.Page,
PageSize: int32(req.PageSize),
})
if err != nil {
err := errors.New("查询失败")
service.Error(c, err)
return
}
reportMap := make(map[string]*cast.CompetitiveReportInfo)
for _, r := range resp.Data {
if r == nil {
continue
}
reportMap[r.Uuid] = r
}
for _, uuid := range uuids {
r, ok := reportMap[uuid]
if !ok {
continue
}
items = append(items, &CompletedItem{
Uuid: r.Uuid,
Title: r.Title,
SubmitTime: r.SubmitTime,
PdfUrl: r.PdfUrl,
})
}
default:
service.Error(c, errors.New("参数错误"))
return
}
service.Success(c, &CompletedListResp{Data: items, Count: int64(len(items))})
}

78
pkg/service/upload/bos.go Normal file
View File

@ -0,0 +1,78 @@
package upload
import (
"fmt"
"github.com/fonchain_enterprise/utils/objstorage"
"github.com/google/uuid"
)
type OssVal struct {
obj objstorage.API
bos Bos
}
var ossObj OssVal
// Oss 对象存储配置信息
type Bos struct {
AccessKeyId string
AccessKeySecret string
Endpoint string
Host string
CdnHost string
BucketName string
BosBaseDir string
}
func LoadEnv(bos Bos) (err error) {
v, err := objstorage.NewBOS(bos.AccessKeyId, bos.AccessKeySecret, bos.Endpoint)
if err != nil {
return err
}
ossObj.bos = bos
ossObj.obj = v
return nil
}
// UploadLocal 上传本地
// UploadLocal("art_block_chain/files/artwork/1.png")
func UploadLocal(ossFile string, localFile string) (string, error) {
api := ossObj.obj
ossConfig := ossObj.bos
fmt.Printf("%+v", ossConfig)
//eTag, err := api.PutObjectFromFile(ossConfig.Endpoint, "art_block_chain/files/artwork/"+tmp1+"_artworkal.jpg", ossConfig.Endpoint)
_, err := api.PutObjectFromFile(ossConfig.BucketName, ossFile, localFile)
if err != nil {
return "", err
}
return ossConfig.Host + "/" + ossConfig.BucketName + "/" + ossFile, nil
}
func UploadToBos(suffix string, fileBytes []byte) (string, error) {
api := ossObj.obj
ossConfig := ossObj.bos
fmt.Printf("1-------------%+v", ossConfig)
newUUid, uerror := uuid.NewUUID()
if uerror != nil {
return "", uerror
}
ossFile := ossConfig.BosBaseDir + "/files/img/" + newUUid.String() + suffix
//eTag, err := api.PutObjectFromFile(ossConfig.Endpoint, "art_block_chain/files/artwork/"+tmp1+"_artworkal.jpg", ossConfig.Endpoint)
_, err := api.PutObjectFromBytes(ossConfig.BucketName, ossFile, fileBytes)
fmt.Println("1---", err)
fmt.Println("1---", ossConfig.BucketName)
if err != nil {
return "", err
}
return ossConfig.CdnHost + "/" + ossFile, nil
}

68
pkg/service/upload/oss.go Normal file
View File

@ -0,0 +1,68 @@
package upload
import (
"fmt"
"github.com/fonchain_enterprise/utils/objstorage"
"github.com/google/uuid"
)
type AliOssVal struct {
obj objstorage.API
bos Bos
}
var aliOssObj AliOssVal
func LoadOssEnv(bos Bos) (err error) {
v, err := objstorage.NewOSS(bos.AccessKeyId, bos.AccessKeySecret, bos.Endpoint)
if err != nil {
return err
}
aliOssObj.bos = bos
aliOssObj.obj = v
return nil
}
// UploadLocal 上传本地
// UploadLocal("art_block_chain/files/artwork/1.png")
func OssUploadLocal(ossFile string, localFile string) (string, error) {
api := aliOssObj.obj
ossConfig := aliOssObj.bos
fmt.Printf("%+v", ossConfig)
//eTag, err := api.PutObjectFromFile(ossConfig.Endpoint, "art_block_chain/files/artwork/"+tmp1+"_artworkal.jpg", ossConfig.Endpoint)
fmt.Println("这边看看", ossFile, localFile)
_, err := api.PutObjectFromFile(ossConfig.BucketName, ossFile, localFile)
if err != nil {
return "", err
}
return ossConfig.CdnHost + "/" + ossFile, nil
}
func OssUploadToBos(suffix string, fileBytes []byte) (string, error) {
api := aliOssObj.obj
ossConfig := aliOssObj.bos
fmt.Printf("1-------------%+v", ossConfig, "文件类型", suffix)
newUUid, uerror := uuid.NewUUID()
if uerror != nil {
return "", uerror
}
ossFile := ossConfig.BosBaseDir + "/files/img/" + newUUid.String() + suffix
//eTag, err := api.PutObjectFromFile(ossConfig.Endpoint, "art_block_chain/files/artwork/"+tmp1+"_artworkal.jpg", ossConfig.Endpoint)
_, err := api.PutObjectFromBytes(ossConfig.BucketName, ossFile, fileBytes)
fmt.Println("1---", err)
fmt.Println("1---", ossConfig.BucketName)
if err != nil {
return "", err
}
return ossConfig.CdnHost + "/" + ossFile, nil
}

View File

@ -7,6 +7,7 @@ import (
"io"
"net/http"
"os"
"strconv"
"strings"
"go.uber.org/zap"
@ -50,3 +51,50 @@ func SaveUrlFileDisk(url string, path string, filename string) (fullPath string,
}
return
}
// GetRemoteFileSize 通过HTTP HEAD请求获取远程文件大小不下载文件
func GetRemoteFileSize(url string) (size int64, err error) {
// 创建HEAD请求
req, err := http.NewRequest("HEAD", url, nil)
if err != nil {
zap.L().Error("GetRemoteFileSize create request err", zap.String("url", url), zap.Error(err))
err = errors.New(e.GetMsg(e.ERROR_DOWNLOAD_FILE))
return
}
// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
zap.L().Error("GetRemoteFileSize request err", zap.String("url", url), zap.Error(err))
err = errors.New(e.GetMsg(e.ERROR_DOWNLOAD_FILE))
return
}
defer resp.Body.Close()
// 检查HTTP状态码
if resp.StatusCode != http.StatusOK {
zap.L().Error("GetRemoteFileSize status code err", zap.String("url", url), zap.Int("status", resp.StatusCode))
err = errors.New(e.GetMsg(e.ERROR_DOWNLOAD_FILE))
return
}
// 获取Content-Length头部
contentLength := resp.Header.Get("Content-Length")
if contentLength == "" {
zap.L().Error("GetRemoteFileSize Content-Length header not found", zap.String("url", url))
err = errors.New("无法获取文件大小")
return
}
// 解析文件大小
size, err = strconv.ParseInt(contentLength, 10, 64)
size = size / 1024 / 1024
if err != nil {
zap.L().Error("GetRemoteFileSize parse size err", zap.String("url", url), zap.String("contentLength", contentLength), zap.Error(err))
err = errors.New("解析文件大小失败")
return
}
return
}

152
pkg/utils/map.go Normal file
View File

@ -0,0 +1,152 @@
package utils
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
)
const baiduIPLocationAPI = "https://api.map.baidu.com/location/ip"
// 建议把 ak 放配置;这里先保留你给的 key后续可改为从配置读取。
const baiduMapAK = "T8DGBYxbZ1iAeXx1J57McKigyHJHulPQ"
type baiduIPResp struct {
Status int `json:"status"`
Address string `json:"address"`
Content struct {
Address string `json:"address"`
} `json:"content"`
Message string `json:"message"`
}
type ReverseGeocodingReq struct {
Ak string `json:"ak"`
Coordtype string `json:"coordtype"`
RetCoordtype string `json:"retCoordtype"`
Location string `json:"location"`
Output string `json:"output"`
Language string `json:"language"`
}
type ReverseGeocodingRes struct {
Status int `json:"status"`
Result struct {
Location struct {
Lng float64 `json:"lng"`
Lat float64 `json:"lat"`
} `json:"location"`
FormattedAddress string `json:"formatted_address"`
Edz struct {
Name string `json:"name"`
} `json:"edz"`
Business string `json:"business"`
AddressComponent struct {
Country string `json:"country"`
CountryCodeIso string `json:"country_code_iso"`
CountryCodeIso2 string `json:"country_code_iso2"`
CountryCode int `json:"country_code"`
Province string `json:"province"`
City string `json:"city"`
CityLevel int `json:"city_level"`
District string `json:"district"`
Town string `json:"town"`
TownCode string `json:"town_code"`
Distance string `json:"distance"`
Direction string `json:"direction"`
Adcode string `json:"adcode"`
Street string `json:"street"`
StreetNumber string `json:"street_number"`
} `json:"addressComponent"`
} `json:"result"`
}
// ReverseGeo 经纬度逆编码
func ReverseGeo(longitude, latitude string, language string) (address string, err error) {
var reverseGeocodingReq ReverseGeocodingReq
reverseGeocodingReq.Ak = "3bAjKGA0pv7qvszGe98RsVZ04Ob5r4ZZ"
reverseGeocodingReq.Coordtype = "gcj02ll"
reverseGeocodingReq.Output = "json"
reverseGeocodingReq.RetCoordtype = "gcj02ll"
reverseGeocodingReq.Location = strings.Join([]string{latitude, longitude}, ",")
reverseGeocodingReq.Language = language
url := "https://api.map.baidu.com/reverse_geocoding/v3/?ak=" + reverseGeocodingReq.Ak + "&output=" + reverseGeocodingReq.Output + "&coordtype=" + reverseGeocodingReq.Coordtype + "&location=" + reverseGeocodingReq.Location + "&ret_coordtype=" + reverseGeocodingReq.RetCoordtype + "&language=" + reverseGeocodingReq.Language
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
var results ReverseGeocodingRes
err = json.Unmarshal(body, &results)
if err != nil {
return "", err
}
if results.Status != 0 {
address = "未知地址"
return address, err
}
address = results.Result.FormattedAddress
return address, nil
}
func GetAddressByIP(ip string) (string, error) {
ip = strings.TrimSpace(ip)
if ip == "" {
return "", fmt.Errorf("ip is empty")
}
q := url.Values{}
q.Set("ip", ip)
q.Set("coor", "bd09ll")
q.Set("ak", baiduMapAK)
reqURL := baiduIPLocationAPI + "?" + q.Encode()
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Get(reqURL)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("baidu api status: %d", resp.StatusCode)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
var r baiduIPResp
if err := json.Unmarshal(body, &r); err != nil {
return "", err
}
if r.Status != 0 {
if r.Message == "" {
r.Message = "baidu api error"
}
return "", fmt.Errorf("%s", r.Message)
}
if strings.TrimSpace(r.Content.Address) != "" {
return r.Content.Address, nil
}
if strings.TrimSpace(r.Address) != "" {
return r.Address, nil
}
return "", nil
}

893
pkg/utils/pdf.go Normal file
View File

@ -0,0 +1,893 @@
package utils
import (
"errors"
"fmt"
"fonchain-fiee/pkg/service/bundle/model"
"image"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
"time"
"unicode"
"unicode/utf8"
"github.com/phpdave11/gofpdf"
"github.com/signintech/gopdf"
"go.uber.org/zap"
)
// cleanTextForPDF 清理文本移除PDF不支持的字符如emoji
// gofpdf库不支持某些特殊字符
func cleanTextForPDF(text string) string {
var result []rune
for _, r := range text {
// 保留基本多文种平面BMP内的字符码点 <= 0xFFFF
// 这样可以保留中文、英文、数字等常用字符但过滤掉emoji等特殊字符
if r <= 0xFFFF && (unicode.IsPrint(r) || unicode.IsSpace(r)) {
result = append(result, r)
}
}
return string(result)
}
// loadChineseFont 加载中文字体
func loadChineseFont(pdf *gofpdf.Fpdf, fontPath string) error {
var fontData []byte
var err error
// 如果提供了本地字体路径,优先使用本地字体
if fontPath == "" {
return errors.New("字体文件路径不能为空")
}
fontData, err = os.ReadFile(fontPath)
if err != nil {
return fmt.Errorf("读取字体文件失败: %v", err)
}
// 使用本地字体文件
pdf.AddUTF8FontFromBytes("Chinese", "", fontData)
return nil
}
// GeneratePDF 生成PDF文件
func GeneratePDF(text, imageURL, outputPath, fontPath string) error {
if text == "" {
return errors.New("文本不能为空")
}
// 创建PDF实例P=纵向mm=毫米单位A4=页面大小
pdf := gofpdf.New("P", "mm", "A4", "")
// 加载中文字体
err := loadChineseFont(pdf, fontPath)
if err != nil {
return fmt.Errorf("加载中文字体失败: %v", err)
}
// 添加新页面
pdf.AddPage()
// 设置字体使用中文字体12号字体
pdf.SetFont("Chinese", "", 12)
// 设置页面边距(左、上、右)
pdf.SetMargins(20, 10, 20)
// 设置当前位置x, y从左上角开始
pdf.SetXY(20, 10)
// 清理文本移除PDF不支持的字符如emoji
cleanedText := cleanTextForPDF(text)
// 添加文本内容
// 使用MultiCell方法处理多行文本支持自动换行
// 参数:宽度、行高、文本内容、边框、对齐方式、是否填充
// A4页面宽度210mm减去左右边距40mm可用宽度170mm
textWidth := 170.0
lineHeight := 7.0
pdf.MultiCell(textWidth, lineHeight, cleanedText, "", "L", false)
// 如果提供了图片URL则添加图片
if imageURL != "" {
// 添加一些间距
pdf.Ln(5)
// 解析URL获取文件扩展名
u, err := url.Parse(imageURL)
if err != nil {
return fmt.Errorf("图片链接解析错误: %v", err)
}
fileExt := filepath.Ext(u.Path)
// 如果没有扩展名,默认使用.jpg
if fileExt == "" {
fileExt = ".jpg"
}
// 下载图片
resp, err := http.Get(imageURL)
if err != nil {
return fmt.Errorf("下载图片失败: %v", err)
}
defer resp.Body.Close()
// 读取图片数据
imageData, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("读取图片数据失败: %v", err)
}
// 将图片数据保存到临时文件gofpdf需要文件路径
tmpFile, err := os.CreateTemp("", "pdf_image_*"+fileExt)
if err != nil {
return fmt.Errorf("创建临时文件失败: %v", err)
}
defer os.Remove(tmpFile.Name()) // 使用完后删除临时文件
defer tmpFile.Close()
// 写入图片数据到临时文件
_, err = tmpFile.Write(imageData)
if err != nil {
return fmt.Errorf("写入临时文件失败: %v", err)
}
tmpFile.Close()
// A4纵向页面宽度210mm减去左右边距40mm可用宽度170mm
// 图片宽度设为可用宽度的70%
imageWidth := textWidth * 0.7
// 计算居中位置页面宽度210mm图片居中
imageX := (210.0 - imageWidth) / 2
currentY := pdf.GetY()
// 注册图片并获取原始尺寸,用于计算缩放后的高度
imgInfo := pdf.RegisterImageOptions(tmpFile.Name(), gofpdf.ImageOptions{})
if imgInfo == nil {
return fmt.Errorf("注册图片失败")
}
// 计算缩放后的图片高度(按比例缩放)
// 原始宽度:原始高度 = 缩放后宽度:缩放后高度
originalWidth, originalHeight := imgInfo.Extent()
imageHeight := (imageWidth / originalWidth) * originalHeight
// A4页面高度297mm底部边距10mm计算可用的最大Y坐标
pageHeight := 297.0
bottomMargin := 10.0
maxY := pageHeight - bottomMargin
// 检查当前页面剩余空间是否足够放下图片
// 如果图片底部会超出页面可用区域,则添加新页面
if currentY+imageHeight > maxY {
pdf.AddPage()
// 新页面从顶部边距开始
currentY = 10.0
}
// 添加图片
// ImageOptions参数图片路径、x坐标、y坐标、宽度、高度、是否流式布局、选项、链接
// 高度设为0表示按比例自动计算
pdf.ImageOptions(tmpFile.Name(), imageX, currentY, imageWidth, 0, false, gofpdf.ImageOptions{}, 0, "")
}
// 生成并保存PDF文件
err = pdf.OutputFileAndClose(outputPath)
if err != nil {
return fmt.Errorf("生成PDF失败: %v", err)
}
return nil
}
// CompetitorReportData 竞品报告数据
type CompetitorReportData struct {
HighlightAnalysis HighlightAnalysisData `json:"highlight_analysis"`
DataPerformance DataPerformanceData `json:"data_performance_analysis"`
OverallSummary string `json:"overall_summary_and_optimization"`
ImageURL string `json:"image_url"` // 图片URL如果有图片则生成单独一页PDF
}
type HighlightAnalysisData struct {
Summary string `json:"summary"`
Points PointsData `json:"points"`
}
type PointsData struct {
Theme string `json:"theme"`
Narrative string `json:"narrative"`
Content string `json:"content"`
Copywriting string `json:"copywriting"`
Data string `json:"data"`
Music string `json:"music,omitempty"`
}
type DataPerformanceData struct {
Views string `json:"views"`
Completion string `json:"completion_rate,omitempty"`
Engagement string `json:"engagement"`
}
// GenerateCompetitorReportPDF 生成竞品报告PDF
// 参数:
// - templatePath: 模板文件路径(保留参数以兼容现有调用,传空则不使用模板)
// - outputPath: 输出PDF路径
// - data: 竞品报告数据
//
// 返回: 错误信息
func GenerateCompetitorReportPDF(templatePath, outputPath string, data CompetitorReportData) error {
fmt.Println("================================templatePath:", templatePath)
fmt.Println("================================outputPath:", outputPath)
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
// 如果有模板路径,则导入模板
if templatePath != "" {
err := pdf.ImportPagesFromSource(templatePath, "/MediaBox")
if err != nil {
return fmt.Errorf("无法导入页面: %v", err)
}
}
// 获取模板文件的总页数(如果有模板)
totalPages := pdf.GetNumberOfPages()
fmt.Printf("模板文件的总页数: %d\n", totalPages)
// 确定字体路径
var fontPath string
if templatePath != "" {
dir := filepath.Dir(templatePath)
fontPath = filepath.Join(dir, "simfang.ttf")
if _, err := os.Stat(fontPath); err != nil {
fontPath = filepath.Join("data", "simfang.ttf")
}
} else {
fontPath = filepath.Join("data", "simfang.ttf")
}
fmt.Printf("字体文件路径: %s\n", fontPath)
// 加载中文字体
ttfErr := pdf.AddTTFFont("simfang", fontPath)
if ttfErr != nil {
zap.L().Error("加载字体失败", zap.String("fontPath", fontPath), zap.Error(ttfErr))
return fmt.Errorf("加载中文字体失败: %v", ttfErr)
}
// 设置字体和字号
err := pdf.SetFont("simfang", "", 10)
if err != nil {
return fmt.Errorf("设置字体失败: %v", err)
}
// 行高15pt
lineHeight := 15.0
// 如果有内容要写入,确保在第一页
if totalPages > 0 || (data.HighlightAnalysis.Summary != "" || data.OverallSummary != "") {
pdf.SetPage(1)
// 概述 - 使用逐行写入一行最多35个字
pdf.SetXY(200, 104)
summaryLines := splitTextByRune(cleanTextForPDF(data.HighlightAnalysis.Summary), 35.0)
for i, line := range summaryLines {
pdf.SetXY(200, 104+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
// 标题亮点 - 一行最多9个字
pdf.SetXY(200, 184)
themeLines := splitTextByRune(cleanTextForPDF(data.HighlightAnalysis.Points.Theme), 9.0)
for i, line := range themeLines {
pdf.SetXY(200, 184+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
// 题材亮点 - 一行最多9个字
pdf.SetXY(330, 184)
narrativeLines := splitTextByRune(cleanTextForPDF(data.HighlightAnalysis.Points.Narrative), 9.0)
for i, line := range narrativeLines {
pdf.SetXY(330, 184+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
// 内容亮点 - 一行最多9个字
pdf.SetXY(460, 184)
contentLines := splitTextByRune(cleanTextForPDF(data.HighlightAnalysis.Points.Content), 9.0)
for i, line := range contentLines {
pdf.SetXY(460, 184+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
// 文案亮点 - 一行最多9个字
pdf.SetXY(200, 323)
copywritingLines := splitTextByRune(cleanTextForPDF(data.HighlightAnalysis.Points.Copywriting), 9.0)
for i, line := range copywritingLines {
pdf.SetXY(200, 323+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
// 数据亮点 - 一行最多9个字
pdf.SetXY(330, 323)
dataLines := splitTextByRune(cleanTextForPDF(data.HighlightAnalysis.Points.Data), 9.0)
for i, line := range dataLines {
pdf.SetXY(330, 323+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
// 配乐亮点(仅视频) - 一行最多9个字
if data.HighlightAnalysis.Points.Music != "" {
pdf.SetXY(460, 323)
musicLines := splitTextByRune(cleanTextForPDF(data.HighlightAnalysis.Points.Music), 9.0)
for i, line := range musicLines {
pdf.SetXY(460, 323+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
}
// 浏览量 - 一行最多35个字
pdf.SetXY(200, 474)
viewsLines := splitTextByRune(cleanTextForPDF(data.DataPerformance.Views), 35.0)
for i, line := range viewsLines {
pdf.SetXY(200, 474+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
// 完播率 - 一行最多35个字
pdf.SetXY(200, 539)
if data.DataPerformance.Completion != "" {
completionLines := splitTextByRune(cleanTextForPDF(data.DataPerformance.Completion), 35.0)
for i, line := range completionLines {
pdf.SetXY(200, 539+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
}
// 点赞/分享/评论 - 一行最多35个字
pdf.SetXY(200, 600)
engagementLines := splitTextByRune(cleanTextForPDF(data.DataPerformance.Engagement), 35.0)
for i, line := range engagementLines {
pdf.SetXY(200, 600+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
// 整体总结及可优化建议 - 一行最多35个字
pdf.SetXY(200, 676)
overallSummaryLines := splitTextByRune(cleanTextForPDF(data.OverallSummary), 35.0)
for i, line := range overallSummaryLines {
pdf.SetXY(200, 676+float64(i)*lineHeight)
pdf.Cell(nil, line)
}
}
// 如果有图片URL添加新页面并居中显示图片
if data.ImageURL != "" {
// 添加新页面
pdf.AddPage()
// 下载图片
resp, err := http.Get(data.ImageURL)
if err != nil {
return fmt.Errorf("下载图片失败: %v", err)
}
defer resp.Body.Close()
imageData, err := io.ReadAll(resp.Body)
if err != nil {
return fmt.Errorf("读取图片数据失败: %v", err)
}
// 解析URL获取文件扩展名
u, err := url.Parse(data.ImageURL)
if err != nil {
return fmt.Errorf("图片链接解析错误: %v", err)
}
fileExt := filepath.Ext(u.Path)
if fileExt == "" {
fileExt = ".jpg"
}
// 保存到临时文件
tmpFile, err := os.CreateTemp("", "pdf_image_*"+fileExt)
if err != nil {
return fmt.Errorf("创建临时文件失败: %v", err)
}
defer os.Remove(tmpFile.Name())
defer tmpFile.Close()
_, err = tmpFile.Write(imageData)
if err != nil {
return fmt.Errorf("写入临时文件失败: %v", err)
}
tmpFile.Close()
// 使用 image 包获取图片原始尺寸
imgFile, err := os.Open(tmpFile.Name())
if err != nil {
return fmt.Errorf("打开图片文件失败: %v", err)
}
defer imgFile.Close()
config, format, err := image.DecodeConfig(imgFile)
if err != nil {
return fmt.Errorf("获取图片尺寸失败: %v", err)
}
_ = format // 忽略格式
// A4页面宽度595pt210mm高度842pt297mm
pageWidth := 595.0
pageHeight := 842.0
margin := 20.0
// 计算可用宽度
availableWidth := pageWidth - 2*margin
// 计算缩放后的图片尺寸保持宽高比宽度为可用宽度的80%
imageWidth := availableWidth * 0.8
originalWidth := float64(config.Width)
originalHeight := float64(config.Height)
imageHeight := (imageWidth / originalWidth) * originalHeight
// 计算居中位置
imageX := (pageWidth - imageWidth) / 2
imageY := (pageHeight - imageHeight) / 2
// 使用 ImageHolderByBytes 添加图片
imgH1, err := gopdf.ImageHolderByBytes(imageData)
if err != nil {
return fmt.Errorf("创建图片Holder失败: %v", err)
}
// 绘制图片
err = pdf.ImageByHolder(imgH1, imageX, imageY, &gopdf.Rect{W: imageWidth, H: imageHeight})
if err != nil {
return fmt.Errorf("绘制图片失败: %v", err)
}
}
// 生成新的 PDF
if err := pdf.WritePdf(outputPath); err != nil {
return fmt.Errorf("error writing final PDF: %v", err)
}
return nil
}
// getCharWidth 获取字符的宽度权重
// 英文字母、数字、英文符号返回 0.5,其他字符返回 1.0
func getCharWidth(r rune) float64 {
// 英文字母 (A-Z, a-z)
if (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') {
return 0.5
}
// 数字 (0-9)
if r >= '0' && r <= '9' {
return 0.5
}
// 英文符号
if (r >= 0x21 && r <= 0x2F) || // ! " # $ % & ' ( ) * + , - . /
(r >= 0x3A && r <= 0x40) || // : ; < = > ? @
(r >= 0x5B && r <= 0x60) || // [ \ ] ^ _ `
(r >= 0x7B && r <= 0x7E) { // { | } ~
return 0.5
}
return 1.0
}
// splitTextByRune 将文本按指定字符宽度拆分成多行
// 按每行最大宽度拆分,英文字母/数字/英文符号按0.5计算其他按1计算
func splitTextByRune(text string, maxWidth float64) []string {
if text == "" {
return []string{}
}
runes := []rune(text)
var lines []string
currentLine := ""
currentWidth := 0.0
for _, r := range runes {
charWidth := getCharWidth(r)
// 检查加上这个字符是否会超过最大宽度
if currentWidth+charWidth > maxWidth {
// 超过最大宽度,保存当前行并开始新行
if currentLine != "" {
lines = append(lines, currentLine)
}
currentLine = string(r)
currentWidth = charWidth
} else {
currentLine += string(r)
currentWidth += charWidth
}
}
// 添加最后一行
if currentLine != "" {
lines = append(lines, currentLine)
}
return lines
}
// TruncateTextByRune 按字符权重截断文本
// 中文字符算1.0,英文字母/数字/英文符号算0.5
// 返回截断后的文本确保总权重不超过maxWidth
func TruncateTextByRune(text string, maxWidth float64) string {
if text == "" {
return ""
}
runes := []rune(text)
var result []rune
currentWidth := 0.0
for _, r := range runes {
charWidth := getCharWidth(r)
if currentWidth+charWidth > maxWidth {
break
}
result = append(result, r)
currentWidth += charWidth
}
return string(result)
}
// ConvertCompetitorReportToText 将竞品报告数据转换为文本格式
// 参数:
// - data: 竞品报告数据
// - isVideo: 是否为视频(视频需要包含完播率和配乐亮点)
//
// 返回: 转换后的文本内容
func ConvertCompetitorReportToText(data CompetitorReportData, isVideo bool) string {
var sb strings.Builder
// 一、亮点表现分析
sb.WriteString("一、亮点表现分析\n")
sb.WriteString(data.HighlightAnalysis.Summary)
sb.WriteString("\n\n")
sb.WriteString("1. 标题亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Theme)
sb.WriteString("\n")
sb.WriteString("2. 题材亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Narrative)
sb.WriteString("\n")
sb.WriteString("3. 内容亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Content)
sb.WriteString("\n")
sb.WriteString("4. 文案亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Copywriting)
sb.WriteString("\n")
sb.WriteString("5. 数据亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Data)
sb.WriteString("\n")
if isVideo && data.HighlightAnalysis.Points.Music != "" {
sb.WriteString("6. 配乐亮点:")
sb.WriteString(data.HighlightAnalysis.Points.Music)
sb.WriteString("\n")
}
// 二、数据表现分析
sb.WriteString("\n二、数据表现分析\n")
sb.WriteString("1. 浏览量表现:")
sb.WriteString(data.DataPerformance.Views)
sb.WriteString("\n")
if isVideo && data.DataPerformance.Completion != "" {
sb.WriteString("2. 完播率表现:")
sb.WriteString(data.DataPerformance.Completion)
sb.WriteString("\n")
sb.WriteString("3. 点赞/分享/评论表现:")
} else {
sb.WriteString("2. 点赞/分享/评论表现:")
}
sb.WriteString(data.DataPerformance.Engagement)
sb.WriteString("\n")
// 三、整体总结及可优化建议
sb.WriteString("\n三、整体总结及可优化建议\n")
sb.WriteString(data.OverallSummary)
return sb.String()
}
//生成问卷调查pdf
func QuestionnaireSurveyPDF(templatePath, outputPath string, data *model.QuestionnairePDFData) error {
pdf := gopdf.GoPdf{}
pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4})
if err := pdf.ImportPagesFromSource(templatePath, "/MediaBox"); err != nil {
return fmt.Errorf("导入模板失败: %w", err)
}
if err := pdf.AddTTFFont("simfang", "./data/simfang.ttf"); err != nil {
return fmt.Errorf("加载字体失败: %w", err)
}
if err := pdf.SetFont("simfang", "", 12); err != nil {
return fmt.Errorf("设置字体失败: %w", err)
}
startTime, err := parseFlexibleDate(data.BundleStartDate)
if err != nil {
return fmt.Errorf("BundleStartDate格式错误: %w", err)
}
endTime, err := parseFlexibleDate(data.BundleEndDate)
if err != nil {
return fmt.Errorf("BundleEndDate格式错误: %w", err)
}
submissionDate, err := parseFlexibleDate(data.SubmissionDate)
if err != nil {
return fmt.Errorf("SubmissionDate格式错误: %w", err)
}
nowTime := time.Now().Format(time.DateTime)
onePage := 1
twoPage := 2
threePage := 3
fourPage := 4
// 第1页客户基本信息
pdf.SetPage(onePage)
//姓名
pdf.SetX(165)
pdf.SetY(420)
pdf.Cell(nil, data.CustomerName)
//套餐名称
pdf.SetX(205)
pdf.SetY(443)
pdf.Cell(nil, data.BundleName)
//开始日期
pdf.SetX(205)
pdf.SetY(467)
pdf.Cell(nil, startTime.Format("2006"))
pdf.SetX(260)
pdf.SetY(467)
pdf.Cell(nil, startTime.Format("01"))
pdf.SetX(300)
pdf.SetY(467)
pdf.Cell(nil, startTime.Format("02"))
//结束日期
pdf.SetX(350)
pdf.SetY(467)
pdf.Cell(nil, endTime.Format("2006"))
pdf.SetX(398)
pdf.SetY(467)
pdf.Cell(nil, endTime.Format("01"))
pdf.SetX(437)
pdf.SetY(467)
pdf.Cell(nil, endTime.Format("02"))
//视频数
pdf.SetX(220)
pdf.SetY(583)
pdf.Cell(nil, data.VideoNum)
//"账号数: "+
pdf.SetX(230)
pdf.SetY(625)
pdf.Cell(nil, data.AccountNum)
// "图文数: "+
pdf.SetX(253)
pdf.SetY(667)
pdf.Cell(nil, data.ImagesNum)
//"数据分析数: "+
pdf.SetX(280)
pdf.SetY(727)
pdf.Cell(nil, data.DataAnalysisNum)
// 第1页内容写完后
if err = addWatermark(&pdf, "确认地址:"+data.Address+"\n确认时间"+nowTime); err != nil {
return err
}
// 第2页服务数量
pdf.SetPage(twoPage)
//"竞品分析数: "+
pdf.SetX(205)
pdf.SetY(72)
pdf.Cell(nil, data.CompetitiveNum)
//"增值视频数: "+
pdf.SetX(270)
pdf.SetY(156)
pdf.Cell(nil, data.ValueAddVideoNum)
//"评分1: "+
pdf.SetX(123)
pdf.SetY(485)
pdf.Cell(nil, scoreStars(data.Score1))
//"评分2: "+
pdf.SetX(343)
pdf.SetY(526)
pdf.Cell(nil, scoreStars(data.Score2))
//"评分3: "+
pdf.SetX(230)
pdf.SetY(568)
pdf.Cell(nil, scoreStars(data.Score3))
//"评分4: "+
pdf.SetX(362)
pdf.SetY(610)
pdf.Cell(nil, scoreStars(data.Score4))
//"评分5: "+
pdf.SetX(220)
pdf.SetY(652)
pdf.Cell(nil, scoreStars(data.Score5))
//"评分6: "+
pdf.SetX(164)
pdf.SetY(694)
pdf.Cell(nil, scoreStars(data.Score6))
//"评分7: "+
pdf.SetX(197)
pdf.SetY(735)
pdf.Cell(nil, scoreStars(data.Score7))
//水印
if err = addWatermark(&pdf, "确认地址:"+data.Address+"\n确认时间"+nowTime); err != nil {
return err
}
// 第3页评分与意见
pdf.SetPage(threePage)
// Opinion 超过100字符时自动换行每行约20个中文字符行高18pt
drawWrappedText(&pdf, data.Opinion1, 90, 145, 24, 34)
drawWrappedText(&pdf, data.Opinion2, 90, 377, 24, 34)
drawWrappedText(&pdf, data.Opinion3, 90, 574, 24, 34)
//水印
if err = addWatermark(&pdf, "确认地址:"+data.Address+"\n确认时间"+nowTime); err != nil {
return err
}
// 第4页提交信息
pdf.SetPage(fourPage)
//"提交人: "+
pdf.SetX(135)
pdf.SetY(103)
pdf.Cell(nil, data.Submitter)
//提交时间: "
pdf.SetX(148)
pdf.SetY(128)
pdf.Cell(nil, submissionDate.Format("2006"))
pdf.SetX(207)
pdf.SetY(128)
pdf.Cell(nil, submissionDate.Format("01"))
pdf.SetX(260)
pdf.SetY(128)
pdf.Cell(nil, submissionDate.Format("02"))
//水印
if err = addWatermark(&pdf, "确认地址:"+data.Address+"\n确认时间"+nowTime); err != nil {
return err
}
if err := pdf.WritePdf(outputPath); err != nil {
return fmt.Errorf("写入PDF失败: %w", err)
}
return nil
}
// addWatermark 在当前页叠加浅色斜向双行水印,并在结束后恢复样式
func addWatermark(pdf *gopdf.GoPdf, text string) error {
const normalFontSize = 12
const watermarkFontSize = 22
const lineHeight = 32.0 // 水印行间距
// 设置水印样式
pdf.SetGrayFill(0.85)
if err := pdf.SetFont("simfang", "", watermarkFontSize); err != nil {
return fmt.Errorf("设置水印字体失败: %w", err)
}
// 按换行拆分逐行绘制Cell 不负责自动换行)
lines := strings.Split(text, "\n")
if len(lines) == 0 {
lines = []string{text}
}
drawBlock := func(x, y, cx, cy float64) {
pdf.Rotate(35, cx, cy)
for i, line := range lines {
pdf.SetX(x)
pdf.SetY(y + float64(i)*lineHeight)
pdf.Cell(nil, line)
}
pdf.RotateReset()
}
// 两处重复水印
drawBlock(90, 420, 300, 420)
drawBlock(130, 620, 300, 420)
// 恢复样式,避免影响后续正文
pdf.SetGrayFill(0)
if err := pdf.SetFont("simfang", "", normalFontSize); err != nil {
return fmt.Errorf("恢复字体失败: %w", err)
}
return nil
}
// drawWrappedText 在 PDF 上绘制自动换行的文字
// pdf: GoPdf 实例, text: 文字内容, startX/startY: 起始坐标
// maxWidth: 最大宽度pt, lineHeight: 行高pt, charsPerLine: 每行最多字符数(按中文字符计)
func drawWrappedText(pdf *gopdf.GoPdf, text string, startX, startY, lineHeight float64, charsPerLine int) {
runes := []rune(text)
total := len(runes)
if total == 0 {
return
}
lineStart := 0
currentLine := 0
for lineStart < total {
end := lineStart + charsPerLine
if end > total {
end = total
}
// 计算实际宽度以决定换行点按字节估算ASCII=0.5中文字符宽)
charCount := 0
splitAt := lineStart
for i := lineStart; i < total; i++ {
r := runes[i]
runeBytes := utf8.RuneLen(r)
if runeBytes > 1 {
charCount += 2 // 中文等宽字符算2个单位
} else {
charCount += 1 // ASCII 算1个单位
}
if charCount > charsPerLine*2 {
break
}
splitAt = i + 1
}
if splitAt == lineStart {
splitAt = lineStart + 1
}
line := string(runes[lineStart:splitAt])
pdf.SetX(startX)
pdf.SetY(startY + float64(currentLine)*lineHeight)
pdf.Cell(nil, line)
lineStart = splitAt
currentLine++
}
}
func scoreStars(score int) string {
switch {
case score <= 1:
return "★☆☆☆☆"
case score == 2:
return "★★☆☆☆"
case score == 3:
return "★★★☆☆"
case score == 4:
return "★★★★☆"
default:
return "★★★★★"
}
}
func parseFlexibleDate(value string) (time.Time, error) {
v := strings.TrimSpace(value)
if v == "" {
return time.Time{}, fmt.Errorf("日期为空")
}
layouts := []string{
"2006-01-02",
time.RFC3339,
"2006-01-02 15:04:05",
"2006-01-02 15:04",
}
var lastErr error
for _, layout := range layouts {
t, err := time.Parse(layout, v)
if err == nil {
return t, nil
}
lastErr = err
}
return time.Time{}, fmt.Errorf("不支持的日期格式: %s, %w", v, lastErr)
}

View File

@ -0,0 +1,304 @@
package utils
import (
"fmt"
"os"
"path/filepath"
"testing"
)
// getProjectRoot 获取项目根目录
func getProjectRoot() string {
// 假设测试从项目根目录运行
dir, _ := os.Getwd()
// 向上查找 go.mod 确定项目根目录
for {
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
return dir
}
parent := filepath.Dir(dir)
if parent == dir {
break
}
dir = parent
}
return ""
}
// TestGenerateCompetitorReportPDF 测试生成竞品报告PDF
func TestGenerateCompetitorReportPDF1(t *testing.T) {
// 获取项目根目录
root := getProjectRoot()
fmt.Printf("项目根目录: %s\n", root)
// 准备测试数据
data := CompetitorReportData{
HighlightAnalysis: HighlightAnalysisData{
Summary: "本视频通过展示产品使用的真实场景,突出用户产品优势和痛点,内容详实且具有吸引力。",
Points: PointsData{
Theme: "标题简洁有力,突出核心卖点'省时省力',引发用户好奇心",
Narrative: "采用情景剧形式展示产品使用场景,剧情贴近生活,易引发共鸣",
Content: "通过前后对比展示产品效果,直观呈现产品价值",
Copywriting: "文案简洁明了,突出用户痛点解决方案,语气亲切自然",
Data: "点赞量10万+评论5000+分享2万+,数据表现优异",
Music: "背景音乐节奏轻快,与视频内容匹配度高,增强观看体验",
},
},
DataPerformance: DataPerformanceData{
Views: "播放量突破500万推荐流量占比60%,自然流量表现优秀",
Completion: "完播率45%高于同类视频平均值30%前3秒吸引力强",
Engagement: "点赞率2%评论率0.1%分享率0.4%,互动数据表现优秀",
},
OverallSummary: "整体来看该竞品视频在内容策划、表现形式和互动数据方面都表现优秀。优势在于1内容真实可信通过实际使用场景展示产品效果2剧情设计合理前3秒抓住用户注意力3文案简洁有力直击用户痛点。建议优化方向1可以增加更多用户评价内容增强可信度2适当增加福利引导提高转化率3结尾可以增加引导关注话术提升粉丝沉淀。",
}
// 模板路径
templatePath := filepath.Join(root, "data", "竞品报告pdf模板.pdf")
// 输出路径
outputPath := filepath.Join(root, "data", "output", "竞品报告测试_multicell.pdf")
// 确保输出目录存在
outputDir := filepath.Dir(outputPath)
if err := os.MkdirAll(outputDir, 0755); err != nil {
t.Errorf("创建输出目录失败: %v", err)
return
}
// 调用函数生成PDF
err := GenerateCompetitorReportPDF(templatePath, outputPath, data)
if err != nil {
t.Errorf("生成竞品报告PDF失败: %v", err)
return
}
fmt.Printf("PDF生成成功: %s\n", outputPath)
}
// TestGenerateCompetitorReportPDFImageOnly 测试仅图片的竞品报告PDF无配乐和完播率
func TestGenerateCompetitorReportPDFImageOnly(t *testing.T) {
// 获取项目根目录
root := getProjectRoot()
// 准备测试数据(仅图片,没有视频的配乐和完播率)
data := CompetitorReportData{
HighlightAnalysis: HighlightAnalysisData{
Summary: "该图文内容通过精美的视觉设计和精准的标签定位,成功吸引目标用户关注。",
Points: PointsData{
Theme: "标题设置悬念,引发用户点击欲望",
Narrative: "采用九宫格形式展示产品特点,视觉冲击力强",
Content: "内容排版清晰,重点突出,便于用户快速获取信息",
Copywriting: "文案简洁,配合表情符号增加趣味性",
Data: "收藏量5万+评论1000+分享8000+",
Music: "", // 图片无配乐
},
},
DataPerformance: DataPerformanceData{
Views: "曝光量100万+点击率3%,表现良好",
Completion: "", // 图文无完播率
Engagement: "收藏率5%评论率0.1%分享率0.8%",
},
OverallSummary: "该图文内容整体表现优秀特别是在视觉设计和内容排版方面。亮点1九宫格形式统一视觉效果好2标签设置精准触达目标用户3发布时间合理获得更多曝光。优化建议1可以增加更多用户案例展示2适当加入互动话题提高评论量。",
}
// 模板路径
templatePath := filepath.Join(root, "data", "竞品报告pdf模板.pdf")
// 输出路径
outputPath := filepath.Join(root, "data", "output", "竞品报告测试_图文11.pdf")
// 确保输出目录存在
outputDir := filepath.Dir(outputPath)
if err := os.MkdirAll(outputDir, 0755); err != nil {
t.Errorf("创建输出目录失败: %v", err)
return
}
// 调用函数生成PDF
err := GenerateCompetitorReportPDF(templatePath, outputPath, data)
if err != nil {
t.Errorf("生成竞品报告PDF失败: %v", err)
return
}
fmt.Printf("PDF生成成功: %s\n", outputPath)
}
// TestGenerateCompetitorReportPDFWithImage 测试带图片的竞品报告PDF
// 注意:此测试需要网络连接来下载图片,如果网络不可用会被跳过
func TestGenerateCompetitorReportPDFWithImage1(t *testing.T) {
// 获取项目根目录
root := getProjectRoot()
// 准备测试数据(带图片)
// 使用一个已知可用的测试图片URL
data := CompetitorReportData{
HighlightAnalysis: HighlightAnalysisData{
Summary: "本视频通过展示产品使用的真实场景,突出用户产品优势和痛点,内容详实且具有吸引力。",
Points: PointsData{
Theme: "标题简洁有力,突出核心卖点'省时省力',引发用户好奇心",
Narrative: "采用情景剧形式展示产品使用场景,剧情贴近生活,易引发共鸣",
Content: "通过前后对比展示产品效果,直观呈现产品价值",
Copywriting: "文案简洁明了,突出用户痛点解决方案,语气亲切自然",
Data: "点赞量10万+评论5000+分享2万+,数据表现优异",
Music: "背景音乐节奏轻快,与视频内容匹配度高,增强观看体验",
},
},
DataPerformance: DataPerformanceData{
Views: "播放量突破500万推荐流量占比60%,自然流量表现优秀",
Completion: "完播率45%高于同类视频平均值30%前3秒吸引力强",
Engagement: "点赞率2%评论率0.1%分享率0.4%,互动数据表现优秀",
},
OverallSummary: "整体来看,该竞品视频在内容策划、表现形式和互动数据方面都表现优秀。",
ImageURL: "https://cdn-test.szjixun.cn/fonchain-main/test/image/12345/artwork/0.png", // 测试用图片URL
}
// 模板路径
templatePath := filepath.Join(root, "data", "竞品报告pdf模板.pdf")
// 输出路径
outputPath := filepath.Join(root, "data", "output", "竞品报告测试_带图片.pdf")
// 确保输出目录存在
outputDir := filepath.Dir(outputPath)
if err := os.MkdirAll(outputDir, 0755); err != nil {
t.Errorf("创建输出目录失败: %v", err)
return
}
// 调用函数生成PDF
err := GenerateCompetitorReportPDF(templatePath, outputPath, data)
if err != nil {
t.Logf("图片下载测试跳过(网络问题): %v", err)
t.Skip("网络不可用,跳过图片测试")
return
}
fmt.Printf("PDF生成成功: %s\n", outputPath)
}
// TestGenerateCompetitorReportPDFMixedContent 测试中英混合、数字、符号的复杂情况
func TestGenerateCompetitorReportPDFMixedContent(t *testing.T) {
root := getProjectRoot()
// 准备包含中英混合、数字、符号的复杂测试数据
data := CompetitorReportData{
HighlightAnalysis: HighlightAnalysisData{
Summary: "这是一个关于2024年短视频创作的爆款分析报告视频总播放量达到1.2亿次点赞率8.5%远超行业平均3.2%。内容包括①生活技巧类占比40% ②知识科普类30% ③娱乐搞笑类30%。推荐算法推荐流量占比85%搜索流量10%其他渠道5%。",
Points: PointsData{
Theme: "标题【逆袭】3个月从0到100万粉丝我是如何做到的必看🔥",
Narrative: "采用问题-解决叙事结构前3秒抛出痛点你还在为XX发愁吗然后展示解决方案ABC",
Content: "内容分为3个板块①前置干货预告15秒 ②核心内容展示30秒 ③互动引导15秒",
Copywriting: "文案使用了大量emoji表情🔥💯👍增加年轻化气息结尾一句评论区见强化互动",
Data: "点赞率8.5%高于同类平均3.2%转发率2.1%评论数2.3万条评论区活跃度TOP10%",
Music: "使用热门BGM孤勇者前奏3秒配合画面节奏卡点音量为Original-3dB",
},
},
DataPerformance: DataPerformanceData{
Views: "发布24小时内播放量突破500万48小时达到1200万72小时稳定在1500万。推荐流量占比85%搜索流量占比10%其他渠道5%。数据表现PV=15000000UV=8500000。",
Completion: "平均完播率45.2%高于行业均值28%3秒留存率72%5秒完播率58%10秒完播率35%属于高质量流量。平均观看时长18.5秒视频总时长42秒。",
Engagement: "点赞数128000点赞率0.85%评论数23000其中神评论占比15%高赞评论TOP3①学到了 ②太棒了 ③收藏了分享数56000。评论区@相关账号12个引发二次传播。",
},
OverallSummary: "该视频成功因素:①标题使用数字热门词激发点击逆袭必看 ②内容结构清晰每15秒一个高潮点 ③BGM选择契合内容情绪孤勇者 ④评论区运营到位。建议优化1可增加合集功能将同类内容串联 2提升粉丝粘性到10%以上 3适当增加直播预告。整体来看这是一条典型的爆款体质视频值得借鉴学习数据支撑ROI=3.5CPM=25元CPC=0.8元。",
ImageURL: "",
}
// 模板路径
templatePath := filepath.Join(root, "data", "竞品报告pdf模板.pdf")
// 输出路径
outputPath := filepath.Join(root, "data", "output", "竞品报告测试_中英混合.pdf")
// 确保输出目录存在
outputDir := filepath.Dir(outputPath)
if err := os.MkdirAll(outputDir, 0755); err != nil {
t.Errorf("创建输出目录失败: %v", err)
return
}
// 调用函数生成PDF
err := GenerateCompetitorReportPDF(templatePath, outputPath, data)
if err != nil {
t.Errorf("生成PDF失败: %v", err)
return
}
fmt.Printf("PDF生成成功中英混合测试: %s\n", outputPath)
}
// TestTruncateTextByRune 测试按字符权重截断文本
func TestTruncateTextByRune(t *testing.T) {
tests := []struct {
name string
text string
maxWidth float64
want string
}{
{
name: "空文本",
text: "",
maxWidth: 10,
want: "",
},
{
name: "纯中文截断",
text: "这是一段很长的中文内容需要被截断",
maxWidth: 10,
want: "这是一段很长的中文内", // 10个中文字=10正好
},
{
name: "纯英文截断按0.5计算)",
text: "abcdefghijklmnop",
maxWidth: 5,
want: "abcdefghij", // 10个字母=5.0,正好
},
{
name: "数字截断按0.5计算)",
text: "1234567890",
maxWidth: 3,
want: "123456", // 6个数字=3.0,正好
},
{
name: "中英混合截断",
text: "hello你好world世界",
maxWidth: 6,
// h(0.5)+e(0.5)+l(0.5)+l(0.5)+o(0.5)=2.5
// +你(1)+好(1)=4.5
// +w(0.5)+o(0.5)+r(0.5)+l(0.5)=2再加就超过6了
// 所以应该是 hello你好wor
want: "hello你好wor",
},
{
name: "符号截断按0.5计算)",
text: "hello,world!",
maxWidth: 5,
// h(0.5)+e(0.5)+l(0.5)+l(0.5)+o(0.5)+,(0.5)=3
// +w(0.5)+o(0.5)+r(0.5)+l(0.5)+d(0.5)+!(0.5)=6超过5
// 所以保留 hello,worl
want: "hello,worl",
},
{
name: "截断到正好边界",
text: "中文字符",
maxWidth: 4,
want: "中文字符", // 4个中文字=4.0,正好
},
{
name: "宽度为0",
text: "hello",
maxWidth: 0,
want: "",
},
{
name: "宽度小于单个字符",
text: "hello",
maxWidth: 0.3,
want: "",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := TruncateTextByRune(tt.text, tt.maxWidth)
if got != tt.want {
t.Errorf("TruncateTextByRune(%q, %v) = %q, want %q", tt.text, tt.maxWidth, got, tt.want)
}
})
}
}