Эх сурвалжийг харах

revert: 移除卡包插入功能,仅保留航信邮件发送

- 删除 WechatPayFapiaoService
- 移除 HuapiaoerInvoiceService.insertToCardPackage
- 移除 InvoiceStatusJob 补插卡包逻辑和 InvoiceDetailService 依赖
- 恢复 WxPayServiceImpl.wxHttpClient 为非公开
- 卡包插入需要微信官方授权流程,自建表单无法满足,邮件已由航信自动处理

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline 2 өдөр өмнө
parent
commit
60220847d8

+ 41 - 0
.claude/settings.local.json

@@ -0,0 +1,41 @@
+{
+  "permissions": {
+    "allow": [
+      "Bash(git checkout *)",
+      "Bash(git add *)",
+      "Bash(git commit -m ' *)",
+      "Bash(claude *)",
+      "WebFetch(domain:fa-piao.com)",
+      "Bash(pnpm install *)",
+      "Bash(pnpm approve-builds *)",
+      "Bash(pnpm --filter @invoice/shared build)",
+      "Bash(pnpm prisma *)",
+      "Bash(pnpm --filter @invoice/database build)",
+      "Bash(pnpm --filter @invoice/sms-gateway build)",
+      "Bash(pnpm --filter @invoice/automation-engine build)",
+      "Bash(pnpm --filter @invoice/api-server build)",
+      "WebSearch",
+      "Bash(npx playwright *)",
+      "Bash(node -e \"require\\('playwright-extra'\\); console.log\\('OK'\\)\")",
+      "Bash(pnpm *)",
+      "Bash(mkdir -p \"D:/快与慢充电桩/code/charge-java/huapiaoer-sdk/src/main/java/com/kym/huapiaoer/enums\")",
+      "Bash(mkdir -p \"D:/快与慢充电桩/code/charge-java/huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/request\")",
+      "Bash(mkdir -p \"D:/快与慢充电桩/code/charge-java/huapiaoer-sdk/src/main/java/com/kym/huapiaoer/model/response\")",
+      "Bash(rmdir \"D:/快与慢充电桩/code/charge-java/huapiaoer-sdk/src/main/java/com/kym\")",
+      "Bash(mvn compile *)",
+      "Bash(mvn install *)",
+      "Bash(git -C \"D:\\\\快与慢充电桩\\\\code\\\\charge-front\" log --oneline -5)",
+      "Bash(git *)",
+      "Bash(mkdir -p \"D:\\\\快与慢充电桩\\\\code\\\\charge-java\\\\charge-front\")",
+      "Bash(cp -r \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/src\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-java\\\\charge-front/\")",
+      "Bash(cp -r \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/types\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-java\\\\charge-front/\")",
+      "Bash(cp \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/index.html\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/package.json\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/package-lock.json\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/tsconfig.json\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/vite.config.ts\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/README.md\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-front/.gitignore\" \"D:\\\\快与慢充电桩\\\\code\\\\charge-java\\\\charge-front/\")",
+      "Bash(node *)",
+      "Bash(mvn test *)",
+      "Bash(grep -v \"^\\\\\\\\[INFO\\\\\\\\] Download\")",
+      "Bash(grep -v \"^\\\\\\\\[INFO\\\\\\\\] Progress\")",
+      "WebFetch(domain:pay.wechatpay.cn)",
+      "WebFetch(domain:pay.weixin.qq.com)"
+    ]
+  }
+}

+ 1 - 0
.qoderignore

@@ -0,0 +1 @@
+# 指定在索引时要忽略的文件或文件夹。与.gitignore匹配规则一致,支持 my-security/ 和 *.log 等通配符模式。

+ 0 - 463
admin-web/CHANGELOG.md

