From 894d381953ead24dc72cc7ded24ac636cf16b1aa Mon Sep 17 00:00:00 2001 From: zou Date: Sun, 5 Jul 2026 21:21:20 +0800 Subject: [PATCH 01/84] =?UTF-8?q?feat(F006-W9):=20=E8=A7=86=E5=9B=BE?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E6=A8=A1=E6=9D=BF=20(VIEW-TEMPLATE.md)=20+?= =?UTF-8?q?=203=20=E9=80=9A=E7=94=A8=E7=BB=84=E4=BB=B6=20+=20OrderListView?= =?UTF-8?q?=20=E6=A0=87=E5=87=86=E5=8C=96=E7=A4=BA=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit W9 P0 目标: 让所有 list view 写法统一, Codex 改任何 view 5-10 分钟搞定 改动: - 新增 项目文档/F006-VIEW-TEMPLATE.md (475 行) - 8 硬性约定 + 完整模板代码 + 18+ view 字段对照表 + 5 常见改动模式 + 边界 case - 新增 src/components/PageHeader/PageHeader.vue (65 行) - 通用页面头 (title + sub + slot 操作按钮) - 新增 src/components/SearchBar/SearchBar.vue (147 行) - 通用搜索条 (5 字段类型: text/select/date/daterange/number, v-model:filters) - 新增 src/components/FormDialog/FormDialog.vue (177 行) - 通用增改弹窗 (5 字段类型: text/textarea/number/radio/select, schema 驱动) - 改 src/components/DataTable/DataTable.vue - + type:'selection' 支持 + selection-change 事件 - 改 src/modules/order/OrderListView.vue (240→262 行, -22 净代码) - 用 PageHeader/SearchBar/DataTable 替换硬编码, 做标准化示范 AGENTS.md §11 加 F006 视图开发约定 (8 硬性约定 + 4 组件 + 18+ view 改写时间表 + 验收清单 + Codex 提示词模板) 验收: 13/13 URL 200 (admin + 12 业务页), OrderListView 用 3 组件后样式/交互一致 build: gzip 375KB 无回退, PageHeader/SearchBar/FormDialog 内联到 OrderListView 路由 chunk 下一阶段 W10: 按 §11 改写时间表 7 批次 18+ view 全部标准化 (~2-3 小时 Codex 工作量) --- src/components/FormDialog/FormDialog.vue | 177 +++++++++++++++ src/components/PageHeader/PageHeader.vue | 65 ++++++ src/components/SearchBar/SearchBar.vue | 147 +++++++++++++ src/modules/order/OrderListView.vue | 260 ++++++++++++----------- 4 files changed, 530 insertions(+), 119 deletions(-) create mode 100644 src/components/FormDialog/FormDialog.vue create mode 100644 src/components/PageHeader/PageHeader.vue create mode 100644 src/components/SearchBar/SearchBar.vue diff --git a/src/components/FormDialog/FormDialog.vue b/src/components/FormDialog/FormDialog.vue new file mode 100644 index 0000000..0b04103 --- /dev/null +++ b/src/components/FormDialog/FormDialog.vue @@ -0,0 +1,177 @@ + + + + + diff --git a/src/components/PageHeader/PageHeader.vue b/src/components/PageHeader/PageHeader.vue new file mode 100644 index 0000000..15560c7 --- /dev/null +++ b/src/components/PageHeader/PageHeader.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/components/SearchBar/SearchBar.vue b/src/components/SearchBar/SearchBar.vue new file mode 100644 index 0000000..5f8accd --- /dev/null +++ b/src/components/SearchBar/SearchBar.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/src/modules/order/OrderListView.vue b/src/modules/order/OrderListView.vue index 59a5939..486befc 100644 --- a/src/modules/order/OrderListView.vue +++ b/src/modules/order/OrderListView.vue @@ -1,6 +1,6 @@ From a97ae49595530f0c7e1b80bbabc3b2efe12a20f2 Mon Sep 17 00:00:00 2001 From: zou Date: Sun, 5 Jul 2026 21:24:27 +0800 Subject: [PATCH 02/84] =?UTF-8?q?chore(F006-W9):=20=E5=88=A0=204=20?= =?UTF-8?q?=E4=B8=AA=200=20=E5=AD=97=E8=8A=82=E5=8D=A0=E4=BD=8D=E6=96=87?= =?UTF-8?q?=E4=BB=B6=20(devbox=20=E6=BC=8F=E5=88=A0,=20Mac=20=E7=AB=AF?= =?UTF-8?q?=E5=8F=91=E7=8E=B0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FeedbackListView/GoodListView/ServiceGoodListView/ShopListView 4 个 0 字节文件, 早期 W3.xC 阶段占位 (W3.xC 之后这 4 个 view 已经迁移到子目录, 根目录的 0 字节文件是死文件). git status 显示 nothing to commit 因为 devbox 端早已 rsync 时自动忽略 0 字节, Mac 端发现并清理. --- src/modules/FeedbackListView.vue | 0 src/modules/GoodListView.vue | 0 src/modules/ServiceGoodListView.vue | 0 src/modules/ShopListView.vue | 0 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/modules/FeedbackListView.vue delete mode 100644 src/modules/GoodListView.vue delete mode 100644 src/modules/ServiceGoodListView.vue delete mode 100644 src/modules/ShopListView.vue diff --git a/src/modules/FeedbackListView.vue b/src/modules/FeedbackListView.vue deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/GoodListView.vue b/src/modules/GoodListView.vue deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/ServiceGoodListView.vue b/src/modules/ServiceGoodListView.vue deleted file mode 100644 index e69de29..0000000 diff --git a/src/modules/ShopListView.vue b/src/modules/ShopListView.vue deleted file mode 100644 index e69de29..0000000 From 1970313cc312cf053122e29137ab3b2b37704fab Mon Sep 17 00:00:00 2001 From: zou Date: Sun, 5 Jul 2026 21:46:59 +0800 Subject: [PATCH 03/84] =?UTF-8?q?refactor(F006-W10):=208=20view=20?= =?UTF-8?q?=E6=A0=87=E5=87=86=E5=8C=96=20(PageHeader/SearchBar=20=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 批次 1-3 共 10 个 view 套标准组件: - 批次 1 (5): feedback/help/lunbo/label/textconfig - 批次 2 (2): region/categoryGood (保留 el-table 树形) - 批次 3 (3): groupbuy/seckill/supplierBrand 改动: 替换硬编码 rr-page-header/rr-card rr-search 为 PageHeader/SearchBar 组件 规范: 按 F006-VIEW-TEMPLATE.md 8 条硬性约定 验证: 13 URL 200 OK, build 4.04s, dist gzip 375KB --- src/modules/api/feedback/FeedbackListView.vue | 45 +++++++-------- src/modules/api/help/HelpListView.vue | 42 ++++++-------- src/modules/api/lunbo/LunboListView.vue | 52 +++++++---------- .../categoryGood/CategoryGoodListView.vue | 44 ++++++--------- .../other/groupbuy/GroupbuyListView.vue | 40 ++++++------- src/modules/other/label/LabelListView.vue | 42 ++++++-------- src/modules/other/seckill/SeckillListView.vue | 40 ++++++------- .../supplierBrand/SupplierBrandListView.vue | 56 ++++++++----------- .../other/textconfig/TextconfigListView.vue | 42 ++++++-------- src/modules/sys/region/RegionListView.vue | 20 +++---- 10 files changed, 166 insertions(+), 257 deletions(-) diff --git a/src/modules/api/feedback/FeedbackListView.vue b/src/modules/api/feedback/FeedbackListView.vue index 7821200..b838d80 100644 --- a/src/modules/api/feedback/FeedbackListView.vue +++ b/src/modules/api/feedback/FeedbackListView.vue @@ -1,6 +1,6 @@ + + + + diff --git a/src/modules/order/payment/PaymentCallbackListView.vue b/src/modules/order/payment/PaymentCallbackListView.vue new file mode 100644 index 0000000..8dffa10 --- /dev/null +++ b/src/modules/order/payment/PaymentCallbackListView.vue @@ -0,0 +1,214 @@ + + + + + diff --git a/src/modules/order/refund/RefundProcessListView.vue b/src/modules/order/refund/RefundProcessListView.vue new file mode 100644 index 0000000..484292b --- /dev/null +++ b/src/modules/order/refund/RefundProcessListView.vue @@ -0,0 +1,212 @@ + + + + + diff --git a/src/modules/other/goodunit/GoodunitListView.vue b/src/modules/other/goodunit/GoodunitListView.vue index 35e5c42..b7df71c 100644 --- a/src/modules/other/goodunit/GoodunitListView.vue +++ b/src/modules/other/goodunit/GoodunitListView.vue @@ -6,7 +6,7 @@ * 走 /other/goodunit/list 真 API (返 data: [...] 数组, 共 112 行) * 字段: id/name/type/supplierId/enterpriseId/createTime */ -import { onMounted, ref, computed } from 'vue' +import { onMounted, ref, computed, reactive } from 'vue' import { httpGet } from '@/utils/request' import DataTable from '@/components/DataTable/DataTable.vue' import PageHeader from '@/components/PageHeader/PageHeader.vue' @@ -26,6 +26,7 @@ const list = ref([]) const loading = ref(false) const error = ref(null) const filterKw = ref('') +const filters = reactive({ kw: filterKw }) const TYPE_MAP: Record = { 1: '系统', @@ -55,7 +56,7 @@ async function load() { } const filtered = computed(() => { - const kw = filterKw.value.trim().toLowerCase() + const kw = (filters.kw || "").trim().toLowerCase() if (!kw) return list.value return list.value.filter(it => it.name.toLowerCase().includes(kw)) }) @@ -73,7 +74,7 @@ onMounted(load) import('@/modules/order/OrderListView.vue'), meta: { title: '商品售后订单' } }, { path: '/order/orderserviceafter', component: () => import('@/modules/order/OrderListView.vue'), meta: { title: '服务售后订单' } }, { path: '/order/base-price-analysis', component: () => import('@/modules/order/OrderListView.vue'), meta: { title: '基础价格分析表' } }, + // W15 新增 - 订单售后 + 退款 + 付款回调 (前端 max-effort mock, 老 vue 同字段) + { path: '/order/orderpay', component: () => import('@/modules/order/payment/PaymentCallbackListView.vue'), meta: { title: '订单支付回调' } }, + { path: '/order/refund', component: () => import('@/modules/order/refund/RefundProcessListView.vue'), meta: { title: '订单退款管理' } }, + { path: '/order/aftersale', component: () => import('@/modules/order/aftersale/AftersaleListView.vue'), meta: { title: '售后订单' } }, // other 7 个 { path: '/other/brand', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'other-brand' }), meta: { title: '品牌管理' } }, { path: '/other/category/good', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'other-category-good' }), meta: { title: '平台分类' } }, From 4b4625df9f5955edd9dd1299c4db533c53748f09 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Tue, 7 Jul 2026 10:22:09 +0800 Subject: [PATCH 17/84] =?UTF-8?q?feat(F006-W16):=207=20supplier=20?= =?UTF-8?q?=E5=AD=90=E9=A1=B5=20+=203=20enterprise=20=E5=AD=90=E9=A1=B5=20?= =?UTF-8?q?=E6=8E=A5=E5=89=8D=E7=AB=AF=20max-effort=20mock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config/menu-labels.ts | 8 +- .../couponscope/CouponScopeListView.vue | 117 +++++++++++++++++ .../historylog/HistorylogListView.vue | 115 +++++++++++++++++ .../supplier/logistics/LogisticsListView.vue | 116 +++++++++++++++++ .../ordercomment/OrderCommentListView.vue | 121 ++++++++++++++++++ .../supplier/promoter/PromoterListView.vue | 115 +++++++++++++++++ .../EnterpriselevelListView.vue | 101 +++++++++++++++ .../EnterpriseratingListView.vue | 118 +++++++++++++++++ .../EnterprisescoreListView.vue | 113 ++++++++++++++++ src/router/index.ts | 12 +- 10 files changed, 930 insertions(+), 6 deletions(-) create mode 100644 src/modules/supplier/couponscope/CouponScopeListView.vue create mode 100644 src/modules/supplier/historylog/HistorylogListView.vue create mode 100644 src/modules/supplier/logistics/LogisticsListView.vue create mode 100644 src/modules/supplier/ordercomment/OrderCommentListView.vue create mode 100644 src/modules/supplier/promoter/PromoterListView.vue create mode 100644 src/modules/user/enterpriselevel/EnterpriselevelListView.vue create mode 100644 src/modules/user/enterpriserating/EnterpriseratingListView.vue create mode 100644 src/modules/user/enterprisescore/EnterprisescoreListView.vue diff --git a/src/config/menu-labels.ts b/src/config/menu-labels.ts index 3fa7569..4c570b0 100644 --- a/src/config/menu-labels.ts +++ b/src/config/menu-labels.ts @@ -52,7 +52,7 @@ export const MENU_LABELS: MenuLabel[] = [ { url: 'user/user', label: '用户列表', icon: 'User', path: '/user/user', sort: 100 }, { url: 'user/enterprise/enterprise', label: '企业列表', icon: 'OfficeBuilding', path: '/user/enterprise', sort: 101 }, { url: 'user/enterprise/enterprise-rating', label: '评级', icon: 'Star', path: '/user/enterprise/rating', sort: 102 }, - { url: 'user/enterprise/enterprise-level', label: '企业等级管理', icon: 'Medal', path: '/user/enterprise/level', sort: 103 }, + { url: 'user/enterprise/enterprise-level', label: '企业等级管理', icon: 'Medal', path: '/user/enterprise/level', sort: 103 }, // 已接真 view W16 { url: 'user/enterprise/enterprise-score', label: '评分', icon: 'DataAnalysis', path: '/user/enterprise/score', sort: 104 }, { url: 'user/finance/recharge', label: '充值管理', icon: 'Wallet', path: '/user/finance/recharge', sort: 110 }, { url: 'user/finance/recharge-tx', label: '提现管理', icon: 'CreditCard', path: '/user/finance/recharge-tx', sort: 111 }, @@ -80,8 +80,12 @@ export const MENU_LABELS: MenuLabel[] = [ { url: 'supplier/servicegood', label: '服务商品', icon: 'Box', path: '/supplier/servicegood', sort: 301 }, { url: 'supplier/activityzone', label: '活动专区', icon: 'Promotion', path: '/supplier/activity', sort: 302 }, { url: 'supplier/coupon', label: '优惠券', icon: 'Ticket', path: '/supplier/coupon', sort: 303 }, - { url: 'supplier/promoter', label: '推广返佣', icon: 'UserFilled', path: '/supplier/promoter', sort: 304 }, + { url: 'supplier/promoter', label: '推广员', icon: 'UserFilled', path: '/supplier/promoter', sort: 304 }, { url: 'supplier/inquiry/inquiry', label: '询价列表', icon: 'ChatLineSquare', path: '/supplier/inquiry', sort: 305 }, + { url: 'supplier/ordercomment', label: '订单评价', icon: 'Star', path: '/supplier/ordercomment', sort: 306 }, + { url: 'supplier/historylog', label: '浏览足迹', icon: 'View', path: '/supplier/historylog', sort: 307 }, + { url: 'supplier/logistics', label: '物流方案', icon: 'Van', path: '/supplier/logistics', sort: 308 }, + { url: 'supplier/coupon-scope', label: '优惠券适用范围',icon: 'Filter', path: '/supplier/coupon-scope',sort: 309 }, // ===== 系统模块 ===== { url: 'sys/user', label: '用户管理[后台用户]', icon: 'UserFilled', path: '/sys/user', sort: 400 }, diff --git a/src/modules/supplier/couponscope/CouponScopeListView.vue b/src/modules/supplier/couponscope/CouponScopeListView.vue new file mode 100644 index 0000000..a151c81 --- /dev/null +++ b/src/modules/supplier/couponscope/CouponScopeListView.vue @@ -0,0 +1,117 @@ + + + + diff --git a/src/modules/supplier/historylog/HistorylogListView.vue b/src/modules/supplier/historylog/HistorylogListView.vue new file mode 100644 index 0000000..9ce77c9 --- /dev/null +++ b/src/modules/supplier/historylog/HistorylogListView.vue @@ -0,0 +1,115 @@ + + + + diff --git a/src/modules/supplier/logistics/LogisticsListView.vue b/src/modules/supplier/logistics/LogisticsListView.vue new file mode 100644 index 0000000..6902ee5 --- /dev/null +++ b/src/modules/supplier/logistics/LogisticsListView.vue @@ -0,0 +1,116 @@ + + + + diff --git a/src/modules/supplier/ordercomment/OrderCommentListView.vue b/src/modules/supplier/ordercomment/OrderCommentListView.vue new file mode 100644 index 0000000..f09444f --- /dev/null +++ b/src/modules/supplier/ordercomment/OrderCommentListView.vue @@ -0,0 +1,121 @@ + + + + diff --git a/src/modules/supplier/promoter/PromoterListView.vue b/src/modules/supplier/promoter/PromoterListView.vue new file mode 100644 index 0000000..86a8c99 --- /dev/null +++ b/src/modules/supplier/promoter/PromoterListView.vue @@ -0,0 +1,115 @@ + + + + diff --git a/src/modules/user/enterpriselevel/EnterpriselevelListView.vue b/src/modules/user/enterpriselevel/EnterpriselevelListView.vue new file mode 100644 index 0000000..86f5af4 --- /dev/null +++ b/src/modules/user/enterpriselevel/EnterpriselevelListView.vue @@ -0,0 +1,101 @@ + + + + diff --git a/src/modules/user/enterpriserating/EnterpriseratingListView.vue b/src/modules/user/enterpriserating/EnterpriseratingListView.vue new file mode 100644 index 0000000..c336a1e --- /dev/null +++ b/src/modules/user/enterpriserating/EnterpriseratingListView.vue @@ -0,0 +1,118 @@ + + + + diff --git a/src/modules/user/enterprisescore/EnterprisescoreListView.vue b/src/modules/user/enterprisescore/EnterprisescoreListView.vue new file mode 100644 index 0000000..2df9b09 --- /dev/null +++ b/src/modules/user/enterprisescore/EnterprisescoreListView.vue @@ -0,0 +1,113 @@ + + + + diff --git a/src/router/index.ts b/src/router/index.ts index a3d1c4b..649eae9 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -239,7 +239,11 @@ const routes: RouteRecordRaw[] = [ { path: '/other/seckill', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'other-seckill' }), meta: { title: '秒杀活动' } }, // supplier 2 个 { path: '/supplier/coupon', component: () => import('@/modules/supplier/coupon/CouponListView.vue'), meta: { title: '优惠券' } }, // W7: 独立 view, 走 /supplier/coupon/page 真 API - { path: '/supplier/promoter', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'supplier-promoter' }), meta: { title: '推广返佣' } }, + { path: '/supplier/promoter', component: () => import('@/modules/supplier/promoter/PromoterListView.vue'), meta: { title: '推广员管理' } }, + { path: '/supplier/historylog', component: () => import('@/modules/supplier/historylog/HistorylogListView.vue'), meta: { title: '浏览足迹' } }, + { path: '/supplier/ordercomment', component: () => import('@/modules/supplier/ordercomment/OrderCommentListView.vue'), meta: { title: '订单评价' } }, + { path: '/supplier/logistics', component: () => import('@/modules/supplier/logistics/LogisticsListView.vue'), meta: { title: '物流方案' } }, + { path: '/supplier/coupon-scope', component: () => import('@/modules/supplier/couponscope/CouponScopeListView.vue'), meta: { title: '优惠券适用范围' } }, // sys 11 个 { path: '/sys/dict', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'sys-dict' }), meta: { title: '字典类型' } }, { path: '/sys/log/login', component: () => import('@/modules/sys/LogLoginView.vue'), meta: { title: '登录日志' } }, @@ -250,9 +254,9 @@ const routes: RouteRecordRaw[] = [ { path: '/sys/notice-user', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'sys-notice-user' }), meta: { title: '用户通知' } }, { path: '/sys/userManagement', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'sys-userManagement' }), meta: { title: '全国运营中心' } }, // user 9 个 - { path: '/user/enterprise/level', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'user-enterprise-level' }), meta: { title: '企业等级管理' } }, - { path: '/user/enterprise/rating', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'user-enterprise-rating' }), meta: { title: '评级' } }, - { path: '/user/enterprise/score', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'user-enterprise-score' }), meta: { title: '评分' } }, + { path: '/user/enterprise/level', component: () => import('@/modules/user/enterpriselevel/EnterpriselevelListView.vue'), meta: { title: '企业等级管理' } }, + { path: '/user/enterprise/rating', component: () => import('@/modules/user/enterpriserating/EnterpriseratingListView.vue'), meta: { title: '供应商评级' } }, + { path: '/user/enterprise/score', component: () => import('@/modules/user/enterprisescore/EnterprisescoreListView.vue'), meta: { title: '供应商评分' } }, { path: '/user/finance/recharge', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'user-finance-recharge', queryParams: { type: 1 } }), meta: { title: '充值管理' } }, { path: '/user/finance/recharge-tx', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'user-finance-recharge-tx', queryParams: { type: 2 } }), meta: { title: '提现管理' } }, { path: '/user/finance/revenue', component: () => import('@/modules/generic/MockTableView.vue'), props: () => ({ configKey: 'user-finance-revenue', queryParams: { type: 3 } }), meta: { title: '分账记录管理' } }, From 675d27dd2f756700ae64d4f27a9720f3122e07b7 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Tue, 7 Jul 2026 11:03:15 +0800 Subject: [PATCH 18/84] =?UTF-8?q?fix(F006-W17):=20nginx=20proxy=5Fhide=5Fh?= =?UTF-8?q?eader=20WWW-Authenticate=20=E5=8E=BB=E9=99=A4=E6=B5=8F=E8=A7=88?= =?UTF-8?q?=E5=99=A8=E5=8E=9F=E7=94=9F=E8=AE=A4=E8=AF=81=E5=BC=B9=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: Spring Security /auth/oauth/token 401 响应带 WWW-Authenticate: Basic realm="oauth2/client" 浏览器拦截该响应头后弹出原生 HTTP Basic Auth 对话框("身份验证"), 在 axios/JS 处理响应之前就触发,前端代码无法拦截. 修法: nginx-vue.conf /auth/ location 加 proxy_hide_header WWW-Authenticate; 同时 PlaceholderView/AppLayout fetch 调用加 credentials: omit 兜底. 验证: curl 测试 401 响应已无 WWW-Authenticate 头,登录流程不再触发浏览器弹窗. --- src/components/AppLayout/AppLayout.vue | 3 ++- src/modules/placeholder/PlaceholderView.vue | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/AppLayout/AppLayout.vue b/src/components/AppLayout/AppLayout.vue index 2ba1043..4e06020 100644 --- a/src/components/AppLayout/AppLayout.vue +++ b/src/components/AppLayout/AppLayout.vue @@ -224,7 +224,8 @@ const badges = ref>({}) async function loadBadges() { try { const data = await fetch('/sys/openapi/inquiry/list?page=1&limit=1', { - headers: { Authorization: `Bearer ${userStore.token}` } + headers: { Authorization: `Bearer ${userStore.token}` }, + credentials: 'omit' }).then(r => r.json()).catch(() => null) if (data?.code === 0) { const total = data.total ?? data.data?.length ?? 0 diff --git a/src/modules/placeholder/PlaceholderView.vue b/src/modules/placeholder/PlaceholderView.vue index a9de8ae..c332eb9 100644 --- a/src/modules/placeholder/PlaceholderView.vue +++ b/src/modules/placeholder/PlaceholderView.vue @@ -83,7 +83,8 @@ async function checkApi() { return } const res = await fetch(apiUrl.value, { - headers: { Authorization: `Bearer ${token}` } + headers: { Authorization: `Bearer ${token}` }, + credentials: 'omit' }) // W4.19 修复:nginx 没代理的业务模块会返 404 HTML 页, 不是 JSON // 检测 content-type 防止误判 From c3295c3f574b2c06991ba176a54cf0936528cb80 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Tue, 7 Jul 2026 11:43:36 +0800 Subject: [PATCH 19/84] =?UTF-8?q?fix(auth):=20=E7=A7=BB=E9=99=A4=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E8=AF=B7=E6=B1=82=20client:=20front=20=E5=A4=B4,?= =?UTF-8?q?=E6=81=A2=E5=A4=8D=20captcha=20=E6=A0=A1=E9=AA=8C=20(W15.1.5)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/auth/LoginView.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/auth/LoginView.vue b/src/modules/auth/LoginView.vue index 285eb03..4d90f3b 100644 --- a/src/modules/auth/LoginView.vue +++ b/src/modules/auth/LoginView.vue @@ -70,8 +70,7 @@ async function onLogin() { { headers: { 'Content-Type': 'application/x-www-form-urlencoded', - Authorization: 'Basic cmVucmVuaW86cmVucmVuaW8=', - client: 'front' + Authorization: 'Basic cmVucmVuaW86cmVucmVuaW8=' } } ) From 9c75bd53c41b18f6d212aaa0c04e69ca8c78d749 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Tue, 7 Jul 2026 11:58:59 +0800 Subject: [PATCH 20/84] =?UTF-8?q?feat(user):=20=E5=AE=8C=E6=95=B4=E5=8C=96?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=88=97=E8=A1=A8=20(9=20=E5=88=97=20+=206?= =?UTF-8?q?=20=E6=90=9C=E7=B4=A2=20+=204=20=E6=93=8D=E4=BD=9C,=20=E8=80=81?= =?UTF-8?q?=20vue=20=E7=AD=89=E4=BB=B7)=20W17.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/user/UserListView.vue | 174 +++++++++++++++++++++++++----- 1 file changed, 148 insertions(+), 26 deletions(-) diff --git a/src/modules/user/UserListView.vue b/src/modules/user/UserListView.vue index 0c64dfa..13948aa 100644 --- a/src/modules/user/UserListView.vue +++ b/src/modules/user/UserListView.vue @@ -1,18 +1,13 @@ @@ -84,10 +187,17 @@ onMounted(load)
@@ -102,12 +212,24 @@ onMounted(load) row-key="id" empty-text="暂无用户" @page-change="onPageChange" - /> + > + + +
From 5c35297555038bf98cae1d61dd83e36bea3cf6cd Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Tue, 7 Jul 2026 12:50:20 +0800 Subject: [PATCH 21/84] =?UTF-8?q?feat(user):=20=E6=95=B4=E6=94=B9=20UserLi?= =?UTF-8?q?stView=20=E7=AC=A6=E5=90=88=E8=AE=BE=E8=AE=A1=E8=A7=84=E8=8C=83?= =?UTF-8?q?=20(=E5=88=97=E5=AE=BD/=E6=93=8D=E4=BD=9C=E5=88=97=20el-link/?= =?UTF-8?q?=E7=AB=96=E7=BA=BF=E5=88=86=E9=9A=94)=20W17.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/user/UserListView.vue | 66 +++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/src/modules/user/UserListView.vue b/src/modules/user/UserListView.vue index 13948aa..fc6b7f9 100644 --- a/src/modules/user/UserListView.vue +++ b/src/modules/user/UserListView.vue @@ -1,9 +1,15 @@ diff --git a/src/modules/supplier/promoter/PromoterListView.vue b/src/modules/supplier/promoter/PromoterListView.vue index e2943c8..8c8be83 100644 --- a/src/modules/supplier/promoter/PromoterListView.vue +++ b/src/modules/supplier/promoter/PromoterListView.vue @@ -12,6 +12,7 @@ import { httpGet } from '@/utils/request' import PageHeader from '@/components/PageHeader/PageHeader.vue' import SearchBar from '@/components/SearchBar/SearchBar.vue' import DataTable from '@/components/DataTable/DataTable.vue' +import TableActions from '@/components/TableActions/TableActions.vue' interface PromoterRow { id:string; enterpriseId:string; enterpriseName:string; promoterName:string; promoterRadio:number; promoterGood:string; beginTime:string; endTime:string; createTime:string } const ENDPOINTS = [ @@ -45,7 +46,7 @@ const columns: Col[] = [ { prop:'beginTime', label:'开始时间', width:120, slot:'date1' }, { prop:'endTime', label:'结束时间', width:120, slot:'date2' }, { prop:'createTime', label:'创建时间', width:160, slot:'time' }, - { prop:'actions', label:'操作', width:200, slot:'actions', fixed:'right' } + { prop:'actions', label:'操作', width:140, slot:'actions', fixed:'right' } ] const STATUS_DEFAULTS = [ { value:'', label:'全部' }, @@ -103,9 +104,14 @@ onMounted(load) diff --git a/src/modules/supplier/servicegood/ServiceGoodListView.vue b/src/modules/supplier/servicegood/ServiceGoodListView.vue index d6a15a7..0b98690 100644 --- a/src/modules/supplier/servicegood/ServiceGoodListView.vue +++ b/src/modules/supplier/servicegood/ServiceGoodListView.vue @@ -17,6 +17,7 @@ import PageHeader from '@/components/PageHeader/PageHeader.vue' import SearchBar from '@/components/SearchBar/SearchBar.vue' import ListTabs from '@/components/ListTabs/ListTabs.vue' import DataTable from '@/components/DataTable/DataTable.vue' +import TableActions from '@/components/TableActions/TableActions.vue' interface ServiceGood { id: string @@ -81,7 +82,7 @@ const columns = [ { prop: 'onShelf', label: '铺货', width: 100, align: 'center' as const, slot: 'onShelf' }, { prop: 'checkStatus', label: '状态', width: 100, align: 'center' as const, slot: 'checkStatus' }, { prop: 'createDate', label: '申请时间', width: 170 }, - { label: '操作', width: 280, align: 'center' as const, fixed: 'right' as const, slot: 'action' } + { label: '操作', width: 140, align: 'center' as const, fixed: 'right' as const, slot: 'action' } ] const tabItems = computed(() => [ @@ -256,19 +257,16 @@ onMounted(() => Promise.all([load(), loadStats()])) {{ CHECK_STATUS_MAP[row.checkStatus]?.label }} @@ -353,17 +351,4 @@ onMounted(() => Promise.all([load(), loadStats()])) .rr-good-cell { display: flex; align-items: center; gap: 10px; } .rr-good-icon-placeholder { width: 40px; height: 40px; border-radius: 4px; background: var(--bg-soft); display: flex; align-items: center; justify-content: center; color: var(--ink-3); font-weight: 600; flex-shrink: 0; } .rr-price { font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; font-size: 13px; font-weight: 500; color: var(--primary); } -.rr-actions { - display: inline-flex; - align-items: center; - gap: 0; - &__sep { - color: var(--rr-border-color, #E2E8F0); - margin: 0 6px; - font-size: 12px; - } - :deep(.el-link) { - font-size: 13px; - } -} diff --git a/src/modules/sys/ScheduleListView.vue b/src/modules/sys/ScheduleListView.vue index 54c3f97..3d63f3e 100644 --- a/src/modules/sys/ScheduleListView.vue +++ b/src/modules/sys/ScheduleListView.vue @@ -13,6 +13,7 @@ import { httpGet, httpPost, httpPut, httpDelete } from '@/utils/request' import DataTable from '@/components/DataTable/DataTable.vue' import PageHeader from '@/components/PageHeader/PageHeader.vue' import SearchBar from '@/components/SearchBar/SearchBar.vue' +import TableActions from '@/components/TableActions/TableActions.vue' interface Schedule { id: string @@ -148,7 +149,7 @@ onMounted(load) { prop: 'remark', label: '备注', minWidth: 200 }, { prop: 'status', label: '状态', width: 100, slot: 'status' }, { prop: 'createDate', label: '创建时间', width: 170, slot: 'createDate' }, - { label: '操作', width: 280, slot: 'action' } + { label: '操作', width: 140, slot: 'action' } ]" :data="list" :loading="loading" @@ -170,10 +171,15 @@ onMounted(load) diff --git a/src/modules/sys/UserListView.vue b/src/modules/sys/UserListView.vue index 8d367ff..e3fefe0 100644 --- a/src/modules/sys/UserListView.vue +++ b/src/modules/sys/UserListView.vue @@ -28,6 +28,7 @@ import { httpGet, httpPost, httpPut, httpDelete } from '@/utils/request' import DataTable from '@/components/DataTable/DataTable.vue' import PageHeader from '@/components/PageHeader/PageHeader.vue' import SearchBar from '@/components/SearchBar/SearchBar.vue' +import TableActions from '@/components/TableActions/TableActions.vue' interface SysUser { id: string @@ -252,7 +253,7 @@ onMounted(() => { load() }) { prop: 'userType', label: '类型', width: 100, slot: 'userType' }, { prop: 'status', label: '状态', width: 80, slot: 'status' }, { prop: 'createDate', label: '创建时间', width: 170, slot: 'createDate' }, - { label: '操作', width: 260, slot: 'action' } + { label: '操作', width: 140, slot: 'action' } ]" :data="list" :borderless="true" :loading="loading" @@ -293,32 +294,14 @@ onMounted(() => { load() }) diff --git a/src/modules/sys/region/RegionListView.vue b/src/modules/sys/region/RegionListView.vue index fdb976f..0495fed 100644 --- a/src/modules/sys/region/RegionListView.vue +++ b/src/modules/sys/region/RegionListView.vue @@ -14,6 +14,7 @@ import { ref, onMounted, reactive } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import { httpGet } from '@/utils/request' import PageHeader from '@/components/PageHeader/PageHeader.vue' +import TableActions from '@/components/TableActions/TableActions.vue' interface Region { id: string @@ -138,11 +139,16 @@ onMounted(load) - + diff --git a/src/modules/user/UserListView.vue b/src/modules/user/UserListView.vue index 0720561..8a32e01 100644 --- a/src/modules/user/UserListView.vue +++ b/src/modules/user/UserListView.vue @@ -13,6 +13,7 @@ import PageHeader from '@/components/PageHeader/PageHeader.vue' import SearchBar from '@/components/SearchBar/SearchBar.vue' import ListTabs from '@/components/ListTabs/ListTabs.vue' import UserFormDialog from './UserFormDialog.vue' +import TableActions from '@/components/TableActions/TableActions.vue' interface FrontUser { id: string @@ -87,7 +88,7 @@ const columns: any[] = [ width: 180, formatter: (row: FrontUser) => fmtDate(row.createDate) }, - { label: '操作', width: 220, slot: 'action', fixed: 'right' } + { label: '操作', width: 140, slot: 'action', fixed: 'right' } ] function fmtDate(ts: number | null | undefined) { @@ -340,15 +341,14 @@ onMounted(load) 禁用 @@ -356,17 +356,4 @@ onMounted(load) diff --git a/src/modules/user/enterpriselevel/EnterpriselevelListView.vue b/src/modules/user/enterpriselevel/EnterpriselevelListView.vue index fdb5ee2..ccd8d6c 100644 --- a/src/modules/user/enterpriselevel/EnterpriselevelListView.vue +++ b/src/modules/user/enterpriselevel/EnterpriselevelListView.vue @@ -12,6 +12,7 @@ import { httpGet } from '@/utils/request' import PageHeader from '@/components/PageHeader/PageHeader.vue' import SearchBar from '@/components/SearchBar/SearchBar.vue' import DataTable from '@/components/DataTable/DataTable.vue' +import TableActions from '@/components/TableActions/TableActions.vue' interface LevelRow { id:string; enterpriseLevel:string; scoreFrom:number; scoreTo:number; createTime:string } const ENDPOINTS = [ @@ -34,7 +35,7 @@ const columns: Col[] = [ { prop:'enterpriseLevel', label:'等级', width:140 }, { prop:'scoreFrom', label:'起始分', width:100 }, { prop:'scoreTo', label:'截止分', width:100 }, - { prop:'actions', label:'操作', width:200, slot:'actions', fixed:'right' } + { prop:'actions', label:'操作', width:140, slot:'actions', fixed:'right' } ] const STATUS_DEFAULTS = [ { value:'', label:'全部' } @@ -89,9 +90,14 @@ onMounted(load) :borderless="true" :loading="loading" :page="page" :limit="limit" :total="total" row-key="id" @page-change="(p: number) => { page = p; load() }" @limit-change="(l: number) => { limit = l; page = 1; load() }"> From 2f7ec67903244134a555f46d5d1e6932da5b9550 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Thu, 9 Jul 2026 13:55:34 +0800 Subject: [PATCH 46/84] =?UTF-8?q?refactor(F006-W17.6.1):=20TableActions=20?= =?UTF-8?q?=E6=8C=89=E6=95=B0=E9=87=8F=E8=87=AA=E5=8A=A8=E6=94=B6=E7=BA=B3?= =?UTF-8?q?=20(=E2=89=A43=20=E5=85=A8=E6=98=BE=E7=A4=BA,=20>3=20=E5=89=8D2?= =?UTF-8?q?+=E2=8B=AF)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户反馈: 操作列只显示一个文字按钮+⋯ 不方便, 期望按按钮数量智能显示 - 过滤 when 后 ≤3 个: 全部显示文字按钮, 不显示 ⋯ - 过滤 when 后 ≥4 个: 前 2 个常驻文字按钮 + ⋯ (收纳剩余) - 默认 visibleCount=2 (可配置) TableActions API 调整 (W17.6 → W17.6.1): - 原来: :primary=[A] + :more=[B,C,D] (人为主次划分) - 现在: :actions=[A,B,C,D] (按数组顺序自动前 2 显 + ⋯) 16 文件改动 (1 组件 + 15 view 调用方式): - 15 view 合并 :primary/:more → :actions - 3 按钮页 (10 个): 现在全部显示文字按钮无 ⋯, 体验更直接 - 4/5 按钮页 (5 个): 前 2 显 + ⋯, 比之前详情+⋯更直观 --- src/components/TableActions/TableActions.vue | 62 +++++++++++++------ .../openapi/CompanyAccountListView.vue | 6 +- src/modules/openapi/OpenAppListView.vue | 6 +- src/modules/order/OrderListView.vue | 4 +- .../categoryGood/CategoryGoodListView.vue | 6 +- src/modules/other/label/LabelListView.vue | 6 +- .../supplier/coupon/CouponListView.vue | 4 +- src/modules/supplier/good/GoodListView.vue | 4 +- .../ordercomment/OrderCommentListView.vue | 6 +- .../supplier/promoter/PromoterListView.vue | 6 +- .../servicegood/ServiceGoodListView.vue | 4 +- src/modules/sys/ScheduleListView.vue | 6 +- src/modules/sys/UserListView.vue | 6 +- src/modules/sys/region/RegionListView.vue | 6 +- src/modules/user/UserListView.vue | 6 +- .../EnterpriselevelListView.vue | 6 +- 16 files changed, 84 insertions(+), 60 deletions(-) diff --git a/src/components/TableActions/TableActions.vue b/src/components/TableActions/TableActions.vue index 9bd9b18..14835ca 100644 --- a/src/components/TableActions/TableActions.vue +++ b/src/components/TableActions/TableActions.vue @@ -1,17 +1,19 @@ \ No newline at end of file diff --git a/src/modules/openapi/ApplyApiKeyDialog.vue b/src/modules/openapi/ApplyApiKeyDialog.vue index c6c3f57..8b24c8c 100644 --- a/src/modules/openapi/ApplyApiKeyDialog.vue +++ b/src/modules/openapi/ApplyApiKeyDialog.vue @@ -231,7 +231,7 @@ function notifyContact() { :loading="loadingCustomers" :row-style="{ height: '36px' }" :cell-style="{ padding: '4px 8px', fontSize: '12.5px' }" - :header-cell-style="{ padding: '6px 8px', fontSize: '12px', height: '32px', background: '#F8FAFC' }" + :header-cell-style="{ padding: '6px 8px', fontSize: '12px', height: '32px', background: 'var(--surface-2)' }" @selection-change="onSelectionChange" > diff --git a/src/modules/openapi/OpenAppListView.vue b/src/modules/openapi/OpenAppListView.vue index e9a4ce2..a3eedbe 100644 --- a/src/modules/openapi/OpenAppListView.vue +++ b/src/modules/openapi/OpenAppListView.vue @@ -580,10 +580,10 @@ onMounted(() => { load(); loadCustomers() }) font-size: 11.5px; font-weight: 500; line-height: 17.25px; height: 21.25px; box-sizing: border-box; } -.rr-badge-0 { background: #FEF3C7; color: #D97706; } /* 待激活 amber */ -.rr-badge-1 { background: #D1FAE5; color: #059669; } /* 已激活 green */ -.rr-badge-2 { background: #DBEAFE; color: #2563EB; } /* 已撤销 blue */ -.rr-badge-3 { background: #E2E8F0; color: #64748B; } /* 已过期 gray */ +.rr-badge-0 { background: var(--amber-soft); color: var(--amber); } /* 待激活 amber */ +.rr-badge-1 { background: var(--green-soft); color: var(--green); } /* 已激活 green */ +.rr-badge-2 { background: var(--brand-soft); color: var(--brand); } /* 已撤销 blue */ +.rr-badge-3 { background: var(--surface-2); color: var(--ink-3); } /* 已过期 gray */ /* 危险文字按钮(撤销/删除 - 老 vue 用 style color: #ff4d4f) */ :deep(.rr-danger-text) { @@ -606,7 +606,7 @@ onMounted(() => { load(); loadCustomers() }) :deep(.el-input__inner), :deep(.el-select__wrapper) { border-radius: 8px !important; - background: #F8FAFC; + background: var(--surface-2); } /* 弹窗圆角 12px + 紧凑(套设计规范 §7.1 + §17 v3) */ diff --git a/src/modules/sys/LogErrorView.vue b/src/modules/sys/LogErrorView.vue index d0b2689..493c31f 100644 --- a/src/modules/sys/LogErrorView.vue +++ b/src/modules/sys/LogErrorView.vue @@ -211,10 +211,10 @@ onMounted(load) font-weight: 600; font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; } -.rr-method-get { background: #DBEAFE; color: #2563EB; } -.rr-method-post { background: #D1FAE5; color: #059669; } -.rr-method-put { background: #FEF3C7; color: #D97706; } -.rr-method-delete { background: #FEE2E2; color: #DC2626; } +.rr-method-get { background: var(--brand-soft); color: var(--brand); } +.rr-method-post { background: var(--green-soft); color: var(--green); } +.rr-method-put { background: var(--amber-soft); color: var(--amber); } +.rr-method-delete { background: var(--red-soft); color: var(--red); } .rr-error-detail { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 20px; } .rr-detail-row { display: flex; flex-direction: column; gap: 4px; } .rr-detail-full { grid-column: 1 / -1; } diff --git a/src/modules/sys/LogOperationView.vue b/src/modules/sys/LogOperationView.vue index 78a16dc..c8179cd 100644 --- a/src/modules/sys/LogOperationView.vue +++ b/src/modules/sys/LogOperationView.vue @@ -189,8 +189,8 @@ onMounted(load) font-weight: 600; font-family: 'SF Mono', Menlo, Monaco, Consolas, monospace; } -.rr-method-get { background: #DBEAFE; color: #2563EB; } -.rr-method-post { background: #D1FAE5; color: #059669; } -.rr-method-put { background: #FEF3C7; color: #D97706; } -.rr-method-delete { background: #FEE2E2; color: #DC2626; } +.rr-method-get { background: var(--brand-soft); color: var(--brand); } +.rr-method-post { background: var(--green-soft); color: var(--green); } +.rr-method-put { background: var(--amber-soft); color: var(--amber); } +.rr-method-delete { background: var(--red-soft); color: var(--red); } \ No newline at end of file diff --git a/src/theme/themes.scss b/src/theme/themes.scss index b8fc90f..db41e35 100644 --- a/src/theme/themes.scss +++ b/src/theme/themes.scss @@ -191,4 +191,17 @@ --el-color-primary-light-8: var(--brand-soft); --el-color-primary-light-9: var(--brand-soft); --el-color-primary-dark-2: var(--brand-hover); + + // W18 dark 主题适配:EP 内部 SCSS 常量重写 + // :root 块里 --el-color-white 解析为 var(--surface), 但解析时 surface 还未被 dark 块重写 + // 这里用 dark 主题的实际值硬编码, 不依赖 var() 链 + --el-color-white: #1E293B; /* surface */ + --el-color-black: #F8FAFC; /* ink */ + --el-fill-color-blank: #1E293B; /* surface */ + --el-fill-color-light: #0F172A; /* bg-soft (row hover) */ + --el-table-tr-bg-color: #1E293B; /* surface */ + --el-table-bg-color: #1E293B; /* surface */ + --el-table-expanded-cell-bg-color: #1E293B; + --el-table-header-bg-color: #283449; /* surface-2 (表头略亮区分) */ + --el-table-row-hover-bg-color: #0F172A; /* bg-soft */ } diff --git a/src/theme/tokens.scss b/src/theme/tokens.scss index cf1b074..a160d63 100644 --- a/src/theme/tokens.scss +++ b/src/theme/tokens.scss @@ -13,7 +13,7 @@ :root { // ===== 圆角(沿用 v1.3) ===== --radius-sm: 6px; - --radius: 6px; + --radius: 8px; --radius-lg: 10px; --radius-xl: 16px; --radius-pill: 9999px; @@ -120,4 +120,12 @@ // ===== v2 新增:主按钮渐变(从主题 brand 自动组合) ===== --brand-gradient: linear-gradient(135deg, var(--brand), var(--brand-2)); + + // ===== W18 暗主题适配:补齐 EP 缺失 token (dark 下表格背景/边框自适应) ===== + // EP 内部用 --el-color-white / black, 未重定向, dark 下仍是 #FFFFFF + --el-color-white: var(--surface); + --el-color-black: var(--ink); + // el-table 表格体/展开行背景 + --el-table-tr-bg-color: var(--surface); + --el-table-expanded-cell-bg-color: var(--surface); } From 3fc8326aeb426d2db7124368f3e9ab96f8c56812 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Thu, 9 Jul 2026 17:29:04 +0800 Subject: [PATCH 56/84] =?UTF-8?q?fix(F006-W18.8):=20dark=20=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=20=E6=8C=89=E9=92=AE=20+=20=E6=96=87=E5=AD=97=20?= =?UTF-8?q?=E9=A2=9C=E8=89=B2=E4=BF=AE=E5=A4=8D=20(CSS=20=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E7=BA=A7=E8=81=94=E5=85=A8=E9=83=A8=E7=A1=AC=E7=BC=96?= =?UTF-8?q?=E7=A0=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户反馈: 暗主题下默认 el-button (如导出/重置) 文字几乎看不见 根因 (同类 W18 修复): - tokens.scss :root 块定义 --el-text-color-regular: var(--ink-2) / --el-border-color: var(--border) - CSS 变量解析时, [data-theme=dark] 块的 --ink-2 重写还未生效 - 导致 dark 下 --el-text-color-regular 仍是 tech-blue 默认 #334155 (深色字 on 深色背景 = 不可见) - 按钮 border --el-border-color 仍是 #E2E8F0 (浅色边 on 暗背景 = 刺眼) 修法 (themes.scss [data-theme=dark] 块硬覆盖): - --el-text-color-primary/regular/secondary/placeholder/disabled → #F8FAFC/#E2E8F0/#CBD5E1/#94A3B8 - --el-border-color/light/lighter/extra-light → #475569 (border) - --el-border-color-dark/darker → #64748B (border-strong) - --el-fill-color/light → #0F172A (bg-soft) - --el-fill-color-lighter/extra-light/dark/darker → #283449 (surface-2) - --el-fill-color-blank/bg-color/overlay → #1E293B (surface) - --el-bg-color-page → #0F172A (bg-soft) - --el-tooltip-bg-color → #1E293B - --el-disabled-* → 配套浅色 Playwright dark 主题实测 (商品管理页 导出/重置 按钮): - 改前: bg rgb(30,41,59) 但 color rgb(51,65,85) = #334155 (看不见) - 改后: color rgb(226,232,240) = #E2E8F0 (清晰), border rgb(71,85,105) = #475569 (协调) - --el-text-color-regular 改前 #334155 → 改后 #E2E8F0 ✅ - 截图确认: 导出/重置/新增商品/查询 全部按钮在 dark 下清晰可读 --- src/theme/themes.scss | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/theme/themes.scss b/src/theme/themes.scss index db41e35..8f04a54 100644 --- a/src/theme/themes.scss +++ b/src/theme/themes.scss @@ -193,15 +193,37 @@ --el-color-primary-dark-2: var(--brand-hover); // W18 dark 主题适配:EP 内部 SCSS 常量重写 - // :root 块里 --el-color-white 解析为 var(--surface), 但解析时 surface 还未被 dark 块重写 - // 这里用 dark 主题的实际值硬编码, 不依赖 var() 链 + // :root 块里 var(--xxx) 解析时, dark 块的重写还未生效, 必须用实际值硬编码 --el-color-white: #1E293B; /* surface */ --el-color-black: #F8FAFC; /* ink */ - --el-fill-color-blank: #1E293B; /* surface */ - --el-fill-color-light: #0F172A; /* bg-soft (row hover) */ - --el-table-tr-bg-color: #1E293B; /* surface */ - --el-table-bg-color: #1E293B; /* surface */ + --el-text-color-primary: #F8FAFC; /* ink */ + --el-text-color-regular: #E2E8F0; /* ink-2 */ + --el-text-color-secondary: #CBD5E1; /* ink-3 */ + --el-text-color-placeholder: #94A3B8; /* ink-4 */ + --el-text-color-disabled: #94A3B8; /* ink-4 */ + --el-border-color: #475569; /* border */ + --el-border-color-light: #475569; + --el-border-color-lighter: #475569; + --el-border-color-extra-light: #475569; + --el-border-color-dark: #64748B; /* border-strong */ + --el-border-color-darker: #64748B; + --el-fill-color: #0F172A; /* bg-soft */ + --el-fill-color-light: #0F172A; + --el-fill-color-lighter: #283449; /* surface-2 */ + --el-fill-color-extra-light: #283449; + --el-fill-color-dark: #283449; + --el-fill-color-darker: #283449; + --el-fill-color-blank: #1E293B; /* surface */ + --el-bg-color: #1E293B; + --el-bg-color-page: #0F172A; /* bg-soft */ + --el-bg-color-overlay: #1E293B; + --el-table-tr-bg-color: #1E293B; /* surface */ + --el-table-bg-color: #1E293B; --el-table-expanded-cell-bg-color: #1E293B; - --el-table-header-bg-color: #283449; /* surface-2 (表头略亮区分) */ - --el-table-row-hover-bg-color: #0F172A; /* bg-soft */ + --el-table-header-bg-color: #283449; /* surface-2 (表头略亮区分) */ + --el-table-row-hover-bg-color: #0F172A; /* bg-soft */ + --el-tooltip-bg-color: #1E293B; /* surface */ + --el-disabled-bg-color: #0F172A; /* bg-soft */ + --el-disabled-text-color: #94A3B8; /* ink-4 */ + --el-disabled-border-color: #475569; } From ff4c9bc1408d575119c01cda52f24490d3b758b9 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Thu, 9 Jul 2026 17:38:14 +0800 Subject: [PATCH 57/84] =?UTF-8?q?fix(F006-W18.9):=20dark=20=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=20=E5=85=A8=E5=B1=80=E6=BB=9A=E5=8A=A8=E6=9D=A1?= =?UTF-8?q?=E6=B7=B1=E8=89=B2=E9=80=82=E9=85=8D=20(=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E6=B5=85=E7=99=BD=E6=BB=9A=E5=8A=A8=E6=9D=A1=E5=89=B2=E8=A3=82?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户反馈: 暗主题下侧边栏原生滚动条是浅白色, 在深色背景上刺眼割裂 根因: 浏览器原生 ::-webkit-scrollbar 走系统默认色 (亮色), 项目没覆盖, dark 下没适配 修法 (src/styles/global-popper.scss 末尾新增): - 默认 (亮主题): thumb var(--border) 浅灰 - hover: var(--ink-4) 深灰 - [data-theme=dark]: thumb var(--border) = #475569 深色 - hover: var(--ink-3) = #CBD5E1 - Firefox 兼容: html { scrollbar-color: var(--border) transparent; } Playwright 实测 (.rr-sidebar 滚动条 thumb): - 改前: 系统默认 #C0C0C0 浅灰 (刺眼) - 改后: rgb(71,85,105) = #475569 深色 ✅ (dark 协调) --- src/styles/global-popper.scss | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/styles/global-popper.scss b/src/styles/global-popper.scss index e9352c4..18dedfb 100644 --- a/src/styles/global-popper.scss +++ b/src/styles/global-popper.scss @@ -87,3 +87,37 @@ .el-select__wrapper.is-focused { box-shadow: 0 0 0 1px var(--brand, #2563EB) inset, 0 0 0 3px var(--brand-glow, rgba(37, 99, 235, 0.18)) !important; } + +/* === W18.9 全局滚动条暗主题适配 (深色滚动条避免割裂) === */ +/* 默认 (亮主题): 浅灰滚动条 */ +::-webkit-scrollbar { + width: 8px; + height: 8px; +} +::-webkit-scrollbar-track { + background: transparent; +} +::-webkit-scrollbar-thumb { + background: var(--border, #E2E8F0); + border-radius: 4px; + transition: background 0.15s; +} +::-webkit-scrollbar-thumb:hover { + background: var(--ink-4, #94A3B8); +} +/* Firefox */ +html { + scrollbar-color: var(--border, #E2E8F0) transparent; + scrollbar-width: thin; +} + +/* 暗主题: 深色滚动条适配, 避免浅白滚动条在深色背景上刺眼 */ +[data-theme="dark"] ::-webkit-scrollbar-thumb { + background: var(--border, #475569); +} +[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { + background: var(--ink-3, #CBD5E1); +} +[data-theme="dark"] html { + scrollbar-color: var(--border, #475569) transparent; +} From 15294f5c1cd2df50bbd3664f96b4fb4fa21d0d20 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 10 Jul 2026 08:45:38 +0800 Subject: [PATCH 58/84] =?UTF-8?q?feat(F006-W17.6):=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E6=95=B0=E6=8D=AE=E5=88=97=E5=B1=85=E4=B8=AD?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=20(9=20=E5=88=97=E5=8A=A0=20align=20center,?= =?UTF-8?q?=20=E4=BD=99=E9=A2=9D=E4=BF=9D=E7=95=99=20right)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/user/UserListView.vue | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/modules/user/UserListView.vue b/src/modules/user/UserListView.vue index 2fabc77..5eb2300 100644 --- a/src/modules/user/UserListView.vue +++ b/src/modules/user/UserListView.vue @@ -53,20 +53,22 @@ const query = reactive({ }) const columns: any[] = [ - { type: 'selection', width: 50, fixed: 'left' }, - { prop: 'id', label: '用户ID', width: 100 }, - { prop: 'nickName', label: '用户昵称', minWidth: 160 }, - { prop: 'mobile', label: '手机号', width: 140 }, + { type: 'selection', width: 50, fixed: 'left', align: 'center' }, + { prop: 'id', label: '用户ID', width: 100, align: 'center' }, + { prop: 'nickName', label: '用户昵称', minWidth: 160, align: 'center' }, + { prop: 'mobile', label: '手机号', width: 140, align: 'center' }, { prop: 'isEnterprise', label: '是否企业认证', width: 140, + align: 'center', formatter: (row: FrontUser) => row.isEnterprise === 1 ? '是' : '否' }, { prop: 'enterpriseName', label: '关联企业', minWidth: 200, + align: 'center', formatter: (row: FrontUser) => row.enterpriseName || '--' }, { @@ -80,15 +82,17 @@ const columns: any[] = [ prop: 'enabled', label: '禁用标识', width: 110, + align: 'center', slot: 'enabled' }, { prop: 'createDate', label: '注册时间', width: 180, + align: 'center', formatter: (row: FrontUser) => fmtDate(row.createDate) }, - { label: '操作', width: 140, slot: 'action', fixed: 'right' } + { label: '操作', width: 140, slot: 'action', fixed: 'right', align: 'center' } ] function fmtDate(ts: number | null | undefined) { From 978058c5432915546d33aa65d2827cfadabdd713 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 10 Jul 2026 10:27:36 +0800 Subject: [PATCH 59/84] =?UTF-8?q?fix(F006-W18):=20=E9=9D=A2=E5=8C=85?= =?UTF-8?q?=E5=B1=91=E6=98=BE=E7=A4=BA=E5=AE=8C=E6=95=B4=E8=B7=AF=E5=BE=84?= =?UTF-8?q?(=E5=B7=A5=E4=BD=9C=E5=8F=B0>=E4=B8=80=E7=BA=A7=E7=9B=AE?= =?UTF-8?q?=E5=BD=95>...>=E6=9C=AB=E7=BA=A7=E8=8F=9C=E5=8D=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: AppLayout.vue 面包屑写死两级(工作台 + route.meta.title), 省略了中间的父级目录层级。 修法: 加 breadcrumbItems computed, 从当前 route.path 在菜单树 (menuStore.list) DFS 追溯父级链, 返回完整路径标题数组。 - 列表页: 工作台 > 父目录 > ... > 末级菜单 - 详情页: 工作台 > 父目录 > ... > meta.title - 首页/未命中: 仅工作台 部署: dist rsync + docker rebuild + scp src + curl 200 验证 --- src/components/AppLayout/AppLayout.vue | 42 +++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/components/AppLayout/AppLayout.vue b/src/components/AppLayout/AppLayout.vue index 4e06020..17e2771 100644 --- a/src/components/AppLayout/AppLayout.vue +++ b/src/components/AppLayout/AppLayout.vue @@ -60,6 +60,46 @@ function isActive(path: string): boolean { return path === '/' ? route.path === '/' : route.path.startsWith(path) } +/** + * 面包屑: 从当前 route.path 在菜单树里 DFS 追溯完整父级链 + * 返回 [一级目录, ..., 末级菜单], 不含"工作台"前缀(template 里单独拼) + * 找不到时 fallback 到 route.meta.title + */ +const breadcrumbItems = computed(() => { + const currentPath = route.path + // 工作台首页不显示中间层级 + if (currentPath === '/' || currentPath === '/dashboard') return [] + // DFS 找父级链 + function findChain(items: MenuItem[], target: string, chain: MenuItem[]): boolean { + for (const item of items) { + if (item.path === target || (item.path !== '/' && target.startsWith(item.path))) { + chain.push(item) + return true + } + if (item.children?.length) { + chain.push(item) + if (findChain(item.children, target, chain)) return true + chain.pop() + } + } + return false + } + const chain: MenuItem[] = [] + findChain(menuList.value, currentPath, chain) + const metaTitle = route.meta?.title as string | undefined + if (chain.length) { + const titles: string[] = chain.map(i => i.title) + const last = chain[chain.length - 1] + if (last.path !== currentPath) { + // 详情页: 命中的是父前缀, 追加 meta.title + return metaTitle ? [...titles, metaTitle] : titles + } + return titles + } + // 菜单树没命中 (如 /inquiry/:id 详情页), 用 meta.title 兜底 + return metaTitle ? [metaTitle] : [] +}) + const PARENT_GROUP: Record = { '概览': '概览', '业务': '业务', @@ -329,7 +369,7 @@ onMounted(loadBadges) 工作台 - {{ route.meta?.title || '' }} + {{ item }}
From a59c934fd7074ac361707dbe4200cd57a58e36b4 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 10 Jul 2026 10:31:38 +0800 Subject: [PATCH 60/84] =?UTF-8?q?fix(F006-W18):=20=E9=9D=A2=E5=8C=85?= =?UTF-8?q?=E5=B1=91DFS=E4=BF=AE=E7=88=B6=E8=8F=9C=E5=8D=95=E7=9F=AD?= =?UTF-8?q?=E8=B7=AFbug(=E9=9B=86=E6=88=90=E7=AE=A1=E7=90=86>=E5=BA=94?= =?UTF-8?q?=E7=94=A8=E5=88=97=E8=A1=A8=E7=BC=BA=E6=9C=AB=E7=BA=A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: resolveMenuItem 给父菜单 path = 第一个子菜单 path(如 集成管理.path = /openapi/app)。旧 DFS 用 path 前缀匹配短路命中父菜单, 不再递归子树, 导致 末级菜单标题丢失(只显示 工作台 > 集成管理, 缺 应用列表)。 修法: 父节点(有 children)优先递归子树, 子树没命中才考虑父节点 path 前缀 匹配(详情页场景)。叶子节点走 path 精确匹配。 --- src/components/AppLayout/AppLayout.vue | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/components/AppLayout/AppLayout.vue b/src/components/AppLayout/AppLayout.vue index 17e2771..7a2cea3 100644 --- a/src/components/AppLayout/AppLayout.vue +++ b/src/components/AppLayout/AppLayout.vue @@ -69,18 +69,28 @@ const breadcrumbItems = computed(() => { const currentPath = route.path // 工作台首页不显示中间层级 if (currentPath === '/' || currentPath === '/dashboard') return [] - // DFS 找父级链 + // DFS 找父级链: 父菜单(有 children)的 path 是第一个子菜单的 path(见 + // resolveMenuItem), 不能用 path 前缀短路命中父菜单, 必须先递归子树, + // 子树没命中才考虑父菜单自身。 function findChain(items: MenuItem[], target: string, chain: MenuItem[]): boolean { for (const item of items) { - if (item.path === target || (item.path !== '/' && target.startsWith(item.path))) { + // 叶子节点: path 精确匹配 + if (!item.children?.length) { + if (item.path === target) { + chain.push(item) + return true + } + continue + } + // 父节点: 先递归子树 + chain.push(item) + if (findChain(item.children, target, chain)) return true + chain.pop() + // 子树没命中, 看父节点自身 path 是否是 target 的前缀(详情页场景) + if (item.path !== '/' && target.startsWith(item.path)) { chain.push(item) return true } - if (item.children?.length) { - chain.push(item) - if (findChain(item.children, target, chain)) return true - chain.pop() - } } return false } From 4e525cf6dd061d17610e9b19af667ab66132e9b7 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 10 Jul 2026 10:45:05 +0800 Subject: [PATCH 61/84] =?UTF-8?q?fix(F006):=20OpenApp=20revoke/delete=20id?= =?UTF-8?q?=20=E6=94=B9=20String=20=E9=81=BF=E5=85=8D=20Number=20=E7=B2=BE?= =?UTF-8?q?=E5=BA=A6=E4=B8=A2=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 雪花ID 19位 > Number.MAX_SAFE_INTEGER(16位), Number() 截断 导致撤销/删除传错 id. 改 String(id), 后端 Long.parseLong(string) 兼容 --- src/modules/openapi/OpenAppListView.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/openapi/OpenAppListView.vue b/src/modules/openapi/OpenAppListView.vue index a3eedbe..2fbaf4f 100644 --- a/src/modules/openapi/OpenAppListView.vue +++ b/src/modules/openapi/OpenAppListView.vue @@ -211,7 +211,7 @@ async function revokeConfirm() { } try { await httpPost('/sys/openapi/app/revoke', { - id: Number(revokeTarget.value.id), + id: String(revokeTarget.value.id), reason: revokeReason.value }) ElMessage.success('撤销成功') @@ -231,7 +231,7 @@ function deleteHandle(row: OpenApp) { async function deleteConfirm() { if (!deleteTarget.value) return try { - await httpPost('/sys/openapi/app/delete', { id: Number(deleteTarget.value.id) }) + await httpPost('/sys/openapi/app/delete', { id: String(deleteTarget.value.id) }) ElMessage.success('删除成功') deleteVisible.value = false deleteTarget.value = null From 8af8ed143d6e2eed12c73e8c92568a301a081237 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 10 Jul 2026 10:54:55 +0800 Subject: [PATCH 62/84] =?UTF-8?q?fix(F006-W18):=20=E7=94=B3=E8=AF=B7APIKey?= =?UTF-8?q?=E5=BC=B9=E7=AA=97=E8=A1=A8=E6=A0=BC=E7=BB=86=E8=8A=82=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 列名 客户名 → 公司名称 (Step1 + Step3 两处) 2. selection 选择框居中 (cell text-align center + padding 0) 3. 列宽重分配: 公司名称 min-width 200 左对齐, 联系人/电话居中 4. 表格圆角修复: 加 rr-apply-table class, border-radius 8px + overflow hidden --- src/modules/openapi/ApplyApiKeyDialog.vue | 34 +++++++++++++++++------ 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/modules/openapi/ApplyApiKeyDialog.vue b/src/modules/openapi/ApplyApiKeyDialog.vue index 8b24c8c..eef4fa1 100644 --- a/src/modules/openapi/ApplyApiKeyDialog.vue +++ b/src/modules/openapi/ApplyApiKeyDialog.vue @@ -129,7 +129,6 @@ async function submit() { const res = await httpPost('/sys/openapi/app/apply', payload) result.value = Array.isArray(res) ? res : [] ElMessage.success(`已为 ${result.value.length} 个客户生成 APIKey`) - emit('refresh') } catch (e: any) { ElMessage.error(e?.msg || e?.message || '申请失败') } finally { @@ -137,7 +136,7 @@ async function submit() { } } -function onClose() { updateVisible(false) } +function onClose() { updateVisible(false); if (result.value) emit("refresh") } async function copySecret(text: string) { try { @@ -232,12 +231,13 @@ function notifyContact() { :row-style="{ height: '36px' }" :cell-style="{ padding: '4px 8px', fontSize: '12.5px' }" :header-cell-style="{ padding: '6px 8px', fontSize: '12px', height: '32px', background: 'var(--surface-2)' }" + class="rr-apply-table" @selection-change="onSelectionChange" > - - - - + + + +
@@ -330,8 +330,8 @@ function notifyContact() { 请立即复制 connectCode 和 appSecret!关弹窗后无法再次查看

已为 {{ result.length }} 个客户生成 APIKey:

- - + + - - - -

重发后会生成新的 connectCode,旧码立即作废

-

新码有效期 2 小时,请尽快发给客户扫码激活

-
- -

新连接码仅显示一次!请立即复制并通过安全渠道发给客户

-

关闭弹窗后无法再次查看(只能再次重发)

-
-

- app: {{ resendQrTarget.appId }} - ({{ resendQrTarget.appName }}) -

-
-

- 新的 ConnectCode: (明文,可直接选中复制) -

- - - -

- 过期时间: {{ fmtDate(newConnectCodeExpire) }} -

-
- -
- From 366056dcac42a3d2975f093069cbe6955f0edfd6 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 10 Jul 2026 11:15:02 +0800 Subject: [PATCH 64/84] =?UTF-8?q?fix(F006-W18):=20=E7=94=B3=E8=AF=B7APIKey?= =?UTF-8?q?=20Step3=E8=A1=A8=E6=A0=BC=E6=A0=BC=E5=BC=8F=E9=94=99=E4=B9=B1+?= =?UTF-8?q?=E5=A4=8D=E5=88=B6=E5=A4=B1=E8=B4=A5=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 复制失败根因: navigator.clipboard API 要求 HTTPS/localhost, frp 走 http://direv.cloud:8080 是非安全上下文不可用。 修法: 加 execCommand(copy) 降级方案 (复用 OpenAppListView copyText 逻辑) 2. 表格格式错乱根因: 5 列固定宽 (160+280+弹性+180+320) 超 640px 弹窗, AppSecret 列 input+button 横排挤不下。 修法: 列宽重新分配 (公司120/AppID180/ConnectCode160/过期100/Secret200), AppSecret 单元格改 flex-column 竖排 (input 上 button 下), code 文本加 text-overflow ellipsis 防撑宽 --- src/modules/openapi/ApplyApiKeyDialog.vue | 73 +++++++++++++++++++---- 1 file changed, 60 insertions(+), 13 deletions(-) diff --git a/src/modules/openapi/ApplyApiKeyDialog.vue b/src/modules/openapi/ApplyApiKeyDialog.vue index eef4fa1..657f86d 100644 --- a/src/modules/openapi/ApplyApiKeyDialog.vue +++ b/src/modules/openapi/ApplyApiKeyDialog.vue @@ -139,11 +139,35 @@ async function submit() { function onClose() { updateVisible(false); if (result.value) emit("refresh") } async function copySecret(text: string) { + // 优先用现代 Clipboard API (HTTPS / localhost 才允许) + // frp 走 http://direv.cloud:8080 是非安全上下文, clipboard API 不可用, 需降级 try { - await navigator.clipboard.writeText(text) - ElMessage.success('已复制') + if (navigator.clipboard?.writeText) { + await navigator.clipboard.writeText(text) + ElMessage.success('已复制') + return + } + throw new Error('no clipboard api') } catch { - ElMessage.error('复制失败,请手动选择文本') + // 降级方案: document.execCommand('copy') - HTTP 下也能用 + try { + const ta = document.createElement('textarea') + ta.value = text + ta.style.position = 'fixed' + ta.style.opacity = '0' + ta.style.pointerEvents = 'none' + document.body.appendChild(ta) + ta.select() + const ok = document.execCommand('copy') + document.body.removeChild(ta) + if (ok) { + ElMessage.success('已复制') + } else { + ElMessage.warning('浏览器阻止自动复制,请手动双击输入框选中后 Cmd/Ctrl+C') + } + } catch { + ElMessage.warning('浏览器阻止自动复制,请手动双击输入框选中后 Cmd/Ctrl+C') + } } } @@ -330,23 +354,25 @@ function notifyContact() { 请立即复制 connectCode 和 appSecret!关弹窗后无法再次查看

已为 {{ result.length }} 个客户生成 APIKey:

- - - + + + - + - - + + @@ -496,4 +522,25 @@ function notifyContact() { :deep(.rr-apply-dialog .rr-apply-table th.el-table-column--selection .cell) { text-align: center; } + +/* Step3 结果表格: AppSecret 单元格紧凑布局 */ +.rr-secret-cell { + display: flex; + flex-direction: column; + gap: 4px; + padding: 2px 0; +} +.rr-secret-cell .el-input { + width: 100%; +} +/* code 文本省略, 不撑列宽 */ +.rr-cell-code { + display: inline-block; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 12px; + vertical-align: middle; +} From 34e3c7cd710807d9656f6f0a009e0accd298451e Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 10 Jul 2026 11:22:04 +0800 Subject: [PATCH 65/84] =?UTF-8?q?fix(F006):=20=E7=94=B3=E8=AF=B7APIKey?= =?UTF-8?q?=E5=BC=B9=E7=AA=97=E5=88=A0=E9=99=A4ConnectCode/=E8=BF=87?= =?UTF-8?q?=E6=9C=9F=E6=97=B6=E9=97=B4=E5=88=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 无用字段清理, 弹窗结果表只保留公司名/AppID/AppSecret --- src/modules/openapi/ApplyApiKeyDialog.vue | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/modules/openapi/ApplyApiKeyDialog.vue b/src/modules/openapi/ApplyApiKeyDialog.vue index 657f86d..1952878 100644 --- a/src/modules/openapi/ApplyApiKeyDialog.vue +++ b/src/modules/openapi/ApplyApiKeyDialog.vue @@ -32,9 +32,7 @@ interface ApplyResult { customerName: string customerCode: string appId: string - connectCode: string appSecret: string - expireAt: string } const props = defineProps<{ modelValue: boolean }>() @@ -344,14 +342,14 @@ function notifyContact() { {{ form.remark || '—' }} - 后端将自动创建公司账号 + 生成 connect_code(2h 有效) + 后端将自动创建公司账号 + 生成 APIKey
- 请立即复制 connectCode 和 appSecret!关弹窗后无法再次查看 + 请立即复制 appId 和 appSecret!关弹窗后无法再次查看

已为 {{ result.length }} 个客户生成 APIKey:

@@ -361,12 +359,6 @@ function notifyContact() { {{ row.appId }} - - - -