diff --git a/.env.production b/.env.production index 34d7624..b80cb74 100644 --- a/.env.production +++ b/.env.production @@ -1,2 +1,5 @@ # 生产环境 -VITE_API_BASE_URL = https://api.cpms.example.com/admin +VITE_API_BASE_URL = https://cpmsapi.yunvip123.com + +# 是否开启本地调试 +LOCAL_DEBUG=false diff --git a/package.json b/package.json index 0ba973b..0e4b766 100644 --- a/package.json +++ b/package.json @@ -6,10 +6,15 @@ "type": "module", "scripts": { "serve": "vite", + "serve:prod": "vite --mode production", "build:dev": "vue-tsc --noEmit && vite build --mode development", "build:test": "vue-tsc --noEmit && vite build --mode test", "build:prod": "vue-tsc --noEmit && vite build --mode production", + "test": "vitest", + "test:run": "vitest run", + "test:coverage": "vitest run --coverage", "preview": "vite preview", + "preview:prod": "pnpm build:prod && vite preview", "type-check": "vue-tsc --noEmit", "lint": "eslint src --ext .js,.ts,.tsx", "lint:fix": "eslint src --ext .js,.ts,.tsx --fix", @@ -42,17 +47,21 @@ "@typescript-eslint/parser": "^6.0.0", "@vitejs/plugin-vue": "^4.5.0", "@vitejs/plugin-vue-jsx": "^4.0.0", + "@vitest/coverage-v8": "2.1.9", + "@vue/test-utils": "^2.4.11", "eslint": "^8.0.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-vue": "^9.0.0", "husky": "^9.1.7", + "jsdom": "^30.0.1", "less": "^4.6.4", "lint-staged": "^15.0.0", "prettier": "^3.0.0", "typescript": "^5.3.0", "vite": "^5.0.0", "vite-plugin-remove-console": "^2.2.0", + "vitest": "^2.1.9", "vue-tsc": "^2.0.0" }, "lint-staged": { diff --git a/permission_list.txt b/permission_list.txt new file mode 100644 index 0000000..2596644 --- /dev/null +++ b/permission_list.txt @@ -0,0 +1,57 @@ +# ============================================================ +# CPMS 运营平台 - 权限标识字符串列表 +# 生成规则: +# 1. 每个页面都有一个 "页面名-查看" 的默认权限 +# 2. 表格操作列中的按钮生成对应操作权限 +# 3. 同一关键字的两个状态按钮(如上架/下架、启用/禁用)合并为一个权限 +# 4. 筛选栏中有"新增"按钮的页面,生成新增权限 +# 5. 标识为英文,附带中文说明(含按钮所在位置) +# ============================================================ + +# ─── 赛事管理模块 ───────────────────────────────────────── + +events.list.view # 赛事列表-查看(页面默认查看权限) +events.list.toggle_status # 赛事列表-上架/下架(表格操作列,根据赛事状态显示"上架"或"下架"按钮,合并为一个权限) +events.regulation.view # 赛事规程-查看(赛事列表表格中的"赛事规程"列,点击"查看"链接) + +events.orders.view # 订单管理-查看(页面默认查看权限) +events.orders.refund # 订单管理-重新退款(表格操作列,退款状态为3时显示"重新退款"按钮) + +events.users.view # 用户列表-查看(页面默认查看权限) +events.users.toggle_status # 用户列表-启用/禁用(表格操作列,根据用户状态显示"启用"或"禁用"按钮,合并为一个权限) + +events.banner.view # Banner配置-查看(页面默认查看权限) +events.banner.add # Banner配置-新增(筛选栏中的"新增"按钮) +events.banner.edit # Banner配置-编辑(表格操作列中的"编辑"按钮) +events.banner.toggle_status # Banner配置-启用/禁用(表格操作列,根据状态显示"启用"或"禁用"按钮,合并为一个权限) +events.banner.delete # Banner配置-删除(表格操作列中的"删除"按钮,红色危险样式) + +events.logs.view # 赛事操作日志-查看(页面默认查看权限,无操作列按钮) + +# ─── 账务管理模块 ───────────────────────────────────────── + +finance.withdraw.view # 提现申请-查看(页面默认查看权限) +finance.withdraw.audit # 提现申请-审核(表格操作列,审核状态为"待审核"时显示"审核"按钮) + +finance.wallet.view # 用户钱包-查看(页面默认查看权限) +finance.wallet.detail # 用户钱包-查看明细(表格操作列中的"明细"按钮,打开交易明细弹窗) + +finance.payments.view # 支付流水-查看(页面默认查看权限,无操作列按钮,仅展示数据+金额汇总) + +finance.reports.view # 账务报表-查看(页面默认查看权限,无操作列按钮,展示统计卡+趋势图+明细表) + +# ─── 系统管理模块 ───────────────────────────────────────── + +system.users.view # 用户管理-查看(页面默认查看权限) +system.users.add # 用户管理-新增(筛选栏中的"新增"按钮) +system.users.edit # 用户管理-编辑(表格操作列中的"编辑"按钮) +system.users.toggle_status # 用户管理-启用/禁用(表格操作列,根据用户状态显示"启用"或"禁用"按钮,合并为一个权限) + +system.roles.view # 角色权限-查看(页面默认查看权限) +system.roles.add # 角色权限-新增(筛选栏中的"新增角色"按钮) +system.roles.edit # 角色权限-编辑(表格操作列中的"编辑"按钮) +system.roles.delete # 角色权限-删除(表格操作列中的"删除"按钮,红色危险样式) + +system.logs.view # 操作日志-查看(页面默认查看权限,无操作列按钮) + +system.params.view # 参数配置-查看 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e2757e6..aa8320a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,12 +11,18 @@ importers: '@ant-design/icons-vue': specifier: ^7.0.1 version: 7.0.1(vue@3.5.40(typescript@5.9.3)) + '@types/big.js': + specifier: ^7.0.0 + version: 7.0.0 '@yp-component/root': specifier: ^0.0.48 version: 0.0.48(typescript@5.9.3) ant-design-vue: specifier: ^4.0.0 version: 4.2.6(vue@3.5.40(typescript@5.9.3)) + big.js: + specifier: ^7.0.1 + version: 7.0.1 china-area-data: specifier: ^5.0.1 version: 5.0.1 @@ -72,6 +78,12 @@ importers: '@vitejs/plugin-vue-jsx': specifier: ^4.0.0 version: 4.2.0(vite@5.4.21(@types/node@20.19.43)(less@4.8.0))(vue@3.5.40(typescript@5.9.3)) + '@vitest/coverage-v8': + specifier: 2.1.9 + version: 2.1.9(vitest@2.1.9(@types/node@20.19.43)(jsdom@30.0.1)(less@4.8.0)) + '@vue/test-utils': + specifier: ^2.4.11 + version: 2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@5.9.3)) eslint: specifier: ^8.0.0 version: 8.57.1 @@ -87,6 +99,9 @@ importers: husky: specifier: ^9.1.7 version: 9.1.7 + jsdom: + specifier: ^30.0.1 + version: 30.0.1 less: specifier: ^4.6.4 version: 4.8.0 @@ -105,12 +120,19 @@ importers: vite-plugin-remove-console: specifier: ^2.2.0 version: 2.2.0 + vitest: + specifier: ^2.1.9 + version: 2.1.9(@types/node@20.19.43)(jsdom@30.0.1)(less@4.8.0) vue-tsc: specifier: ^2.0.0 version: 2.2.12(typescript@5.9.3) packages: + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + '@ant-design/colors@6.0.0': resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} @@ -122,6 +144,14 @@ packages: peerDependencies: vue: '>=3.0.3' + '@asamuzakjp/css-color@6.0.5': + resolution: {integrity: sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA==} + engines: {node: ^22.13.0 || >=24.0.0} + + '@asamuzakjp/dom-selector@8.3.2': + resolution: {integrity: sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==} + engines: {node: ^22.13.0 || >=24.0.0} + '@babel/code-frame@7.29.7': resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} engines: {node: '>=6.9.0'} @@ -243,6 +273,13 @@ packages: resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@bramus/specificity@2.4.2': + resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} + hasBin: true + '@commitlint/cli@20.5.3': resolution: {integrity: sha512-OJdL0EXWD5y9LPa0nr/geOwzaS8BsdaybKkcloB0JgsguGxNv2R+hC2FTPqrAcprg35zF33KOQerY0x8W1aesA==} engines: {node: '>=v18'} @@ -324,6 +361,42 @@ packages: conventional-commits-parser: optional: true + '@csstools/color-helpers@6.1.0': + resolution: {integrity: sha512-064IFJdjTfUqnjpCVpMOdbr8FLQBhinbZj6yRv2An2E41O/pLEXqfFRWqGq/SxlE5PEUYTlvWsG2r8MswAVvkg==} + engines: {node: '>=20.19.0'} + + '@csstools/css-calc@3.3.0': + resolution: {integrity: sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-color-parser@4.1.10': + resolution: {integrity: sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-parser-algorithms': ^4.0.0 + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-parser-algorithms@4.0.0': + resolution: {integrity: sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==} + engines: {node: '>=20.19.0'} + peerDependencies: + '@csstools/css-tokenizer': ^4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.7': + resolution: {integrity: sha512-fQ+05118eQS1cofO3aJpB5efgpBZMvIzwr/sbC8kDLVA5XLG8q1kJV5yzrUAI1f7lvhPnm8fgIjzFB8/O/5Dig==} + peerDependencies: + css-tree: ^3.2.1 + peerDependenciesMeta: + css-tree: + optional: true + + '@csstools/css-tokenizer@4.0.0': + resolution: {integrity: sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==} + engines: {node: '>=20.19.0'} + '@ctrl/tinycolor@3.6.1': resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} engines: {node: '>=10'} @@ -490,6 +563,15 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@exodus/bytes@1.15.1': + resolution: {integrity: sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + peerDependencies: + '@noble/hashes': ^1.8.0 || ^2.0.0 + peerDependenciesMeta: + '@noble/hashes': + optional: true + '@humanwhocodes/config-array@0.13.0': resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} engines: {node: '>=10.10.0'} @@ -503,6 +585,14 @@ packages: resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/schema@0.1.6': + resolution: {integrity: sha512-+Sg6GCR/wy1oSmQDFq4LQDAhm3ETKnorxN+y5nbLULOR3P0c14f2Wurzj3/xqPXtasLFfHd5iRFQ7AJt4KH2cw==} + engines: {node: '>=8'} + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -531,6 +621,13 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@one-ini/wasm@0.1.1': + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@pkgr/core@0.3.6': resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} engines: {node: ^14.18.0 || >=16.0.0} @@ -692,6 +789,9 @@ packages: resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==} engines: {node: '>=18'} + '@types/big.js@7.0.0': + resolution: {integrity: sha512-WfAGp7IbJvyB8EmWK4tJD24rJRAL6uVbw3LV/hJntFNam+os9KWKj0PzXo8rRRpjupYK8U0M8FoBB8dBhWF2dg==} + '@types/estree@1.0.9': resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==} @@ -782,6 +882,44 @@ packages: vite: ^4.0.0 || ^5.0.0 vue: ^3.2.25 + '@vitest/coverage-v8@2.1.9': + resolution: {integrity: sha512-Z2cOr0ksM00MpEfyVE8KXIYPEcBFxdbLSs56L8PO0QQMxt/6bDj45uQfxoc96v05KW3clk7vvgP0qfDit9DmfQ==} + peerDependencies: + '@vitest/browser': 2.1.9 + vitest: 2.1.9 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@2.1.9': + resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==} + + '@vitest/mocker@2.1.9': + resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@2.1.9': + resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==} + + '@vitest/runner@2.1.9': + resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==} + + '@vitest/snapshot@2.1.9': + resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==} + + '@vitest/spy@2.1.9': + resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==} + + '@vitest/utils@2.1.9': + resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==} + '@volar/language-core@2.4.15': resolution: {integrity: sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==} @@ -848,9 +986,23 @@ packages: '@vue/shared@3.5.40': resolution: {integrity: sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==} + '@vue/test-utils@2.4.11': + resolution: {integrity: sha512-GDqaqZsA6m2E5vNzej0aYiIb6BX8xV9pNSbbbXKOfEYwg7ZNblVX8suyqmUBThq8VIrgAJNxn+z72hVtUeiWHA==} + peerDependencies: + '@vue/compiler-dom': 3.x + '@vue/server-renderer': 3.x + vue: 3.x + peerDependenciesMeta: + '@vue/server-renderer': + optional: true + '@yp-component/root@0.0.48': resolution: {integrity: sha512-TOp8adAob3pMSfecQjEC4uVNCGqNWcShDjSQysd4pYY34i5ldFLRGSiJdpLsFG1xKkcSudiqEc/Si/ZfYoDSqA==} + abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + accepts@2.0.0: resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==} engines: {node: '>= 0.6'} @@ -913,12 +1065,20 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + async-validator@4.2.5: resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + base64-arraybuffer@1.0.2: resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} engines: {node: '>= 0.6.0'} @@ -928,6 +1088,12 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + + big.js@7.0.1: + resolution: {integrity: sha512-iFgV784tD8kq4ccF1xtNMZnXeZzVuXWWM+ERFzKQjv+A5G9HC8CY3DuV45vgzFFcW+u2tIvmF95+AzWgs6BjCg==} + body-parser@2.3.0: resolution: {integrity: sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==} engines: {node: '>=18'} @@ -941,6 +1107,10 @@ packages: brace-expansion@2.1.2: resolution: {integrity: sha512-w5JZcKgdhDOgOwm8H+KgbosopHMuGcl6qbulwjtz3SM7I7P3yW1eAjzMPLrIE+NQ9vjgANKHWeMHnrT0OXW1oA==} + brace-expansion@5.0.9: + resolution: {integrity: sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==} + engines: {node: 20 || >=22} + braces@3.0.3: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} @@ -954,6 +1124,10 @@ packages: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -969,6 +1143,10 @@ packages: caniuse-lite@1.0.30001806: resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -977,6 +1155,10 @@ packages: resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + china-area-data@5.0.1: resolution: {integrity: sha512-BQDPpiv5Nn+018ekcJK2oSD9PAD+E1bvXB0wgabc//dFVS/KvRqCgg0QOEUt3vBkx9XzB5a9BmkJCEZDBxVjVw==} @@ -1002,6 +1184,10 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + commander@13.1.0: resolution: {integrity: sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==} engines: {node: '>=18'} @@ -1015,6 +1201,9 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + content-disposition@1.1.0: resolution: {integrity: sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==} engines: {node: '>=18'} @@ -1085,6 +1274,10 @@ packages: css-line-break@2.1.0: resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + css-tree@3.2.1: + resolution: {integrity: sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -1093,6 +1286,10 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + data-urls@7.0.0: + resolution: {integrity: sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + dayjs@1.11.21: resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} @@ -1124,6 +1321,13 @@ packages: supports-color: optional: true + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1153,9 +1357,17 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + echarts@5.6.0: resolution: {integrity: sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==} + editorconfig@1.0.7: + resolution: {integrity: sha512-e0GOtq/aTQhVdNyDU9e02+wz9oDDM+SIOQxWME2QRjzRX5yyLAuHDE+0aE8vHb9XRC8XD37eO2u57+F09JqFhw==} + engines: {node: '>=14'} + hasBin: true + ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} @@ -1168,6 +1380,9 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encodeurl@2.0.0: resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} engines: {node: '>= 0.8'} @@ -1176,6 +1391,10 @@ packages: resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} engines: {node: '>=0.12'} + entities@8.0.0: + resolution: {integrity: sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==} + engines: {node: '>=20.19.0'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -1199,6 +1418,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} @@ -1281,6 +1503,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -1296,6 +1521,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + expect-type@1.4.0: + resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + engines: {node: '>=12.0.0'} + express@5.2.1: resolution: {integrity: sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==} engines: {node: '>= 18'} @@ -1345,6 +1574,10 @@ packages: flatted@3.4.3: resolution: {integrity: sha512-/zipXxyO6rGvuNGDiULY9MvEGSkb2gaG4GGH4ygMi0ZZzyMHdUZBmntJmx5x1G2VuPytCwGN4xsJP6cw+sK+vQ==} + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -1401,6 +1634,10 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported @@ -1443,6 +1680,13 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + html-encoding-sniffer@6.0.0: + resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html2canvas@1.4.1: resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} engines: {node: '>=8.0.0'} @@ -1494,6 +1738,9 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + ini@6.0.0: resolution: {integrity: sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ==} engines: {node: ^20.17.0 || >=22.9.0} @@ -1545,6 +1792,9 @@ packages: resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==} engines: {node: '>=0.10.0'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -1559,10 +1809,37 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + js-beautify@1.15.4: + resolution: {integrity: sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==} + engines: {node: '>=14'} + hasBin: true + + js-cookie@3.0.8: + resolution: {integrity: sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -1570,6 +1847,15 @@ packages: resolution: {integrity: sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==} hasBin: true + jsdom@30.0.1: + resolution: {integrity: sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==} + engines: {node: ^22.22.2 || ^24.15.0 || >=26.0.0} + peerDependencies: + canvas: ^3.2.3 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -1644,12 +1930,29 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@11.5.2: + resolution: {integrity: sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + make-dir@5.1.0: resolution: {integrity: sha512-IfpFq6UM39dUNiphpA6uDezNx/AvWyhwfICWPR3t1VspkgkMZrL+Rk1RbN1bx+aeNYwOrqGJgEgV3yotk+ZUVw==} engines: {node: '>=18'} @@ -1658,6 +1961,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdn-data@2.27.1: + resolution: {integrity: sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==} + media-typer@1.1.0: resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==} engines: {node: '>= 0.8'} @@ -1702,6 +2008,10 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} + minimatch@10.2.6: + resolution: {integrity: sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==} + engines: {node: 18 || 20 || >=22} + minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} @@ -1716,6 +2026,10 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -1754,6 +2068,11 @@ packages: resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} engines: {node: '>=18'} + nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1792,6 +2111,9 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -1804,6 +2126,9 @@ packages: resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} engines: {node: '>= 0.10'} + parse5@8.0.1: + resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -1827,6 +2152,10 @@ packages: resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} engines: {node: '>=12'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@8.4.2: resolution: {integrity: sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==} @@ -1834,6 +2163,13 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -1874,6 +2210,9 @@ packages: probe-image-size@7.3.0: resolution: {integrity: sha512-7CaDeBwiAbh6ohXsvLbAZhO7wzsZAmaevfxe39qvCwRh8LyaZfDlBGGLU1CCTgrTLtCOdwBBhjOrIHaIIimHfQ==} + proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -1954,6 +2293,10 @@ packages: resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} engines: {node: '>=11.0.0'} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scroll-into-view-if-needed@2.2.31: resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==} @@ -2004,6 +2347,9 @@ packages: resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -2028,10 +2374,16 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + statuses@2.0.2: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + stream-parser@0.3.1: resolution: {integrity: sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==} @@ -2043,6 +2395,10 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} @@ -2070,10 +2426,17 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + synckit@0.11.13: resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} engines: {node: ^14.18.0 || >=16.0.0} + test-exclude@7.0.2: + resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} + engines: {node: '>=18'} + text-segmentation@1.0.3: resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} @@ -2084,10 +2447,35 @@ packages: resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} engines: {node: '>=12.22'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.2.4: resolution: {integrity: sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==} engines: {node: '>=18'} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@1.2.0: + resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tldts-core@7.4.10: + resolution: {integrity: sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==} + + tldts@7.4.10: + resolution: {integrity: sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2096,6 +2484,14 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + tough-cookie@6.0.2: + resolution: {integrity: sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==} + engines: {node: '>=16'} + + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + ts-api-utils@1.4.3: resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} @@ -2125,6 +2521,10 @@ packages: undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + undici@8.10.0: + resolution: {integrity: sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==} + engines: {node: '>=22.19.0'} + unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -2148,6 +2548,11 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + vite-node@2.1.9: + resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + vite-plugin-remove-console@2.2.0: resolution: {integrity: sha512-qgjh5pz75MdE9Kzs8J0kBwaCfifHV0ezRbB9rpGsIOxam+ilcGV7WOk91vFJXquzRmiKrFh3Hxlh0JJWAmXTbQ==} @@ -2182,9 +2587,37 @@ packages: terser: optional: true + vitest@2.1.9: + resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 2.1.9 + '@vitest/ui': 2.1.9 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + vue-component-type-helpers@3.3.9: + resolution: {integrity: sha512-3c/UfMe0SqyEfcGTyH7mfshHagJ9QTCbppCb0/uGpHZpFug7+If3GeGZN7I0YheKEExemx3xldQPoO7PQSOLQg==} + vue-eslint-parser@9.4.3: resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} engines: {node: ^14.17.0 || >=16.0.0} @@ -2221,14 +2654,39 @@ packages: typescript: optional: true + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + warning@4.0.3: resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + webidl-conversions@8.0.1: + resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} + engines: {node: '>=20'} + + whatwg-mimetype@5.0.0: + resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==} + engines: {node: '>=20'} + + whatwg-url@16.0.1: + resolution: {integrity: sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==} + engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + + whatwg-url@17.1.0: + resolution: {integrity: sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==} + engines: {node: ^22.14.0 || >=24.0.0} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -2237,6 +2695,10 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} @@ -2248,6 +2710,13 @@ packages: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -2277,6 +2746,11 @@ packages: snapshots: + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@ant-design/colors@6.0.0': dependencies: '@ctrl/tinycolor': 3.6.1 @@ -2289,6 +2763,21 @@ snapshots: '@ant-design/icons-svg': 4.5.0 vue: 3.5.40(typescript@5.9.3) + '@asamuzakjp/css-color@6.0.5': + dependencies: + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-color-parser': 4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + lru-cache: 11.5.2 + + '@asamuzakjp/dom-selector@8.3.2': + dependencies: + bidi-js: 1.0.3 + css-tree: 3.2.1 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.2 + '@babel/code-frame@7.29.7': dependencies: '@babel/helper-validator-identifier': 7.29.7 @@ -2458,6 +2947,12 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 + '@bcoe/v8-coverage@0.2.3': {} + + '@bramus/specificity@2.4.2': + dependencies: + css-tree: 3.2.1 + '@commitlint/cli@20.5.3(@types/node@20.19.43)(conventional-commits-parser@6.4.0)(typescript@5.9.3)': dependencies: '@commitlint/format': 20.5.0 @@ -2576,6 +3071,30 @@ snapshots: optionalDependencies: conventional-commits-parser: 6.4.0 + '@csstools/color-helpers@6.1.0': {} + + '@csstools/css-calc@3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-color-parser@4.1.10(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/color-helpers': 6.1.0 + '@csstools/css-calc': 3.3.0(@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0))(@csstools/css-tokenizer@4.0.0) + '@csstools/css-parser-algorithms': 4.0.0(@csstools/css-tokenizer@4.0.0) + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-parser-algorithms@4.0.0(@csstools/css-tokenizer@4.0.0)': + dependencies: + '@csstools/css-tokenizer': 4.0.0 + + '@csstools/css-syntax-patches-for-csstree@1.1.7(css-tree@3.2.1)': + optionalDependencies: + css-tree: 3.2.1 + + '@csstools/css-tokenizer@4.0.0': {} + '@ctrl/tinycolor@3.6.1': {} '@emotion/hash@0.9.2': {} @@ -2674,6 +3193,8 @@ snapshots: '@eslint/js@8.57.1': {} + '@exodus/bytes@1.15.1': {} + '@humanwhocodes/config-array@0.13.0': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -2686,6 +3207,17 @@ snapshots: '@humanwhocodes/object-schema@2.0.3': {} + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/schema@0.1.6': {} + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2717,6 +3249,11 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@one-ini/wasm@0.1.1': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + '@pkgr/core@0.3.6': {} '@rolldown/pluginutils@1.0.1': {} @@ -2823,6 +3360,8 @@ snapshots: '@simple-libs/stream-utils@1.2.0': {} + '@types/big.js@7.0.0': {} + '@types/estree@1.0.9': {} '@types/json-schema@7.0.15': {} @@ -2939,6 +3478,64 @@ snapshots: vite: 5.4.21(@types/node@20.19.43)(less@4.8.0) vue: 3.5.40(typescript@5.9.3) + '@vitest/coverage-v8@2.1.9(vitest@2.1.9(@types/node@20.19.43)(jsdom@30.0.1)(less@4.8.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 0.2.3 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.2.0 + magic-string: 0.30.21 + magicast: 0.3.5 + std-env: 3.10.0 + test-exclude: 7.0.2 + tinyrainbow: 1.2.0 + vitest: 2.1.9(@types/node@20.19.43)(jsdom@30.0.1)(less@4.8.0) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@2.1.9': + dependencies: + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + tinyrainbow: 1.2.0 + + '@vitest/mocker@2.1.9(vite@5.4.21(@types/node@20.19.43)(less@4.8.0))': + dependencies: + '@vitest/spy': 2.1.9 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 5.4.21(@types/node@20.19.43)(less@4.8.0) + + '@vitest/pretty-format@2.1.9': + dependencies: + tinyrainbow: 1.2.0 + + '@vitest/runner@2.1.9': + dependencies: + '@vitest/utils': 2.1.9 + pathe: 1.1.2 + + '@vitest/snapshot@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + magic-string: 0.30.21 + pathe: 1.1.2 + + '@vitest/spy@2.1.9': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@2.1.9': + dependencies: + '@vitest/pretty-format': 2.1.9 + loupe: 3.2.1 + tinyrainbow: 1.2.0 + '@volar/language-core@2.4.15': dependencies: '@volar/source-map': 2.4.15 @@ -3054,6 +3651,15 @@ snapshots: '@vue/shared@3.5.40': {} + '@vue/test-utils@2.4.11(@vue/compiler-dom@3.5.40)(@vue/server-renderer@3.5.40)(vue@3.5.40(typescript@5.9.3))': + dependencies: + '@vue/compiler-dom': 3.5.40 + js-beautify: 1.15.4 + vue: 3.5.40(typescript@5.9.3) + vue-component-type-helpers: 3.3.9 + optionalDependencies: + '@vue/server-renderer': 3.5.40 + '@yp-component/root@0.0.48(typescript@5.9.3)': dependencies: cropperjs: 1.6.2 @@ -3061,6 +3667,8 @@ snapshots: transitivePeerDependencies: - typescript + abbrev@2.0.0: {} + accepts@2.0.0: dependencies: mime-types: 3.0.2 @@ -3136,14 +3744,24 @@ snapshots: array-union@2.1.0: {} + assertion-error@2.0.1: {} + async-validator@4.2.5: {} balanced-match@1.0.2: {} + balanced-match@4.0.4: {} + base64-arraybuffer@1.0.2: {} baseline-browser-mapping@2.11.1: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + + big.js@7.0.1: {} + body-parser@2.3.0: dependencies: bytes: 3.1.2 @@ -3169,6 +3787,10 @@ snapshots: dependencies: balanced-match: 1.0.2 + brace-expansion@5.0.9: + dependencies: + balanced-match: 4.0.4 + braces@3.0.3: dependencies: fill-range: 7.1.1 @@ -3183,6 +3805,8 @@ snapshots: bytes@3.1.2: {} + cac@6.7.14: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -3197,6 +3821,14 @@ snapshots: caniuse-lite@1.0.30001806: {} + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -3204,6 +3836,8 @@ snapshots: chalk@5.6.2: {} + check-error@2.1.3: {} + china-area-data@5.0.1: {} cli-cursor@5.0.0: @@ -3229,6 +3863,8 @@ snapshots: colorette@2.0.20: {} + commander@10.0.1: {} + commander@13.1.0: {} compare-func@2.0.0: @@ -3240,6 +3876,11 @@ snapshots: concat-map@0.0.1: {} + config-chain@1.1.13: + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + content-disposition@1.1.0: {} content-type@1.0.5: {} @@ -3299,10 +3940,22 @@ snapshots: dependencies: utrie: 1.0.2 + css-tree@3.2.1: + dependencies: + mdn-data: 2.27.1 + source-map-js: 1.2.1 + cssesc@3.0.0: {} csstype@3.2.3: {} + data-urls@7.0.0: + dependencies: + whatwg-mimetype: 5.0.0 + whatwg-url: 16.0.1 + transitivePeerDependencies: + - '@noble/hashes' + dayjs@1.11.21: {} de-indent@1.0.2: {} @@ -3321,6 +3974,10 @@ snapshots: dependencies: ms: 2.1.3 + decimal.js@10.6.0: {} + + deep-eql@5.0.2: {} + deep-is@0.1.4: {} depd@2.0.0: {} @@ -3347,11 +4004,20 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + echarts@5.6.0: dependencies: tslib: 2.3.0 zrender: 5.6.1 + editorconfig@1.0.7: + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.9 + semver: 7.8.5 + ee-first@1.1.1: {} electron-to-chromium@1.5.395: {} @@ -3360,10 +4026,14 @@ snapshots: emoji-regex@8.0.0: {} + emoji-regex@9.2.2: {} + encodeurl@2.0.0: {} entities@7.0.1: {} + entities@8.0.0: {} + env-paths@2.2.1: {} environment@1.1.0: {} @@ -3381,6 +4051,8 @@ snapshots: es-errors@1.3.0: {} + es-module-lexer@1.7.0: {} + es-object-atoms@1.1.2: dependencies: es-errors: 1.3.0 @@ -3514,6 +4186,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.9 + esutils@2.0.3: {} etag@1.8.1: {} @@ -3532,6 +4208,8 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + expect-type@1.4.0: {} + express@5.2.1: dependencies: accepts: 2.0.0 @@ -3619,6 +4297,11 @@ snapshots: flatted@3.4.3: {} + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + forwarded@0.2.0: {} fresh@2.0.0: {} @@ -3672,6 +4355,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.9 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -3715,6 +4407,14 @@ snapshots: he@1.2.0: {} + html-encoding-sniffer@6.0.0: + dependencies: + '@exodus/bytes': 1.15.1 + transitivePeerDependencies: + - '@noble/hashes' + + html-escaper@2.0.2: {} + html2canvas@1.4.1: dependencies: css-line-break: 2.1.0 @@ -3764,6 +4464,8 @@ snapshots: inherits@2.0.4: {} + ini@1.3.8: {} + ini@6.0.0: {} ipaddr.js@1.9.1: {} @@ -3794,6 +4496,8 @@ snapshots: is-plain-object@3.0.1: {} + is-potential-custom-element-name@1.0.1: {} + is-promise@4.0.0: {} is-stream@3.0.0: {} @@ -3802,14 +4506,77 @@ snapshots: isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + debug: 4.4.3 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jiti@2.6.1: {} + js-beautify@1.15.4: + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.7 + glob: 10.4.5 + js-cookie: 3.0.8 + nopt: 7.2.1 + + js-cookie@3.0.8: {} + js-tokens@4.0.0: {} js-yaml@4.3.0: dependencies: argparse: 2.0.1 + jsdom@30.0.1: + dependencies: + '@asamuzakjp/css-color': 6.0.5 + '@asamuzakjp/dom-selector': 8.3.2 + '@bramus/specificity': 2.4.2 + '@csstools/css-syntax-patches-for-csstree': 1.1.7(css-tree@3.2.1) + '@exodus/bytes': 1.15.1 + css-tree: 3.2.1 + data-urls: 7.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 6.0.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.5.2 + parse5: 8.0.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.2 + undici: 8.10.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.1 + whatwg-mimetype: 5.0.0 + whatwg-url: 17.1.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - '@noble/hashes' + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -3898,6 +4665,12 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@3.2.1: {} + + lru-cache@10.4.3: {} + + lru-cache@11.5.2: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -3906,11 +4679,23 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magicast@0.3.5: + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.8.5 + make-dir@5.1.0: optional: true math-intrinsics@1.1.0: {} + mdn-data@2.27.1: {} + media-typer@1.1.0: {} meow@13.2.0: {} @@ -3939,6 +4724,10 @@ snapshots: mimic-function@5.0.1: {} + minimatch@10.2.6: + dependencies: + brace-expansion: 5.0.9 + minimatch@3.1.5: dependencies: brace-expansion: 1.1.16 @@ -3953,6 +4742,8 @@ snapshots: minimist@1.2.8: {} + minipass@7.1.3: {} + ms@2.0.0: optional: true @@ -3985,6 +4776,10 @@ snapshots: node-releases@2.0.51: {} + nopt@7.2.1: + dependencies: + abbrev: 2.0.0 + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 @@ -4028,6 +4823,8 @@ snapshots: dependencies: p-limit: 3.1.0 + package-json-from-dist@1.0.1: {} + parent-module@1.0.1: dependencies: callsites: 3.1.0 @@ -4041,6 +4838,10 @@ snapshots: parse-node-version@1.0.1: {} + parse5@8.0.1: + dependencies: + entities: 8.0.0 + parseurl@1.3.3: {} path-browserify@1.0.1: {} @@ -4053,10 +4854,19 @@ snapshots: path-key@4.0.0: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + path-to-regexp@8.4.2: {} path-type@4.0.0: {} + pathe@1.1.2: {} + + pathval@2.0.1: {} + picocolors@1.1.1: {} picomatch@2.3.2: {} @@ -4093,6 +4903,8 @@ snapshots: - supports-color optional: true + proto-list@1.2.4: {} + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -4192,6 +5004,10 @@ snapshots: sax@1.6.0: optional: true + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scroll-into-view-if-needed@2.2.31: dependencies: compute-scroll-into-view: 1.0.20 @@ -4263,6 +5079,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + signal-exit@4.1.0: {} slash@3.0.0: {} @@ -4282,8 +5100,12 @@ snapshots: source-map@0.6.1: optional: true + stackback@0.0.2: {} + statuses@2.0.2: {} + std-env@3.10.0: {} + stream-parser@0.3.1: dependencies: debug: 2.6.9 @@ -4299,6 +5121,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + string-width@7.2.0: dependencies: emoji-regex: 10.6.0 @@ -4323,10 +5151,18 @@ snapshots: dependencies: has-flag: 4.0.0 + symbol-tree@3.2.4: {} + synckit@0.11.13: dependencies: '@pkgr/core': 0.3.6 + test-exclude@7.0.2: + dependencies: + '@istanbuljs/schema': 0.1.6 + glob: 10.4.5 + minimatch: 10.2.6 + text-segmentation@1.0.3: dependencies: utrie: 1.0.2 @@ -4335,14 +5171,38 @@ snapshots: throttle-debounce@5.0.2: {} + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + tinyexec@1.2.4: {} + tinypool@1.1.1: {} + + tinyrainbow@1.2.0: {} + + tinyspy@3.0.2: {} + + tldts-core@7.4.10: {} + + tldts@7.4.10: + dependencies: + tldts-core: 7.4.10 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 toidentifier@1.0.1: {} + tough-cookie@6.0.2: + dependencies: + tldts: 7.4.10 + + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + ts-api-utils@1.4.3(typescript@5.9.3): dependencies: typescript: 5.9.3 @@ -4365,6 +5225,8 @@ snapshots: undici-types@6.21.0: {} + undici@8.10.0: {} + unpipe@1.0.0: {} update-browserslist-db@1.2.3(browserslist@4.28.7): @@ -4385,6 +5247,24 @@ snapshots: vary@1.1.2: {} + vite-node@2.1.9(@types/node@20.19.43)(less@4.8.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 1.1.2 + vite: 5.4.21(@types/node@20.19.43)(less@4.8.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vite-plugin-remove-console@2.2.0: {} vite@5.4.21(@types/node@20.19.43)(less@4.8.0): @@ -4397,8 +5277,46 @@ snapshots: fsevents: 2.3.3 less: 4.8.0 + vitest@2.1.9(@types/node@20.19.43)(jsdom@30.0.1)(less@4.8.0): + dependencies: + '@vitest/expect': 2.1.9 + '@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@20.19.43)(less@4.8.0)) + '@vitest/pretty-format': 2.1.9 + '@vitest/runner': 2.1.9 + '@vitest/snapshot': 2.1.9 + '@vitest/spy': 2.1.9 + '@vitest/utils': 2.1.9 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.4.0 + magic-string: 0.30.21 + pathe: 1.1.2 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.1.1 + tinyrainbow: 1.2.0 + vite: 5.4.21(@types/node@20.19.43)(less@4.8.0) + vite-node: 2.1.9(@types/node@20.19.43)(less@4.8.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 20.19.43 + jsdom: 30.0.1 + transitivePeerDependencies: + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + vscode-uri@3.1.0: {} + vue-component-type-helpers@3.3.9: {} + vue-eslint-parser@9.4.3(eslint@8.57.1): dependencies: debug: 4.4.3 @@ -4442,14 +5360,43 @@ snapshots: optionalDependencies: typescript: 5.9.3 + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + warning@4.0.3: dependencies: loose-envify: 1.4.0 + webidl-conversions@8.0.1: {} + + whatwg-mimetype@5.0.0: {} + + whatwg-url@16.0.1: + dependencies: + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + + whatwg-url@17.1.0: + dependencies: + '@exodus/bytes': 1.15.1 + tr46: 6.0.0 + webidl-conversions: 8.0.1 + transitivePeerDependencies: + - '@noble/hashes' + which@2.0.2: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} wrap-ansi@7.0.0: @@ -4458,6 +5405,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 @@ -4468,6 +5421,10 @@ snapshots: xml-name-validator@4.0.0: {} + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + y18n@5.0.8: {} yallist@3.1.1: {} diff --git a/src/api/banner/types.ts b/src/api/banner/types.ts index d95d867..ad2ac86 100644 --- a/src/api/banner/types.ts +++ b/src/api/banner/types.ts @@ -47,7 +47,7 @@ export interface BannerActiveParams { } export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } diff --git a/src/api/events/types.ts b/src/api/events/types.ts index c2c53a6..d7e25cd 100644 --- a/src/api/events/types.ts +++ b/src/api/events/types.ts @@ -87,7 +87,7 @@ export interface PageData { /** 统一响应包裹 */ export interface ApiResult { /** 编码:200表示成功,其他值表示失败 */ - code: number; + code: number | string; /** 消息内容 */ msg: string; /** 响应数据 */ diff --git a/src/api/login/index.ts b/src/api/login/index.ts index 1acfc8a..aff4797 100644 --- a/src/api/login/index.ts +++ b/src/api/login/index.ts @@ -5,8 +5,15 @@ export type { LoginResult } from './types'; export const login = (params: { phone: string; password: string }) => { return post(`/op/login`, params) as Promise<{ - code: number; + code: number | string; msg: string; data: LoginResult; }>; }; + +export const logout = () => { + return post(`/op/logout`) as Promise<{ + code: number | string; + msg: string; + }>; +}; diff --git a/src/api/logs/types.ts b/src/api/logs/types.ts index 87cdf03..cda14a7 100644 --- a/src/api/logs/types.ts +++ b/src/api/logs/types.ts @@ -57,7 +57,7 @@ export interface PageData { } export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } diff --git a/src/api/menu.ts b/src/api/menu.ts index f9be5b1..5fb2961 100644 --- a/src/api/menu.ts +++ b/src/api/menu.ts @@ -18,6 +18,7 @@ export interface AuthData { } const AUTH_FETCH_FAIL_MSG = '账户权限获取失败,请重新登录'; +const AUTH_EMPTY_MSG = '当前账户权限无任何权限,请联系管理员'; function normalizeAuthData(res: any): AuthData { if (res?.code != null && res.code != 200) { @@ -29,7 +30,7 @@ function normalizeAuthData(res: any): AuthData { const permsList = data.permsList || []; if (permsList.length === 0) { - throw new Error(AUTH_FETCH_FAIL_MSG); + throw new Error(AUTH_EMPTY_MSG); } const nickname = data.nickName || ''; @@ -46,9 +47,9 @@ function normalizeAuthData(res: any): AuthData { return { roleList, permsList, nickname, phone }; } -function handleAuthFetchFailure() { +function handleAuthFetchFailure(msg?: string) { clearAuthDataCache(); - forceReLogin(AUTH_FETCH_FAIL_MSG); + forceReLogin(msg); } /** @@ -62,8 +63,8 @@ export function fetchAuthData(): Promise { const promise = get('/op/permission') .then((res) => normalizeAuthData(res)) - .catch((err) => { - handleAuthFetchFailure(); + .catch((err: Error) => { + handleAuthFetchFailure(err.message); throw err; }); diff --git a/src/api/orders/types.ts b/src/api/orders/types.ts index 5040641..b83bff0 100644 --- a/src/api/orders/types.ts +++ b/src/api/orders/types.ts @@ -88,7 +88,7 @@ export interface PageData { /** 统一响应包裹 */ export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } @@ -99,14 +99,8 @@ export interface ApiResult { /** 退款记录 */ export interface InnerRefundInfo { - /** 已退金额;0.00格式 */ - refundedAmount: string; - /** 总退款次数(接口实际返回 string) */ - totalRefundCount: string; /** 退款金额;0.00格式 */ refundAmount: string; - /** 是否全部退款;0=否,1=是(接口实际返回 string) */ - isFullRefund: string; /** 退款方式 */ refundMethod: string; /** 退款申请时间 */ @@ -115,6 +109,10 @@ export interface InnerRefundInfo { refundOutTradeNo: string; /** 退款完成时间 */ refundTime: string; + /** 退款状态;1=退款中,2=退款成功,3=退款失败 */ + refundStatus: string; + /** 退款选手名称合集文字 */ + refundSignupNames: string; } /** 订单详情 */ @@ -142,9 +140,9 @@ export interface TournamentAdminOrderInfoVO { /** 订单详情查询参数 */ export interface OrderDetailQueryParams { /** 订单编号 */ - orderNo: string; + orderNo?: string; /** 选手ID */ - uniqueId: string; + uniqueId?: string; } // ============================================================ @@ -180,9 +178,9 @@ export interface TournamentAdminOrderInfoPageVO { /** 选手列表查询参数 */ export interface OrderPlayerListQueryParams { /** 订单编号 */ - orderNo: string; + orderNo?: string; /** 选手ID */ - uniqueId: string; + uniqueId?: string; page: string; limit: string; } diff --git a/src/api/params/index.ts b/src/api/params/index.ts new file mode 100644 index 0000000..593e017 --- /dev/null +++ b/src/api/params/index.ts @@ -0,0 +1,49 @@ +/** + * 参数配置 API + * + * TODO: 等后端接口确定后,替换占位的 URL 和返回类型 + */ +import { get, post, put, del } from '@/utils/request'; +import type { ParamQueryParams, SysParamVO, PageData, ApiResult } from './types'; + +// 类型重导出,方便页面 model 层统一引用 +export type { SysParamVO, ParamQueryParams, PageData, ApiResult } from './types'; + +// ============================================================ +// URL 常量(占位,等后端接口确定后替换) +// ============================================================ + +/** 配置列表分页查询 */ +const PARAM_LIST = '/admin/sys/param/page'; +/** 新增配置 */ +const PARAM_ADD = '/admin/sys/param/add'; +/** 编辑配置 */ +const PARAM_UPDATE = '/admin/sys/param/update'; +/** 删除配置 */ +const PARAM_DELETE = '/admin/sys/param/delete'; + +// ============================================================ +// API 函数(占位) +// ============================================================ + +/** 配置列表分页 */ +export async function getParamList( + params: ParamQueryParams, +): Promise>> { + return get(PARAM_LIST, params as Record); +} + +/** 新增配置 */ +export async function addParam(data: Partial): Promise> { + return post(PARAM_ADD, data); +} + +/** 编辑配置 */ +export async function updateParam(data: Partial): Promise> { + return put(PARAM_UPDATE, data); +} + +/** 删除配置 */ +export async function deleteParam(id: number): Promise> { + return del(`${PARAM_DELETE}`, { id }); +} diff --git a/src/api/params/types.ts b/src/api/params/types.ts new file mode 100644 index 0000000..5a6c40c --- /dev/null +++ b/src/api/params/types.ts @@ -0,0 +1,40 @@ +/** + * 参数配置 — 类型定义 + * + * TODO: 等后端接口确定后,根据实际字段补充完整类型 + */ + +/** 配置项列表项 */ +export interface SysParamVO { + /** 配置项 ID */ + id: number; + /** 配置项 key */ + // paramKey: string; + /** 配置项 value */ + // paramValue: string; + /** 备注 */ + // remark: string; + /** 更新时间 */ + // updateTime: string; +} + +/** 配置列表查询参数 */ +export interface ParamQueryParams { + page?: string; + limit?: string; + /** 搜索关键字 */ + // keyword?: string; +} + +/** 分页数据结构 */ +export interface PageData { + total: number; + list: T[]; +} + +/** API 统一响应格式 */ +export interface ApiResult { + code: number | string; + msg: string; + data: T; +} diff --git a/src/api/payments/types.ts b/src/api/payments/types.ts index 48b433f..a946cec 100644 --- a/src/api/payments/types.ts +++ b/src/api/payments/types.ts @@ -58,7 +58,7 @@ export interface PaymentFlowPageData { } export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } diff --git a/src/api/reports/types.ts b/src/api/reports/types.ts index 150473a..d82a477 100644 --- a/src/api/reports/types.ts +++ b/src/api/reports/types.ts @@ -42,7 +42,7 @@ export interface ReportQueryParams { } export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } diff --git a/src/api/roles/types.ts b/src/api/roles/types.ts index b4b6219..fc9b4d1 100644 --- a/src/api/roles/types.ts +++ b/src/api/roles/types.ts @@ -59,7 +59,7 @@ export interface PageData { list: T[]; } export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } diff --git a/src/api/users/types.ts b/src/api/users/types.ts index 0dbcf4a..1c8eb6c 100644 --- a/src/api/users/types.ts +++ b/src/api/users/types.ts @@ -65,7 +65,7 @@ export interface PageData { list: T[]; } export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } diff --git a/src/api/wallet/types.ts b/src/api/wallet/types.ts index a0dc2aa..7dba886 100644 --- a/src/api/wallet/types.ts +++ b/src/api/wallet/types.ts @@ -55,7 +55,7 @@ export interface PageData { list: T[]; } export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } @@ -84,6 +84,8 @@ export interface WalletTransactionVO { orderNo: string; /** 时间 */ createDate: string; + /** 状态;1=已解冻,2=冻结中,3=正常 */ + status: number; } /** 交易明细查询参数 */ diff --git a/src/api/withdraw/types.ts b/src/api/withdraw/types.ts index f8c688e..74c432e 100644 --- a/src/api/withdraw/types.ts +++ b/src/api/withdraw/types.ts @@ -23,7 +23,7 @@ export interface WithdrawVO { auditStatus: number; /** 到账状态:0=未支付,1=支付成功,2=支付失败 */ payStatus: number; - /** 流水单号 */ + /** 第三方单号 */ serialNumber: string; /** 申请时间 */ createDate: string; @@ -50,7 +50,7 @@ export interface PageData { list: T[]; } export interface ApiResult { - code: number; + code: number | string; msg: string; data: T; } @@ -101,4 +101,6 @@ export interface WithdrawInfoVO { auditImg: string; /** 审核图片列表 */ auditImgList: string[]; + /** 审核结果 */ + checkMsg: string; } diff --git a/src/assets/img/default.png b/src/assets/img/default.png new file mode 100644 index 0000000..d8b4f5b Binary files /dev/null and b/src/assets/img/default.png differ diff --git a/src/components/pageTabs/index.tsx b/src/components/pageTabs/index.tsx index 524bc36..14abe16 100644 --- a/src/components/pageTabs/index.tsx +++ b/src/components/pageTabs/index.tsx @@ -165,9 +165,9 @@ const PageTabs = defineComponent({ case 'other': props.onCloseOther?.(props.activeKey); break; - case 'all': - props.onCloseAll?.(); - break; + // case 'all': + // props.onCloseAll?.(); + // break; } }; @@ -278,7 +278,7 @@ const PageTabs = defineComponent({ {renderBatchMenuItem('left', renderAiIcon(LuPanelLeftClose), '关闭左侧标签页')} {renderBatchMenuItem('right', renderAiIcon(LuPanelRightClose), '关闭右侧标签页')} {renderBatchMenuItem('other', renderAiIcon(LuCopyX), '关闭其它标签页')} - {renderBatchMenuItem('all', renderAiIcon(LuListX), '关闭全部标签页')} + {/* {renderBatchMenuItem('all', renderAiIcon(LuListX), '关闭全部标签页')} */} ), }} diff --git a/src/config/fallbackRoutes.ts b/src/config/fallbackRoutes.ts index efe6173..67eb757 100644 --- a/src/config/fallbackRoutes.ts +++ b/src/config/fallbackRoutes.ts @@ -164,6 +164,15 @@ export const FALLBACK_MENU_NODES: MenuNode[] = [ icon: 'AiOutlineSafetyCertificate', permission: 'system.roles.view', }, + { + id: 'system_params', + name: '参数配置', + path: 'system/params', + component: 'system/params', + componentName: 'SystemParams', + icon: 'AiOutlineSetting', + permission: 'system.params.view', + }, { id: 'system_logs', name: '操作日志', diff --git a/src/hooks/useAuth.ts b/src/hooks/useAuth.ts index 8a81d87..51efda7 100644 --- a/src/hooks/useAuth.ts +++ b/src/hooks/useAuth.ts @@ -7,6 +7,7 @@ import { usePermissionStore } from '@/stores/permissionStore'; import { useTabsStore } from '@/stores/tabsStore'; import { useUserStore } from '@/stores/userStore'; import { clearAuthDataCache } from '@/api/authCache'; +import { logout as logoutApi } from '@/api/login'; import router from '@/router'; const TOKEN_KEY = 'MY_APP_AUTH_TOKEN'; @@ -66,9 +67,14 @@ function createAuth() { }; /** - * 退出:清除 token → 清除菜单+权限 → 清除动态路由 → 跳转登录页 + * 退出:调用登出接口 → 清除 token → 清除菜单+权限 → 清除动态路由 → 跳转登录页 */ - const logout = () => { + const logout = async () => { + try { + await logoutApi(); + } catch { + // 即使接口失败也要继续清除本地会话 + } clearSession(); router.push('/login'); }; @@ -95,7 +101,7 @@ export function forceReLogin(msg = '账户权限获取失败,请重新登录') notification.error({ message: '提示', description: msg, - duration: 2600, + duration: 3, }); auth.clearSession(); router.push('/login'); diff --git a/src/layouts/BasicLayout.tsx b/src/layouts/BasicLayout.tsx index bcbd633..d502668 100644 --- a/src/layouts/BasicLayout.tsx +++ b/src/layouts/BasicLayout.tsx @@ -79,7 +79,7 @@ export default defineComponent({ const { menuItems } = useMenuStore(); const { phone, nickname } = useUserStore(); - const displayName = computed(() => nickname.value || phone.value); + const displayName = computed(() => phone.value || nickname.value); const { tabs, cachedViews, @@ -108,13 +108,11 @@ export default defineComponent({ /** ===== 退出登录 ===== */ const handleLogout = () => { Modal.confirm({ - title: '提示', - content: '是否退出登录?', + title: '确认退出', + content: '确认要退出当前账号吗?', okText: '确认', cancelText: '取消', onOk: () => { - const { clearUser } = useUserStore(); - clearUser(); auth.logout(); }, }); @@ -298,7 +296,7 @@ export default defineComponent({ -
六个羽友赛事运营平台 ©{new Date().getFullYear()}
+ {/*
六个羽友赛事运营平台 ©{new Date().getFullYear()}
*/} {/* 修改密码弹窗 */} diff --git a/src/pages/events/banner/model/useBannerModel.ts b/src/pages/events/banner/model/useBannerModel.ts index 0357a5f..7adaafc 100644 --- a/src/pages/events/banner/model/useBannerModel.ts +++ b/src/pages/events/banner/model/useBannerModel.ts @@ -132,7 +132,10 @@ export function useBannerModel() { // ===== 方法 ===== /** 查询 */ - const handleSearch = () => fetchList(); + const handleSearch = () => { + pagination.reset(); + fetchList(); + }; /** 重置 */ const handleReset = useThrottleFn(async () => { diff --git a/src/pages/events/list/components/EventDetailModal.module.less b/src/pages/events/list/components/EventDetailModal.module.less index 61044c5..d8c4f7f 100644 --- a/src/pages/events/list/components/EventDetailModal.module.less +++ b/src/pages/events/list/components/EventDetailModal.module.less @@ -28,12 +28,29 @@ } .desc { + :global(.ant-descriptions-view table) { + table-layout: fixed; + width: 100%; + } + :global(.ant-descriptions-item-label) { width: 110px; color: rgba(0, 0, 0, 0.65); } } + // 首列内容区加宽(省市区、公开活动、创建时间等) + .wideCol:global(.ant-descriptions-item-content) { + width: 38%; + min-width: 200px; + } + + // 较长 label 加宽且不换行(class 同时挂在 label/content 上,需用复合选择器) + .wideLabel:global(.ant-descriptions-item-label) { + width: 132px; + white-space: nowrap; + } + // Item 的 class 会同时挂在 label/content 两个同级 td/th 上,不能用后代选择器 .statCell:global(.ant-descriptions-item-content) { min-width: 60px; @@ -59,11 +76,6 @@ font-weight: 500; } - .tableWrap { - max-height: 200px; - overflow-y: auto; - } - .paginationRow { display: flex; justify-content: flex-end; @@ -80,30 +92,4 @@ font-size: 13px; color: rgba(0, 0, 0, 0.65); } - - .idImageGrid { - display: flex; - gap: 8px; - flex-wrap: wrap; - } - - .idImageCell { - width: 128px; - height: 82px; - border-radius: 4px; - overflow: hidden; - border: 1px solid #f0f0f0; - flex-shrink: 0; - - :global(.ant-image) { - width: 100%; - height: 100%; - - img { - width: 100%; - height: 100%; - object-fit: cover; - } - } - } } diff --git a/src/pages/events/list/components/EventDetailModal.tsx b/src/pages/events/list/components/EventDetailModal.tsx index 7584bc6..2fd5620 100644 --- a/src/pages/events/list/components/EventDetailModal.tsx +++ b/src/pages/events/list/components/EventDetailModal.tsx @@ -1,6 +1,7 @@ -import { defineComponent, reactive, ref } from 'vue'; -import { Modal, Descriptions, Image, Table, Pagination, Spin } from 'ant-design-vue'; +import { defineComponent, computed, reactive, ref } from 'vue'; +import { Modal, Descriptions, Image, Table, Pagination, Spin, Space } from 'ant-design-vue'; import { message } from 'ant-design-vue'; +import { EyeOutlined } from '@ant-design/icons-vue'; import { getEventDetail, getSignupList, @@ -9,6 +10,7 @@ import { type TournamentAdminInfoSignupVO, } from '../model/services'; import { useState, useEffect } from '@/hooks'; +import defaultCover from '@/assets/img/default.png'; import styles from './EventDetailModal.module.less'; interface EventDetailModalProps { @@ -27,27 +29,30 @@ const formatYN = (v: string) => YES_NO_MAP[v] ?? v; const formatPublic = (v: string) => PUBLIC_MAP[v] ?? v; const formatGender = (v: string) => GENDER_MAP[v] ?? v; -const PAGE_SIZE = 10; +const PAGE_SIZE = 5; -/** 渲染身份证图片(cover 填充,与封面显示方式一致) */ +/** 渲染身份证图片(缩略图,点击可预览) */ const renderIdImages = (imgList: string[], singleImg: string) => { const urls = imgList.length > 0 ? imgList : singleImg ? [singleImg] : []; if (urls.length === 0) return --; return ( - -
- {urls.map((url) => ( -
- -
- ))} -
-
+ + {urls.map((url) => ( + } + /> + ))} + ); }; -/** 选手表格列 */ -const PLAYER_COLUMNS = [ +/** 选手表格基础列(不含证件号/证件图片,由 setup 内 computed 按需拼接) */ +const BASE_PLAYER_COLUMNS: any[] = [ { title: '选手', dataIndex: 'realName', key: 'realName', width: 100 }, { title: '性别', @@ -57,21 +62,30 @@ const PLAYER_COLUMNS = [ customRender: ({ text }: { text: string }) => formatGender(text), }, { title: '手机号', dataIndex: 'phone', key: 'phone', width: 130 }, - { - title: '证件号', - dataIndex: 'idCard', - key: 'idCard', - width: 180, - customRender: ({ record }: { record?: TournamentAdminInfoSignupVO }) => - record?.idCard ? record.idCard : --, - }, - { - title: '证件图片', - key: 'idCardImgs', - width: 280, - customRender: ({ record }: { record?: TournamentAdminInfoSignupVO }) => - record ? renderIdImages(record.idCardImgList || [], record.idCardImg || '') : --, - }, +]; + +const ID_CARD_COLUMN: any = { + title: '证件号', + dataIndex: 'idCard', + key: 'idCard', + width: 180, + customRender: ({ record }: { record?: TournamentAdminInfoSignupVO }) => + record?.idCard ? record.idCard : --, +}; + +const ID_CARD_IMG_COLUMN: any = { + title: '证件图片', + key: 'idCardImgs', + width: 120, + customRender: ({ record }: { record?: TournamentAdminInfoSignupVO }) => + record ? renderIdImages(record.idCardImgList || [], record.idCardImg || '') : --, +}; + +type ConditionalColumnKey = 'isRequireIdCardNo' | 'isRequireIdCardImg'; + +const CONDITIONAL_PLAYER_COLUMNS: { key: ConditionalColumnKey; column: any }[] = [ + { key: 'isRequireIdCardNo', column: ID_CARD_COLUMN }, + { key: 'isRequireIdCardImg', column: ID_CARD_IMG_COLUMN }, ]; export default defineComponent({ @@ -86,6 +100,14 @@ export default defineComponent({ const [detail, setDetail] = useState(null); const [detailLoading, setDetailLoading] = useState(false); + /** 动态列:根据赛事是否要求证件号/证件图片决定显示 */ + const playerColumns = computed(() => [ + ...BASE_PLAYER_COLUMNS, + ...CONDITIONAL_PLAYER_COLUMNS.filter(({ key }) => detail.value?.[key] === '1').map( + ({ column }) => column, + ), + ]); + // ===== 每个组别的选手数据(key = categoryId) ===== const categoryPlayers = ref>({}); const categoryPlayerTotal = ref>({}); @@ -149,6 +171,12 @@ export default defineComponent({ } }; + /** 显示报名起止时间 */ + const signupTimeDisplay = (startTime?: string, endTime?: string) => { + if (!startTime || !endTime) return '--'; + return `${startTime} 至 ${endTime}`; + }; + // 弹窗打开且 有 record.id 时自动请求(useEffect 带 immediate: true,兼容 destroyOnClose 重建场景) useEffect(() => { if (props.visible && props.record?.id) { @@ -160,7 +188,7 @@ export default defineComponent({
基础信息
- {detail.value.name} - + + {detail.value.name} + + {detail.value.startTimeBegin} 至 {detail.value.startTimeEnd} - {detail.value.descr} +
+ {detail.value.descr} +
- - {detail.value.signupTimeBegin} 至 {detail.value.signupTimeEnd} + + {signupTimeDisplay(detail.value.signupTimeBegin, detail.value.signupTimeEnd)} - {detail.value.venueArea} + + {detail.value.venueArea} + {detail.value.venue} {detail.value.venueNo || '--'} - + {formatPublic(detail.value.isPublic)} @@ -206,12 +240,16 @@ export default defineComponent({ {formatYN(detail.value.isRequireIdCardImg)} - {detail.value.createTime} + + {detail.value.createTime} + {detail.value.createNickname} - {detail.value.signupCount} + + {detail.value.signupCount} + {detail.value.dropoutCount} - + {detail.value.matchTotalCount} @@ -230,12 +268,14 @@ export default defineComponent({ {/* ===== 封面 ===== */} - {detail.value.img && ( -
-
封面
- -
- )} +
+
封面
+ +
{/* ===== 赛事公告 ===== */} {detail.value.notice && ( @@ -249,21 +289,20 @@ export default defineComponent({ {detail.value.categoryList && detail.value.categoryList.length > 0 && (
组别信息
- {detail.value.categoryList.map((cat: InnerCategoryVO) => ( + {detail.value.categoryList.map((cat: InnerCategoryVO, idx: number) => (
- {cat.name}({CATEGORY_TYPE_MAP[cat.type] ?? cat.type}) -
-
- + 组别{idx + 1}:{cat.name}({CATEGORY_TYPE_MAP[cat.type] ?? cat.type}) +
{categoryPlayerTotal.value[cat.id] > 0 && (
fetchList(); + const handleSearch = () => { + pagination.reset(); + fetchList(); + }; const handleReset = async () => { Object.assign(filterForm, FILTER_DEFAULTS); @@ -142,8 +145,8 @@ export function useEventListModel() { const isRemoved = record.status === '4'; const actionText = isRemoved ? '上架' : '下架'; const descText = isRemoved - ? `确认上架"${record.name}"吗?上架后用户可搜索和报名该赛事。` - : `确认下架"${record.name}"吗?下架后用户将无法搜索和报名该赛事。`; + ? `确认上架"${record.name}"该赛事吗?` + : `确认下架"${record.name}"吗?下架后用户将无法搜索和报名该赛事,已有报名和订单不受影响。`; Modal.confirm({ title: `${actionText}确认`, @@ -154,14 +157,14 @@ export function useEventListModel() { setTogglingId(record.id); try { const res = await toggleEventOnline({ id: record.id, online: isRemoved ? '1' : '0' }); - if (res.code === 200) { + if (res.code == 200) { message.success(`${actionText}成功`); fetchList(); } else { message.error(res.msg || `${actionText}失败`); } } catch (e: any) { - message.error(e?.message || `${actionText}失败`); + console.error(`${actionText}失败:`, e); } finally { setTogglingId(''); } diff --git a/src/pages/events/logs/index.tsx b/src/pages/events/logs/index.tsx index 087687c..57ea258 100644 --- a/src/pages/events/logs/index.tsx +++ b/src/pages/events/logs/index.tsx @@ -7,7 +7,7 @@ import { Form, Space, Select, - Tooltip, + Modal, Pagination, } from 'ant-design-vue'; import { useLogModel, ACTION_TYPE_OPTIONS, ACTION_SOURCE_OPTIONS } from './model/useLogModel'; @@ -24,6 +24,7 @@ const LogContentCell = defineComponent({ setup(props) { const textRef = ref(null); const [overflow, setOverflow] = useState(false); + const [modalOpen, setModalOpen] = useState(false); const checkOverflow = () => { const el = textRef.value; if (el) setOverflow(el.scrollHeight > el.clientHeight); @@ -47,10 +48,23 @@ const LogContentCell = defineComponent({ {raw}
{overflow.value ? ( - - 查看 - + setModalOpen(true)}> + 查看 + ) : null} + setModalOpen(false)} + > +
+ {raw} +
+
); }; @@ -93,7 +107,7 @@ export default defineComponent({ record: any; index: number; }) => { - if (column.key === 'content') { + if (column.key === 'obj') { const raw = text || ''; return raw ? : --; } diff --git a/src/pages/events/logs/model/useLogModel.ts b/src/pages/events/logs/model/useLogModel.ts index adad4fd..079acd1 100644 --- a/src/pages/events/logs/model/useLogModel.ts +++ b/src/pages/events/logs/model/useLogModel.ts @@ -120,7 +120,10 @@ export function useLogModel() { ); }); - const handleSearch = () => fetchList(); + const handleSearch = () => { + pagination.reset(); + fetchList(); + }; const handleReset = async () => { filterForm.dateRange = null; diff --git a/src/pages/events/orders/components/OrderDetailModal.module.less b/src/pages/events/orders/components/OrderDetailModal.module.less index 05743f2..68f0ac4 100644 --- a/src/pages/events/orders/components/OrderDetailModal.module.less +++ b/src/pages/events/orders/components/OrderDetailModal.module.less @@ -79,11 +79,6 @@ margin-bottom: 12px; } - .tableWrap { - max-height: 200px; - overflow-y: auto; - } - .paginationRow { display: flex; justify-content: flex-end; @@ -160,12 +155,6 @@ font-weight: 500; } - .partialMark { - margin-left: 4px; - color: #fa8c16; - font-size: 12px; - } - .refundEmpty { padding: 32px 0; text-align: center; @@ -176,10 +165,8 @@ border: 1px dashed #e0e0e0; } - .refundPagination { - display: flex; - justify-content: flex-end; - margin-top: 12px; + .refundPlayers { + margin-left: 0; } .modalFooter { diff --git a/src/pages/events/orders/components/OrderDetailModal.tsx b/src/pages/events/orders/components/OrderDetailModal.tsx index 0447451..4ba3cbf 100644 --- a/src/pages/events/orders/components/OrderDetailModal.tsx +++ b/src/pages/events/orders/components/OrderDetailModal.tsx @@ -1,5 +1,6 @@ import { defineComponent, computed } from 'vue'; import { Modal, Table, Button, Pagination, Image, Space, Spin } from 'ant-design-vue'; +import { EyeOutlined } from '@ant-design/icons-vue'; import { StatusTag, type StatusTagTone } from '@/components'; import { useState, useEffect } from '@/hooks'; import { @@ -8,6 +9,7 @@ import { type TournamentAdminOrderInfoVO, type InnerRefundInfo, type TournamentAdminOrderInfoPageVO, + OrderDetailQueryParams, } from '../model/services'; import styles from './OrderDetailModal.module.less'; @@ -44,22 +46,31 @@ const PLAYER_COLUMNS = [ customRender: ({ text }: { text: string }) => formatGender(text), }, { title: '手机号', dataIndex: 'phone', key: 'phone', width: 130 }, - { title: '证件号', dataIndex: 'idCard', key: 'idCard', width: 180 }, + { + title: '证件号', + dataIndex: 'idCard', + key: 'idCard', + width: 180, + customRender: ({ text }: { text: string }) => text || '--', + }, { title: '证件图片', key: 'idCardImg', width: 170, customRender: ({ record }: { record: TournamentAdminOrderInfoPageVO }) => { - const urls = record.idCardImgList?.length - ? record.idCardImgList - : record.idCardImg - ? [record.idCardImg] - : []; + const urls = record.idCardImgList || []; if (!urls.length) return --; return ( {urls.map((src) => ( - + } + /> ))} ); @@ -108,8 +119,9 @@ const PLAYER_COLUMNS = [ ]; const REFUND_STATUS_MAP: Record = { - success: { label: '退款成功', tone: 'success' }, - failed: { label: '退款失败', tone: 'danger' }, + '1': { label: '退款中', tone: 'orange' }, + '2': { label: '退款成功', tone: 'success' }, + '3': { label: '退款失败', tone: 'danger' }, }; export default defineComponent({ @@ -129,8 +141,6 @@ export default defineComponent({ const [playersLoading, setPlayersLoading] = useState(true); const [playerPage, setPlayerPage] = useState(1); const [playerTotal, setPlayerTotal] = useState(0); - const [refundPage, setRefundPage] = useState(1); - const [refundPageSize] = useState(2); const playerPageSize = 5; /** 获取选手列表(分页) */ @@ -138,8 +148,7 @@ export default defineComponent({ setPlayersLoading(true); try { const res = await getOrderPlayerList({ - orderNo: props.orderNo, - uniqueId: props.uniqueId, + ...(props.orderNo ? { orderNo: props.orderNo } : { uniqueId: props.uniqueId }), page: String(page), limit: String(playerPageSize), }); @@ -158,27 +167,26 @@ export default defineComponent({ const hasRefundFailed = computed(() => { const records = refundRecords.value; if (!records || !records.length) return false; - return records.some((r) => { - if (!r) return false; - const hasRefundAmount = parseFloat(r.refundAmount || '0') > 0; - const hasRefundTime = r.refundTime && r.refundTime !== '--'; - return hasRefundAmount && !hasRefundTime; - }); + return records.some((r) => r?.refundStatus === '3'); }); - const pagedRefunds = computed(() => { - const start = (refundPage.value - 1) * refundPageSize.value; - return refundRecords.value.slice(start, start + refundPageSize.value); - }); + const refundSuccessList = computed(() => + refundRecords.value.filter((r) => r.refundStatus === '2'), + ); const totalRefunded = computed(() => { - const records = refundRecords.value; - if (!records.length) return 0; - return records.reduce((sum, r) => sum + parseFloat(r.refundAmount || '0'), 0); + const list = refundSuccessList.value; + if (!list.length) return 0; + return list.reduce((sum, r) => sum + parseFloat(r.refundAmount || '0'), 0); }); + const refundSuccessCount = computed(() => refundSuccessList.value.length); + const fetchData = async () => { - const params = { orderNo: props.orderNo, uniqueId: props.uniqueId }; + const params: OrderDetailQueryParams = {}; + if (props.orderNo) params['orderNo'] = props.orderNo; + else params['uniqueId'] = props.uniqueId; + const [detailRes] = await Promise.all([getOrderDetail(params), fetchPlayers(1)]); if (detailRes.code == 200) { setDetail(detailRes.data); @@ -194,10 +202,6 @@ export default defineComponent({ fetchPlayers(page); }; - const handleRefundPageChange = (page: number) => { - setRefundPage(page); - }; - return () => (
选手信息
-
+
@@ -291,28 +295,18 @@ export default defineComponent({ <>
已退金额:{totalRefunded.value.toFixed(2)}元 - 退款次数:{refundRecords.value.length}次 + 退款次数:{refundSuccessCount.value}次
- {pagedRefunds.value.map((r, idx) => { - const realIdx = (refundPage.value - 1) * refundPageSize.value + idx + 1; - const isSuccess = parseFloat(r.refundTime || '') > 0 || !!r.refundTime; - const statusInfo = { - label: isSuccess - ? '退款成功' - : r.isFullRefund === '1' - ? '退款待处理' - : '退款中', - tone: (isSuccess - ? 'success' - : r.isFullRefund === '1' - ? 'warning' - : 'orange') as StatusTagTone, + {refundRecords.value.map((r, idx) => { + const statusInfo = REFUND_STATUS_MAP[r.refundStatus] || { + label: '未知', + tone: 'default' as StatusTagTone, }; return (
- 第{realIdx}次退款 + 第{idx + 1}次退款
@@ -321,37 +315,23 @@ export default defineComponent({ 退款金额: ¥{formatMoney(r.refundAmount)} - {r.isFullRefund === '1' && ( - (全部退款) - )} - {r.isFullRefund === '0' && ( - (部分退款) - )} + {`(${r.refundSignupNames})`}
申请时间:{r.refundApplyTime}
-
完款时间:{r.refundTime || '--'}
+
完成时间:{r.refundTime || '--'}
退款方式:{r.refundMethod}
第三方退款单号:{r.refundOutTradeNo || '--'}
-
已退金额:¥{formatMoney(r.refundedAmount)}
); })} -
- -
) : (
暂无退款记录
diff --git a/src/pages/events/orders/index.tsx b/src/pages/events/orders/index.tsx index 7257675..2b82bb7 100644 --- a/src/pages/events/orders/index.tsx +++ b/src/pages/events/orders/index.tsx @@ -72,6 +72,7 @@ function renderBodyCell({ if (column.dataIndex === 'name') { const maxLen = 15; const raw = text || ''; + if (!raw) return --; const display = raw.length > maxLen ? raw.slice(0, maxLen) + '...' : raw; return raw.length > maxLen ? ( diff --git a/src/pages/events/orders/model/useOrderModel.ts b/src/pages/events/orders/model/useOrderModel.ts index b3b2569..101084f 100644 --- a/src/pages/events/orders/model/useOrderModel.ts +++ b/src/pages/events/orders/model/useOrderModel.ts @@ -125,22 +125,77 @@ export function useOrderModel() { }; const columns = [ - { title: '订单编号', dataIndex: 'orderNo', key: 'orderNo', width: 200 }, - { title: '赛事名称', dataIndex: 'name', key: 'name', width: 180 }, - { title: '选手名称', dataIndex: 'realName', key: 'realName', width: 100 }, - { title: '手机号', dataIndex: 'phone', key: 'phone', width: 130 }, - { title: '比赛组别', dataIndex: 'categoryName', key: 'categoryName', width: 120 }, - { title: '报名人', dataIndex: 'creatorName', key: 'creatorName', width: 100 }, - { title: '报名人手机号', dataIndex: 'creatorPhone', key: 'creatorPhone', width: 130 }, + { + title: '订单编号', + dataIndex: 'orderNo', + key: 'orderNo', + width: 200, + customRender: ({ text }: { text: string }) => text || '--', + }, + { + title: '赛事名称', + dataIndex: 'name', + key: 'name', + width: 180, + customRender: ({ text }: { text: string }) => text || '--', + }, + { + title: '选手名称', + dataIndex: 'realName', + key: 'realName', + width: 100, + customRender: ({ text }: { text: string }) => text || '--', + }, + { + title: '手机号', + dataIndex: 'phone', + key: 'phone', + width: 130, + customRender: ({ text }: { text: string }) => text || '--', + }, + { + title: '比赛组别', + dataIndex: 'categoryName', + key: 'categoryName', + width: 120, + customRender: ({ text }: { text: string }) => text || '--', + }, + { + title: '报名人', + dataIndex: 'creatorName', + key: 'creatorName', + width: 100, + customRender: ({ text }: { text: string }) => text || '--', + }, + { + title: '报名人手机号', + dataIndex: 'creatorPhone', + key: 'creatorPhone', + width: 130, + customRender: ({ text }: { text: string }) => text || '--', + }, { title: '报名人数', dataIndex: 'creatorSignupCount', key: 'creatorSignupCount', width: 90, align: 'center' as const, + customRender: ({ text }: { text: number }) => (text != null ? text : '--'), + }, + { + title: '订单时间', + dataIndex: 'orderTime', + key: 'orderTime', + width: 170, + customRender: ({ text }: { text: string }) => text || '--', + }, + { + title: '支付时间', + dataIndex: 'payTime', + key: 'payTime', + width: 170, + customRender: ({ text }: { text: string }) => text || '--', }, - { title: '订单时间', dataIndex: 'orderTime', key: 'orderTime', width: 170 }, - { title: '支付时间', dataIndex: 'payTime', key: 'payTime', width: 170 }, { title: '订单总金额', dataIndex: 'creatorSignupFee', @@ -199,7 +254,10 @@ export function useOrderModel() { }, ]; - const handleSearch = () => fetchList(); + const handleSearch = () => { + pagination.reset(); + fetchList(); + }; const handleReset = async () => { Object.assign(filterForm, FILTER_DEFAULTS); diff --git a/src/pages/events/users/index.tsx b/src/pages/events/users/index.tsx index 231a01b..5ee1987 100644 --- a/src/pages/events/users/index.tsx +++ b/src/pages/events/users/index.tsx @@ -12,7 +12,7 @@ import pageStyles from '@/assets/styles/pageLayout.module.less'; * 架构分层: * - 数据层:services.ts(API 调用) * - 逻辑层:useUserModel.ts(状态 + 业务逻辑 + 交互处理) - * - 视图层:useUserColumns.ts(表格列配置)+ 本组件(纯 UI 渲染) + * - 视图层:useUserColumns.tsx(表格列配置)+ 本组件(纯 UI 渲染) */ export default defineComponent({ name: 'EventUsers', @@ -46,7 +46,7 @@ export default defineComponent({ loading={togglingId.value === record.id} onClick={() => handleToggleStatus(record)} > - {isActive ? '停用' : '启用'} + {isActive ? '禁用' : '启用'} ); }; @@ -79,6 +79,16 @@ export default defineComponent({ onPressEnter={handleSearch} /> + + (filterForm.phone = val.target?.value ?? val ?? '')} + onPressEnter={handleSearch} + /> + (filterForm.minBalance = val ?? '')} + style={{ width: '140px' }} + value={filterForm.minBalance || undefined} + precision={0} + min={0} + controls={false} + onUpdate:value={(val: any) => + (filterForm.minBalance = val != null ? String(val) : '') + } onPressEnter={handleSearch} - allowClear /> - (filterForm.maxBalance = val ?? '')} + style={{ width: '140px' }} + value={filterForm.maxBalance || undefined} + precision={0} + min={0} + controls={false} + onUpdate:value={(val: any) => + (filterForm.maxBalance = val != null ? String(val) : '') + } onPressEnter={handleSearch} - allowClear /> diff --git a/src/pages/finance/wallet/model/useWalletModel.ts b/src/pages/finance/wallet/model/useWalletModel.ts index 1da9c6c..dbd7912 100644 --- a/src/pages/finance/wallet/model/useWalletModel.ts +++ b/src/pages/finance/wallet/model/useWalletModel.ts @@ -1,7 +1,7 @@ -import { computed, reactive, toRef, Ref, nextTick } from 'vue'; +import { computed, reactive, nextTick, h } from 'vue'; +import { StatusTag, type StatusTagTone } from '@/components'; import { useState, - useDebounce, useThrottleFn, useRequest, usePagination, @@ -37,13 +37,29 @@ export const TRANSACTION_TYPE_MAP: Record = { 3: '取消报名退款', }; -/** 交易状态文案映射(弹窗内表格渲染用) */ +/** 交易状态文案映射(筛选下拉用,对应请求参数,值与接口返回一致) */ export const TRANSACTION_STATUS_LABEL_MAP: Record = { 1: '已解冻', 2: '冻结中', 3: '正常', }; +/** 交易状态色调映射(表格 StatusTag 显示用,对应接口返回的 status 值:1=已解冻,2=冻结中,3=正常) */ +const TRANSACTION_STATUS_MAP: Record = { + 1: { label: '已解冻', tone: 'success' }, + 2: { label: '冻结中', tone: 'warning' }, + 3: { label: '正常', tone: 'default' }, +}; + +/** 渲染交易状态 StatusTag(表格列用) */ +export function renderTransactionStatus(status: number) { + const info = TRANSACTION_STATUS_MAP[status] || { + label: String(status ?? '--'), + tone: 'default' as const, + }; + return h(StatusTag, { label: info.label, tone: info.tone }); +} + // ============================================================ // Model // ============================================================ @@ -57,15 +73,6 @@ export function useWalletModel() { maxBalance: '', }); - const { debouncedValue: debouncedNickname } = useDebounce( - toRef(filterForm, 'nickname') as Ref, - { delay: 300 }, - ); - const { debouncedValue: debouncedPhone } = useDebounce( - toRef(filterForm, 'phone') as Ref, - { delay: 300 }, - ); - // ===== 分页 ===== const pagination = usePagination({ defaultCurrent: 1, defaultPageSize: 10 }); @@ -83,8 +90,8 @@ export function useWalletModel() { page: String((pagination as any).current.value), limit: String((pagination as any).pageSize.value), }; - if (debouncedNickname.value.trim()) params.nickname = debouncedNickname.value.trim(); - if (debouncedPhone.value.trim()) params.phone = debouncedPhone.value.trim(); + if (filterForm.nickname.trim()) params.nickname = filterForm.nickname.trim(); + if (filterForm.phone.trim()) params.phone = filterForm.phone.trim(); if (filterForm.minBalance) params.amountBegin = filterForm.minBalance; if (filterForm.maxBalance) params.amountEnd = filterForm.maxBalance; return params; @@ -150,8 +157,8 @@ export function useWalletModel() { // ===== 计算属性 ===== const hasFilter = computed(() => { return ( - debouncedNickname.value.trim() !== '' || - debouncedPhone.value.trim() !== '' || + filterForm.nickname.trim() !== '' || + filterForm.phone.trim() !== '' || filterForm.minBalance !== '' || filterForm.maxBalance !== '' ); @@ -159,7 +166,10 @@ export function useWalletModel() { // ===== 方法 ===== - const handleSearch = () => fetchList(); + const handleSearch = useThrottleFn(() => { + pagination.reset(); + fetchList(); + }, 300); const handleReset = useThrottleFn(async () => { filterForm.nickname = ''; diff --git a/src/pages/finance/withdraw/components/WithdrawDetailModal.module.less b/src/pages/finance/withdraw/components/WithdrawDetailModal.module.less index adee022..5877990 100644 --- a/src/pages/finance/withdraw/components/WithdrawDetailModal.module.less +++ b/src/pages/finance/withdraw/components/WithdrawDetailModal.module.less @@ -96,16 +96,12 @@ min-width: 0; color: rgba(0, 0, 0, 0.85); font-size: 13px; + font-weight: 600; word-break: break-all; overflow: hidden; text-overflow: ellipsis; } - .descValueBold { - font-weight: 600; - color: rgba(0, 0, 0, 0.85); - } - .auditImgList { display: flex; gap: 5px; diff --git a/src/pages/finance/withdraw/components/WithdrawDetailModal.tsx b/src/pages/finance/withdraw/components/WithdrawDetailModal.tsx index 1bd89d2..a26fb95 100644 --- a/src/pages/finance/withdraw/components/WithdrawDetailModal.tsx +++ b/src/pages/finance/withdraw/components/WithdrawDetailModal.tsx @@ -150,17 +150,17 @@ export default defineComponent({ } }; - const renderItem = (label: string, value: any, isBold = false) => ( + const renderItem = (label: string, value: any) => (
{label} - {value || '--'} + {value || '--'}
); /** 渲染内容区(加载完成后) */ const renderContent = () => { const d = detail.value!; - const bankCardTypeLabel = d.bankCardType === 1 ? '个人' : d.bankCardType || '--'; + const bankCardTypeLabel = d.bankCardType == 1 ? '个人' : d.bankCardType || '--'; const isPending = d.auditStatus == 0; return ( @@ -175,12 +175,12 @@ export default defineComponent({ {renderItem('申请时间:', d.createDate)} {renderItem('打款类型:', d.withdrawType)}
- {renderItem('提现金额:', `¥${d.withdrawAmount}`, true)} + {renderItem('提现金额:', `¥${d.withdrawAmount}`)} {renderItem('费率:', `${(Number(d.feeRate) * 100).toFixed(2)}%`)} {renderItem('手续费:', `¥${d.feeAmount}`)} - {renderItem('到账金额:', `¥${d.receivedAmount}`, true)} - {renderItem('审核状态:', getAuditStatusText(d.auditStatus), true)} - {renderItem('列账状态:', getPayStatusText(d.payStatus))} + {renderItem('到账金额:', `¥${d.receivedAmount}`)} + {renderItem('审核状态:', getAuditStatusText(d.auditStatus))} + {renderItem('到账状态:', getPayStatusText(d.payStatus))}
@@ -267,6 +267,7 @@ export default defineComponent({
{renderItem('审核时间:', d.auditDate)} {renderItem('审核人:', d.auditNickname)} + {d.checkMsg && renderItem('审核内容:', d.checkMsg)}
审核图片: {d.auditImgList?.length ? ( diff --git a/src/pages/finance/withdraw/model/useWithdrawModel.ts b/src/pages/finance/withdraw/model/useWithdrawModel.ts index e62c76d..7fc9518 100644 --- a/src/pages/finance/withdraw/model/useWithdrawModel.ts +++ b/src/pages/finance/withdraw/model/useWithdrawModel.ts @@ -1,8 +1,7 @@ -import { computed, reactive, toRef, Ref, h, nextTick } from 'vue'; +import { computed, reactive, h, nextTick } from 'vue'; import { StatusTag, type StatusTagTone } from '@/components'; import { useState, - useDebounce, useThrottleFn, useRequest, usePagination, @@ -87,20 +86,6 @@ export function useWithdrawModel() { payStatus: '', }); - // 可搜索字段防抖 - const { debouncedValue: debouncedNickname } = useDebounce( - toRef(filterForm, 'nickname') as Ref, - { delay: 300 }, - ); - const { debouncedValue: debouncedPhone } = useDebounce( - toRef(filterForm, 'phone') as Ref, - { delay: 300 }, - ); - const { debouncedValue: debouncedRealName } = useDebounce( - toRef(filterForm, 'realName') as Ref, - { delay: 300 }, - ); - // ===== 分页 ===== const pagination = usePagination({ defaultCurrent: 1, defaultPageSize: 10 }); @@ -110,9 +95,9 @@ export function useWithdrawModel() { page: String((pagination as any).current.value), limit: String((pagination as any).pageSize.value), }; - if (debouncedNickname.value.trim()) params.nickname = debouncedNickname.value.trim(); - if (debouncedPhone.value.trim()) params.phone = debouncedPhone.value.trim(); - if (debouncedRealName.value.trim()) params.realName = debouncedRealName.value.trim(); + if (filterForm.nickname.trim()) params.nickname = filterForm.nickname.trim(); + if (filterForm.phone.trim()) params.phone = filterForm.phone.trim(); + if (filterForm.realName.trim()) params.realName = filterForm.realName.trim(); if (filterForm.auditStatus) params.auditStatus = filterForm.auditStatus; if (filterForm.payStatus) params.payStatus = filterForm.payStatus; return params; @@ -162,16 +147,16 @@ export function useWithdrawModel() { }, { title: '审核状态', dataIndex: 'auditStatus', key: 'auditStatus', width: 110 }, { title: '到账状态', dataIndex: 'payStatus', key: 'payStatus', width: 110 }, - { title: '流水单号', dataIndex: 'serialNumber', key: 'serialNumber', width: 180 }, + { title: '第三方单号', dataIndex: 'serialNumber', key: 'serialNumber', width: 180 }, { title: '申请时间', dataIndex: 'createDate', key: 'createDate', width: 180 }, ]; // ===== 计算属性 ===== const hasFilter = computed(() => { return ( - debouncedNickname.value.trim() !== '' || - debouncedPhone.value.trim() !== '' || - debouncedRealName.value.trim() !== '' || + filterForm.nickname.trim() !== '' || + filterForm.phone.trim() !== '' || + filterForm.realName.trim() !== '' || filterForm.auditStatus !== '' || filterForm.payStatus !== '' ); @@ -179,7 +164,10 @@ export function useWithdrawModel() { // ===== 方法 ===== - const handleSearch = () => fetchList(); + const handleSearch = useThrottleFn(() => { + pagination.reset(); + fetchList(); + }, 300); /** 重置(重置后自动查询) */ const handleReset = useThrottleFn(async () => { diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx index 629ba99..cb7f965 100644 --- a/src/pages/login/index.tsx +++ b/src/pages/login/index.tsx @@ -130,7 +130,7 @@ export default defineComponent({
-
六个羽友赛事运营平台 ©{new Date().getFullYear()}
+ {/*
六个羽友赛事运营平台 ©{new Date().getFullYear()}
*/} @@ -186,7 +186,7 @@ export default defineComponent({ -
六个羽友赛事运营平台 ©{new Date().getFullYear()}
+ {/*
六个羽友赛事运营平台 ©{new Date().getFullYear()}
*/} diff --git a/src/pages/system/logs/model/useLogModel.ts b/src/pages/system/logs/model/useLogModel.ts index 24f4967..850702f 100644 --- a/src/pages/system/logs/model/useLogModel.ts +++ b/src/pages/system/logs/model/useLogModel.ts @@ -1,6 +1,6 @@ -import { computed, reactive, toRef, Ref, nextTick } from 'vue'; +import { computed, reactive, nextTick } from 'vue'; import dayjs from 'dayjs'; -import { useDebounce, useThrottleFn } from '@/hooks'; +import { useThrottleFn } from '@/hooks'; import { useRequest } from '@/hooks/useRequest'; import { useEffect } from '@/hooks/useEffect'; import { usePagination, syncPaginationTotal } from '@/hooks/usePagination'; @@ -23,6 +23,7 @@ export const ACTION_TYPE_OPTIONS = [ { value: '2', label: '上架赛事' }, { value: '3', label: '禁用用户' }, { value: '4', label: '启用用户' }, + { value: '7', label: '系统参数' }, ] as const; /** 操作类型文案映射 */ @@ -31,6 +32,7 @@ export const ACTION_TYPE_MAP: Record = { 2: '上架赛事', 3: '禁用用户', 4: '启用用户', + 7: '系统参数', }; // ============================================================ @@ -48,12 +50,6 @@ export function useLogModel() { searchOperator: '', }); - // 操作人字段防抖 300ms - const { debouncedValue: debouncedOperator } = useDebounce( - toRef(filterForm, 'searchOperator') as Ref, - { delay: 300 }, - ); - // ===== 分页 ===== const pagination = usePagination({ defaultCurrent: 1, defaultPageSize: 10 }); @@ -76,9 +72,9 @@ export function useLogModel() { params.type = filterForm.actionType; } - // 操作人昵称(防抖后的值) - if (debouncedOperator.value.trim()) { - params.nickname = debouncedOperator.value.trim(); + // 操作人昵称 + if (filterForm.searchOperator.trim()) { + params.nickname = filterForm.searchOperator.trim(); } return params; @@ -116,13 +112,16 @@ export function useLogModel() { return ( filterForm.actionTimeRange !== null || filterForm.actionType !== '' || - debouncedOperator.value.trim() !== '' + filterForm.searchOperator.trim() !== '' ); }); // ===== 方法 ===== - const handleSearch = () => fetchList(); + const handleSearch = useThrottleFn(() => { + pagination.reset(); + fetchList(); + }, 300); /** 重置(重置后自动查询) */ const handleReset = useThrottleFn(async () => { diff --git a/src/pages/system/params/components/ParamFormModal.module.less b/src/pages/system/params/components/ParamFormModal.module.less new file mode 100644 index 0000000..d26e83b --- /dev/null +++ b/src/pages/system/params/components/ParamFormModal.module.less @@ -0,0 +1,10 @@ +.paramFormModalMain { + .footer { + display: flex; + justify-content: flex-end; + gap: 8px; + padding-top: 16px; + border-top: 1px solid #f0f0f0; + margin-top: 8px; + } +} diff --git a/src/pages/system/params/components/ParamFormModal.tsx b/src/pages/system/params/components/ParamFormModal.tsx new file mode 100644 index 0000000..d2c6f9e --- /dev/null +++ b/src/pages/system/params/components/ParamFormModal.tsx @@ -0,0 +1,142 @@ +import { defineComponent, ref, reactive, nextTick } from 'vue'; +import { useEffect } from '@/hooks'; +import { Modal, Form, Input, Button } from 'ant-design-vue'; +import { paramCodeRules, paramValueRules, remarkRules } from '../model/form'; +import type { SysParamsDTO } from '../model/services'; +import styles from './ParamFormModal.module.less'; + +const { TextArea } = Input; + +interface ParamFormModalProps { + visible: boolean; + record: SysParamsDTO | null; + submitting?: boolean; + onClose: () => void; + onSave: (formData: { paramCode: string; paramValue: string; remark: string }) => void; +} + +/** 默认表单数据 */ +const getDefaultForm = () => ({ + paramCode: '', + paramValue: '', + remark: '', +}); + +export default defineComponent({ + name: 'ParamFormModal', + props: { + visible: { type: Boolean, default: false }, + record: { type: Object, default: null }, + submitting: { type: Boolean, default: false }, + onClose: { type: Function, required: true }, + onSave: { type: Function, required: true }, + }, + setup(props: ParamFormModalProps) { + const formRef = ref(); + const formData = reactive(getDefaultForm()); + + /** 根据 record 初始化表单 */ + const initFormFromRecord = (record: SysParamsDTO | null) => { + if (record) { + Object.assign(formData, { + paramCode: record.paramCode || '', + paramValue: record.paramValue || '', + remark: record.remark || '', + }); + } else { + Object.assign(formData, getDefaultForm()); + } + }; + + /** 监听 visible 变化重置表单 */ + useEffect(() => { + if (props.visible) { + initFormFromRecord(props.record); + nextTick().then(() => formRef.value?.clearValidate()); + } + }, [() => props.visible]); + + /** 提交 */ + const handleSubmit = async () => { + try { + await formRef.value?.validate(); + + props.onSave({ + paramCode: formData.paramCode, + paramValue: formData.paramValue, + remark: formData.remark, + }); + } catch { + // 校验未通过,Form 已展示错误,无需处理 + } + }; + + /** 关闭 */ + const handleClose = () => { + props.onClose(); + }; + + return () => { + const isEdit = !!props.record; + + return ( + +
+ + { + formData.paramCode = val?.target?.value ?? val ?? ''; + }} + placeholder="请输入参数编码" + allowClear + readonly={isEdit} + /> + + + + { + formData.paramValue = val?.target?.value ?? val ?? ''; + }} + placeholder="请输入参数值" + allowClear + /> + + + +