@@ -1,463 +0,0 @@
-# <a href="https://gitee.com/lyt-top/vue-next-admin" target="_blank">vue-next-admin 更新日志</a>
-
-🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
-
-## 2.4.31
-
-`2023.03.10`
-
-- 🌟 更新 依赖更新最新版本
-- 🐞 修复 顶栏背景渐变设置不生效
-- 🐞 修复 顶栏背景渐变、菜单背景渐变时,深色主题不生效
-- 🐞 修复 顶栏搜索框移动端显示问题
-- 🎯 优化 `main.ts`,相关 issues [#I6KNFH](https://gitee.com/lyt-top/vue-next-admin/issues/I6KNFH)、[#I6JRH6](https://gitee.com/lyt-top/vue-next-admin/issues/I6JRH6)
-- 🎯 优化 菜单横向模式显示(horizontal)
-- 🎯 优化 分栏布局,[希望分栏布局做一下优化,在没有二级菜单的时候,直接全屏展示一级菜单链接](https://gitee.com/lyt-top/vue-next-admin/issues/I6HW7H),感谢[@jiuping](https://gitee.com/jiuping),`tagsview` 点击时处理 `收起/展开` 菜单
-
-## 2.4.3
-
-`2023.02.22`
-
-🚩🚩🚩 感谢 [驰骋工作流引擎-表单引擎-低代码开发平台](http://www.ccflow.org/) 赞助商的赞助。驰骋公司为社会提供流程引擎+表单引擎+低代码开发平台一体的开源软件解决方案,欢迎广大开发者前去体验!
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 赞助商组件(`/src/layout/sponsors`),[项目目录结构查看](https://lyt-top.gitee.io/vue-next-admin-doc-preview/config/)
-- 🐞 修复 [过滤筛选组件展开点击不了](https://gitee.com/lyt-top/vue-next-admin/issues/I688WG)
-- 🐞 修复 [设置锁屏时间时直接白屏了不能恢复,除非删除主题配置才会重新加载](https://gitee.com/lyt-top/vue-next-admin/issues/I6AF8P),感谢[@baizunxian](https://gitee.com/xb_xiaobai)
-- 🐞 修复 `分栏布局` 地址栏输入不存在的路由报错问题
-- 🎨 合并 [!44 tagsViewName 正则匹配错误,匹配到含 en 单词](https://gitee.com/lyt-top/vue-next-admin/pulls/44/files),感谢[@tony 星](https://gitee.com/tony_tong_xin)
-- 🎨 合并 [!45 fix 地址栏出现 false 问题](https://gitee.com/lyt-top/vue-next-admin/pulls/45),感谢[@随心](https://gitee.com/jiangqiang1996)
-- 🎯 优化 `/src/utils/storage` 下 `key` 编写成 `${__NEXT_NAME__}:${key}`,防止部署多套系统到同一域名不同目录时,变量共用的问题(`__NEXT_NAME__`为 `package.json` 中的 `name`)
-- 🎯 优化 watermark 单词拼写错误
-
-## 2.4.21
-
-`2022.12.12`
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 菜单背景高亮颜色可自定义,通过 `布局配置 -> 菜单设置 -> 菜单高亮背景色` 进行设置
-- 🐞 修复 `分栏布局` 二级导航菜单内容多时,无法滚动问题,感谢群友@静雨轩主人
-- 🐞 修复 [!42 修复 工作流无法添加新节点问题](https://gitee.com/lyt-top/vue-next-admin/pulls/42),感谢[@beta](https://gitee.com/beta_dz)
-- 🎯 优化 `/make/tableDemo` 表头很多时,无法滚动问题,感谢群友@糊涂涂涂
-
-## 2.4.2
-
-`2022.12.09`
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 国际化自动导入文件功能,只需在 `/src/i18n/pages` 下新建文件夹定义即可
-- 🎉 新增 `/make/tableDemo` 中 [搜索框展开,收缩功能,高级筛选组件 有计划做吗](https://gitee.com/lyt-top/vue-next-admin/issues/I6511L)
-- 🐞 修复 [!40 开启 TagsView 缓存后,刷新后所有的路由都变成组件缓存了](https://gitee.com/lyt-top/vue-next-admin/pulls/40),感谢[@mrjimin](https://gitee.com/mrjimin)
-- 🐞 修复 [!41 修复 get 请求传递嵌套对象或数组时无法正常编码问题](https://gitee.com/lyt-top/vue-next-admin/pulls/41),感谢[@随心](https://gitee.com/jiangqiang1996)
-- 🐞 修复 组件 wangEditor 回显值的问题
-- 🐞 修复 `/fun/echartsMap`(地理坐标/地图)、`visualizingDemo2`(数据可视化演示 2) 演示报错问题
-- 🎯 优化 版本升级提示
-- 🎯 优化 无权限登录时增加提示信息,[BUG:因前端加载路由(initFrontEndControlRoutes)中当前用户角色为一个陌生角色, 导致 router.beforeEach 会死循环 浏览器崩溃](https://gitee.com/lyt-top/vue-next-admin/issues/I64HVO),感谢[@canroc](https://gitee.com/canroc)、[@随心](https://gitee.com/jiangqiang1996)
-- 🌈 重构 `/views/system` 新增修改组件合并。[可以把新增修改组件合并成一个吧](https://gitee.com/lyt-top/vue-next-admin/issues/I64WES)
-- 🌈 重构 图标选择器,[图标选择器没办法筛选,只能筛选 ali 的](https://gitee.com/lyt-top/vue-next-admin/issues/I64HZD),感谢[@随心](https://gitee.com/jiangqiang1996)
-
-## 2.4.1
-
-`2022.11.30`
-
-- 🎉 新增 版本升级提示
-- 🐞 修复 [先打开 F12 再登录进去,然后改变浏览器大小 js 报错](https://gitee.com/lyt-top/vue-next-admin/issues/I63ZZT),感谢[@Quber](https://gitee.com/quber)
-
-## 2.4.0
-
-`2022.11.29`
-
-⚡⚡⚡ 此版为破坏性更新,应群友建议 `script lang="ts"` 改 `script lang="ts" setup 语法糖`。
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 表格封装演示,路径:`组件封装 -> 表格封装演示`
-- 🎉 新增 master 分支 script lang="ts" 改成 script lang="ts" setup 语法糖,将同步基础分支
-- 🐞 修复 [v2.3.0 版本报错问题处理](https://gitee.com/lyt-top/vue-next-admin/issues/I623RP)
-- 🐞 修复 [el-backtop 滚动高度不触发(固定了 header)](https://gitee.com/lyt-top/vue-next-admin/issues/I63N0D),感谢[@dejavuuuuu](https://gitee.com/zc19951010)
-- 🎯 优化 完善 ts 类型,删除根目录 `plugins.d.ts、shim.d.ts、source.d.ts`,移入到 `/src/types/global.d.ts`
-- 🎯 优化 代码 `watch` 移动到 `生命周期钩子` 最后,文字注释等
-
-## 2.3.0
-
-`2022.11.16`
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 新版登录页
-- 🎉 新增 tagsview 鼠标中键 `关闭当前 tagsview`
-- 🎉 新增 `分栏菜单鼠标悬停预加载`。[分栏模式如何去掉鼠标悬浮父级菜单,分栏菜单自动加载的功能啊](https://gitee.com/lyt-top/vue-next-admin/issues/I5RUY7)。操作路径:`布局配置 -> 分栏设置`
-- 🐞 修复 [vue-i18n](https://vue-i18n.intlify.dev/api/general.html#createi18n) 报错,[!39 修复 i18n 兼容性问题](https://toscode.gitee.com/lyt-top/vue-next-admin/pulls/39/files),感谢[@随心](https://toscode.gitee.com/jiangqiang1996)
-- 🐞 修复 顶栏搜索功能点击蒙蔽弹窗不关闭
-- 🐞 修复 [!38 fix: bug refreshRouterViewKey 值为 null 导致路由缓存第一次无效](https://toscode.gitee.com/lyt-top/vue-next-admin/pulls/38/files),感谢[@P)](https://toscode.gitee.com/foxp8y)
-- 🐞 修复 `路由参数 -> 普通路由/动态路由` 国际化演示时,`tagsView` 和 `浏览器标题` 显示异常。[演示中:路由参数界面 -> 动态路由,国际化显示时面包屑、浏览器标题有 bug](https://gitee.com/lyt-top/vue-next-admin/issues/I5JRJG)
-- 🐞 修复 `路由参数 -> 普通路由/动态路由` 动态设置 `tagsViewName` 时,`tagsView 右键菜单刷新` 功能失效(也就是路由后面有参数时,query、params)。[普通或动态路由新建页面后点击 tagview 刷新无效](https://gitee.com/lyt-top/vue-next-admin/issues/I5K3YO),感谢[@dejavuuuuu](https://gitee.com/zc19951010)
-- 🐞 修复 [表单(el-form)中,字体图标偏移问题](https://gitee.com/lyt-top/vue-next-admin/issues/I5K1PM)
-- 🐞 修复 路由 `router.addRoute` 时,一直提示 `No match found for location with path 'xxx'`
-- 🎯 优化 全局 `getCurrentInstance` 替换成 [`provide/inject`](https://cn.vuejs.org/api/application.html#app-provide) 或通过 `ref` 处理
-- 🎯 优化 引入组件方式 `(import xxx from xxx)` 改成 `defineAsyncComponent(() => import(xxx))`
-- 🎯 优化 页面高度 100% 问题,重写布局配置 `界面设置 -> 固定 Header` 多余的 `el-scrollbar` 逻辑、重写各界面需 `计算属性 computed` 设置动态高度问题(改为 css `flex` 设置自适应高度,具体查看文档:[设置可视区高度 100%](https://lyt-top.gitee.io/vue-next-admin-doc-preview/config/otherIssues/#%E8%AE%BE%E7%BD%AE%E5%8F%AF%E8%A7%86%E5%8C%BA%E9%AB%98%E5%BA%A6-100)。[!31 修复页面样式无法通过百分比设置的问题](https://toscode.gitee.com/lyt-top/vue-next-admin/pulls/31),感谢[@LostDeer](https://toscode.gitee.com/lyt-top/vue-next-admin/pulls/31/files)。`(改动较大,删除多余代码)`
-- 🎯 优化 [wangeditor](https://www.wangeditor.com/) 组件,`@wangeditor/editor-for-vue`。可自行修改,组件位置:`/src/components/editor`。相关 Issues:[wangeditor 编辑器多个菜单不能回弹](https://gitee.com/lyt-top/vue-next-admin/issues/I5M5H7)
-- 🌈 重构 外链、内嵌 iframe 逻辑 + 美化,iframe 支持缓存
-
-## 2.2.0
-
-`2022.07.10`
-
-⚡⚡⚡ [/sec/stores/userInfo.ts](https://gitee.com/lyt-top/vue-next-admin/blob/master/src/stores/userInfo.ts) 下添加了 `getApiUserInfo` 接口模拟数据 `setTimeout` 为 3 秒
-
-- 🌟 更新 依赖更新最新版本
-- 🐞 修复 [主界面重新授权按钮点击卡死不跳转登录界面#I5C3JS](https://gitee.com/lyt-top/vue-next-admin/issues/I5C3JS),感谢[@Hero-Typ](https://gitee.com/tian_yu_peng)
-- 🐞 修复 编译警告[#I5CVSB](https://gitee.com/lyt-top/vue-next-admin/issues/I5CVSB),全局替换成 `:deep(attr)`,感谢[@Linvas](https://gitee.com/linvas)。参考文档:[vue3 sfc-style](https://v3.cn.vuejs.org/api/sfc-style.html#style-scoped)。`node_modules\print-js\dist\print.js` 需 `print-js` 作者适配或去除 `package.json` 中的 `"print-js": "^1.6.0"`
-- 🐞 修复 [vue-next-admin-template-js 版本前端控制路由:userInfo.js 请求用户信息接口报错,加载不到路由 可以写个定时器模拟一下接口 一样的报错#I5F1HP](https://gitee.com/lyt-top/vue-next-admin/issues/I5F1HP),感谢[@白开水](https://gitee.com/libin951223)
-
-## 2.1.1
-
-`2022.05.27`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 深色模式下,`<el-button text></el-button>` 时,`:active` 样式
-- 🎯 优化 [页面缓存在刷新之后失效 #I58U75](https://gitee.com/lyt-top/vue-next-admin/issues/I58U75)),感谢[@ls0428](https://gitee.com/ls0428)
-- 🎯 优化 [SvgIcon 对下载的 Svg 图像设置颜色无效 #I59ND0](https://gitee.com/lyt-top/vue-next-admin/issues/I59ND0)),感谢[@elus_z](https://gitee.com/elus_z)
-- 🎯 优化 `/src/utils/toolsValidate.ts` 工具类
-- 🐞 修复 [布局切换,TagsView 显示的 tab 会多一个出来 #I58WGM](https://gitee.com/lyt-top/vue-next-admin/issues/I58WGM),感谢[@lg_boy](https://gitee.com/lg_boy)
-- 🐞 修复 [如果设置顶部面包屑导航开启图标 isBreadcrumbIcon=true 后,样式有点问题 如果不开启就是正常的 #I58VB8](https://gitee.com/lyt-top/vue-next-admin/issues/I58VB8)
-- 🐞 修复 地址栏路由地址输入错误时,返回首页后,再次输入路由地址错误时,不跳转 404 问题
-- 🐞 修复 [2.1.0 版本的图标选择组件多次点击后功能失效 #I590TH](https://gitee.com/lyt-top/vue-next-admin/issues/I590TH),感谢[@quber](https://gitee.com/quber)
-
-## 2.1.0
-
-`2022.04.18`
-
-⚡⚡⚡ 此版本为破环性更新,优化内容如下:(谨慎更新!谨慎更新!!谨慎更新!!!)。因为 `vuex` 替换成 `pinia`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 部分界面图片不显示问题(更换 gitee 在线图片地址源)
-- 🎯 优化 各界面方法引入与逻辑之间添加一行空行,方便区分内容
-- 🎯 优化 图标选择器 [#I4YAHB](https://gitee.com/lyt-top/vue-next-admin/issues/I4YAHB),感谢[@真有你的](https://gitee.com/sunliusen)
-- 🎯 优化 图标选择器 icon type 类型为 all 时,类型 ali、ele、awe 回显问题
-- 🎯 优化 去掉开发环境 i18n 控制台警告,页面代码:[i18n/index.ts](https://gitee.com/lyt-top/vue-next-admin/blob/master/src/i18n/index.ts)
-- 🎯 优化 `NextLoading.start()` 方法,防止第一次进入界面时出现短暂空白
-- 🎯 优化 地址栏有参数退出登录,再次登录不跳之前界面问题 `src/layout/navBars/breadcrumb/user.vue`
-- 🎯 优化 `SvgIcon` 组件,防止 `开启 Tagsview 图标` 时,`tagsView 右键菜单关闭` 报错问题,工作流不可连线、全屏时关闭按钮消失问题
-- 🎯 优化 [如果 url 中有中文等特殊字符,第一次切换该 tab 时 keep-alive 失效#I55JS7](https://gitee.com/lyt-top/vue-next-admin/issues/I55JS7),感谢[yuyong1566](https://gitee.com/yuyong1566)
-- 🎯 优化 [wangEditor](https://www.wangeditor.com/) 更新到 v5,[vue3 版本线上示例中 wangeditor 富文本编辑器 demo 实例,无法换行#I5565B](https://gitee.com/lyt-top/vue-next-admin/issues/I5565B),感谢@[jenchih](https://gitee.com/jenchih)
-- 🎯 优化 [在关闭 tagview 时,高度刷新时会会变化,出现滚动条](https://gitee.com/lyt-top/vue-next-admin/issues/I55FHM),感谢[张松](https://gitee.com/zs310071113)
-- 🎯 优化 [路由参数](https://lyt-top.gitee.io/vue-next-admin-preview/#/params/common)演示
-- 🎉 新增 [vuex](https://vuex.vuejs.org/) 替换成 [pinia](https://pinia.vuejs.org/getting-started.html)
-- 🎉 新增 tagsView 支持自定义 tagsView 名称(文章详情时有用),前往体验:[路由参数/普通路由](https://lyt-top.gitee.io/vue-next-admin-preview/#/params/common)。新增 tagsView 支持自定义名称国际化,感谢[@q7but](https://gitee.com/q7but)、[!22 add 添加自定义 tagVIewName 拓展,支持国际化](https://gitee.com/lyt-top/vue-next-admin/pulls/22/files)、感谢[@tony_tong_xin](https://gitee.com/tony_tong_xin)
-- 🐞 修复 适配 `"element-plus": "^2.1.9",2.2.0` 版本
-- 🐞 修复 [导航栏横向布局后,一级菜单显示问题#I4Z3M3](https://gitee.com/lyt-top/vue-next-admin/issues/I4Z3M3)
-- 🐞 修复 横向布局三级及以上导航菜单高亮、导航高度不统一问题
-- 🐞 修复 分栏模式下,选中的菜单是 primary 样式,鼠标移入字也变成 primary 色了,感谢群友@孤夜-流殇
-- 🐞 修复 [vuex 里面改了颜色 但是不生效 #I4WFMA](https://gitee.com/lyt-top/vue-next-admin/issues/I4WFMA)
-- 🐞 修复 全局主题 primary 清空颜色后报错,[#I4X0LG](https://gitee.com/lyt-top/vue-next-admin/issues/I4X0LG),感谢[面向 BUG 编程](https://gitee.com/fhtfy)
-- 🐞 修复 [.eslintrc.js 文件 rules 标签名错误 #I53IPK](https://gitee.com/lyt-top/vue-next-admin/issues/I53IPK),感谢[yuyong1566](https://gitee.com/yuyong1566)
-- 🐞 修复 `开启 Tagsview 图标` 时,`tagsView 右键菜单关闭` 报错问题
-- 🐞 修复 `router.push` 路径找不到时报错问题,`404、401 界面` 已移入到 `main` 主布局里(之前全屏)
-- 🐞 修复 [全局修改组件大小失效了](https://gitee.com/lyt-top/vue-next-admin/issues/I551RP),感谢[lg_boy](https://gitee.com/lg_boy)
-- 🐞 修复 [修改一下配置时,需要每次都清理 `window.localStorage` 浏览器永久缓存,配置才会生效,问题解决#I567R1](https://gitee.com/lyt-top/vue-next-admin/issues/I567R1),感谢[@lanbao123](https://gitee.com/lanbao123)
-- 🐞 修复 [标记为需要缓存的 tab 页后,再次从左侧菜单打开,还是显示被缓存的页面内容#I4UY3G](https://gitee.com/lyt-top/vue-next-admin/issues/I4UY3G),感谢@axcc1234、特别感谢群友@华仔
-- 🌈 重构 路由(`/src/router/index.ts`)解决 No match found for location with path "xxx"(前端控制,后端控制未解决) 问题
-
-## 2.0.2
-
-`2022.03.04`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 Alert 提示添加边框
-- 🎯 优化 功能 / 数字滚动 演示界面
-- 🐞 修复 全局主题按钮颜色 :active 问题
-- 🐞 修复 Dropdown 下拉菜单样式问题
-- 🐞 修复 SvgIcon 图标组件动态切换时报警告问题,[SvgIcon 改变 name 时可能导致图像不显示](https://gitee.com/lyt-top/vue-next-admin/issues/I4VGE0),感谢@axcc1234
-
-## 2.0.1
-
-`2022.02.25`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 svgIcon 图标组件
-- 🎯 优化 vite.config.ts 打包,感谢群友@YourObjec
-- 🐞 修复 tagViews 开启图标不显示问题(风格 5),感谢群友@坏人
-- 🐞 修复 [Element Plus 1.2.0-beta.6 以后的版本 el-table 在移动端无法左右滑动](https://gitee.com/lyt-top/vue-next-admin/issues/I4UPTP),感谢@YGDada
-
-## 2.0.0
-
-`2022.02.21`
-
-⚡⚡⚡ 此版本为破环性更新,优化内容如下:(谨慎更新!谨慎更新!!谨慎更新!!!)。演示界面建议直接覆盖文件。如需使用之前版本,请前往[gitee 发行版](https://gitee.com/lyt-top/vue-next-admin/releases) 进行对应版本下载。基础版会基于 `master` 分支进行修改
-
-- 🌟 更新 依赖更新最新版本
-- 🌟 更新 登录页、首页
-- 💔 移除 vue-web-screen-shot
-- 💔 移除 城市多级联动,完整 json 数据请去 [vue-next-admin-images/menu](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 仓库查看
-- 💔 移除 功能/echartsTree 树图
-- 💔 移除 其它设置/Tagsview 风格 2、Tagsview 风格 3
-- 💔 移除 功能/验证器
-- 🚧 调整 src/api 编写方式
-- 🚧 调整 自定义封装公用组件演示,更好的维护
-- 🎉 新增 Volar 支持,vs code 配置参考 [Vue Language Features (Volar)](https://lyt-top.gitee.io/vue-next-admin-doc-preview/home/vscode/)
-- 🎉 新增 `SvgIcon` 支持本地 svg 图标使用
-- 🎉 新增 表单表格验证演示
-- 🎯 优化 全局主题(移除 success、info、warning、danger)
-- 🎯 优化 工作流(开源)
-- 🎯 优化 element plus svg 图标,`elementXXX` 改成 `ele-XXX`
-- 🌈 重构 深色模式
-- 🌹 合并 [处理 parent 的 h100 由于外层有 min-height 导致失效的问题](https://gitee.com/lyt-top/vue-next-admin/pulls/20),感谢@MaxNull、@21030442-mao
-- 🐞 修复 element plus 升级 `^1.3.0-beta.5` 后 组件 size 大小问题(大改:涉及布局、演示界面)
-- 🐞 修复 vs code 使用 Vue Language Features (Volar) 插件 代码报红问题(可以把公用的 ts 类型定义封装起来公用)
-
-## 1.2.2
-
-`2021.12.21`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 iframes 滚动条问题
-- 🎯 优化 部署后每次都要强制刷新清浏览器缓存问题
-- 🎉 新增 工具类百分比验证演示
-- 🐞 修复 [tag-view 标签右键会超出浏览器 #I4KN78](https://gitee.com/lyt-top/vue-next-admin/issues/I4KN78)
-
-## 1.2.1
-
-`2021.12.12`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 cropper 裁剪时卡顿问题 [#I4M2VQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4M2VQ)
-- 🎯 优化 Wangeditor 富文本编辑器的问题 [#I4LPC1](https://gitee.com/lyt-top/vue-next-admin/issues/I4LPC1)、[#I4LM7I](https://gitee.com/lyt-top/vue-next-admin/issues/I4LM7I)
-- 🐞 修复 浏览器标题问题
-- 🐞 修复 element plus svg 图标引入
-- 🐞 修复 工作流不可以拖线连接问题
-
-## 1.2.0
-
-`2021.11.28`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 深色模式
-- 🎯 优化 `/@/utils` 文件夹,合并删除单一内容
-- 🎯 优化 系统设置:菜单管理(新增、修改)、角色管理(新增菜单权限)、用户管理、部门管理、字典管理
-- 🎯 优化 登录界面逻辑、权限管理逻辑
-- 🎯 优化 同步 [vue-next-admin-images](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 后端控制菜单模拟数据
-- 🎉 新增 适配 Font Icon 向 SVG Icon 迁移(改动大,"element-plus": "^1.2.0-beta.4" 谨慎更新)
-- 🐞 修复 热更新问题,感谢@甜蜜蜜
-- 🐞 修复 页面/element 字体图标演示
-- 🐞 修复 功能/图标选择器演示,新增高级功能 [issues #I4GJXQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4GJXQ)
-
-## 1.1.2
-
-`2021.10.17`
-
-- 🌟 更新 依赖更新最新版本
-- 🐞 修复 开启全屏时,刷新界面被还原成未全屏的状态
-- 🎯 优化 tagsView 右键菜单关闭逻辑
-- 🎯 优化 wangeditor 富文本编辑器(增加双向绑定)
-- 🎉 新增 工作流(暂不开源)
-- 🎉 新增 基础版 ts(不带国际化),切换 `vue-next-admin-template` 分支
-
-## 1.1.1
-
-`2021.09.25`
-
-- 🌟 更新 依赖更新最新版本(`"element-plus": "^1.1.0-beta.13"` 版本运行错误,`^1.1.0-beta.16`修复横向菜单卡死问题)
-- 🐞 修复 Dialog 弹窗位置错误、Drawer 抽屉内边距、el-menu 菜单收起时背景色问题
-- 🎯 优化 锁屏界面自动锁屏(s/秒)必须设置至少 1 秒
-- 🎉 新增 分栏布局,鼠标移入当前项时,显示当前项菜单内容
-- 🎉 新增 工作流(未完成)
-
-## 1.1.0
-
-`2021.09.10`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 小屏模式下登录页二维码遮挡标题问题
-- 🎉 新增 图片验证器
-- 🎉 新增 动态复杂表单
-- 🎉 新增 工作流(未完成)
-- 🎉 新增 深色主题(伪深色,样式变动大,谨慎更新)
-
-## 1.0.18
-
-`2021.08.29`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 权限组件去掉顶级 div(`/src/components/auth`)
-- 🎉 新增 布局配置添加恢复默认按钮
-- 🐞 修复 升级 <a href="https://element-plus.gitee.io/#/zh-CN/component/changelog" target="_blank">element plus 1.1.0-beta.7</a>后项目无法启动、el-menu 菜单
-- 🐞 修复 表格固定列时的层级、设置了相对定位时,遮挡左侧导航菜单问题
-
-## 1.0.17
-
-`2021.08.22`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 去除设置布局切换,重置主题样式(initSetLayoutChange),切换布局需手动设置样式,设置的样式自动同步各布局
-- 🎯 优化 Dropdown 下拉菜单用户账号靠边时换行问题
-- 🎯 优化 左侧导航菜单,共用菜单树,防止 `布局配置` 设置 `菜单 / 顶栏` 时,样式丢失等问题
-- 🐞 修复 固定 header 后没有回到顶部的 bug,拉取项目后运行不起来的 bug。<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/14" target="_blank">!14</a>,感谢<a href="https://gitee.com/wjs0509" target="_blank">@wjs0509</a>
-- 🐞 修复 tagView 右键全屏后,浏览器窗口大小发生任何变化都会导致左边菜单显示出来,并且可点击打开对应页面。<a href="https://gitee.com/lyt-top/vue-next-admin/issues/I46E6T" target="_blank">I46E6T</a>
-- 🐞 修复 默认设置 `菜单 / 顶栏` 样式不生效问题(/@/src/store/modules/themeConfig.ts)
-
-## 1.0.16
-
-`2021.08.14`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 菜单高亮(详情且详情设置了 meta.isHide 时,顶级菜单高亮),感谢群友@YourObject
-- 🎯 优化 详情路径写法:如父级(/pages/filtering),那么详情为(/pages/filtering/details?id=1)。这样写可实现(详情时,父级菜单高亮),否则写成(/pages/filteringDetails?id=1)顶级菜单将不会高亮。可参考:`页面/过滤筛选组件`,点击当前图片进行测试
-- 🎯 优化 tagsView 右键菜单全屏时,打开的界面高度问题
-- 🎯 优化 图表批量 resize 问题
-- 🐞 修复 菜单收起时(设置全局主题:primary 且有二级菜单时),文字高亮颜色不对
-- 🐞 修复 国际化 <a href="https://gitee.com/lyt-top/vue-next-admin/issues/I43NPE" target="_blank">#I43NPE</a>。可参考:`页面/过滤筛选组件`,点击顶部语言切换,进行底部分页国际化查看
-
-## 1.0.15
-
-`2021.08.06`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 tagsView 右键菜单点击时的字段名(id 已修改成 contextMenuClickId)与路由中返回的 id 名冲突问题,感谢群友@伯牙已遇钟子期
-- 🎉 新增 多个 form 表单验证界面演示
-
-## 1.0.14
-
-`2021.07.29`
-
-- 🌟 更新 依赖更新最新版本(vue、vuex、vue-router),出现问题,请手动降级。版本查看:<a href="https://www.npmjs.com/" target="_blank">vnpm</a>
-- 🎯 优化 数据可视化图表演示加载卡顿问题、优化有图表的演示界面
-- 🎯 优化 路由参数演示界面
-- 🎯 优化 tagsView 操作演示界面,由于存在相同路由多标签,必须要传全部参数值(query 或者 params)
-- 🎉 新增 开启 TagsView 共用,开启时:(多个路由菜单共用一个详情组件(参数为后点击的覆盖前面点击的),tagsView 中只会出现一个(不支持同时出现多个 tagsView 标签))。关闭时:(多个路由菜单共用一个详情组件,参数不同,会同时出现多个 tagsView 标签)
-- 🐞 修复 tagsView 共用(单标签)时,右键菜单功能点击,参数不对的问题(第 2n+个参数未覆盖第一个参数值)
-- 🐞 修复 多 tagsView 标签(参数不同)、单个 tagsView 标签公用(参数不同)所带来的刷新功能、横向自动滚动等问题
-- 🐞 修复 处理全屏若干问题,<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/12" target="_blank">pr!12</a>,感谢群友@另一个前端
-
-## 1.0.13
-
-`2021.07.25`
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 数据可视化演示界面(/visualizingDemo1、/visualizingDemo2)
-- 🎉 新增 登录页扫码登录
-
-## 1.0.12
-
-`2021.07.16`
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 数据可视化演示空界面(待完善)
-- 🎯 优化 tagsView 动态路由(xxx/:id/:name)时的右键菜单刷新、关闭其它时参数丢失问题(2021.07.15 优化)
-- 🐞 修复 路由带参数时,复制路径到登录页,跳转后参数消失的问题
-- 🐞 修复 设置多个外链,点击后,页面内容停留在上一个内容(内容未改变)、国际化处理、打开新窗口 sessionStorage 共享等
-
-## 1.0.11
-
-`2021.07.14`
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 路由参数、图片懒加载界面演示
-- ⚠️ 警告 Form 表单 `binding value must be a string or number`,解决:加上 `label-position="top"` 不报警告(等待官方修复)
-- 🎯 优化 锁屏界面动画效果、首页图表显示
-- 🎯 优化 tagsView 右键菜单 `关闭` 功能逻辑
-- 🐞 修复 开启 TagsView 拖拽报错及小于 `1000px` 时自动设置禁止拖拽(<a href="https://gitee.com/lyt-top/vue-next-admin/issues/I3ZRRI" target="_blank">#I3ZRRI</a>)
-- 🐞 修复 `iframe 内嵌、外链` 高度问题,使用 computed 进行计算
-- 🐞 修复 默认布局开启 `侧边栏 Logo` 与关闭 `菜单水平折叠`,切换到横向布局时,菜单看不见的问题
-- 🐞 修复 切换不同布局时,再去开启 `经典布局分割菜单` 功能不生效问题
-- 🐞 修复 浏览器窗口标题中/英文切换不实时生效的问题
-- 🐞 修复 切换布局时,某些功能不可以使用。部分界面不需要取消事件监听(proxy.mittBus.off('xxx'))
-- 🐞 修复 动态路由带参数,router-link 跳转问题(<a href="hhttps://gitee.com/lyt-top/vue-next-admin/issues/I3YX6G" target="_blank">#I3YX6G</a>)
-- 🐞 修复 横向菜单有二级菜单时,点击子级菜单不高亮问题
-- 🐞 修复 功能 tagsView 操作演示不生效
-
-## 1.0.10
-
-`2021.07.07`
-
-- 🌟 更新 依赖更新最新版本(字体图标无问题)
-- 🎯 优化 内嵌 iframe、外链,解决 tagsView 刷新问题
-
-## 1.0.9
-
-`2021.07.02`
-
-- 🌟 更新 依赖更新最新版本
-- 🎯 优化 图标选择器设置宽度、v-model 等问题
-- 🎯 优化 滚动通知栏在手机上的体验
-- 🎯 优化 系统管理/新增菜单(编辑菜单),使用 `图标选择器` 进行模拟
-- 🎯 优化 字体图标(自动载入) 逻辑
-- 🐞 修复 screenfull 全屏时,按键盘 esc 键图标不改变问题,感谢群友@伯牙已遇钟子期
-
-## 1.0.8
-
-`2021.06.29`
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 表单中英文切换演示
-- 🎯 优化 登录页查看密码 icon 图标
-- 🎯 优化 图标选择器
-- 🎯 优化 拖动指令
-- 🐞 修复 form 表单在页面小于 576px 时的排版问题
-
-## 1.0.7
-
-`2021.06.24`
-
-- 🌟 更新 依赖更新最新版本
-- 🎉 新增 拖动指令及其演示界面
-- 🎯 优化 锁屏界面,解锁提示
-- 🎯 优化 登录页在手机上显示的效果
-
-## 1.0.6
-
-`2021.06.23`
-
-- 🎯 优化 去掉内嵌 iframe 内边距(padding)
-- 🎯 优化 城市多级联动组件
-- 🎯 优化 Tree 树形控件改成表格组件
-- 🐞 修复 Cascader 级联选择器高度问题
-
-## 1.0.5
-
-`2021.06.22`
-
-- 🌟 更新 vite 降级为@vite2.3.7,降级方法 `cnpm install vite@2.3.7`,防止 element plus 字体图标消失
-- 🐞 修复 开启后端控制路由(isRequestRoutes = true)时,内嵌 iframe、外链不可使用的问题
-
-## 1.0.4
-
-`2021.06.19`
-
-- 🌟 更新 依赖更新最新版本("vite": "^2.3.7")热更新无问题
-- 🎉 新增 深克隆工具,方便开发,感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/6" target="_blank">#6</a>)
-- 🎯 优化 vuex 模块自动导入。感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/4" target="_blank">#4</a>),感谢群友@web 小学生-第五君
-- 🎯 优化 类型定义提高编码体验,修复不能将类型“string | undefined”分配给类型“string”的问题。感谢<a href="https://gitee.com/kangert" target="_blank">@kangert</a>(<a href="https://gitee.com/lyt-top/vue-next-admin/pulls/5" target="_blank">#5</a>)
-- 🎯 优化 `layout` 文件夹移动到与 `views` 文件夹同级(改动较大,`/@/views/layout` 变成 `/@/layout`)
-- 🎯 优化 页面有 `console.log` 时 `eslint` 不生效问题
-- 🎯 优化 页面、ts 中 `any` 类型问题(改动较大)
-- 🎯 优化 登录页在手机上显示的效果
-- 🎯 优化 多行注释信息,鼠标放到方法名即可查看,更加直观的知道方法参数等。引入方法时需去掉以 `.ts` 结尾的后缀(改动较大)
-- 🎯 优化 移除 `utils/storage.ts` 下的旧写法(改动较大)
-- 🎯 优化 拆分 `router` 下内容,路由、前端、后端控制分开写,方便理解
-- 🐞 修复 鼠标移入顶部用户信息栏 `开/关全屏` 文字反向问题
-- 🐞 修复 热更新时,NextLoading(界面 loading) 不消失问题 `window.nextLoading === undefined`
-- 🐞 修复 vuex 中不可以使用 `/@/api/xxx` 下的接口调用问题
-
-## 1.0.3
-
-`2021.06.02`
-
-- ❄️ 删除 G6 思维导图界面
-- 🌟 更新 手动更新 vue、vue-router、vuex 到最近最多人使用的版本,出现不可预测的问题请降低版本。版本查看:<a href="https://www.npmjs.com/package/vue" target="_blank">vue 版本查看</a>
-- 🐞 修复 开启后端控制路由 `isRequestRoutes` 在非首页刷新页面后,回到首页的问题,感谢群友@伯牙已遇钟子期
-
-## 1.0.2
-
-`2021.06.01`
-
-- 🌟 更新 依赖更新最新版本
-- 🐞 修复 菜单搜索中文不可以搜索的问题,感谢群友@逍遥天意
-
-## 1.0.1
-
-`2021.05.31`
-
-- 🎉 新增 更新日志文件 `CHANGELOG.md`,以后每次更新都会在这里显示对应内容
-- 🌟 更新 依赖更新最新版本
-- 🐞 修复 分栏、经典布局路由设置 `meta.isHide` 为 `true` 时报错问题,感谢群友@29、@芭芭拉
-- 🐞 修复 经典布局点击 `tagsView` 左侧菜单数据不变问题

+ 0 - 144
admin-web/README.md

@@ -1,144 +0,0 @@
-<div align="center">
-	<img src="https://img-blog.csdnimg.cn/9efd5420327a46b7bd6d93524a97229d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbHl0LXRvcA==,size_14,color_FFFFFF,t_70,g_se,x_16">
-	<p align="center">
-		<a href="https://v3.vuejs.org/" target="_blank">
-			<img src="https://img.shields.io/badge/vue.js-vue3.x-green" alt="vue">
-		</a>
-		<a href="https://element-plus.gitee.io/#/zh-CN/component/changelog" target="_blank">
-			<img src="https://img.shields.io/badge/element--plus-%3E1.0.0-blue" alt="element plus">
-		</a>
-		<a href="https://www.tslang.cn/" target="_blank">
-	    <img src="https://img.shields.io/badge/typescript-%3E4.0.0-blue" alt="typescript">
-	  </a>
-		<a href="https://vitejs.dev/" target="_blank">
-		  <img src="https://img.shields.io/badge/vite-%3E2.0.0-yellow" alt="vite">
-		</a>
-		<a href="https://gitee.com/lyt-top/vue-next-admin/blob/master/LICENSE" target="_blank">
-		  <img src="https://img.shields.io/badge/license-MIT-success" alt="license">
-		</a>
-	</p>
-	<p>&nbsp;</p>
-</div>
-
-#### 💝 长期赞助商
-
-<a href="http://www.ccflow.org/" target="_blank">
-	<img src="./src/assets/ccflowRightNextAdmin.png" width="50%" height="70px">
-</a>
-
-#### 🌈 介绍
-
-基于 vue3.x + CompositionAPI setup 语法糖 + typescript + vite + element plus + vue-router-next + pinia 技术,适配手机、平板、pc 的后台开源免费模板,希望减少工作量,帮助大家实现快速开发。
-
-#### ⛱️ 线上预览
-
-- vue3.x 版本预览(vue-next-admin)<a href="https://lyt-top.gitee.io/vue-next-admin-preview/#/login" target="_blank">https://lyt-top.gitee.io/vue-next-admin-preview/#/login</a>
-- vue2.x 版本预览(vue-prev-admin)<a href="https://lyt-top.gitee.io/vue-prev-admin-preview/#/login" target="_blank">https://lyt-top.gitee.io/vue-prev-admin-preview/#/login</a>
-- vue3.x + uni-app 商城 H5(vue-next-admin-shop)<a href="https://lyt-top.gitee.io/vue-next-admin-shop-preview" target="_blank">https://lyt-top.gitee.io/vue-next-admin-shop-preview</a>
-
-#### 💒 代码仓库
-
-- vue3.x 版本 <a href="https://gitee.com/lyt-top/vue-next-admin" target="_blank">https://gitee.com/lyt-top/vue-next-admin</a>
-- vue2.x 版本 <a href="https://gitee.com/lyt-top/vue-next-admin/tree/vue-prev-admin" target="_blank">https://gitee.com/lyt-top/vue-next-admin/tree/vue-prev-admin</a>
-
-#### 🚧 安装 cnpm、yarn
-
-- 复制代码(桌面 cmd 运行) `npm install -g cnpm --registry=https://registry.npm.taobao.org`
-- 复制代码(桌面 cmd 运行) `npm install -g yarn`
-
-#### 🏭 环境支持
-
-| Edge      | Firefox      | Chrome      | Safari      |
-| --------- | ------------ | ----------- | ----------- |
-| Edge ≥ 88 | Firefox ≥ 78 | Chrome ≥ 87 | Safari ≥ 13 |
-
-> 由于 Vue3 不再支持 IE11,故而 ElementPlus 也不支持 IE11 及之前版本。
-
-#### ⚡ 使用说明
-
-建议使用 cnpm,因为 yarn 有时会报错。<a href="http://nodejs.cn/" target="_blank">node 版本 > 14.18+/16+</a>
-
-> Vite 不再支持 Node 12 / 13 / 15,因为上述版本已经进入了 EOL 阶段。现在你必须使用 Node 14.18+ / 16+ 版本。
-
-```bash
-# 克隆项目
-git clone https://gitee.com/lyt-top/vue-next-admin.git
-
-# 进入项目
-cd vue-next-admin
-
-# 安装依赖
-cnpm install
-
-# 运行项目
-cnpm run dev
-
-# 打包发布
-cnpm run build
-```
-
-#### 📚 开发文档
-
-- 查看开发文档:<a href="https://lyt-top.gitee.io/vue-next-admin-doc-preview" target="_blank">vue-next-admin-doc</a>
-
-#### 💯 学习交流加 QQ 群
-
-> 1 - 4 交流群已满,请加 vue-next-admin 交流群 5
-
-群号:556254895
-
-其它交流群请查看文档首页 [vueNextAdmin 解疑问](https://lyt-top.gitee.io/vue-next-admin-doc-preview/)
-
-#### 💒 集成后端
-
-- <a target="_blank" href="https://github.com/PandaGoAdmin/PandaX">@熊猫 PandaGoAdmin</a>
-- <a target="_blank" href="https://toscode.gitee.com/GionConnection/gopro_free">@甜蜜蜜 GoPro 平台</a>
-- <a target="_blank" href="https://gitee.com/GionConnection/niupi-free">@甜蜜蜜 NiuPi 平台</a>
-- <a target="_blank" href="https://gitee.com/tiger1103/gfast/tree/os-v3/">@游子 GFast-V3</a>
-- <a target="_blank" href="https://gitee.com/diygw/diygw-ui-php/">@diygw.com gw-ui-php</a>
-- <a target="_blank" href="https://gitee.com/zsvg/vboot-net">@zsvg vboot-net</a>
-- <a target="_blank" href="https://gitee.com/zsvg/vboot-java">@zsvg vboot-java</a>
-- <a target="_blank" href="https://gitee.com/wonderful-code/buildadmin">@青红造了个白 buildadmin</a>
-- <a target="_blank" href="https://github.com/xiaodingding/iotfast">@Goodwell iotfast(一个开源的物联网平台)</a>
-
-#### ❤️ 鸣谢列表
-
-- <a href="https://github.com/vuejs/vue" target="_blank">vue</a>
-- <a href="https://github.com/vuejs/vue-next" target="_blank">vue-next</a>
-- <a href="https://github.com/ElemeFE/element" target="_blank">element-ui</a>
-- <a href="https://github.com/element-plus/element-plus" target="_blank">element-plus</a>
-- <a href="https://github.com/vuejs/vue-router-next" target="_blank">vue-router-next</a>
-- <a href="https://github.com/vuejs/pinia" target="_blank">pinia</a>
-- <a href="https://github.com/apache/echarts" target="_blank">echarts</a>
-- <a href="https://github.com/axios/axios" target="_blank">axios</a>
-- <a href="https://github.com/zenorocha/clipboard.js" target="_blank">clipboard</a>
-- <a href="https://github.com/inorganik/countUp.js" target="_blank">countUp</a>
-- <a href="https://github.com/developit/mitt" target="_blank">mitt</a>
-- <a href="https://github.com/rstacruz/nprogress" target="_blank">nprogress</a>
-- <a href="https://github.com/sindresorhus/screenfull.js" target="_blank">screenfull</a>
-- <a href="https://github.com/SortableJS/Sortable" target="_blank">sortablejs</a>
-- <a href="https://github.com/sass/sass" target="_blank">sass</a>
-- <a href="https://github.com/microsoft/TypeScript" target="_blank">typescript</a>
-- <a href="https://github.com/vitejs/vite" target="_blank">vite</a>
-- <a href="https://github.com/wangeditor-team/wangEditor" target="_blank">wangeditor</a>
-- <a href="https://github.com/fengyuanchen/cropperjs" target="_blank">cropperjs</a>
-- <a href="https://github.com/davidshimjs/qrcodejs" target="_blank">qrcodejs</a>
-- <a href="https://github.com/crabbly/Print.js" target="_blank">print-js</a>
-- <a href="https://github.com/jbaysolutions/vue-grid-layout" target="_blank">vue-grid-layout</a>
-- <a href="https://github.com/antoniandre/splitpanes" target="_blank">splitpanes</a>
-- <a href="https://github.com/jsplumb/jsplumb" target="_blank">jsplumb</a>
-- <a href="https://github.com/hxj9102/table2excel" target="_blank">js-table2excel</a>
-
-#### 💕 特别感谢
-
-特别感谢老哥们的建议、指导与帮忙。谢谢!
-
-- <a href="https://gitee.com/click33/sa-plus" target="_blank">@省长</a>
-- <a href="https://gitee.com/jskz/Jskz-SpringCloud" target="_blank">@唐参</a>
-- <a href="https://gitee.com/chuange" target="_blank">@川歌</a>
-- @华仔
-
-#### 💌 支持作者
-
-如果觉得框架不错,或者已经在使用了,希望你可以去 <a target="_blank" href="https://github.com/lyt-Top/vue-next-admin">Github</a> 或者
-<a target="_blank" href="https://gitee.com/lyt-top/vue-next-admin">Gitee</a> 帮我点个 ⭐ Star,这将是对我极大的鼓励与支持。

+ 2 - 50
admin/src/main/java/com/kym/admin/jobs/InvoiceStatusJob.java

@@ -1,12 +1,10 @@
 package com.kym.admin.jobs;
 
 import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
-import com.kym.entity.admin.InvoiceDetail;
 import com.kym.entity.miniapp.ChargeOrder;
 import com.kym.entity.miniapp.Invoice;
 import com.kym.entity.wechat.InvoiceOrderDetail;
 import com.kym.huapiaoer.enums.InvoiceQueryType;
-import com.kym.service.admin.InvoiceDetailService;
 import com.kym.service.miniapp.ChargeOrderService;
 import com.kym.service.miniapp.HuapiaoerInvoiceService;
 import com.kym.service.miniapp.InvoiceService;
@@ -24,21 +22,18 @@ public class InvoiceStatusJob {
     private final InvoiceService invoiceService;
     private final ChargeOrderService chargeOrderService;
     private final HuapiaoerInvoiceService huapiaoerInvoiceService;
-    private final InvoiceDetailService invoiceDetailService;
 
     public InvoiceStatusJob(InvoiceService invoiceService, ChargeOrderService chargeOrderService,
-                            HuapiaoerInvoiceService huapiaoerInvoiceService,
-                            InvoiceDetailService invoiceDetailService) {
+                            HuapiaoerInvoiceService huapiaoerInvoiceService) {
         this.invoiceService = invoiceService;
         this.chargeOrderService = chargeOrderService;
         this.huapiaoerInvoiceService = huapiaoerInvoiceService;
-        this.invoiceDetailService = invoiceDetailService;
     }
 
     /**
      * 每5分钟轮询航信查询开票结果,处理开票中的发票,并对已开票但未插卡包的发票补插
      */
-    @Scheduled(cron = "0 */5 * * * ?")
+    @Scheduled(cron = "0 */1 * * * ?")
     public void execute() {
         log.info("执行发票状态轮询任务...开始");
 
@@ -69,7 +64,6 @@ public class InvoiceStatusJob {
                 }
 
                 // 邮件已由航信在开票时根据 head.recmail 自动发送,无需重复调用
-                huapiaoerInvoiceService.insertToCardPackage(invoice, result);
 
                 log.info("发票轮询处理成功, applyId:{}, invoiceCode:{}, invoiceNumber:{}",
                         invoice.getApplyId(), result.getInvoicecode(), result.getInvoicenumber());
@@ -78,49 +72,7 @@ public class InvoiceStatusJob {
             }
         }
 
-        // 第二阶段:对已开票但 cardInformation 为空的发票补插卡包
-        retryCardInsertion();
-
         log.info("执行发票状态轮询任务...结束");
     }
 
-    private void retryCardInsertion() {
-        List<String> applyIds;
-        try {
-            DynamicDataSourceContextHolder.push("db-admin");
-            applyIds = invoiceDetailService.lambdaQuery()
-                    .eq(InvoiceDetail::getStatus, "ISSUED")
-                    .isNull(InvoiceDetail::getCardInformation)
-                    .select(InvoiceDetail::getApplyId)
-                    .list().stream().map(InvoiceDetail::getApplyId).toList();
-        } finally {
-            DynamicDataSourceContextHolder.poll();
-        }
-
-        if (applyIds.isEmpty()) {
-            return;
-        }
-
-        log.info("发现 {} 条已开票但未插卡包的发票,开始补插", applyIds.size());
-
-        for (String applyId : applyIds) {
-            try {
-                DynamicDataSourceContextHolder.push("db-miniapp");
-                var invoice = invoiceService.lambdaQuery().eq(Invoice::getApplyId, applyId).one();
-                DynamicDataSourceContextHolder.poll();
-
-                if (invoice == null) {
-                    log.warn("补插卡包: 找不到发票记录, applyId:{}", applyId);
-                    continue;
-                }
-
-                var result = huapiaoerInvoiceService.queryInvoiceResult(applyId, InvoiceQueryType.BLUE.getCode());
-                huapiaoerInvoiceService.insertToCardPackage(invoice, result);
-            } catch (Exception e) {
-                log.error("补插卡包失败, applyId:{}", applyId, e);
-                DynamicDataSourceContextHolder.poll();
-            }
-        }
-    }
-
 }

+ 2 - 2
admin/src/main/resources/application-prod.yml

@@ -92,7 +92,7 @@ spring:
   data:
     redis:
       port: 6379
-      host: 127.0.0.1
+      host: 121.40.98.15
       password: OPYCJ3mJpaU4IsP7ZeIyaus6FtHjLYmhNDGteuRc1gIFCAm7wi
       database: 10
       lettuce:
@@ -108,7 +108,7 @@ spring:
       # 缓存过期时间:7天
       time-to-live: 604800
   rabbitmq:
-    host: 127.0.0.1
+    host: 121.40.98.15
     port: 5680
     username: kym
     password: vMRbZPfunLX8kDwfyy737y1Ahzfgr5ib

+ 10 - 2
admin/src/test/java/TestCase.java

@@ -11,8 +11,16 @@ public class TestCase {
     @Test
     public void test1() {
         Digester MD5 = new Digester(DigestAlgorithm.MD5);
-        String mobile = "15071072750";
-        String password = "1234";
+        String mobile = "15012630633";
+        String password = "abc123";
+        String s = MD5.digestHex(password.concat(MD5.digestHex(mobile).substring(0, 5)));
+        System.out.println(s);
+    }
+
+    public static void main(String[] args) {
+        Digester MD5 = new Digester(DigestAlgorithm.MD5);
+        String mobile = "15012630633";
+        String password = "abc123";
         String s = MD5.digestHex(password.concat(MD5.digestHex(mobile).substring(0, 5)));
         System.out.println(s);
     }

+ 3 - 2
charge-front/src/utils/constant.ts

@@ -12,7 +12,8 @@ console.log("env", env);
 isDevelopment = env === "develop" || env === "trial";
 // #endif
 
-export const domain = isDevelopment ? "localhost:8088" : "www.kuaiyuman.cn";
-export const host = `http://${domain}/api`;
+// export const domain = isDevelopment ? "localhost:8088" : "www.kuaiyuman.cn";
+export const domain = isDevelopment ? "dev.kuaiyuman.cn" : "www.kuaiyuman.cn";
+export const host = `https://${domain}/api`;
 
 export const isDebug = false

+ 3 - 1
database/1.sql

@@ -50,6 +50,8 @@ values
     ( 'Refund.status', '退款成功 ', 1, 'SUCCESS', null, '2023-10-29 21:51:47', '2023-10-29 21:51:47'),
     ( 'Refund.status', '退款关闭 ', 1, 'CLOSED', null, '2023-10-29 21:51:47', '2023-10-29 21:51:47'),
     ( 'Refund.status', '退款处理中 ', 1, 'PROCESSING', null, '2023-10-29 21:51:47', '2023-10-29 21:51:47'),
-    ( 'Refund.status', '退款异常 ', 1, 'ABNORMAL', null, '2023-10-29 21:51:47', '2023-10-29 21:51:47')
+    ( 'Refund.status', '退款异常 ', 1, 'ABNORMAL', null, '2023-10-29 21:51:47', '2023-10-29 21:51:47'),
+    ( 'Refund.status', '新申请 ', 1, 'NEW', null, '2023-10-29 21:51:47', '2023-10-29 21:51:47'),
+    ( 'Refund.status', '挂起 ', 1, 'SUSPENDED', null, '2023-10-29 21:51:47', '2023-10-29 21:51:47')
 
 ;

+ 9 - 0
database/7.sql

@@ -0,0 +1,9 @@
+-- 航信电子发票替换:发票详情增加下载链接字段
+ALTER TABLE charge_admin.t_invoice_detail
+    ADD COLUMN IF NOT EXISTS invoice_url VARCHAR(512) COMMENT '发票PDF下载地址',
+    ADD COLUMN IF NOT EXISTS ofd_url VARCHAR(512) COMMENT '发票OFD下载地址',
+    ADD COLUMN IF NOT EXISTS xml_url VARCHAR(512) COMMENT '发票XML下载地址';
+
+-- 发票抬头管理:增加默认抬头字段
+ALTER TABLE charge_app.t_invoice_title
+    ADD COLUMN IF NOT EXISTS is_default TINYINT(1) DEFAULT 0 COMMENT '是否默认抬头';

+ 132 - 0
docs/开票时序图.md

@@ -0,0 +1,132 @@
+# 开发票操作时序图
+
+```mermaid
+sequenceDiagram
+    actor User as 用户(小程序)
+    actor Admin as 管理员(后台)
+    participant Ctrl as InvoiceController
+    participant Svc as InvoiceServiceImpl
+    participant DB as 数据库
+    participant FinCtrl as FinanceController
+    participant HPSvc as HuapiaoerInvoiceService
+    participant HPClient as HuapiaoerClient
+    participant HPAPI as 航信API(票儿)
+    participant Job as InvoiceStatusJob(定时任务)
+    participant Mail as 邮件服务
+
+    %% ===== 阶段1: 用户申请开票 =====
+    rect rgb(230, 245, 255)
+        Note over User,DB: 阶段1: 用户申请开票
+        User->>Ctrl: POST /invoice/applyInvoice
+        Ctrl->>Svc: applyInvoice(params)
+        Svc->>DB: 查询 ChargeOrder (by orderSn)
+        DB-->>Svc: 返回订单信息
+        alt 订单不存在或已开票
+            Svc-->>Ctrl: 返回错误
+            Ctrl-->>User: 申请失败
+        else 订单有效
+            Svc->>Svc: 计算金额<br/>(payAmount + elecMoney + serviceMoney)
+            Svc->>DB: 创建 Invoice 记录<br/>状态=待开票(0)
+            Svc->>DB: 自动保存 InvoiceTitle(如需要)
+            Svc->>DB: 更新 ChargeOrder.invoiceStatus=开票中(3)
+            Svc-->>Ctrl: 返回 Invoice
+            Ctrl-->>User: 申请成功
+        end
+    end
+
+    %% ===== 阶段2: 管理员开票 =====
+    rect rgb(255, 245, 230)
+        Note over Admin,HPAPI: 阶段2: 管理员开票
+        Admin->>FinCtrl: GET /finance/handleInvoice/{invoiceId}
+        FinCtrl->>DB: 查询 Invoice
+        DB-->>FinCtrl: 返回 Invoice
+        alt 状态不是待开票(0)
+            FinCtrl-->>Admin: 状态异常,无法开票
+        else 状态正常
+            FinCtrl->>DB: 记录开票人(biller)
+            FinCtrl->>HPSvc: openBlueInvoice(invoice)
+            HPSvc->>HPSvc: buildOpenBlueInvoiceRequest()<br/>行项1: 充电电费 @13%<br/>行项2: 充电服务费 @6%
+            HPSvc->>HPClient: openBlueInvoice(request)
+            HPClient->>HPAPI: POST /outopenapis/openBlueInvoice
+            HPAPI-->>HPClient: 返回 {code, data}
+            HPClient-->>HPSvc: OpenInvoiceResponse
+            alt code == "200"
+                HPSvc-->>FinCtrl: 成功
+                FinCtrl->>DB: 更新 Invoice.status=开票中(3)
+                FinCtrl-->>Admin: 开票请求已提交
+            else code != "200"
+                HPSvc-->>FinCtrl: 失败
+                FinCtrl-->>Admin: 开票失败
+            end
+        end
+    end
+
+    %% ===== 阶段3: 定时轮询开票结果 =====
+    rect rgb(230, 255, 230)
+        Note over Job,Mail: 阶段3: 定时轮询开票结果 (每5分钟)
+        loop 每5分钟执行
+            Job->>DB: 查询 status=开票中(3) 的 Invoice
+            DB-->>Job: 返回待查询发票列表
+            loop 每张发票
+                Job->>HPSvc: queryInvoiceResult(applyId, 1)
+                HPSvc->>HPClient: getInvoice(orderId, invoiceType)
+                HPClient->>HPAPI: POST /outopenapis/getInvoice
+                HPAPI-->>HPClient: 返回发票信息<br/>(发票代码/号码/PDF/OFD/XML)
+                HPClient-->>HPSvc: InvoiceInfo
+                alt 开票成功
+                    HPSvc->>DB: 写入 InvoiceDetail<br/>(发票代码/号码/下载URL等)
+                    HPSvc-->>Job: 返回发票详情
+                    Job->>DB: 更新 ChargeOrder.invoiceStatus=已开票(1)
+                    Job->>DB: 更新 Invoice.status=已开票(1)
+                    opt 用户填写了邮箱
+                        Job->>HPSvc: sendInvoiceEmail(orderId, email)
+                        HPSvc->>HPClient: sendMail(orderId, invoiceType, email)
+                        HPClient->>HPAPI: POST /outopenapis/sendMail
+                        HPAPI-->>HPClient: 发送结果
+                    end
+                else 开票处理中
+                    HPSvc-->>Job: 仍在处理,等待下次轮询
+                else 开票失败
+                    HPSvc-->>Job: 开票失败
+                    Note over Job: 保持原状态,等待人工处理
+                end
+            end
+        end
+    end
+
+    %% ===== 阶段4: 手动确认开票(备用) =====
+    rect rgb(255, 230, 230)
+        Note over Admin,DB: 阶段4: 手动确认开票 (备用路径)
+        Admin->>FinCtrl: POST /finance/confirmManualInvoice/{id}
+        FinCtrl->>Svc: confirmManualInvoice(invoiceId)
+        Svc->>DB: 查询 Invoice
+        alt 状态为开票中(3) 或 待开票(0)
+            Svc->>DB: 更新 ChargeOrder.invoiceStatus=已开票(1)
+            Svc->>DB: 更新 Invoice.status=已开票(1)
+            Svc->>DB: 创建 InvoiceDetail(status=ISSUED)
+            Svc-->>FinCtrl: 确认成功
+            FinCtrl-->>Admin: 手动确认完成
+        else 状态不符
+            Svc-->>FinCtrl: 状态异常
+            FinCtrl-->>Admin: 操作失败
+        end
+    end
+
+    %% ===== 阶段5: 用户下载发票 =====
+    rect rgb(245, 230, 255)
+        Note over User,DB: 阶段5: 用户查看/下载发票
+        User->>Ctrl: GET /invoice/list?status=1
+        Ctrl->>Svc: listInvoiceForApp(userId, status)
+        Svc->>DB: 查询 Invoice 列表
+        DB-->>Svc: 返回已开票列表
+        Svc-->>Ctrl: 返回发票列表
+        Ctrl-->>User: 展示发票列表
+
+        Admin->>FinCtrl: GET /finance/downloadInvoice/{id}
+        FinCtrl->>DB: 查询 InvoiceDetail
+        DB-->>FinCtrl: 返回详情(含PDF/OFD/XML URL)
+        FinCtrl->>HPSvc: getInvoiceDownloadUrls(id, detail)
+        HPSvc-->>FinCtrl: 返回下载URL
+        FinCtrl-->>Admin: 返回下载链接
+    end
+```

+ 35 - 37
miniapp/src/main/java/com/kym/miniapp/controller/TestController.java

@@ -1,20 +1,19 @@
 package com.kym.miniapp.controller;
 
 import com.kym.common.R;
+import com.kym.common.utils.wx.WxPbUtil;
 import com.kym.entity.miniapp.UserCoupon;
-import com.kym.service.miniapp.MpRelationService;
-import com.kym.service.miniapp.UserService;
 import com.kym.service.mq.producer.UserCouponSender;
-import com.kym.service.wechat.WeixinMPService;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
-import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
+import me.chanjar.weixin.mp.bean.result.WxMpUser;
+import me.chanjar.weixin.mp.bean.result.WxMpUserList;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
 
 
 @RestController
@@ -26,18 +25,10 @@ public class TestController {
 
     private final WxMpService wxMpService;
 
-    private final UserService userService;
-    private final MpRelationService mpRelationService;
-
-    private final WeixinMPService weixinMPService;
-
-    public TestController(UserCouponSender userCouponSender, WxMpService wxMpService, UserService userService, MpRelationService mpRelationService, WeixinMPService weixinMPService) {
+    public TestController(UserCouponSender userCouponSender, WxMpService wxMpService) {
 
         this.userCouponSender = userCouponSender;
         this.wxMpService = wxMpService;
-        this.userService = userService;
-        this.mpRelationService = mpRelationService;
-        this.weixinMPService = weixinMPService;
     }
 
     /**
@@ -54,41 +45,48 @@ public class TestController {
         return R.success();
     }
 
-    @GetMapping(value = "/test1")
-    R<?> test1() throws WxErrorException {
-        mpRelationService.batchBindMpUser();
-        return R.success();
-    }
-
     /**
      * 测试公众号消息
      *
      * @return
      */
     @GetMapping(value = "/test2")
-    R<?> test2() throws WxErrorException {
+    R<?> test2() {
         // 通过unionid获取公众号openid
-        WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()
-                .toUser("ox6fm6KbWb8Y8q0-xFs3kPREaPm8")
-                .templateId("SjszYYiHcN-GaEeZTKJsCcB6ACxYJWfTddkSywf1q1g")
-                .url("")
-                .build();
-
-        templateMessage.addData(new WxMpTemplateData("character_string2", "3820221130166989945749995"));
-        templateMessage.addData(new WxMpTemplateData("thing9", "测试站点"));
-        templateMessage.addData(new WxMpTemplateData("character_string3", "SN0001"));
-        templateMessage.addData(new WxMpTemplateData("time4", "2022-12-01 19:30:00"));
-
-        wxMpService.getTemplateMsgService().sendTemplateMsg(templateMessage);
 
+        var params = Map.of(
+                "character_string2.DATA", "order111222333",
+                "thing9.DATA", "测试站点",
+                "character_string3.DATA", "SN0001",
+                "time4.DATA", "2024-07-29 12:00:00"
+        );
+        WxPbUtil.sendPublicTemplateMessage("", "SjszYYiHcN-GaEeZTKJsCcB6ACxYJWfTddkSywf1q1g", params, "", "");
         return R.success();
     }
 
+    /**
+     * 测试拉取公众号关注者列表
+     * @return
+     */
     @GetMapping(value = "/test3")
     R<?> test3() throws WxErrorException {
-        var dateList = List.of("3820221130166989945749995", "测试站点", "SN0001", "2022-12-01 19:30:00");
-        weixinMPService.sendMPTemplateMessage("ox6fm6KbWb8Y8q0-xFs3kPREaPm8", "充电开始通知", dateList);
-        return R.success();
+        // 获取公众号所有关注者列表
+        WxMpUserList wxUserList = wxMpService.getUserService().userList();
+        // 通过unionid获取公众号openid
+        String lang = "zh_CN";
+        var unionid2openid = new HashMap<>();
+        wxUserList.getOpenids().forEach(openid -> {
+            try {
+                WxMpUser mpUser = wxMpService.getUserService().userInfo(openid,lang);
+                unionid2openid.put(mpUser.getUnionId(),openid);
+            } catch (WxErrorException e) {
+                throw new RuntimeException(e);
+            }
+        });
+
+
+        return R.success(wxUserList);
     }
 
+
 }

+ 1 - 1
miniapp/src/main/resources/application-dev.yml

@@ -111,7 +111,7 @@ spring:
     password: kym!@123
     virtual-host: /dev
     publisher-returns: true
-    publisher-confirms: true
+    publisher-confirm-type: correlated
     listener:
       simple:
         acknowledge-mode: manual

+ 4 - 4
miniapp/src/main/resources/application-prod.yml

@@ -73,19 +73,19 @@ spring:
       strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
       datasource:
         db-admin:
-          url: jdbc:mysql://127.0.0.1:3306/charge_admin?serverTimezone=Asia/Shanghai
+          url: jdbc:mysql://121.40.98.15:3306/charge_admin?serverTimezone=Asia/Shanghai
           username: kym
           password: qYhQLZLP6e7paVmQN5foEwRYJ1yFNpwM
           driver-class-name: com.mysql.cj.jdbc.Driver
         db-miniapp:
-          url: jdbc:mysql://127.0.0.1:3306/charge_app?serverTimezone=Asia/Shanghai
+          url: jdbc:mysql://121.40.98.15:3306/charge_app?serverTimezone=Asia/Shanghai
           username: kym
           password: qYhQLZLP6e7paVmQN5foEwRYJ1yFNpwM
           driver-class-name: com.mysql.cj.jdbc.Driver
   data:
     redis:
       port: 6379
-      host: 127.0.0.1
+      host: 121.40.98.15
       password: OPYCJ3mJpaU4IsP7ZeIyaus6FtHjLYmhNDGteuRc1gIFCAm7wi
       database: 10
       lettuce:
@@ -101,7 +101,7 @@ spring:
       # 缓存过期时间:7天
       time-to-live: 604800
   rabbitmq:
-    host: 127.0.0.1
+    host: 121.40.98.15
     port: 5680
     username: kym
     password: vMRbZPfunLX8kDwfyy737y1Ahzfgr5ib

+ 0 - 51
service/src/main/java/com/kym/service/miniapp/HuapiaoerInvoiceService.java

@@ -20,7 +20,6 @@ import com.kym.huapiaoer.model.request.OpenBlueInvoiceRequest;
 import com.kym.huapiaoer.model.response.InvoiceInfo;
 import com.kym.huapiaoer.model.response.OpenInvoiceResponse;
 import com.kym.service.admin.InvoiceDetailService;
-import com.kym.service.wechat.impl.WechatPayFapiaoService;
 import jakarta.annotation.PostConstruct;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -39,7 +38,6 @@ public class HuapiaoerInvoiceService {
 
     private final HuapiaoerProperties properties;
     private final InvoiceDetailService invoiceDetailService;
-    private final WechatPayFapiaoService wechatPayFapiaoService;
 
     private HuapiaoerClient client;
     private volatile String issuerId;
@@ -110,55 +108,6 @@ public class HuapiaoerInvoiceService {
         }
     }
 
-    /**
-     * 将已开具的电子发票插入用户微信卡包(通过微信支付 v3 API)。
-     * 先检查是否已有卡包记录,避免重复插入。
-     */
-    public void insertToCardPackage(Invoice invoice, InvoiceInfo result) {
-        if (invoice.getOpenid() == null || invoice.getOpenid().isBlank()) {
-            log.info("用户无 openid,跳过卡包插入, applyId:{}", invoice.getApplyId());
-            return;
-        }
-
-        try {
-            DynamicDataSourceContextHolder.push("db-admin");
-            var detail = invoiceDetailService.lambdaQuery()
-                    .eq(InvoiceDetail::getApplyId, invoice.getApplyId()).one();
-            DynamicDataSourceContextHolder.poll();
-
-            if (detail != null && detail.getCardInformation() != null) {
-                log.info("卡包已插入过,跳过, applyId:{}", invoice.getApplyId());
-                return;
-            }
-        } catch (Exception e) {
-            DynamicDataSourceContextHolder.poll();
-            log.error("查询卡包记录异常, applyId:{}", invoice.getApplyId(), e);
-            return;
-        }
-
-        boolean success = wechatPayFapiaoService.insertToCard(invoice, result);
-
-        if (success) {
-            try {
-                DynamicDataSourceContextHolder.push("db-admin");
-                var cardInfo = new FapiaoApplications.CardInfo();
-                cardInfo.setCard_appid("wx93b0ef1be901bd19");
-                cardInfo.setCard_openid(invoice.getOpenid());
-                cardInfo.setCard_status("INSERT_ACCEPTED");
-
-                invoiceDetailService.lambdaUpdate()
-                        .set(InvoiceDetail::getCardInformation, cardInfo)
-                        .eq(InvoiceDetail::getApplyId, invoice.getApplyId())
-                        .update();
-                log.info("卡包插入请求已提交, applyId:{}", invoice.getApplyId());
-            } finally {
-                DynamicDataSourceContextHolder.poll();
-            }
-        } else {
-            log.warn("卡包插入失败, applyId:{}", invoice.getApplyId());
-        }
-    }
-
     /**
      * 根据航信查询结果更新开票详情
      */

+ 0 - 257
service/src/main/java/com/kym/service/wechat/impl/WechatPayFapiaoService.java

@@ -1,257 +0,0 @@
-package com.kym.service.wechat.impl;
-
-import com.alibaba.fastjson2.JSON;
-import com.alibaba.fastjson2.JSONObject;
-import com.kym.entity.miniapp.Invoice;
-import com.kym.entity.wechat.InvoiceOrderDetail;
-import com.kym.huapiaoer.model.response.InvoiceInfo;
-import com.wechat.pay.java.core.http.*;
-import lombok.extern.slf4j.Slf4j;
-import okhttp3.*;
-import org.springframework.stereotype.Service;
-
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * 通过微信支付 v3 电子发票 API 将航信发票插入用户微信卡包。
- * 三步流程:创建申请单 → 上传PDF → 插入卡包
- */
-@Service
-@Slf4j
-public class WechatPayFapiaoService {
-
-    private static final String API_BASE = "https://api.mch.weixin.qq.com";
-    private static final String CREATE_APP = "/v3/new-tax-control-fapiao/fapiao-applications";
-    private static final String UPLOAD_FILE = "/v3/new-tax-control-fapiao/fapiao-applications/%s/fapiao-files";
-    private static final String INSERT_CARDS = "/v3/new-tax-control-fapiao/fapiao-applications/%s/insert-cards";
-    private static final String MCH_SERIAL = "6A45EEB068369430B2FFD45EA29F641A8E18165F";
-
-    private static final HttpHeaders JSON_HEADERS;
-
-    static {
-        JSON_HEADERS = new HttpHeaders();
-        JSON_HEADERS.addHeader("Accept", "application/json");
-        JSON_HEADERS.addHeader("Content-Type", "application/json");
-    }
-
-    private final OkHttpClient okHttpClient = new OkHttpClient.Builder()
-            .connectTimeout(15, TimeUnit.SECONDS).readTimeout(30, TimeUnit.SECONDS).build();
-
-    public boolean insertToCard(Invoice invoice, InvoiceInfo invoiceInfo) {
-        if (invoice.getOpenid() == null || invoice.getOpenid().isBlank()) {
-            log.info("用户无 openid,跳过卡包插入, applyId:{}", invoice.getApplyId());
-            return false;
-        }
-        try {
-            // Step 1: 创建发票申请单
-            var appReq = buildCreateAppRequest(invoice, invoiceInfo);
-            log.info("创建发票申请单, applyId:{}, body:{}", invoice.getApplyId(), JSON.toJSONString(appReq));
-
-            HttpResponse<JSONObject> appResp = WxPayServiceImpl.wxHttpClient.post(
-                    JSON_HEADERS, API_BASE + CREATE_APP,
-                    new JsonRequestBody.Builder().body(JSON.toJSONString(appReq)).build(),
-                    JSONObject.class);
-            log.info("创建申请单响应, applyId:{}, resp:{}",
-                    invoice.getApplyId(), JSON.toJSONString(appResp.getServiceResponse()));
-
-            // Step 2: 下载航信PDF并上传到微信支付
-            byte[] pdfBytes = downloadPdf(invoiceInfo.getInvoiceurl());
-            if (pdfBytes == null || pdfBytes.length == 0) {
-                log.warn("下载航信 PDF 失败, applyId:{}", invoice.getApplyId());
-                return false;
-            }
-            String mediaId = uploadFile(invoice.getApplyId(), pdfBytes);
-            if (mediaId == null) {
-                log.warn("上传发票文件失败, applyId:{}", invoice.getApplyId());
-                return false;
-            }
-
-            // Step 3: 插入卡包
-            var cardReq = buildInsertCardsRequest(invoice, invoiceInfo, mediaId);
-            String cardUrl = API_BASE + String.format(INSERT_CARDS, invoice.getApplyId());
-            log.info("插入发票卡包, applyId:{}, body:{}", invoice.getApplyId(), JSON.toJSONString(cardReq));
-
-            HttpResponse<JSONObject> cardResp = WxPayServiceImpl.wxHttpClient.post(
-                    JSON_HEADERS, cardUrl,
-                    new JsonRequestBody.Builder().body(JSON.toJSONString(cardReq)).build(),
-                    JSONObject.class);
-            log.info("插入卡包响应, applyId:{}, resp:{}",
-                    invoice.getApplyId(), JSON.toJSONString(cardResp.getServiceResponse()));
-            return true;
-        } catch (Exception e) {
-            log.error("微信卡包插入异常, applyId:{}, msg:{}", invoice.getApplyId(), e.getMessage());
-            return false;
-        }
-    }
-
-    // ========== Step 1: 创建申请单 ==========
-
-    private HashMap<String, Object> buildCreateAppRequest(Invoice invoice, InvoiceInfo info) {
-        var orderDetails = invoice.getOrderDetails();
-        int elecMoney = orderDetails.stream().mapToInt(InvoiceOrderDetail::getElecMoney).sum();
-        int serviceMoney = orderDetails.stream().mapToInt(InvoiceOrderDetail::getServiceMoney).sum();
-        int discount = orderDetails.stream().mapToInt(InvoiceOrderDetail::getServiceMoneyDiscount).sum();
-        int netServiceMoney = serviceMoney - discount;
-
-        var items = new ArrayList<HashMap<String, Object>>();
-        int totalAmount = 0;
-        if (elecMoney > 0) { items.add(buildAppItem("充电电费", elecMoney, "1100101020200000000", 1300)); totalAmount += elecMoney; }
-        if (netServiceMoney > 0) { items.add(buildAppItem("充电服务费", netServiceMoney, "1100101020200000000", 1300)); totalAmount += netServiceMoney; }
-
-        var fapiaoInfo = new HashMap<String, Object>();
-        fapiaoInfo.put("fapiao_id", invoice.getApplyId());
-        fapiaoInfo.put("total_amount", totalAmount);
-        fapiaoInfo.put("fapiao_bill_type", "COMM_FAPIAO");
-        fapiaoInfo.put("billing_person_id", "2061377495014797313");
-        fapiaoInfo.put("billing_person", "*磊 2417");
-        fapiaoInfo.put("items", items);
-        if (invoice.getRemark() != null && !invoice.getRemark().isBlank()) {
-            fapiaoInfo.put("remark", invoice.getRemark());
-        }
-
-        var buyerInfo = new HashMap<String, Object>();
-        buyerInfo.put("type", invoice.getInvoiceType());
-        buyerInfo.put("name", invoice.getInvoiceTitle());
-        if (invoice.getTaxId() != null && !invoice.getTaxId().isBlank()) {
-            buyerInfo.put("taxpayer_id", invoice.getTaxId());
-        }
-
-        var req = new HashMap<String, Object>();
-        req.put("fapiao_apply_id", invoice.getApplyId());
-        req.put("scene", "WITHOUT_WECHATPAY");
-        req.put("buyer_information", buyerInfo);
-        req.put("fapiao_information", List.of(fapiaoInfo));
-
-        return req;
-    }
-
-    private HashMap<String, Object> buildAppItem(String name, int totalAmount, String taxCode, int taxRate) {
-        var item = new HashMap<String, Object>();
-        item.put("tax_code", taxCode);
-        item.put("goods_name", name);
-        item.put("quantity", 100000000);
-        item.put("total_amount", totalAmount);
-        item.put("tax_rate", taxRate);
-        item.put("discount", false);
-        item.put("preferential_policy_code", 1);
-        return item;
-    }
-
-    // ========== Step 2: 下载PDF & 上传文件 ==========
-
-    private byte[] downloadPdf(String url) {
-        try {
-            var req = new Request.Builder().url(url).get().build();
-            try (var resp = okHttpClient.newCall(req).execute()) {
-                if (resp.isSuccessful() && resp.body() != null) return resp.body().bytes();
-            }
-        } catch (Exception e) { log.error("下载 PDF 异常, url:{}", url, e); }
-        return null;
-    }
-
-    private String uploadFile(String applyId, byte[] pdfBytes) throws Exception {
-        String meta = JSON.toJSONString(Map.of(
-                "file_type", "FAPIAO_PDF",
-                "fapiao_apply_id", applyId
-        ));
-
-        String boundary = "WxPayUp" + System.currentTimeMillis();
-        okhttp3.RequestBody multipartBody = new MultipartBody.Builder(boundary)
-                .setType(MultipartBody.FORM)
-                .addFormDataPart("meta", null,
-                        okhttp3.RequestBody.create(meta, okhttp3.MediaType.parse("application/json")))
-                .addFormDataPart("file", "invoice.pdf",
-                        okhttp3.RequestBody.create(pdfBytes, okhttp3.MediaType.parse("application/pdf")))
-                .build();
-
-        String url = API_BASE + String.format(UPLOAD_FILE, applyId);
-        String auth = WxPayServiceImpl.config.createCredential()
-                .getAuthorization(new java.net.URI(url), "POST", meta);
-
-        okhttp3.Request request = new Request.Builder()
-                .url(url).header("Authorization", auth)
-                .header("Accept", "application/json")
-                .header("Wechatpay-Serial", MCH_SERIAL)
-                .post(multipartBody).build();
-
-        try (okhttp3.Response resp = okHttpClient.newCall(request).execute()) {
-            if (resp.isSuccessful() && resp.body() != null) {
-                JSONObject json = JSONObject.parseObject(resp.body().string());
-                String mediaId = json.getString("fapiao_media_id");
-                log.info("上传发票文件成功, applyId:{}, mediaId:{}", applyId, mediaId);
-                return mediaId;
-            }
-            String err = resp.body() != null ? resp.body().string() : "";
-            log.error("上传文件失败, applyId:{}, HTTP:{}, body:{}", applyId, resp.code(), err);
-        }
-        return null;
-    }
-
-    // ========== Step 3: 插入卡包 ==========
-
-    private HashMap<String, Object> buildInsertCardsRequest(Invoice invoice, InvoiceInfo info, String mediaId) {
-        var orderDetails = invoice.getOrderDetails();
-        int elecMoney = orderDetails.stream().mapToInt(InvoiceOrderDetail::getElecMoney).sum();
-        int serviceMoney = orderDetails.stream().mapToInt(InvoiceOrderDetail::getServiceMoney).sum();
-        int discount = orderDetails.stream().mapToInt(InvoiceOrderDetail::getServiceMoneyDiscount).sum();
-        int netServiceMoney = serviceMoney - discount;
-
-        var items = new ArrayList<HashMap<String, Object>>();
-        int totalAmount = 0;
-        int totalTax = 0;
-        if (elecMoney > 0) { int tax = elecMoney - (int)Math.round(elecMoney/1.13); items.add(buildItem("充电电费", elecMoney, "1100101020200000000", 1300)); totalAmount += elecMoney; totalTax += tax; }
-        if (netServiceMoney > 0) { int tax = netServiceMoney - (int)Math.round(netServiceMoney/1.13); items.add(buildItem("充电服务费", netServiceMoney, "1100101020200000000", 1300)); totalAmount += netServiceMoney; totalTax += tax; }
-
-        String ticketDate = info.getTicketDate();
-        if (ticketDate != null && ticketDate.length() == 16) ticketDate += ":00";
-        String fapiaoTime = ticketDate != null
-                ? LocalDateTime.parse(ticketDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
-                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss+08:00"))
-                : LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss+08:00"));
-
-        var sellerInfo = new HashMap<String, Object>();
-        sellerInfo.put("name", "深圳市快与慢科技有限公司");
-        sellerInfo.put("taxpayer_id", "91440300MA5HJNDG14");
-
-        var cardInfo = new HashMap<String, Object>();
-        cardInfo.put("fapiao_media_id", mediaId);
-        cardInfo.put("fapiao_number", info.getInvoicenumber());
-        cardInfo.put("fapiao_code", info.getInvoicecode() != null ? info.getInvoicecode() : "");
-        cardInfo.put("fapiao_time", fapiaoTime);
-        cardInfo.put("total_amount", totalAmount);
-        cardInfo.put("tax_amount", totalTax);
-        cardInfo.put("amount", totalAmount - totalTax);
-        cardInfo.put("seller_information", sellerInfo);
-        cardInfo.put("extra_information", new HashMap<>());
-        cardInfo.put("items", items);
-        if (invoice.getRemark() != null && !invoice.getRemark().isBlank()) cardInfo.put("remark", invoice.getRemark());
-
-        var buyerInfo = new HashMap<String, Object>();
-        buyerInfo.put("type", invoice.getInvoiceType());
-        buyerInfo.put("name", invoice.getInvoiceTitle());
-        if (invoice.getTaxId() != null && !invoice.getTaxId().isBlank()) buyerInfo.put("taxpayer_id", invoice.getTaxId());
-
-        var req = new HashMap<String, Object>();
-        req.put("scene", "WITHOUT_WECHATPAY");
-        req.put("buyer_information", buyerInfo);
-        req.put("fapiao_card_information", List.of(cardInfo));
-        return req;
-    }
-
-    private HashMap<String, Object> buildItem(String name, int totalAmount, String taxCode, int taxRate) {
-        var item = new HashMap<String, Object>();
-        item.put("tax_code", taxCode);
-        item.put("goods_name", name);
-        item.put("quantity", 100000000);
-        item.put("total_amount", totalAmount);
-        item.put("tax_rate", taxRate);
-        item.put("discount", false);
-        return item;
-    }
-}

+ 1 - 1
service/src/main/java/com/kym/service/wechat/impl/WxPayServiceImpl.java

@@ -81,7 +81,7 @@ public class WxPayServiceImpl implements WxPayService {
 
     public static Config config;
 
-    public static OkHttpClientAdapter wxHttpClient;
+    private OkHttpClientAdapter wxHttpClient;
 
     private final WxPayConfig conf;