Browse Source

上传服务后台代码

main
liwei1dao 2 months ago
parent
commit
8924a3cd3b
  1. 1
      CLAUDE.md
  2. 2
      apps/admin/.output/nitro.json
  3. 2
      apps/admin/.output/public/_nuxt/0CGOegeu.js
  4. 2
      apps/admin/.output/public/_nuxt/32XpWsQL.js
  5. 1
      apps/admin/.output/public/_nuxt/32rNuZwS.js
  6. 6
      apps/admin/.output/public/_nuxt/6O01ZZML.js
  7. 2
      apps/admin/.output/public/_nuxt/AeilnnXP.js
  8. 2
      apps/admin/.output/public/_nuxt/B-G7qD0T.js
  9. 1
      apps/admin/.output/public/_nuxt/BAkLwAvM.js
  10. 2
      apps/admin/.output/public/_nuxt/BCmMvQNl.js
  11. 2
      apps/admin/.output/public/_nuxt/BIYq6SKh.js
  12. 1
      apps/admin/.output/public/_nuxt/BNW9rRgN.js
  13. 2
      apps/admin/.output/public/_nuxt/BSXoR6Yx.js
  14. 2
      apps/admin/.output/public/_nuxt/BZR1IKC1.js
  15. 1
      apps/admin/.output/public/_nuxt/BgasD__e.js
  16. 2
      apps/admin/.output/public/_nuxt/BqBJfKQo.js
  17. 2
      apps/admin/.output/public/_nuxt/BrJ9pewm.js
  18. 2
      apps/admin/.output/public/_nuxt/BvvkbLjV.js
  19. 2
      apps/admin/.output/public/_nuxt/C8kc9IUa.js
  20. 1
      apps/admin/.output/public/_nuxt/C9zSjFPi.js
  21. 2
      apps/admin/.output/public/_nuxt/CAhwHUW5.js
  22. 1
      apps/admin/.output/public/_nuxt/CDB8L8go.js
  23. 2
      apps/admin/.output/public/_nuxt/CEFq2Pq9.js
  24. 2
      apps/admin/.output/public/_nuxt/CPoAe5lL.js
  25. 2
      apps/admin/.output/public/_nuxt/CS9TbzfM.js
  26. 2
      apps/admin/.output/public/_nuxt/CasIUDzx.js
  27. 2
      apps/admin/.output/public/_nuxt/CkLfApYf.js
  28. 2
      apps/admin/.output/public/_nuxt/DC2vBYza.js
  29. 2
      apps/admin/.output/public/_nuxt/DDe4k6KN.js
  30. 2
      apps/admin/.output/public/_nuxt/DPKLCcBs.js
  31. 2
      apps/admin/.output/public/_nuxt/DQ6zmqs4.js
  32. 2
      apps/admin/.output/public/_nuxt/DRVBzPRY.js
  33. 1
      apps/admin/.output/public/_nuxt/DT3lD2sm.js
  34. 1
      apps/admin/.output/public/_nuxt/DTVoyhwb.js
  35. 2
      apps/admin/.output/public/_nuxt/DZfr_EfO.js
  36. 2
      apps/admin/.output/public/_nuxt/Dehik56a.js
  37. 2
      apps/admin/.output/public/_nuxt/DlMn1R4f.js
  38. 1
      apps/admin/.output/public/_nuxt/GUJrhX2S.js
  39. 1
      apps/admin/.output/public/_nuxt/NtXZuCUg.js
  40. 2
      apps/admin/.output/public/_nuxt/VxS1tujf.js
  41. 2
      apps/admin/.output/public/_nuxt/_yKEhqk3.js
  42. 1
      apps/admin/.output/public/_nuxt/accounts.B-g1r2A7.css
  43. 1
      apps/admin/.output/public/_nuxt/accounts.maMJCEm_.css
  44. 2
      apps/admin/.output/public/_nuxt/builds/latest.json
  45. 1
      apps/admin/.output/public/_nuxt/builds/meta/12df8bde-c7e1-423a-8c26-514d561b95ec.json
  46. 1
      apps/admin/.output/public/_nuxt/builds/meta/15e7ab28-16d6-4f4e-8edd-c6a8122f81cf.json
  47. 2
      apps/admin/.output/public/_nuxt/dashboard.CuNO2Lt5.css
  48. 2
      apps/admin/.output/public/_nuxt/entry.B1mQ-Tl2.css
  49. 2
      apps/admin/.output/public/_nuxt/oWVa2rll.js
  50. 2
      apps/admin/.output/public/_nuxt/q-Oqovwl.js
  51. 2
      apps/admin/.output/public/_nuxt/xsgK-Nup.js
  52. 222
      apps/admin/.output/server/chunks/build/accounts-CM5YEJ4p.mjs
  53. 1
      apps/admin/.output/server/chunks/build/accounts-CM5YEJ4p.mjs.map
  54. 201
      apps/admin/.output/server/chunks/build/accounts-CampayFP.mjs
  55. 1
      apps/admin/.output/server/chunks/build/accounts-CampayFP.mjs.map
  56. 8
      apps/admin/.output/server/chunks/build/accounts-styles.B912aimJ.mjs
  57. 1
      apps/admin/.output/server/chunks/build/accounts-styles.B912aimJ.mjs.map
  58. 8
      apps/admin/.output/server/chunks/build/accounts-styles.Bwl6sYRz.mjs
  59. 1
      apps/admin/.output/server/chunks/build/accounts-styles.Bwl6sYRz.mjs.map
  60. 2
      apps/admin/.output/server/chunks/build/client.precomputed.mjs
  61. 1
      apps/admin/.output/server/chunks/build/dashboard-C7m4n3tj.mjs.map
  62. 56
      apps/admin/.output/server/chunks/build/dashboard-Y8255DFm.mjs
  63. 1
      apps/admin/.output/server/chunks/build/dashboard-Y8255DFm.mjs.map
  64. 11
      apps/admin/.output/server/chunks/build/dashboard-styles.CnnmNtqM.mjs
  65. 1
      apps/admin/.output/server/chunks/build/dashboard-styles.CnnmNtqM.mjs.map
  66. 11
      apps/admin/.output/server/chunks/build/dashboard-styles.DHIbN8CY.mjs
  67. 1
      apps/admin/.output/server/chunks/build/dashboard-styles.DHIbN8CY.mjs.map
  68. 37
      apps/admin/.output/server/chunks/build/product-3h7bsXRI.mjs
  69. 1
      apps/admin/.output/server/chunks/build/product-3h7bsXRI.mjs.map
  70. 1
      apps/admin/.output/server/chunks/build/product-CDTf1lTs.mjs.map
  71. 21
      apps/admin/.output/server/chunks/build/server.mjs
  72. 14
      apps/admin/.output/server/chunks/build/styles.mjs
  73. 472
      apps/admin/.output/server/chunks/nitro/nitro.mjs
  74. 26
      apps/admin/app/pages/accounts.vue
  75. 12
      apps/admin/app/pages/dashboard.vue
  76. 51
      apps/admin/app/pages/product.vue
  77. 17
      apps/admin/app/pages/users.vue
  78. 13
      apps/admin/app/stores/auth.ts
  79. 8
      apps/admin/app/utils/menus.ts
  80. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/0CGOegeu.js
  81. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/32XpWsQL.js
  82. 1
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/32rNuZwS.js
  83. 6
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/6O01ZZML.js
  84. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/AeilnnXP.js
  85. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/B-G7qD0T.js
  86. 1
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BAkLwAvM.js
  87. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BCmMvQNl.js
  88. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BIYq6SKh.js
  89. 1
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BNW9rRgN.js
  90. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BSXoR6Yx.js
  91. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BZR1IKC1.js
  92. 1
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BgasD__e.js
  93. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BqBJfKQo.js
  94. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BrJ9pewm.js
  95. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BvvkbLjV.js
  96. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/C8kc9IUa.js
  97. 1
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/C9zSjFPi.js
  98. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/CAhwHUW5.js
  99. 1
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/CDB8L8go.js
  100. 2
      apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/CEFq2Pq9.js

1
CLAUDE.md

@ -120,6 +120,7 @@ admin/console 的 `prod-deploy.sh` 已改为**多生产环境档案**(`env_pro
- ⚠️ 调用时 `method` **不要带 `api_` 前缀**,否则变成 `api_api_xxx` → `code:11`。 - ⚠️ 调用时 `method` **不要带 `api_` 前缀**,否则变成 `api_api_xxx` → `code:11`。
- 方法名以 `get/list/load/query/fetch/search/count/stat/export/check` 开头视为只读,不弹全屏遮罩;其余(add/update/del/save/create…)视为写操作,请求期间套遮罩防重复提交。 - 方法名以 `get/list/load/query/fetch/search/count/stat/export/check` 开头视为只读,不弹全屏遮罩;其余(add/update/del/save/create…)视为写操作,请求期间套遮罩防重复提交。
- 选中应用通过请求头 `X-App-Id` 传给后端。 - 选中应用通过请求头 `X-App-Id` 传给后端。
- **应用下拉统一走 `api_getmyapps`**(超管/管理员例外,仍用 `console/api/apps/list`):后端按账号绑定下发可选部署。品牌商/渠道商账号的可见应用**不靠手工勾选**,而是由「名下产品绑定的应用」推导——产品的应用归属存 `DBProduct.appnames`(应用名 CSV,产品管理页多选),见 [scope_app.go](apps/services/modules/console/scope_app.go)。
- **后端返回常多包一层**:如 `getfactorys → {factorys}`、`getproducts → {products}`、`getproduct → {product}`;保存 payload 也常包一层(厂家 `{Factory:{...}}`、产品 `{product:{...}}`);统计 trend 日期字段是 `stat_day`。列表 ID 多以十六进制展示(`id.toString(16).toUpperCase()`)。 - **后端返回常多包一层**:如 `getfactorys → {factorys}`、`getproducts → {products}`、`getproduct → {product}`;保存 payload 也常包一层(厂家 `{Factory:{...}}`、产品 `{product:{...}}`);统计 trend 日期字段是 `stat_day`。列表 ID 多以十六进制展示(`id.toString(16).toUpperCase()`)。
- 样式:`app/assets/css/console.css` 由 nuxt.config 引用;DaisyUI 固定 4.x。 - 样式:`app/assets/css/console.css` 由 nuxt.config 引用;DaisyUI 固定 4.x。

2
apps/admin/.output/nitro.json

@ -1,5 +1,5 @@
{ {
"date": "2026-08-14T08:52:12.283Z", "date": "2026-08-15T09:07:22.851Z",
"preset": "node-server", "preset": "node-server",
"framework": { "framework": {
"name": "nuxt", "name": "nuxt",

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/CUR2rcGX.js → apps/admin/.output/public/_nuxt/0CGOegeu.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/ChqjEN2N.js → apps/admin/.output/public/_nuxt/32XpWsQL.js

File diff suppressed because one or more lines are too long

1
apps/admin/.output/public/_nuxt/32rNuZwS.js

File diff suppressed because one or more lines are too long

6
apps/admin/.output/public/_nuxt/DSy_gLdM.js → apps/admin/.output/public/_nuxt/6O01ZZML.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/Bp86Q8ON.js → apps/admin/.output/public/_nuxt/AeilnnXP.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/BSO50kj0.js → apps/admin/.output/public/_nuxt/B-G7qD0T.js

File diff suppressed because one or more lines are too long

1
apps/admin/.output/public/_nuxt/BAkLwAvM.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/DhKR78CK.js → apps/admin/.output/public/_nuxt/BCmMvQNl.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/D5UrQ7F3.js → apps/admin/.output/public/_nuxt/BIYq6SKh.js

@ -1 +1 @@
import{_ as t,o,c as s,R as c}from"./DSy_gLdM.js";const r={},a={class:"min-h-screen","data-theme":"corporate"};function n(e,_){return o(),s("div",a,[c(e.$slots,"default")])}const l=t(r,[["render",n]]);export{l as default}; import{_ as t,o,c as s,S as c}from"./6O01ZZML.js";const r={},a={class:"min-h-screen","data-theme":"corporate"};function n(e,_){return o(),s("div",a,[c(e.$slots,"default")])}const l=t(r,[["render",n]]);export{l as default};

1
apps/admin/.output/public/_nuxt/BNW9rRgN.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/B8hrjpgL.js → apps/admin/.output/public/_nuxt/BSXoR6Yx.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/Bad2XFSd.js → apps/admin/.output/public/_nuxt/BZR1IKC1.js

File diff suppressed because one or more lines are too long

1
apps/admin/.output/public/_nuxt/BgasD__e.js

@ -0,0 +1 @@
import{e as y,aa as h,ab as w,A as g,j as d,k as b}from"./6O01ZZML.js";const k="$s";function A(...t){const s=typeof t[t.length-1]=="string"?t.pop():void 0;typeof t[0]!="string"&&t.unshift(s);const[a,o]=t;if(!a||typeof a!="string")throw new TypeError("[nuxt] [useState] key must be a string: "+a);if(o!==void 0&&typeof o!="function")throw new Error("[nuxt] [useState] init must be a function: "+o);const i=k+a,r=y(),n=h(r.payload.state,i);if(o&&(r._state[i]??={_default:o}),n.value===void 0&&o){const e=o();if(w(e))return r.payload.state[i]=e,e;n.value=e}return n}function m(){const t=A("app:loading",()=>0),s=g(()=>t.value>0);function a(){t.value++}function o(){t.value=Math.max(0,t.value-1)}return{count:t,loading:s,begin:a,end:o}}async function f(t,s,a){const o=d(),i=b(),r={"Content-Type":"application/json"};o.token&&(r.Authorization=o.token),a&&Object.assign(r,a);const n=await fetch(t,{method:"POST",headers:r,body:JSON.stringify(s)});if(!n.ok)throw new Error(`HTTP error: ${n.status}`);const e=await n.json();if(e.code===18)throw o.logout(),i.push("/"),new Error(e.msg||"Unauthorized");if(e.code!==0)throw new Error(e.msg||"Unknown error");return e.data}const S=/^(get|list|load|query|fetch|search|count|stat|export|check)/i;function v(t){return!S.test(t)}function x(){const t=d(),{begin:s,end:a}=m();async function o(n,e){const u={};if(t.currentAppId&&(u["X-App-Id"]=String(t.currentAppId)),!v(n))return f(`/web/api/api_${n}`,e??{},u);s();try{return await f(`/web/api/api_${n}`,e??{},u)}finally{a()}}async function i(n,e){return f(`/console/api/${n}`,e??{})}async function r(n,e){const u=n.type||"application/octet-stream",c=await o("getcostoken",{path:e,filename:n.name,content_type:u}),p=c.upload_url||c.url||"";if(!p)throw new Error("未获取到上传地址:请确认已在【第三方服务配置→存储】配置并启用「阿里云 OSS」");const l=await fetch(p,{method:"PUT",headers:{"Content-Type":u},body:n});if(!l.ok)throw new Error(`Upload failed: ${l.status}`);return c.url||p.split("?")[0]}return{webApi:o,consoleApi:i,uploadFile:r}}export{m as a,A as b,x as u};

2
apps/admin/.output/public/_nuxt/yis2MfHE.js → apps/admin/.output/public/_nuxt/BqBJfKQo.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/D4Um3zt0.js → apps/admin/.output/public/_nuxt/BrJ9pewm.js

@ -1 +1 @@
import{L as y,l as x}from"./DD3V9C6_.js";import{g as V,c as t,F as u,a as l,n as C,r,l as g,t as o,A as h,o as s,d as B,_ as N}from"./DSy_gLdM.js";const L={class:"lang-select"},O={class:"lang-chip-name"},S=["onClick"],j={key:0,class:"lang-empty"},A={key:0,class:"lang-dd"},F={class:"lang-dd-sum"},I={class:"lang-dd-panel"},T=["checked","onChange"],$={class:"lang-opt-code"},w={class:"lang-opt-name"},z=["value","disabled"],D=["value"],E=V({__name:"LangSelect",props:{modelValue:{},multiple:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},options:{default:void 0}},emits:["update:modelValue"],setup(c,{emit:f}){const d=c,m=f,p=h(()=>d.options&&d.options.length?d.options:y),i=h(()=>(d.modelValue||"").split(",").map(a=>a.trim()).filter(Boolean));function v(a){return x(a)}function _(a){if(d.disabled)return;const n=i.value.slice(),e=n.indexOf(a);e>=0?n.splice(e,1):n.push(a),m("update:modelValue",n.join(","))}function b(a){m("update:modelValue",a.target.value)}return(a,n)=>(s(),t("div",L,[c.multiple?(s(),t(u,{key:0},[l("div",{class:C(["lang-chips",{"lang-disabled":c.disabled}])},[(s(!0),t(u,null,r(i.value,e=>(s(),t("span",{key:e,class:"lang-chip"},[B(o(e),1),l("span",O,o(v(e)),1),l("button",{type:"button",class:"lang-x",onClick:k=>_(e)},"×",8,S)]))),128)),i.value.length?g("",!0):(s(),t("span",j,"未选择语言"))],2),c.disabled?g("",!0):(s(),t("details",A,[l("summary",F,"+ 选择语言(已选 "+o(i.value.length)+")",1),l("div",I,[(s(!0),t(u,null,r(p.value,e=>(s(),t("label",{key:e.code,class:"lang-opt"},[l("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary",checked:i.value.includes(e.code),onChange:k=>_(e.code)},null,40,T),l("span",$,o(e.code),1),l("span",w,o(e.name),1)]))),128))])]))],64)):(s(),t("select",{key:1,class:"select select-bordered select-sm w-full text-xs",value:c.modelValue,disabled:c.disabled,onChange:b},[n[0]||(n[0]=l("option",{value:""},"(未设置)",-1)),(s(!0),t(u,null,r(p.value,e=>(s(),t("option",{key:e.code,value:e.code},o(e.code)+" · "+o(e.name),9,D))),128))],40,z))]))}}),q=Object.assign(N(E,[["__scopeId","data-v-4903af59"]]),{__name:"LangSelect"});export{q as _}; import{L as y,l as x}from"./DD3V9C6_.js";import{g as V,c as t,F as u,a as l,n as C,r,l as g,t as o,A as h,o as s,d as B,_ as N}from"./6O01ZZML.js";const L={class:"lang-select"},O={class:"lang-chip-name"},S=["onClick"],j={key:0,class:"lang-empty"},A={key:0,class:"lang-dd"},F={class:"lang-dd-sum"},I={class:"lang-dd-panel"},T=["checked","onChange"],$={class:"lang-opt-code"},w={class:"lang-opt-name"},z=["value","disabled"],D=["value"],E=V({__name:"LangSelect",props:{modelValue:{},multiple:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},options:{default:void 0}},emits:["update:modelValue"],setup(c,{emit:f}){const d=c,m=f,p=h(()=>d.options&&d.options.length?d.options:y),i=h(()=>(d.modelValue||"").split(",").map(a=>a.trim()).filter(Boolean));function v(a){return x(a)}function _(a){if(d.disabled)return;const n=i.value.slice(),e=n.indexOf(a);e>=0?n.splice(e,1):n.push(a),m("update:modelValue",n.join(","))}function b(a){m("update:modelValue",a.target.value)}return(a,n)=>(s(),t("div",L,[c.multiple?(s(),t(u,{key:0},[l("div",{class:C(["lang-chips",{"lang-disabled":c.disabled}])},[(s(!0),t(u,null,r(i.value,e=>(s(),t("span",{key:e,class:"lang-chip"},[B(o(e),1),l("span",O,o(v(e)),1),l("button",{type:"button",class:"lang-x",onClick:k=>_(e)},"×",8,S)]))),128)),i.value.length?g("",!0):(s(),t("span",j,"未选择语言"))],2),c.disabled?g("",!0):(s(),t("details",A,[l("summary",F,"+ 选择语言(已选 "+o(i.value.length)+")",1),l("div",I,[(s(!0),t(u,null,r(p.value,e=>(s(),t("label",{key:e.code,class:"lang-opt"},[l("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary",checked:i.value.includes(e.code),onChange:k=>_(e.code)},null,40,T),l("span",$,o(e.code),1),l("span",w,o(e.name),1)]))),128))])]))],64)):(s(),t("select",{key:1,class:"select select-bordered select-sm w-full text-xs",value:c.modelValue,disabled:c.disabled,onChange:b},[n[0]||(n[0]=l("option",{value:""},"(未设置)",-1)),(s(!0),t(u,null,r(p.value,e=>(s(),t("option",{key:e.code,value:e.code},o(e.code)+" · "+o(e.name),9,D))),128))],40,z))]))}}),q=Object.assign(N(E,[["__scopeId","data-v-4903af59"]]),{__name:"LangSelect"});export{q as _};

2
apps/admin/.output/public/_nuxt/obp34o1K.js → apps/admin/.output/public/_nuxt/BvvkbLjV.js

@ -1 +1 @@
import{u as a,e as s,h as u,i as r,f as h}from"./DSy_gLdM.js";function i(t){const e=t||s();return e.ssrContext?.head||e.runWithContext(()=>{if(u()){const n=r(h);if(!n)throw new Error("[nuxt] [unhead] Missing Unhead instance.");return n}})}function d(t,e={}){const n=e.head||i(e.nuxt);return a(t,{head:n,...e})}export{d as u}; import{u as a,e as s,h as u,i as r,f as h}from"./6O01ZZML.js";function i(t){const e=t||s();return e.ssrContext?.head||e.runWithContext(()=>{if(u()){const n=r(h);if(!n)throw new Error("[nuxt] [unhead] Missing Unhead instance.");return n}})}function d(t,e={}){const n=e.head||i(e.nuxt);return a(t,{head:n,...e})}export{d as u};

2
apps/admin/.output/public/_nuxt/w_7nuVJ9.js → apps/admin/.output/public/_nuxt/C8kc9IUa.js

File diff suppressed because one or more lines are too long

1
apps/admin/.output/public/_nuxt/C9zSjFPi.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/DlgycG-C.js → apps/admin/.output/public/_nuxt/CAhwHUW5.js

@ -1,4 +1,4 @@
import{g as G,C as K,Q as P,c as a,a as e,d as u,q as g,s as U,F as f,r as B,v as Q,x as Y,t as n,y as i,A as E,o,n as F,l as A,_ as Z}from"./DSy_gLdM.js";import{u as J}from"./NtXZuCUg.js";import{u as W}from"./EeX3zgoF.js";const X=globalThis.setInterval,$={class:"flex items-center justify-between mb-4 flex-wrap gap-3"},tt={class:"flex items-center gap-2 flex-wrap"},et=["value"],st={class:"flex items-center gap-1 text-xs text-slate-500 cursor-pointer"},lt={class:"flex items-center gap-4 mb-3 text-xs text-slate-500"},nt={class:"text-slate-700"},at={class:"text-slate-700"},ot={class:"text-slate-700"},rt={class:"muted"},ut={class:"panel overflow-hidden"},it={id:"logBody",style:{"max-height":"calc(100vh - 230px)","overflow-y":"auto"}},ct={key:0,class:"text-center text-slate-400 py-10"},dt={key:1,class:"text-center text-red-400 py-10"},vt={key:2,class:"text-center text-slate-400 py-10"},pt={class:"t"},mt={class:"app-name"},ft={key:0,class:"unreg",title:"该应用名未在 console 注册,快照已收到但不会写入统计库"},_t={key:1,class:"muted"},gt={class:"muted"},xt={class:"muted"},yt={class:"muted"},bt={class:"muted"},ht={key:0,class:"muted"},wt={class:"t"},kt={key:0,class:"late"},Ct=G({__name:"statlog",setup(Tt){const{webApi:I}=J(),{success:O,error:R}=W(),H={cn:"中国",us:"美国",ea:"东亚",sea:"东南亚",sa:"南亚",me:"中东",eu:"欧洲",ru:"俄罗斯",af:"非洲",sam:"南美",nam:"北美",oc:"大洋洲",br:"巴西",in:"印度"};function D(l){return l?H[l]||l:"-"}const c=i([]),x=i(!1),_=i(""),L=i("-"),N=i("-"),y=i(""),v=i(0),b=i(""),h=i(""),w=i(!1);let d=null;function p(l=0){const s=new Date(Date.now()+l*864e5),t=new Intl.DateTimeFormat("en-CA",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit"}).format(s);return parseInt(t.replace(/-/g,""),10)}function k(l){const s=""+l;return s.length===8?s.slice(0,4)+"-"+s.slice(4,6)+"-"+s.slice(6,8):s}function C(l){if(!l)return"--";const s=new Date(l*1e3),t=r=>r<10?"0"+r:""+r;return t(s.getHours())+":"+t(s.getMinutes())+":"+t(s.getSeconds())}function S(l){return l?"0x"+(l>>>0).toString(16).toUpperCase():"全部"}const V=E(()=>[{value:p(0),label:"今天 "+k(p(0))},{value:p(-1),label:"昨天 "+k(p(-1))}]);function M(l){return l==="error"?{cls:"lv-error",txt:"解析失败"}:l==="warn"?{cls:"lv-warn",txt:"未落库"}:{cls:"lv-info",txt:"已落库"}}function j(l){return!!(l.snap_ts&&l.ts&&l.ts-l.snap_ts>120)}const T=E(()=>{const l=b.value,s=h.value.trim().toLowerCase();return c.value.filter(t=>!(l&&t.level!==l||s&&((t.app||"")+" "+(t.region||"")+" "+D(t.region)+" "+(t.product_id||"")+" "+S(t.product_id)+" "+(t.channel_id||"")+" "+(t.stat_day||"")).toLowerCase().indexOf(s)<0))});async function m(){x.value=!0,_.value="";try{const l=await I("getstatlogs",{day:v.value||0});c.value=l?.entries||[],L.value=l?.total!=null?l.total:c.value.length,N.value=c.value.length?C(c.value[0].ts):"--"}catch(l){_.value=l?.message||"网络异常"}finally{x.value=!1}}async function q(){const l=v.value||0,s=V.value.find(r=>r.value===l),t=s?s.label:""+l;if(window.confirm("确定清空「"+t+`」的接收流水吗? import{g as G,C as K,Q as P,c as a,a as e,d as u,q as g,s as U,F as f,r as B,v as Q,x as Y,t as n,y as i,A as E,o,n as F,l as A,_ as Z}from"./6O01ZZML.js";import{u as J}from"./BgasD__e.js";import{u as W}from"./xsgK-Nup.js";const X=globalThis.setInterval,$={class:"flex items-center justify-between mb-4 flex-wrap gap-3"},tt={class:"flex items-center gap-2 flex-wrap"},et=["value"],st={class:"flex items-center gap-1 text-xs text-slate-500 cursor-pointer"},lt={class:"flex items-center gap-4 mb-3 text-xs text-slate-500"},nt={class:"text-slate-700"},at={class:"text-slate-700"},ot={class:"text-slate-700"},rt={class:"muted"},ut={class:"panel overflow-hidden"},it={id:"logBody",style:{"max-height":"calc(100vh - 230px)","overflow-y":"auto"}},ct={key:0,class:"text-center text-slate-400 py-10"},dt={key:1,class:"text-center text-red-400 py-10"},vt={key:2,class:"text-center text-slate-400 py-10"},pt={class:"t"},mt={class:"app-name"},ft={key:0,class:"unreg",title:"该应用名未在 console 注册,快照已收到但不会写入统计库"},_t={key:1,class:"muted"},gt={class:"muted"},xt={class:"muted"},yt={class:"muted"},bt={class:"muted"},ht={key:0,class:"muted"},wt={class:"t"},kt={key:0,class:"late"},Ct=G({__name:"statlog",setup(Tt){const{webApi:I}=J(),{success:O,error:R}=W(),H={cn:"中国",us:"美国",ea:"东亚",sea:"东南亚",sa:"南亚",me:"中东",eu:"欧洲",ru:"俄罗斯",af:"非洲",sam:"南美",nam:"北美",oc:"大洋洲",br:"巴西",in:"印度"};function D(l){return l?H[l]||l:"-"}const c=i([]),x=i(!1),_=i(""),L=i("-"),N=i("-"),y=i(""),v=i(0),b=i(""),h=i(""),w=i(!1);let d=null;function p(l=0){const s=new Date(Date.now()+l*864e5),t=new Intl.DateTimeFormat("en-CA",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit"}).format(s);return parseInt(t.replace(/-/g,""),10)}function k(l){const s=""+l;return s.length===8?s.slice(0,4)+"-"+s.slice(4,6)+"-"+s.slice(6,8):s}function C(l){if(!l)return"--";const s=new Date(l*1e3),t=r=>r<10?"0"+r:""+r;return t(s.getHours())+":"+t(s.getMinutes())+":"+t(s.getSeconds())}function S(l){return l?"0x"+(l>>>0).toString(16).toUpperCase():"全部"}const V=E(()=>[{value:p(0),label:"今天 "+k(p(0))},{value:p(-1),label:"昨天 "+k(p(-1))}]);function M(l){return l==="error"?{cls:"lv-error",txt:"解析失败"}:l==="warn"?{cls:"lv-warn",txt:"未落库"}:{cls:"lv-info",txt:"已落库"}}function j(l){return!!(l.snap_ts&&l.ts&&l.ts-l.snap_ts>120)}const T=E(()=>{const l=b.value,s=h.value.trim().toLowerCase();return c.value.filter(t=>!(l&&t.level!==l||s&&((t.app||"")+" "+(t.region||"")+" "+D(t.region)+" "+(t.product_id||"")+" "+S(t.product_id)+" "+(t.channel_id||"")+" "+(t.stat_day||"")).toLowerCase().indexOf(s)<0))});async function m(){x.value=!0,_.value="";try{const l=await I("getstatlogs",{day:v.value||0});c.value=l?.entries||[],L.value=l?.total!=null?l.total:c.value.length,N.value=c.value.length?C(c.value[0].ts):"--"}catch(l){_.value=l?.message||"网络异常"}finally{x.value=!1}}async function q(){const l=v.value||0,s=V.value.find(r=>r.value===l),t=s?s.label:""+l;if(window.confirm("确定清空「"+t+`」的接收流水吗?
只清除本核对面板的记录,不影响已落库的统计数据。 只清除本核对面板的记录,不影响已落库的统计数据。
清空后可重新触发埋点,观察是否正常进来。`))try{const r=await I("clearstatlogs",{day:l});O("已清空 "+(r&&r.cleared!=null?r.cleared:0)+" 条"),m()}catch(r){R("清空失败:"+(r?.message||"网络异常"))}}function z(){w.value?(d=X(m,15e3),y.value="· 每 15 秒自动刷新"):(d&&clearInterval(d),d=null,y.value="")}return K(()=>{v.value=p(0),m()}),P(()=>{d&&clearInterval(d)}),(l,s)=>(o(),a("div",null,[e("div",$,[s[6]||(s[6]=e("div",null,[e("h2",{class:"text-lg font-bold text-slate-700"},"统计日志"),e("p",{class:"text-xs text-slate-400 mt-0.5"},[u("console 从 NATS 收到的「当日统计快照」接收流水(最新在前,按接收时间分天存 Redis)。各业务部署每个同步周期/启动时/0点 推送一次当日绝对快照,console 收到后覆盖落库。用于核对每个部署是否在正常汇报;带 "),e("span",{class:"unreg"},"未注册"),u(" 的应用快照已收到但"),e("b",null,"不会落库"),u("(应用名需与 console 注册表完全一致)。")])],-1)),e("div",tt,[g(e("select",{"onUpdate:modelValue":s[0]||(s[0]=t=>v.value=t),class:"select select-bordered select-sm",onChange:m},[(o(!0),a(f,null,B(V.value,t=>(o(),a("option",{key:t.value,value:t.value},n(t.label),9,et))),128))],544),[[U,v.value,void 0,{number:!0}]]),g(e("select",{"onUpdate:modelValue":s[1]||(s[1]=t=>b.value=t),class:"select select-bordered select-sm"},[...s[4]||(s[4]=[e("option",{value:""},"全部级别",-1),e("option",{value:"info"},"已落库",-1),e("option",{value:"warn"},"未落库",-1),e("option",{value:"error"},"解析失败",-1)])],512),[[U,b.value]]),g(e("input",{"onUpdate:modelValue":s[2]||(s[2]=t=>h.value=t),class:"input input-bordered input-sm w-44",placeholder:"筛选 应用/区域/产品/渠道商"},null,512),[[Q,h.value]]),e("label",st,[g(e("input",{"onUpdate:modelValue":s[3]||(s[3]=t=>w.value=t),type:"checkbox",class:"checkbox checkbox-xs",onChange:z},null,544),[[Y,w.value]]),s[5]||(s[5]=u(" 自动刷新 ",-1))]),e("button",{class:"btn btn-primary btn-sm text-white",onClick:m},"刷新"),e("button",{class:"btn btn-outline btn-error btn-sm",title:"清空本日核对流水(不影响已落库的统计数据),清空后可重新观察埋点是否正常进来",onClick:q},"清空本日")])]),e("div",lt,[e("span",null,[s[7]||(s[7]=u("该日保留 ",-1)),e("b",nt,n(L.value),1),s[8]||(s[8]=u(" 条",-1))]),e("span",null,[s[9]||(s[9]=u("当前显示 ",-1)),e("b",at,n(T.value.length),1),s[10]||(s[10]=u(" 条",-1))]),e("span",null,[s[11]||(s[11]=u("最近接收 ",-1)),e("b",ot,n(N.value),1)]),e("span",rt,n(y.value),1)]),e("div",ut,[s[12]||(s[12]=e("div",{id:"logHead"},[e("div",null,"接收时间"),e("div",null,"级别"),e("div",null,"应用 · 区域 · 产品 · 渠道商"),e("div",null,"统计日"),e("div",null,"指标摘要 / 说明"),e("div",null,"快照时间")],-1)),e("div",it,[x.value?(o(),a("div",ct,"加载中...")):_.value?(o(),a("div",dt,"加载失败:"+n(_.value),1)):T.value.length?(o(!0),a(f,{key:3},B(T.value,(t,r)=>(o(),a("div",{key:r,class:"logrow"},[e("div",pt,n(C(t.ts)),1),e("div",null,[e("span",{class:F(["lv",M(t.level).cls])},n(M(t.level).txt),3)]),e("div",null,[t.app?(o(),a(f,{key:0},[e("span",mt,n(t.app),1),t.registered?A("",!0):(o(),a("span",ft,"未注册"))],64)):(o(),a("span",_t,"(无应用名)")),e("span",gt," · "+n(D(t.region)),1),e("span",xt," · "+n(S(t.product_id)),1),e("span",yt," · "+n(t.channel_id||"未分配渠道"),1)]),e("div",bt,n(t.stat_day?k(t.stat_day):"-"),1),e("div",null,[t.msg?(o(),a(f,{key:0},[e("span",{class:F(t.level==="error"?"text-red-600":"text-amber-600")},n(t.msg),3),t.summary?(o(),a("span",ht," · "+n(t.summary),1)):A("",!0)],64)):(o(),a(f,{key:1},[u(n(t.summary||"无增量"),1)],64))]),e("div",wt,[u(n(C(t.snap_ts)),1),j(t)?(o(),a("span",kt,"迟到"+n(t.ts-t.snap_ts)+"s",1)):A("",!0)])]))),128)):(o(),a("div",vt,n(c.value.length?"无匹配记录":"该日暂无接收记录"),1))])])]))}}),Lt=Z(Ct,[["__scopeId","data-v-e7a3debc"]]);export{Lt as default}; 清空后可重新触发埋点,观察是否正常进来。`))try{const r=await I("clearstatlogs",{day:l});O("已清空 "+(r&&r.cleared!=null?r.cleared:0)+" 条"),m()}catch(r){R("清空失败:"+(r?.message||"网络异常"))}}function z(){w.value?(d=X(m,15e3),y.value="· 每 15 秒自动刷新"):(d&&clearInterval(d),d=null,y.value="")}return K(()=>{v.value=p(0),m()}),P(()=>{d&&clearInterval(d)}),(l,s)=>(o(),a("div",null,[e("div",$,[s[6]||(s[6]=e("div",null,[e("h2",{class:"text-lg font-bold text-slate-700"},"统计日志"),e("p",{class:"text-xs text-slate-400 mt-0.5"},[u("console 从 NATS 收到的「当日统计快照」接收流水(最新在前,按接收时间分天存 Redis)。各业务部署每个同步周期/启动时/0点 推送一次当日绝对快照,console 收到后覆盖落库。用于核对每个部署是否在正常汇报;带 "),e("span",{class:"unreg"},"未注册"),u(" 的应用快照已收到但"),e("b",null,"不会落库"),u("(应用名需与 console 注册表完全一致)。")])],-1)),e("div",tt,[g(e("select",{"onUpdate:modelValue":s[0]||(s[0]=t=>v.value=t),class:"select select-bordered select-sm",onChange:m},[(o(!0),a(f,null,B(V.value,t=>(o(),a("option",{key:t.value,value:t.value},n(t.label),9,et))),128))],544),[[U,v.value,void 0,{number:!0}]]),g(e("select",{"onUpdate:modelValue":s[1]||(s[1]=t=>b.value=t),class:"select select-bordered select-sm"},[...s[4]||(s[4]=[e("option",{value:""},"全部级别",-1),e("option",{value:"info"},"已落库",-1),e("option",{value:"warn"},"未落库",-1),e("option",{value:"error"},"解析失败",-1)])],512),[[U,b.value]]),g(e("input",{"onUpdate:modelValue":s[2]||(s[2]=t=>h.value=t),class:"input input-bordered input-sm w-44",placeholder:"筛选 应用/区域/产品/渠道商"},null,512),[[Q,h.value]]),e("label",st,[g(e("input",{"onUpdate:modelValue":s[3]||(s[3]=t=>w.value=t),type:"checkbox",class:"checkbox checkbox-xs",onChange:z},null,544),[[Y,w.value]]),s[5]||(s[5]=u(" 自动刷新 ",-1))]),e("button",{class:"btn btn-primary btn-sm text-white",onClick:m},"刷新"),e("button",{class:"btn btn-outline btn-error btn-sm",title:"清空本日核对流水(不影响已落库的统计数据),清空后可重新观察埋点是否正常进来",onClick:q},"清空本日")])]),e("div",lt,[e("span",null,[s[7]||(s[7]=u("该日保留 ",-1)),e("b",nt,n(L.value),1),s[8]||(s[8]=u(" 条",-1))]),e("span",null,[s[9]||(s[9]=u("当前显示 ",-1)),e("b",at,n(T.value.length),1),s[10]||(s[10]=u(" 条",-1))]),e("span",null,[s[11]||(s[11]=u("最近接收 ",-1)),e("b",ot,n(N.value),1)]),e("span",rt,n(y.value),1)]),e("div",ut,[s[12]||(s[12]=e("div",{id:"logHead"},[e("div",null,"接收时间"),e("div",null,"级别"),e("div",null,"应用 · 区域 · 产品 · 渠道商"),e("div",null,"统计日"),e("div",null,"指标摘要 / 说明"),e("div",null,"快照时间")],-1)),e("div",it,[x.value?(o(),a("div",ct,"加载中...")):_.value?(o(),a("div",dt,"加载失败:"+n(_.value),1)):T.value.length?(o(!0),a(f,{key:3},B(T.value,(t,r)=>(o(),a("div",{key:r,class:"logrow"},[e("div",pt,n(C(t.ts)),1),e("div",null,[e("span",{class:F(["lv",M(t.level).cls])},n(M(t.level).txt),3)]),e("div",null,[t.app?(o(),a(f,{key:0},[e("span",mt,n(t.app),1),t.registered?A("",!0):(o(),a("span",ft,"未注册"))],64)):(o(),a("span",_t,"(无应用名)")),e("span",gt," · "+n(D(t.region)),1),e("span",xt," · "+n(S(t.product_id)),1),e("span",yt," · "+n(t.channel_id||"未分配渠道"),1)]),e("div",bt,n(t.stat_day?k(t.stat_day):"-"),1),e("div",null,[t.msg?(o(),a(f,{key:0},[e("span",{class:F(t.level==="error"?"text-red-600":"text-amber-600")},n(t.msg),3),t.summary?(o(),a("span",ht," · "+n(t.summary),1)):A("",!0)],64)):(o(),a(f,{key:1},[u(n(t.summary||"无增量"),1)],64))]),e("div",wt,[u(n(C(t.snap_ts)),1),j(t)?(o(),a("span",kt,"迟到"+n(t.ts-t.snap_ts)+"s",1)):A("",!0)])]))),128)):(o(),a("div",vt,n(c.value.length?"无匹配记录":"该日暂无接收记录"),1))])])]))}}),Lt=Z(Ct,[["__scopeId","data-v-e7a3debc"]]);export{Lt as default};

1
apps/admin/.output/public/_nuxt/CDB8L8go.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/DBzpctzV.js → apps/admin/.output/public/_nuxt/CEFq2Pq9.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/D5EVRMZE.js → apps/admin/.output/public/_nuxt/CPoAe5lL.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/rUi_Q6ng.js → apps/admin/.output/public/_nuxt/CS9TbzfM.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/Cy52Ecc0.js → apps/admin/.output/public/_nuxt/CasIUDzx.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/D8jvJLAX.js → apps/admin/.output/public/_nuxt/CkLfApYf.js

@ -1 +1 @@
import{_ as o,o as s,c as a,a as t,t as r}from"./DSy_gLdM.js";import{u as i}from"./obp34o1K.js";const u={class:"antialiased bg-white dark:bg-[#020420] dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-[#020420] tracking-wide"},c={class:"max-w-520px text-center"},l=["textContent"],d=["textContent"],p=["textContent"],f={__name:"error-500",props:{appName:{type:String,default:"Nuxt"},status:{type:Number,default:500},statusText:{type:String,default:"Internal server error"},description:{type:String,default:"This page is temporarily unavailable."},refresh:{type:String,default:"Refresh this page"}},setup(e){const n=e;return i({title:`${n.status} - ${n.statusText} | ${n.appName}`,script:[{innerHTML:`!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver(e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)}).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();`}],style:[{innerHTML:'*,:after,:before{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}h1,h2{font-size:inherit;font-weight:inherit}h1,h2,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }'}]}),(h,m)=>(s(),a("div",u,[t("div",c,[t("h1",{class:"font-semibold leading-none mb-4 sm:text-[110px] tabular-nums text-[80px]",textContent:r(e.status)},null,8,l),t("h2",{class:"font-semibold mb-2 sm:text-3xl text-2xl",textContent:r(e.statusText)},null,8,d),t("p",{class:"mb-4 px-2 text-[#64748B] text-md",textContent:r(e.description)},null,8,p)])]))}},x=o(f,[["__scopeId","data-v-2c2ce9e3"]]);export{x as default}; import{_ as o,o as s,c as a,a as t,t as r}from"./6O01ZZML.js";import{u as i}from"./BvvkbLjV.js";const u={class:"antialiased bg-white dark:bg-[#020420] dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-[#020420] tracking-wide"},c={class:"max-w-520px text-center"},l=["textContent"],d=["textContent"],p=["textContent"],f={__name:"error-500",props:{appName:{type:String,default:"Nuxt"},status:{type:Number,default:500},statusText:{type:String,default:"Internal server error"},description:{type:String,default:"This page is temporarily unavailable."},refresh:{type:String,default:"Refresh this page"}},setup(e){const n=e;return i({title:`${n.status} - ${n.statusText} | ${n.appName}`,script:[{innerHTML:`!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver(e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)}).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();`}],style:[{innerHTML:'*,:after,:before{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}h1,h2{font-size:inherit;font-weight:inherit}h1,h2,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }'}]}),(h,m)=>(s(),a("div",u,[t("div",c,[t("h1",{class:"font-semibold leading-none mb-4 sm:text-[110px] tabular-nums text-[80px]",textContent:r(e.status)},null,8,l),t("h2",{class:"font-semibold mb-2 sm:text-3xl text-2xl",textContent:r(e.statusText)},null,8,d),t("p",{class:"mb-4 px-2 text-[#64748B] text-md",textContent:r(e.description)},null,8,p)])]))}},x=o(f,[["__scopeId","data-v-2c2ce9e3"]]);export{x as default};

2
apps/admin/.output/public/_nuxt/BDDumZok.js → apps/admin/.output/public/_nuxt/DC2vBYza.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/BKXYxnNU.js → apps/admin/.output/public/_nuxt/DDe4k6KN.js

@ -1 +1 @@
import{g as h,j as x,k as w,C as y,c as r,a as e,t as d,l as b,p as _,q as v,v as f,n as k,z as M,y as u,o as p,_ as z}from"./DSy_gLdM.js";const A={class:"login-bg flex items-center justify-center px-4"},B={class:"login-card"},C={class:"text-center"},S={style:{"font-size":"22px","font-weight":"700",color:"#0F172A",margin:"0 0 4px"}},T={key:0,class:"login-error show"},V={style:{width:"16px",height:"16px","flex-shrink":"0"},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},j={style:{"margin-bottom":"16px"}},q={style:{"margin-bottom":"24px"}},D=h({__name:"index",setup(L){const a=x(),c=w(),o=M({account:"",password:""}),l=u(!1),n=u(""),m=u("Admin");y(async()=>{if(a.restore(),a.token){c.push("/dashboard");return}try{const t=(await $fetch("/web/api/api_getsiteinfo",{method:"POST",body:{}}))?.data?.sitename;t&&(m.value=t+" Admin",a.setSiteTitle(t))}catch{}});async function g(){l.value=!0,n.value="";try{const s=await $fetch("/web/api/api_login",{method:"POST",body:{account:o.account,password:o.password}});s.code===0&&s.data?(a.setLoginData(s.data),c.push("/dashboard")):n.value=s.msg||"登录失败"}catch{n.value="网络错误,请检查连接"}finally{l.value=!1}}return(s,t)=>(p(),r("div",A,[e("div",B,[e("div",C,[t[2]||(t[2]=e("div",{class:"logo-icon"},[e("svg",{class:"h-7 w-7 text-white",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"})])],-1)),e("h1",S,d(m.value),1),t[3]||(t[3]=e("p",{style:{"font-size":"13px",color:"#94A3B8",margin:"0 0 32px"}},"管理控制台",-1))]),n.value?(p(),r("div",T,[(p(),r("svg",V,[...t[4]||(t[4]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"},null,-1)])])),e("span",null,d(n.value),1)])):b("",!0),e("form",{onSubmit:_(g,["prevent"])},[e("div",j,[t[5]||(t[5]=e("label",{class:"login-label"},"账号",-1)),v(e("input",{"onUpdate:modelValue":t[0]||(t[0]=i=>o.account=i),type:"text",class:"login-input",placeholder:"请输入管理员账号",autocomplete:"username",required:""},null,512),[[f,o.account]])]),e("div",q,[t[6]||(t[6]=e("label",{class:"login-label"},"密码",-1)),v(e("input",{"onUpdate:modelValue":t[1]||(t[1]=i=>o.password=i),type:"password",class:"login-input",placeholder:"请输入密码",autocomplete:"current-password",required:""},null,512),[[f,o.password]])]),e("button",{type:"submit",class:k(["login-btn",{loading:l.value}])},d(l.value?"登录中...":"登 录"),3)],32),t[7]||(t[7]=e("p",{style:{"text-align":"center","font-size":"11px",color:"#94A3B8","margin-top":"24px"}}," © 2025 Admin Console · v1.0.1 ",-1))])]))}}),O=z(D,[["__scopeId","data-v-4f88fb34"]]);export{O as default}; import{g as h,j as x,k as w,C as y,c as r,a as e,t as d,l as b,p as _,q as v,v as f,n as k,z as M,y as u,o as p,_ as z}from"./6O01ZZML.js";const A={class:"login-bg flex items-center justify-center px-4"},B={class:"login-card"},C={class:"text-center"},S={style:{"font-size":"22px","font-weight":"700",color:"#0F172A",margin:"0 0 4px"}},T={key:0,class:"login-error show"},V={style:{width:"16px",height:"16px","flex-shrink":"0"},fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},j={style:{"margin-bottom":"16px"}},q={style:{"margin-bottom":"24px"}},D=h({__name:"index",setup(L){const a=x(),c=w(),o=M({account:"",password:""}),l=u(!1),n=u(""),m=u("Admin");y(async()=>{if(a.restore(),a.token){c.push("/dashboard");return}try{const t=(await $fetch("/web/api/api_getsiteinfo",{method:"POST",body:{}}))?.data?.sitename;t&&(m.value=t+" Admin",a.setSiteTitle(t))}catch{}});async function g(){l.value=!0,n.value="";try{const s=await $fetch("/web/api/api_login",{method:"POST",body:{account:o.account,password:o.password}});s.code===0&&s.data?(a.setLoginData(s.data),c.push("/dashboard")):n.value=s.msg||"登录失败"}catch{n.value="网络错误,请检查连接"}finally{l.value=!1}}return(s,t)=>(p(),r("div",A,[e("div",B,[e("div",C,[t[2]||(t[2]=e("div",{class:"logo-icon"},[e("svg",{class:"h-7 w-7 text-white",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor"},[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"})])],-1)),e("h1",S,d(m.value),1),t[3]||(t[3]=e("p",{style:{"font-size":"13px",color:"#94A3B8",margin:"0 0 32px"}},"管理控制台",-1))]),n.value?(p(),r("div",T,[(p(),r("svg",V,[...t[4]||(t[4]=[e("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"},null,-1)])])),e("span",null,d(n.value),1)])):b("",!0),e("form",{onSubmit:_(g,["prevent"])},[e("div",j,[t[5]||(t[5]=e("label",{class:"login-label"},"账号",-1)),v(e("input",{"onUpdate:modelValue":t[0]||(t[0]=i=>o.account=i),type:"text",class:"login-input",placeholder:"请输入管理员账号",autocomplete:"username",required:""},null,512),[[f,o.account]])]),e("div",q,[t[6]||(t[6]=e("label",{class:"login-label"},"密码",-1)),v(e("input",{"onUpdate:modelValue":t[1]||(t[1]=i=>o.password=i),type:"password",class:"login-input",placeholder:"请输入密码",autocomplete:"current-password",required:""},null,512),[[f,o.password]])]),e("button",{type:"submit",class:k(["login-btn",{loading:l.value}])},d(l.value?"登录中...":"登 录"),3)],32),t[7]||(t[7]=e("p",{style:{"text-align":"center","font-size":"11px",color:"#94A3B8","margin-top":"24px"}}," © 2025 Admin Console · v1.0.1 ",-1))])]))}}),O=z(D,[["__scopeId","data-v-4f88fb34"]]);export{O as default};

2
apps/admin/.output/public/_nuxt/DVest5s8.js → apps/admin/.output/public/_nuxt/DPKLCcBs.js

@ -1,2 +1,2 @@
import{u as r}from"./EeX3zgoF.js";import{g as x,c as i,a as t,t as o,l as f,o as l}from"./DSy_gLdM.js";const b={key:0,class:"modal modal-open"},u={class:"modal-box max-w-md"},p={class:"font-bold text-base mb-1"},y={class:"rounded-xl border border-slate-200 bg-slate-50 p-3 space-y-2"},g={class:"flex items-center justify-between gap-3"},v={class:"font-mono font-semibold text-sm"},_={class:"flex items-center justify-between gap-3"},w={class:"font-mono font-semibold text-sm"},h={key:0,class:"mt-3 text-xs text-emerald-600"},k={key:1,class:"mt-3 text-xs text-amber-600"},C={class:"modal-action"},T=x({__name:"AccountCredentialDialog",props:{info:{}},emits:["close"],setup(s){const n=s,{success:c,warn:m}=r();async function d(){if(!n.info)return;const a=`用户名:${n.info.username} import{u as r}from"./xsgK-Nup.js";import{g as x,c as i,a as t,t as o,l as f,o as l}from"./6O01ZZML.js";const b={key:0,class:"modal modal-open"},u={class:"modal-box max-w-md"},p={class:"font-bold text-base mb-1"},y={class:"rounded-xl border border-slate-200 bg-slate-50 p-3 space-y-2"},g={class:"flex items-center justify-between gap-3"},v={class:"font-mono font-semibold text-sm"},_={class:"flex items-center justify-between gap-3"},w={class:"font-mono font-semibold text-sm"},h={key:0,class:"mt-3 text-xs text-emerald-600"},k={key:1,class:"mt-3 text-xs text-amber-600"},C={class:"modal-action"},T=x({__name:"AccountCredentialDialog",props:{info:{}},emits:["close"],setup(s){const n=s,{success:c,warn:m}=r();async function d(){if(!n.info)return;const a=`用户名:${n.info.username}
初始密码:${n.info.password}`;try{await navigator.clipboard.writeText(a),c("凭据已复制")}catch{m("复制失败,请手工记录")}}return(a,e)=>s.info?(l(),i("div",b,[t("div",u,[t("h3",p,o(s.info.title),1),e[3]||(e[3]=t("p",{class:"text-xs text-slate-400 mb-3"},"初始密码仅在此显示一次,关闭后无法再查看(如需重设请到「后台账号」改密)。",-1)),t("div",y,[t("div",g,[e[1]||(e[1]=t("span",{class:"text-xs text-slate-500"},"登录用户名",-1)),t("span",v,o(s.info.username),1)]),t("div",_,[e[2]||(e[2]=t("span",{class:"text-xs text-slate-500"},"初始密码",-1)),t("span",w,o(s.info.password),1)])]),s.info.mailTo?(l(),i("div",h," ✓ 凭据已邮件发送至 "+o(s.info.mailTo),1)):(l(),i("div",k," ⚠ 凭据未能邮件送达"+o(s.info.mailError?":"+s.info.mailError:"")+",请手工转达上面的用户名和密码。 ",1)),t("div",C,[t("button",{class:"btn btn-ghost btn-sm",onClick:d},"复制"),t("button",{class:"btn btn-primary btn-sm text-white",onClick:e[0]||(e[0]=$=>a.$emit("close"))},"我已记录,关闭")])])])):f("",!0)}}),D=Object.assign(T,{__name:"AccountCredentialDialog"});export{D as _}; 初始密码:${n.info.password}`;try{await navigator.clipboard.writeText(a),c("凭据已复制")}catch{m("复制失败,请手工记录")}}return(a,e)=>s.info?(l(),i("div",b,[t("div",u,[t("h3",p,o(s.info.title),1),e[3]||(e[3]=t("p",{class:"text-xs text-slate-400 mb-3"},"初始密码仅在此显示一次,关闭后无法再查看(如需重设请到「后台账号」改密)。",-1)),t("div",y,[t("div",g,[e[1]||(e[1]=t("span",{class:"text-xs text-slate-500"},"登录用户名",-1)),t("span",v,o(s.info.username),1)]),t("div",_,[e[2]||(e[2]=t("span",{class:"text-xs text-slate-500"},"初始密码",-1)),t("span",w,o(s.info.password),1)])]),s.info.mailTo?(l(),i("div",h," ✓ 凭据已邮件发送至 "+o(s.info.mailTo),1)):(l(),i("div",k," ⚠ 凭据未能邮件送达"+o(s.info.mailError?":"+s.info.mailError:"")+",请手工转达上面的用户名和密码。 ",1)),t("div",C,[t("button",{class:"btn btn-ghost btn-sm",onClick:d},"复制"),t("button",{class:"btn btn-primary btn-sm text-white",onClick:e[0]||(e[0]=$=>a.$emit("close"))},"我已记录,关闭")])])])):f("",!0)}}),D=Object.assign(T,{__name:"AccountCredentialDialog"});export{D as _};

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BFjsaYIf.js → apps/admin/.output/public/_nuxt/DQ6zmqs4.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/CLee_yMD.js → apps/admin/.output/public/_nuxt/DRVBzPRY.js

File diff suppressed because one or more lines are too long

1
apps/admin/.output/public/_nuxt/DT3lD2sm.js

File diff suppressed because one or more lines are too long

1
apps/admin/.output/public/_nuxt/DTVoyhwb.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/Bs6lDwyi.js → apps/admin/.output/public/_nuxt/DZfr_EfO.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/BZKwWPxz.js → apps/admin/.output/public/_nuxt/Dehik56a.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/PbGQRI_R.js → apps/admin/.output/public/_nuxt/DlMn1R4f.js

File diff suppressed because one or more lines are too long

1
apps/admin/.output/public/_nuxt/GUJrhX2S.js

File diff suppressed because one or more lines are too long

1
apps/admin/.output/public/_nuxt/NtXZuCUg.js

@ -1 +0,0 @@
import{e as y,a9 as h,aa as w,A as g,j as d,k}from"./DSy_gLdM.js";const A="$s";function b(...t){const s=typeof t[t.length-1]=="string"?t.pop():void 0;typeof t[0]!="string"&&t.unshift(s);const[a,o]=t;if(!a||typeof a!="string")throw new TypeError("[nuxt] [useState] key must be a string: "+a);if(o!==void 0&&typeof o!="function")throw new Error("[nuxt] [useState] init must be a function: "+o);const i=A+a,r=y(),n=h(r.payload.state,i);if(o&&(r._state[i]??={_default:o}),n.value===void 0&&o){const e=o();if(w(e))return r.payload.state[i]=e,e;n.value=e}return n}function m(){const t=b("app:loading",()=>0),s=g(()=>t.value>0);function a(){t.value++}function o(){t.value=Math.max(0,t.value-1)}return{count:t,loading:s,begin:a,end:o}}async function f(t,s,a){const o=d(),i=k(),r={"Content-Type":"application/json"};o.token&&(r.Authorization=o.token),a&&Object.assign(r,a);const n=await fetch(t,{method:"POST",headers:r,body:JSON.stringify(s)});if(!n.ok)throw new Error(`HTTP error: ${n.status}`);const e=await n.json();if(e.code===18)throw o.logout(),i.push("/"),new Error(e.msg||"Unauthorized");if(e.code!==0)throw new Error(e.msg||"Unknown error");return e.data}const S=/^(get|list|load|query|fetch|search|count|stat|export|check)/i;function v(t){return!S.test(t)}function x(){const t=d(),{begin:s,end:a}=m();async function o(n,e){const u={};if(t.currentAppId&&(u["X-App-Id"]=String(t.currentAppId)),!v(n))return f(`/web/api/api_${n}`,e??{},u);s();try{return await f(`/web/api/api_${n}`,e??{},u)}finally{a()}}async function i(n,e){return f(`/console/api/${n}`,e??{})}async function r(n,e){const u=n.type||"application/octet-stream",c=await o("getcostoken",{path:e,filename:n.name,content_type:u}),p=c.upload_url||c.url||"";if(!p)throw new Error("未获取到上传地址:请确认已在【第三方服务配置→存储】配置并启用「阿里云 OSS」");const l=await fetch(p,{method:"PUT",headers:{"Content-Type":u},body:n});if(!l.ok)throw new Error(`Upload failed: ${l.status}`);return c.url||p.split("?")[0]}return{webApi:o,consoleApi:i,uploadFile:r}}export{m as a,b,x as u};

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/DAaIRqev.js → apps/admin/.output/public/_nuxt/VxS1tujf.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/DBJku-16.js → apps/admin/.output/public/_nuxt/_yKEhqk3.js

@ -1 +1 @@
import{g as t,C as n,P as a,c as o,a as s,o as c}from"./DSy_gLdM.js";const i={class:"py-16 text-center text-slate-400"},m=t({__name:"mcpconfig",setup(l){return n(()=>{a("/serviceconfig")}),(r,e)=>(c(),o("div",i,[...e[0]||(e[0]=[s("span",{class:"loading loading-spinner loading-sm"},null,-1),s("p",{class:"text-sm mt-3"},"MCP 配置已并入「第三方服务配置」,正在跳转…",-1)])]))}});export{m as default}; import{g as t,C as n,P as a,c as o,a as s,o as c}from"./6O01ZZML.js";const i={class:"py-16 text-center text-slate-400"},m=t({__name:"mcpconfig",setup(l){return n(()=>{a("/serviceconfig")}),(r,e)=>(c(),o("div",i,[...e[0]||(e[0]=[s("span",{class:"loading loading-spinner loading-sm"},null,-1),s("p",{class:"text-sm mt-3"},"MCP 配置已并入「第三方服务配置」,正在跳转…",-1)])]))}});export{m as default};

1
apps/admin/.output/public/_nuxt/accounts.B-g1r2A7.css

@ -0,0 +1 @@
.chk[data-v-a2832f1b]{display:flex;align-items:center;gap:6px;padding:5px 9px;border:1px solid #e2e8f0;border-radius:8px;font-size:12px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chk[data-v-a2832f1b]:hover{background:#f8fafc}.chk input[data-v-a2832f1b]{width:14px;height:14px}

1
apps/admin/.output/public/_nuxt/accounts.maMJCEm_.css

@ -1 +0,0 @@
.chk[data-v-b47e60f8]{display:flex;align-items:center;gap:6px;padding:5px 9px;border:1px solid #e2e8f0;border-radius:8px;font-size:12px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chk[data-v-b47e60f8]:hover{background:#f8fafc}.chk input[data-v-b47e60f8]{width:14px;height:14px}

2
apps/admin/.output/public/_nuxt/builds/latest.json

@ -1 +1 @@
{"id":"12df8bde-c7e1-423a-8c26-514d561b95ec","timestamp":1786697524151} {"id":"15e7ab28-16d6-4f4e-8edd-c6a8122f81cf","timestamp":1786784834591}

1
apps/admin/.output/public/_nuxt/builds/meta/12df8bde-c7e1-423a-8c26-514d561b95ec.json

@ -1 +0,0 @@
{"id":"12df8bde-c7e1-423a-8c26-514d561b95ec","timestamp":1786697524151,"prerendered":[]}

1
apps/admin/.output/public/_nuxt/builds/meta/15e7ab28-16d6-4f4e-8edd-c6a8122f81cf.json

@ -0,0 +1 @@
{"id":"15e7ab28-16d6-4f4e-8edd-c6a8122f81cf","timestamp":1786784834591,"prerendered":[]}

2
apps/admin/.output/public/_nuxt/dashboard.BgaEnlue.css → apps/admin/.output/public/_nuxt/dashboard.CuNO2Lt5.css

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/entry.CF8jJHbs.css → apps/admin/.output/public/_nuxt/entry.B1mQ-Tl2.css

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/Bm2Gu08J.js → apps/admin/.output/public/_nuxt/oWVa2rll.js

@ -1 +1 @@
import{_ as s}from"./32rNuZwS.js";import{_ as a,o as i,c as u,a as t,t as n,b as c,w as l,d}from"./DSy_gLdM.js";import{u as f}from"./obp34o1K.js";const p={class:"antialiased bg-white dark:bg-[#020420] dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-[#020420] tracking-wide"},m={class:"max-w-520px text-center"},h=["textContent"],b=["textContent"],x=["textContent"],g={class:"flex items-center justify-center w-full"},y={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},status:{type:Number,default:404},statusText:{type:String,default:"Page not found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(e){const r=e;return f({title:`${r.status} - ${r.statusText} | ${r.appName}`,script:[{innerHTML:`!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver(e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)}).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();`}],style:[{innerHTML:'*,:after,:before{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}h1,h2{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}h1,h2,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }'}]}),(k,_)=>{const o=s;return i(),u("div",p,[t("div",m,[t("h1",{class:"font-semibold leading-none mb-4 sm:text-[110px] tabular-nums text-[80px]",textContent:n(e.status)},null,8,h),t("h2",{class:"font-semibold mb-2 sm:text-3xl text-2xl",textContent:n(e.statusText)},null,8,b),t("p",{class:"mb-4 px-2 text-[#64748B] text-md",textContent:n(e.description)},null,8,x),t("div",g,[c(o,{to:"/",class:"font-medium hover:text-[#00DC82] text-sm underline underline-offset-3"},{default:l(()=>[d(n(e.backHome),1)]),_:1})])])])}}},z=a(y,[["__scopeId","data-v-52418c85"]]);export{z as default}; import{_ as s}from"./CDB8L8go.js";import{_ as a,o as i,c as u,a as t,t as n,b as c,w as l,d}from"./6O01ZZML.js";import{u as f}from"./BvvkbLjV.js";const p={class:"antialiased bg-white dark:bg-[#020420] dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-[#020420] tracking-wide"},m={class:"max-w-520px text-center"},h=["textContent"],b=["textContent"],x=["textContent"],g={class:"flex items-center justify-center w-full"},y={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},status:{type:Number,default:404},statusText:{type:String,default:"Page not found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(e){const r=e;return f({title:`${r.status} - ${r.statusText} | ${r.appName}`,script:[{innerHTML:`!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver(e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)}).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();`}],style:[{innerHTML:'*,:after,:before{box-sizing:border-box;border-width:0;border-style:solid;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}h1,h2{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}h1,h2,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }'}]}),(k,_)=>{const o=s;return i(),u("div",p,[t("div",m,[t("h1",{class:"font-semibold leading-none mb-4 sm:text-[110px] tabular-nums text-[80px]",textContent:n(e.status)},null,8,h),t("h2",{class:"font-semibold mb-2 sm:text-3xl text-2xl",textContent:n(e.statusText)},null,8,b),t("p",{class:"mb-4 px-2 text-[#64748B] text-md",textContent:n(e.description)},null,8,x),t("div",g,[c(o,{to:"/",class:"font-medium hover:text-[#00DC82] text-sm underline underline-offset-3"},{default:l(()=>[d(n(e.backHome),1)]),_:1})])])])}}},z=a(y,[["__scopeId","data-v-52418c85"]]);export{z as default};

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/B9UHsPCY.js → apps/admin/.output/public/_nuxt/q-Oqovwl.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/EeX3zgoF.js → apps/admin/.output/public/_nuxt/xsgK-Nup.js

@ -1 +1 @@
import{b as a}from"./NtXZuCUg.js";let i=0;function f(){const o=a("app:toasts",()=>[]);function e(s,t="info",r=3e3){const n=++i;o.value.push({id:n,type:t,msg:s}),r>0&&setTimeout(()=>{o.value=o.value.filter(u=>u.id!==n)},r)}return{toasts:o,toast:e,success:(s,t)=>e(s,"success",t),error:(s,t)=>e(s,"error",t),info:(s,t)=>e(s,"info",t),warn:(s,t)=>e(s,"warning",t)}}export{f as u}; import{b as a}from"./BgasD__e.js";let i=0;function f(){const o=a("app:toasts",()=>[]);function e(s,t="info",r=3e3){const n=++i;o.value.push({id:n,type:t,msg:s}),r>0&&setTimeout(()=>{o.value=o.value.filter(u=>u.id!==n)},r)}return{toasts:o,toast:e,success:(s,t)=>e(s,"success",t),error:(s,t)=>e(s,"error",t),info:(s,t)=>e(s,"info",t),warn:(s,t)=>e(s,"warning",t)}}export{f as u};

222
apps/admin/.output/server/chunks/build/accounts-CM5YEJ4p.mjs

@ -0,0 +1,222 @@
import { defineComponent, ref, computed, reactive, watch, unref, useSSRContext } from 'vue';
import { ssrRenderAttrs, ssrRenderStyle, ssrRenderList, ssrInterpolate, ssrRenderClass, ssrRenderAttr, ssrIncludeBooleanAttr, ssrLooseContain, ssrLooseEqual } from 'vue/server-renderer';
import { u as useApi } from './useApi-BNSkSrat.mjs';
import { u as useToast } from './useToast-MBvLaNjH.mjs';
import { _ as _export_sfc, R as ROLE_ACCESS_CEILING, A as ALL_MENU_IDS, M as MENU_GROUPS, D as DEFAULT_ADMIN_ACCESS } from './server.mjs';
import { R as REGION_OPTIONS } from './regions-D1dSykUW.mjs';
import '../nitro/nitro.mjs';
import 'node:http';
import 'node:https';
import 'node:events';
import 'node:buffer';
import 'node:fs';
import 'node:path';
import 'node:crypto';
import 'node:url';
import '../routes/renderer.mjs';
import 'vue-bundle-renderer/runtime';
import 'unhead/server';
import 'devalue';
import 'unhead/utils';
import 'pinia';
import 'perfect-debounce';
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "accounts",
__ssrInlineRender: true,
setup(__props) {
useApi();
useToast();
const ROLE = { 1: "超管", 2: "管理员", 3: "品牌商", 4: "运营", 5: "渠道商" };
const ROLE_CLS = { 1: "badge-error", 2: "badge-primary", 3: "badge-warning", 4: "badge-info", 5: "badge-accent" };
const view = ref("list");
const rows = ref([]);
const apps = ref([]);
const appNames = computed(
() => [...new Set(apps.value.map((a) => a.app_name || a.name).filter(Boolean))].sort()
);
const loading = ref(false);
const submitting = ref(false);
const editId = ref(0);
const form = reactive({
username: "",
password: "",
identity: 2,
enabled: "1",
remark: "",
brandid: 0,
channelid: ""
});
const roleCeiling = computed(() => ROLE_ACCESS_CEILING[form.identity] ?? null);
computed(() => roleCeiling.value ?? ALL_MENU_IDS);
const menuGroupsForRole = computed(() => {
const ceiling = roleCeiling.value;
if (!ceiling) return MENU_GROUPS;
return MENU_GROUPS.map((g) => ({ ...g, items: g.items.filter((m) => ceiling.includes(m.id)) })).filter((g) => g.items.length > 0);
});
const channels = ref([]);
const accountChannelOptions = computed(
() => form.brandid ? channels.value.filter((ch) => ch.brandid === form.brandid) : []
);
const sel = reactive({
access: [],
apps: [],
regions: [],
products: []
});
const brands = ref([]);
const productGroups = ref([]);
const prodLoading = ref(false);
function fromCsv(s) {
return (s || "").split(",").map((x) => x.trim()).filter((x) => x);
}
function scopeParts(a) {
const parts = [];
if (a.apps) parts.push("应用:" + fromCsv(a.apps).length);
if (a.regions) parts.push("区域:" + fromCsv(a.regions).length);
if (a.products) parts.push("产品:" + fromCsv(a.products).length);
if (a.access) parts.push("页面:" + fromCsv(a.access).length);
return parts;
}
watch(() => form.identity, (idt) => {
if (idt === 2 && sel.access.length === 0) sel.access = DEFAULT_ADMIN_ACCESS.slice();
const ceiling = ROLE_ACCESS_CEILING[idt];
if (ceiling) sel.access = sel.access.filter((id) => ceiling.includes(id));
});
ref(null);
ref(0);
const topup = reactive({
name: "",
cur: "",
vipday: 0,
trademin: 0,
meetmin: 0
});
return (_ctx, _push, _parent, _attrs) => {
_push(`<div${ssrRenderAttrs(_attrs)} data-v-a2832f1b><div style="${ssrRenderStyle(view.value === "list" ? null : { display: "none" })}" data-v-a2832f1b><div class="flex items-center justify-between mb-4" data-v-a2832f1b><div data-v-a2832f1b><h2 class="text-lg font-bold text-slate-700" data-v-a2832f1b>后台账号</h2><p class="text-xs text-slate-400 mt-0.5" data-v-a2832f1b>超管 / 管理员 / 代理 / 运营。代理·运营可绑定应用·区域·产品,登录后仪表盘按绑定限制。</p></div><button class="btn btn-primary btn-sm text-white" data-v-a2832f1b>+ 新建账号</button></div><div class="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden" data-v-a2832f1b><table class="table table-sm" data-v-a2832f1b><thead data-v-a2832f1b><tr class="text-slate-500" data-v-a2832f1b><th data-v-a2832f1b>ID</th><th data-v-a2832f1b>用户名</th><th data-v-a2832f1b>角色</th><th data-v-a2832f1b>状态</th><th data-v-a2832f1b>绑定作用域</th><th data-v-a2832f1b>备注</th><th class="text-right" data-v-a2832f1b>操作</th></tr></thead><tbody data-v-a2832f1b>`);
if (loading.value) {
_push(`<tr data-v-a2832f1b><td colspan="7" class="text-center text-slate-400 py-8" data-v-a2832f1b>加载中...</td></tr>`);
} else if (!rows.value.length) {
_push(`<tr data-v-a2832f1b><td colspan="7" class="text-center text-slate-400 py-8" data-v-a2832f1b>暂无账号(引导超管不在此列)</td></tr>`);
} else {
_push(`<!---->`);
}
_push(`<!--[-->`);
ssrRenderList(rows.value, (a) => {
_push(`<tr data-v-a2832f1b><td class="font-mono" data-v-a2832f1b>${ssrInterpolate(a.id)}</td><td class="font-medium" data-v-a2832f1b>${ssrInterpolate(a.username || "")}</td><td data-v-a2832f1b><span class="${ssrRenderClass([ROLE_CLS[a.identity] || "", "badge badge-sm"])}" data-v-a2832f1b>${ssrInterpolate(ROLE[a.identity] || a.identity)}</span></td><td data-v-a2832f1b>`);
if (a.enabled) {
_push(`<span class="text-green-600 text-xs" data-v-a2832f1b>启用</span>`);
} else {
_push(`<span class="text-slate-400 text-xs" data-v-a2832f1b>停用</span>`);
}
_push(`</td><td data-v-a2832f1b>`);
if (a.identity === 3 || a.identity === 4) {
_push(`<!--[-->`);
if (scopeParts(a).length) {
_push(`<span class="text-xs text-slate-500" data-v-a2832f1b>${ssrInterpolate(scopeParts(a).join(" · "))}</span>`);
} else {
_push(`<span class="text-xs text-slate-300" data-v-a2832f1b>未绑定(不限)</span>`);
}
_push(`<!--]-->`);
} else if (a.identity === 2) {
_push(`<!--[-->`);
if (a.access) {
_push(`<span class="text-xs text-slate-500" data-v-a2832f1b>菜单:${ssrInterpolate(fromCsv(a.access).length)}</span>`);
} else {
_push(`<span class="text-xs text-slate-300" data-v-a2832f1b>默认(除SaaS/系统管理)</span>`);
}
_push(`<!--]-->`);
} else {
_push(`<span class="text-xs text-slate-300" data-v-a2832f1b>全部权限</span>`);
}
if (a.identity === 3) {
_push(`<div class="text-[11px] text-emerald-600 mt-0.5" data-v-a2832f1b> 余额 VIP${ssrInterpolate(a.balance_vipday || 0)}天 · 翻译${ssrInterpolate(a.balance_trademin || 0)}分 · 会议${ssrInterpolate(a.balance_meetmin || 0)}分 </div>`);
} else {
_push(`<!---->`);
}
_push(`</td><td class="text-xs text-slate-500" data-v-a2832f1b>${ssrInterpolate(a.remark || "")}</td><td data-v-a2832f1b><div class="flex gap-1 justify-end" data-v-a2832f1b>`);
if (a.identity === 3) {
_push(`<button class="btn btn-ghost btn-xs text-emerald-600" data-v-a2832f1b>充值</button>`);
} else {
_push(`<!---->`);
}
_push(`<button class="btn btn-ghost btn-xs" data-v-a2832f1b>编辑</button><button class="btn btn-ghost btn-xs text-amber-600" data-v-a2832f1b>改密</button><button class="btn btn-ghost btn-xs text-red-500" data-v-a2832f1b>删除</button></div></td></tr>`);
});
_push(`<!--]--></tbody></table></div></div><div style="${ssrRenderStyle(view.value === "form" ? null : { display: "none" })}" data-v-a2832f1b><div class="flex items-center gap-3 mb-5" data-v-a2832f1b><button class="btn btn-ghost btn-sm" data-v-a2832f1b>← 返回列表</button><h2 class="text-lg font-semibold text-slate-800" data-v-a2832f1b>${ssrInterpolate(editId.value ? "编辑账号 #" + editId.value : "新建账号")}</h2></div><div class="bg-white rounded-xl shadow-sm border border-slate-100 p-6 max-w-2xl" data-v-a2832f1b><div class="grid grid-cols-2 gap-3" data-v-a2832f1b><div data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>用户名</label><input${ssrRenderAttr("value", form.username)}${ssrIncludeBooleanAttr(!!editId.value) ? " disabled" : ""} class="input input-bordered input-sm w-full" placeholder="登录用户名" data-v-a2832f1b></div><div style="${ssrRenderStyle(!editId.value ? null : { display: "none" })}" data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>密码</label><input${ssrRenderAttr("value", form.password)} type="password" class="input input-bordered input-sm w-full" placeholder="登录密码" data-v-a2832f1b></div><div data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>角色</label><select class="select select-bordered select-sm w-full" data-v-a2832f1b><option${ssrRenderAttr("value", 2)} data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 2) : ssrLooseEqual(form.identity, 2)) ? " selected" : ""}>管理员(默认除 SaaS/系统管理外全部)</option><option${ssrRenderAttr("value", 3)} data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 3) : ssrLooseEqual(form.identity, 3)) ? " selected" : ""}>品牌商(绑定品牌商,见名下全部渠道商)</option><option${ssrRenderAttr("value", 5)} data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 5) : ssrLooseEqual(form.identity, 5)) ? " selected" : ""}>渠道商(绑定单个渠道商,只见自己数据)</option><option${ssrRenderAttr("value", 4)} data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 4) : ssrLooseEqual(form.identity, 4)) ? " selected" : ""}>运营(内部,按绑定限制)</option><option${ssrRenderAttr("value", 1)} data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 1) : ssrLooseEqual(form.identity, 1)) ? " selected" : ""}>超管(全部权限)</option></select></div><div data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>状态</label><select class="select select-bordered select-sm w-full" data-v-a2832f1b><option value="1" data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.enabled) ? ssrLooseContain(form.enabled, "1") : ssrLooseEqual(form.enabled, "1")) ? " selected" : ""}>启用</option><option value="0" data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.enabled) ? ssrLooseContain(form.enabled, "0") : ssrLooseEqual(form.enabled, "0")) ? " selected" : ""}>停用</option></select></div><div class="col-span-2" data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>备注</label><input${ssrRenderAttr("value", form.remark)} class="input input-bordered input-sm w-full" placeholder="可选" data-v-a2832f1b></div></div><div class="mt-4 border-t border-slate-100 pt-4" style="${ssrRenderStyle(form.identity !== 1 ? null : { display: "none" })}" data-v-a2832f1b><div class="flex items-center justify-between mb-1" data-v-a2832f1b><div class="text-sm font-semibold text-slate-600" data-v-a2832f1b>菜单权限</div><div class="flex gap-1" data-v-a2832f1b>`);
if (!roleCeiling.value) {
_push(`<button type="button" class="btn btn-ghost btn-xs" data-v-a2832f1b>管理员默认</button>`);
} else {
_push(`<!---->`);
}
_push(`<button type="button" class="btn btn-ghost btn-xs" data-v-a2832f1b>全选</button><button type="button" class="btn btn-ghost btn-xs" data-v-a2832f1b>清空</button></div></div>`);
if (roleCeiling.value) {
_push(`<p class="text-xs text-slate-400 mb-3" data-v-a2832f1b>该角色为外部账号,可见页面固定在下列范围内(留空即全部开放这些页面)。</p>`);
} else {
_push(`<p class="text-xs text-slate-400 mb-3" data-v-a2832f1b>管理员默认开放除「SaaS 管理 / 系统管理」以外的全部菜单(权限留空时按默认生效);代理/运营需显式勾选。</p>`);
}
_push(`<!--[-->`);
ssrRenderList(menuGroupsForRole.value, (g) => {
_push(`<div class="mb-2.5" data-v-a2832f1b><div class="text-xs text-slate-500 mb-1.5" data-v-a2832f1b>${ssrInterpolate(g.label)}`);
if (g.restricted) {
_push(`<span class="text-amber-500 ml-1" data-v-a2832f1b>(管理员默认不开放)</span>`);
} else {
_push(`<!---->`);
}
_push(`</div><div class="flex flex-wrap gap-2" data-v-a2832f1b><!--[-->`);
ssrRenderList(g.items, (m) => {
_push(`<label class="chk" data-v-a2832f1b><input${ssrIncludeBooleanAttr(Array.isArray(sel.access) ? ssrLooseContain(sel.access, m.id) : sel.access) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", m.id)} data-v-a2832f1b>${ssrInterpolate(m.label)}</label>`);
});
_push(`<!--]--></div></div>`);
});
_push(`<!--]--></div><div class="mt-4 border-t border-slate-100 pt-4" style="${ssrRenderStyle(form.identity === 3 || form.identity === 5 ? null : { display: "none" })}" data-v-a2832f1b><div class="text-sm font-semibold text-slate-600 mb-2" data-v-a2832f1b> 归属绑定 <span class="text-xs text-slate-400 font-normal" data-v-a2832f1b>(品牌商账号只绑品牌商;渠道商账号两者都要绑)</span></div><div class="grid grid-cols-2 gap-3" data-v-a2832f1b><div data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>所属品牌商 *</label><select class="select select-bordered select-sm w-full" data-v-a2832f1b><option${ssrRenderAttr("value", 0)} data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.brandid) ? ssrLooseContain(form.brandid, 0) : ssrLooseEqual(form.brandid, 0)) ? " selected" : ""}>请选择品牌商</option><!--[-->`);
ssrRenderList(brands.value, (b) => {
_push(`<option${ssrRenderAttr("value", b.id)} data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.brandid) ? ssrLooseContain(form.brandid, b.id) : ssrLooseEqual(form.brandid, b.id)) ? " selected" : ""}>${ssrInterpolate(b.brand)}</option>`);
});
_push(`<!--]--></select></div><div style="${ssrRenderStyle(form.identity === 5 ? null : { display: "none" })}" data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>所属渠道商 *</label><select class="select select-bordered select-sm w-full"${ssrIncludeBooleanAttr(!accountChannelOptions.value.length) ? " disabled" : ""} data-v-a2832f1b><option value="" data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.channelid) ? ssrLooseContain(form.channelid, "") : ssrLooseEqual(form.channelid, "")) ? " selected" : ""}>${ssrInterpolate(form.brandid ? accountChannelOptions.value.length ? "请选择渠道商" : "该品牌商暂无渠道商" : "请先选择品牌商")}</option><!--[-->`);
ssrRenderList(accountChannelOptions.value, (ch) => {
_push(`<option${ssrRenderAttr("value", ch.id)} data-v-a2832f1b${ssrIncludeBooleanAttr(Array.isArray(form.channelid) ? ssrLooseContain(form.channelid, ch.id) : ssrLooseEqual(form.channelid, ch.id)) ? " selected" : ""}>${ssrInterpolate(ch.name)} (${ssrInterpolate(ch.id)})</option>`);
});
_push(`<!--]--></select></div></div><p class="text-xs text-slate-400 mt-2" data-v-a2832f1b> 数据隔离由后端强制:品牌商账号只能看到本品牌商及其名下渠道商的数据,渠道商账号只能看到自己渠道的数据。 </p></div><div class="mt-4 border-t border-slate-100 pt-4" style="${ssrRenderStyle(form.identity === 3 || form.identity === 4 ? null : { display: "none" })}" data-v-a2832f1b><div class="text-sm font-semibold text-slate-600 mb-2" data-v-a2832f1b>作用域绑定 <span class="text-xs text-slate-400 font-normal" data-v-a2832f1b>(代理/运营生效;限制仪表盘数据范围)</span></div><div class="mb-3" data-v-a2832f1b><div class="text-xs text-slate-500 mb-1.5" data-v-a2832f1b>绑定应用 <span class="text-slate-300" data-v-a2832f1b>(仪表盘只显示这些应用数据;不勾=不限)</span></div><div class="flex flex-wrap gap-2" data-v-a2832f1b>`);
if (appNames.value.length) {
_push(`<!--[-->`);
ssrRenderList(appNames.value, (n) => {
_push(`<label class="chk" data-v-a2832f1b><input${ssrIncludeBooleanAttr(Array.isArray(sel.apps) ? ssrLooseContain(sel.apps, n) : sel.apps) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", n)} data-v-a2832f1b>${ssrInterpolate(n)}</label>`);
});
_push(`<!--]-->`);
} else {
_push(`<span class="text-xs text-slate-300" data-v-a2832f1b>无注册应用</span>`);
}
_push(`</div></div><div class="mb-3" data-v-a2832f1b><div class="text-xs text-slate-500 mb-1.5" data-v-a2832f1b>绑定区域 <span class="text-slate-300" data-v-a2832f1b>(不勾=不限)</span></div><div class="flex flex-wrap gap-2" data-v-a2832f1b><!--[-->`);
ssrRenderList(unref(REGION_OPTIONS), (r) => {
_push(`<label class="chk" data-v-a2832f1b><input${ssrIncludeBooleanAttr(Array.isArray(sel.regions) ? ssrLooseContain(sel.regions, r.value) : sel.regions) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", r.value)} data-v-a2832f1b>${ssrInterpolate(r.label)}</label>`);
});
_push(`<!--]--></div></div><div data-v-a2832f1b><div class="text-xs text-slate-500 mb-1.5" data-v-a2832f1b>绑定产品 <span class="text-slate-300" data-v-a2832f1b>(按厂家分组;仪表盘只显示这些产品数据;不勾=不限)</span></div><div class="max-h-56 overflow-y-auto pr-1 border border-slate-100 rounded-lg p-2" data-v-a2832f1b>`);
if (prodLoading.value) {
_push(`<span class="text-xs text-slate-300" data-v-a2832f1b>加载产品中...</span>`);
} else if (!productGroups.value.length) {
_push(`<span class="text-xs text-slate-300" data-v-a2832f1b>无产品</span>`);
} else {
_push(`<!--[-->`);
ssrRenderList(productGroups.value, (g) => {
_push(`<div class="mb-2 last:mb-0" data-v-a2832f1b><div class="text-[11px] font-semibold text-slate-500 mb-1 sticky top-0 bg-white py-0.5" data-v-a2832f1b>🏭 ${ssrInterpolate(g.label)}</div><div class="flex flex-wrap gap-2" data-v-a2832f1b><!--[-->`);
ssrRenderList(g.products, (p) => {
_push(`<label class="chk" data-v-a2832f1b><input${ssrIncludeBooleanAttr(Array.isArray(sel.products) ? ssrLooseContain(sel.products, String(p.id)) : sel.products) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", String(p.id))} data-v-a2832f1b>${ssrInterpolate((p.devicename || "产品") + " #" + p.id)}</label>`);
});
_push(`<!--]--></div></div>`);
});
_push(`<!--]-->`);
}
_push(`</div></div></div><div class="flex gap-3 justify-end mt-6" data-v-a2832f1b><button class="btn btn-ghost btn-sm" data-v-a2832f1b>取消</button><button class="btn btn-primary btn-sm text-white"${ssrIncludeBooleanAttr(submitting.value) ? " disabled" : ""} data-v-a2832f1b>保存</button></div></div></div><dialog class="modal" data-v-a2832f1b><div class="modal-box max-w-md" data-v-a2832f1b><h3 class="font-bold text-lg mb-1" data-v-a2832f1b>充值 / 调整资源点</h3><p class="text-xs text-slate-400 mb-3" data-v-a2832f1b>代理:<span class="font-medium text-slate-600" data-v-a2832f1b>${ssrInterpolate(topup.name)}</span>。填增量(可填负数下调),当前余额:<span class="text-emerald-600" data-v-a2832f1b>${ssrInterpolate(topup.cur)}</span></p><div class="grid grid-cols-3 gap-3" data-v-a2832f1b><div data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>VIP天数</label><input${ssrRenderAttr("value", topup.vipday)} type="number" class="input input-bordered input-sm w-full" data-v-a2832f1b></div><div data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>翻译分钟</label><input${ssrRenderAttr("value", topup.trademin)} type="number" class="input input-bordered input-sm w-full" data-v-a2832f1b></div><div data-v-a2832f1b><label class="text-xs text-slate-500" data-v-a2832f1b>会议分钟</label><input${ssrRenderAttr("value", topup.meetmin)} type="number" class="input input-bordered input-sm w-full" data-v-a2832f1b></div></div><div class="modal-action" data-v-a2832f1b><button class="btn btn-ghost btn-sm" data-v-a2832f1b>取消</button><button class="btn btn-primary btn-sm text-white" data-v-a2832f1b>确认</button></div></div><form method="dialog" class="modal-backdrop" data-v-a2832f1b><button data-v-a2832f1b>close</button></form></dialog></div>`);
};
}
});
const _sfc_setup = _sfc_main.setup;
_sfc_main.setup = (props, ctx) => {
const ssrContext = useSSRContext();
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("pages/accounts.vue");
return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
};
const accounts = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-a2832f1b"]]);
export { accounts as default };
//# sourceMappingURL=accounts-CM5YEJ4p.mjs.map

1
apps/admin/.output/server/chunks/build/accounts-CM5YEJ4p.mjs.map

@ -0,0 +1 @@
{"version":3,"file":"accounts-CM5YEJ4p.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/accounts-CM5YEJ4p.js"],"names":[],"mappings":"","x_google_ignoreList":[0]}

201
apps/admin/.output/server/chunks/build/accounts-CampayFP.mjs

@ -1,201 +0,0 @@
import { defineComponent, ref, computed, reactive, watch, unref, useSSRContext } from 'vue';
import { ssrRenderAttrs, ssrRenderStyle, ssrRenderList, ssrInterpolate, ssrRenderClass, ssrRenderAttr, ssrIncludeBooleanAttr, ssrLooseContain, ssrLooseEqual } from 'vue/server-renderer';
import { u as useApi } from './useApi-BNSkSrat.mjs';
import { u as useToast } from './useToast-MBvLaNjH.mjs';
import { _ as _export_sfc, D as DEFAULT_ADMIN_ACCESS, M as MENU_GROUPS } from './server.mjs';
import { R as REGION_OPTIONS } from './regions-D1dSykUW.mjs';
import '../nitro/nitro.mjs';
import 'node:http';
import 'node:https';
import 'node:events';
import 'node:buffer';
import 'node:fs';
import 'node:path';
import 'node:crypto';
import 'node:url';
import '../routes/renderer.mjs';
import 'vue-bundle-renderer/runtime';
import 'unhead/server';
import 'devalue';
import 'unhead/utils';
import 'pinia';
import 'perfect-debounce';
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "accounts",
__ssrInlineRender: true,
setup(__props) {
useApi();
useToast();
const ROLE = { 1: "超管", 2: "管理员", 3: "品牌商", 4: "运营", 5: "渠道商" };
const ROLE_CLS = { 1: "badge-error", 2: "badge-primary", 3: "badge-warning", 4: "badge-info", 5: "badge-accent" };
const view = ref("list");
const rows = ref([]);
const apps = ref([]);
const appNames = computed(
() => [...new Set(apps.value.map((a) => a.app_name || a.name).filter(Boolean))].sort()
);
const loading = ref(false);
const submitting = ref(false);
const editId = ref(0);
const form = reactive({
username: "",
password: "",
identity: 2,
enabled: "1",
remark: "",
brandid: 0,
channelid: ""
});
const channels = ref([]);
const accountChannelOptions = computed(
() => form.brandid ? channels.value.filter((ch) => ch.brandid === form.brandid) : []
);
const sel = reactive({
access: [],
apps: [],
regions: [],
products: []
});
const brands = ref([]);
const productGroups = ref([]);
const prodLoading = ref(false);
function fromCsv(s) {
return (s || "").split(",").map((x) => x.trim()).filter((x) => x);
}
function scopeParts(a) {
const parts = [];
if (a.apps) parts.push("应用:" + fromCsv(a.apps).length);
if (a.regions) parts.push("区域:" + fromCsv(a.regions).length);
if (a.products) parts.push("产品:" + fromCsv(a.products).length);
if (a.access) parts.push("页面:" + fromCsv(a.access).length);
return parts;
}
watch(() => form.identity, (idt) => {
if (idt === 2 && sel.access.length === 0) sel.access = DEFAULT_ADMIN_ACCESS.slice();
});
ref(null);
ref(0);
const topup = reactive({
name: "",
cur: "",
vipday: 0,
trademin: 0,
meetmin: 0
});
return (_ctx, _push, _parent, _attrs) => {
_push(`<div${ssrRenderAttrs(_attrs)} data-v-b47e60f8><div style="${ssrRenderStyle(view.value === "list" ? null : { display: "none" })}" data-v-b47e60f8><div class="flex items-center justify-between mb-4" data-v-b47e60f8><div data-v-b47e60f8><h2 class="text-lg font-bold text-slate-700" data-v-b47e60f8>后台账号</h2><p class="text-xs text-slate-400 mt-0.5" data-v-b47e60f8>超管 / 管理员 / 代理 / 运营。代理·运营可绑定应用·区域·产品,登录后仪表盘按绑定限制。</p></div><button class="btn btn-primary btn-sm text-white" data-v-b47e60f8>+ 新建账号</button></div><div class="bg-white rounded-xl shadow-sm border border-slate-100 overflow-hidden" data-v-b47e60f8><table class="table table-sm" data-v-b47e60f8><thead data-v-b47e60f8><tr class="text-slate-500" data-v-b47e60f8><th data-v-b47e60f8>ID</th><th data-v-b47e60f8>用户名</th><th data-v-b47e60f8>角色</th><th data-v-b47e60f8>状态</th><th data-v-b47e60f8>绑定作用域</th><th data-v-b47e60f8>备注</th><th class="text-right" data-v-b47e60f8>操作</th></tr></thead><tbody data-v-b47e60f8>`);
if (loading.value) {
_push(`<tr data-v-b47e60f8><td colspan="7" class="text-center text-slate-400 py-8" data-v-b47e60f8>加载中...</td></tr>`);
} else if (!rows.value.length) {
_push(`<tr data-v-b47e60f8><td colspan="7" class="text-center text-slate-400 py-8" data-v-b47e60f8>暂无账号(引导超管不在此列)</td></tr>`);
} else {
_push(`<!---->`);
}
_push(`<!--[-->`);
ssrRenderList(rows.value, (a) => {
_push(`<tr data-v-b47e60f8><td class="font-mono" data-v-b47e60f8>${ssrInterpolate(a.id)}</td><td class="font-medium" data-v-b47e60f8>${ssrInterpolate(a.username || "")}</td><td data-v-b47e60f8><span class="${ssrRenderClass([ROLE_CLS[a.identity] || "", "badge badge-sm"])}" data-v-b47e60f8>${ssrInterpolate(ROLE[a.identity] || a.identity)}</span></td><td data-v-b47e60f8>`);
if (a.enabled) {
_push(`<span class="text-green-600 text-xs" data-v-b47e60f8>启用</span>`);
} else {
_push(`<span class="text-slate-400 text-xs" data-v-b47e60f8>停用</span>`);
}
_push(`</td><td data-v-b47e60f8>`);
if (a.identity === 3 || a.identity === 4) {
_push(`<!--[-->`);
if (scopeParts(a).length) {
_push(`<span class="text-xs text-slate-500" data-v-b47e60f8>${ssrInterpolate(scopeParts(a).join(" · "))}</span>`);
} else {
_push(`<span class="text-xs text-slate-300" data-v-b47e60f8>未绑定(不限)</span>`);
}
_push(`<!--]-->`);
} else if (a.identity === 2) {
_push(`<!--[-->`);
if (a.access) {
_push(`<span class="text-xs text-slate-500" data-v-b47e60f8>菜单:${ssrInterpolate(fromCsv(a.access).length)}</span>`);
} else {
_push(`<span class="text-xs text-slate-300" data-v-b47e60f8>默认(除SaaS/系统管理)</span>`);
}
_push(`<!--]-->`);
} else {
_push(`<span class="text-xs text-slate-300" data-v-b47e60f8>全部权限</span>`);
}
if (a.identity === 3) {
_push(`<div class="text-[11px] text-emerald-600 mt-0.5" data-v-b47e60f8> 余额 VIP${ssrInterpolate(a.balance_vipday || 0)}天 · 翻译${ssrInterpolate(a.balance_trademin || 0)}分 · 会议${ssrInterpolate(a.balance_meetmin || 0)}分 </div>`);
} else {
_push(`<!---->`);
}
_push(`</td><td class="text-xs text-slate-500" data-v-b47e60f8>${ssrInterpolate(a.remark || "")}</td><td data-v-b47e60f8><div class="flex gap-1 justify-end" data-v-b47e60f8>`);
if (a.identity === 3) {
_push(`<button class="btn btn-ghost btn-xs text-emerald-600" data-v-b47e60f8>充值</button>`);
} else {
_push(`<!---->`);
}
_push(`<button class="btn btn-ghost btn-xs" data-v-b47e60f8>编辑</button><button class="btn btn-ghost btn-xs text-amber-600" data-v-b47e60f8>改密</button><button class="btn btn-ghost btn-xs text-red-500" data-v-b47e60f8>删除</button></div></td></tr>`);
});
_push(`<!--]--></tbody></table></div></div><div style="${ssrRenderStyle(view.value === "form" ? null : { display: "none" })}" data-v-b47e60f8><div class="flex items-center gap-3 mb-5" data-v-b47e60f8><button class="btn btn-ghost btn-sm" data-v-b47e60f8>← 返回列表</button><h2 class="text-lg font-semibold text-slate-800" data-v-b47e60f8>${ssrInterpolate(editId.value ? "编辑账号 #" + editId.value : "新建账号")}</h2></div><div class="bg-white rounded-xl shadow-sm border border-slate-100 p-6 max-w-2xl" data-v-b47e60f8><div class="grid grid-cols-2 gap-3" data-v-b47e60f8><div data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>用户名</label><input${ssrRenderAttr("value", form.username)}${ssrIncludeBooleanAttr(!!editId.value) ? " disabled" : ""} class="input input-bordered input-sm w-full" placeholder="登录用户名" data-v-b47e60f8></div><div style="${ssrRenderStyle(!editId.value ? null : { display: "none" })}" data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>密码</label><input${ssrRenderAttr("value", form.password)} type="password" class="input input-bordered input-sm w-full" placeholder="登录密码" data-v-b47e60f8></div><div data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>角色</label><select class="select select-bordered select-sm w-full" data-v-b47e60f8><option${ssrRenderAttr("value", 2)} data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 2) : ssrLooseEqual(form.identity, 2)) ? " selected" : ""}>管理员(默认除 SaaS/系统管理外全部)</option><option${ssrRenderAttr("value", 3)} data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 3) : ssrLooseEqual(form.identity, 3)) ? " selected" : ""}>品牌商(绑定品牌商,见名下全部渠道商)</option><option${ssrRenderAttr("value", 5)} data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 5) : ssrLooseEqual(form.identity, 5)) ? " selected" : ""}>渠道商(绑定单个渠道商,只见自己数据)</option><option${ssrRenderAttr("value", 4)} data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 4) : ssrLooseEqual(form.identity, 4)) ? " selected" : ""}>运营(内部,按绑定限制)</option><option${ssrRenderAttr("value", 1)} data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.identity) ? ssrLooseContain(form.identity, 1) : ssrLooseEqual(form.identity, 1)) ? " selected" : ""}>超管(全部权限)</option></select></div><div data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>状态</label><select class="select select-bordered select-sm w-full" data-v-b47e60f8><option value="1" data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.enabled) ? ssrLooseContain(form.enabled, "1") : ssrLooseEqual(form.enabled, "1")) ? " selected" : ""}>启用</option><option value="0" data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.enabled) ? ssrLooseContain(form.enabled, "0") : ssrLooseEqual(form.enabled, "0")) ? " selected" : ""}>停用</option></select></div><div class="col-span-2" data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>备注</label><input${ssrRenderAttr("value", form.remark)} class="input input-bordered input-sm w-full" placeholder="可选" data-v-b47e60f8></div></div><div class="mt-4 border-t border-slate-100 pt-4" style="${ssrRenderStyle(form.identity !== 1 ? null : { display: "none" })}" data-v-b47e60f8><div class="flex items-center justify-between mb-1" data-v-b47e60f8><div class="text-sm font-semibold text-slate-600" data-v-b47e60f8>菜单权限</div><div class="flex gap-1" data-v-b47e60f8><button type="button" class="btn btn-ghost btn-xs" data-v-b47e60f8>管理员默认</button><button type="button" class="btn btn-ghost btn-xs" data-v-b47e60f8>全选</button><button type="button" class="btn btn-ghost btn-xs" data-v-b47e60f8>清空</button></div></div><p class="text-xs text-slate-400 mb-3" data-v-b47e60f8>管理员默认开放除「SaaS 管理 / 系统管理」以外的全部菜单(权限留空时按默认生效);代理/运营需显式勾选。</p><!--[-->`);
ssrRenderList(unref(MENU_GROUPS), (g) => {
_push(`<div class="mb-2.5" data-v-b47e60f8><div class="text-xs text-slate-500 mb-1.5" data-v-b47e60f8>${ssrInterpolate(g.label)}`);
if (g.restricted) {
_push(`<span class="text-amber-500 ml-1" data-v-b47e60f8>(管理员默认不开放)</span>`);
} else {
_push(`<!---->`);
}
_push(`</div><div class="flex flex-wrap gap-2" data-v-b47e60f8><!--[-->`);
ssrRenderList(g.items, (m) => {
_push(`<label class="chk" data-v-b47e60f8><input${ssrIncludeBooleanAttr(Array.isArray(sel.access) ? ssrLooseContain(sel.access, m.id) : sel.access) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", m.id)} data-v-b47e60f8>${ssrInterpolate(m.label)}</label>`);
});
_push(`<!--]--></div></div>`);
});
_push(`<!--]--></div><div class="mt-4 border-t border-slate-100 pt-4" style="${ssrRenderStyle(form.identity === 3 || form.identity === 5 ? null : { display: "none" })}" data-v-b47e60f8><div class="text-sm font-semibold text-slate-600 mb-2" data-v-b47e60f8> 归属绑定 <span class="text-xs text-slate-400 font-normal" data-v-b47e60f8>(品牌商账号只绑品牌商;渠道商账号两者都要绑)</span></div><div class="grid grid-cols-2 gap-3" data-v-b47e60f8><div data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>所属品牌商 *</label><select class="select select-bordered select-sm w-full" data-v-b47e60f8><option${ssrRenderAttr("value", 0)} data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.brandid) ? ssrLooseContain(form.brandid, 0) : ssrLooseEqual(form.brandid, 0)) ? " selected" : ""}>请选择品牌商</option><!--[-->`);
ssrRenderList(brands.value, (b) => {
_push(`<option${ssrRenderAttr("value", b.id)} data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.brandid) ? ssrLooseContain(form.brandid, b.id) : ssrLooseEqual(form.brandid, b.id)) ? " selected" : ""}>${ssrInterpolate(b.brand)}</option>`);
});
_push(`<!--]--></select></div><div style="${ssrRenderStyle(form.identity === 5 ? null : { display: "none" })}" data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>所属渠道商 *</label><select class="select select-bordered select-sm w-full"${ssrIncludeBooleanAttr(!accountChannelOptions.value.length) ? " disabled" : ""} data-v-b47e60f8><option value="" data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.channelid) ? ssrLooseContain(form.channelid, "") : ssrLooseEqual(form.channelid, "")) ? " selected" : ""}>${ssrInterpolate(form.brandid ? accountChannelOptions.value.length ? "请选择渠道商" : "该品牌商暂无渠道商" : "请先选择品牌商")}</option><!--[-->`);
ssrRenderList(accountChannelOptions.value, (ch) => {
_push(`<option${ssrRenderAttr("value", ch.id)} data-v-b47e60f8${ssrIncludeBooleanAttr(Array.isArray(form.channelid) ? ssrLooseContain(form.channelid, ch.id) : ssrLooseEqual(form.channelid, ch.id)) ? " selected" : ""}>${ssrInterpolate(ch.name)} (${ssrInterpolate(ch.id)})</option>`);
});
_push(`<!--]--></select></div></div><p class="text-xs text-slate-400 mt-2" data-v-b47e60f8> 数据隔离由后端强制:品牌商账号只能看到本品牌商及其名下渠道商的数据,渠道商账号只能看到自己渠道的数据。 </p></div><div class="mt-4 border-t border-slate-100 pt-4" style="${ssrRenderStyle(form.identity === 3 || form.identity === 4 ? null : { display: "none" })}" data-v-b47e60f8><div class="text-sm font-semibold text-slate-600 mb-2" data-v-b47e60f8>作用域绑定 <span class="text-xs text-slate-400 font-normal" data-v-b47e60f8>(代理/运营生效;限制仪表盘数据范围)</span></div><div class="mb-3" data-v-b47e60f8><div class="text-xs text-slate-500 mb-1.5" data-v-b47e60f8>绑定应用 <span class="text-slate-300" data-v-b47e60f8>(仪表盘只显示这些应用数据;不勾=不限)</span></div><div class="flex flex-wrap gap-2" data-v-b47e60f8>`);
if (appNames.value.length) {
_push(`<!--[-->`);
ssrRenderList(appNames.value, (n) => {
_push(`<label class="chk" data-v-b47e60f8><input${ssrIncludeBooleanAttr(Array.isArray(sel.apps) ? ssrLooseContain(sel.apps, n) : sel.apps) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", n)} data-v-b47e60f8>${ssrInterpolate(n)}</label>`);
});
_push(`<!--]-->`);
} else {
_push(`<span class="text-xs text-slate-300" data-v-b47e60f8>无注册应用</span>`);
}
_push(`</div></div><div class="mb-3" data-v-b47e60f8><div class="text-xs text-slate-500 mb-1.5" data-v-b47e60f8>绑定区域 <span class="text-slate-300" data-v-b47e60f8>(不勾=不限)</span></div><div class="flex flex-wrap gap-2" data-v-b47e60f8><!--[-->`);
ssrRenderList(unref(REGION_OPTIONS), (r) => {
_push(`<label class="chk" data-v-b47e60f8><input${ssrIncludeBooleanAttr(Array.isArray(sel.regions) ? ssrLooseContain(sel.regions, r.value) : sel.regions) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", r.value)} data-v-b47e60f8>${ssrInterpolate(r.label)}</label>`);
});
_push(`<!--]--></div></div><div data-v-b47e60f8><div class="text-xs text-slate-500 mb-1.5" data-v-b47e60f8>绑定产品 <span class="text-slate-300" data-v-b47e60f8>(按厂家分组;仪表盘只显示这些产品数据;不勾=不限)</span></div><div class="max-h-56 overflow-y-auto pr-1 border border-slate-100 rounded-lg p-2" data-v-b47e60f8>`);
if (prodLoading.value) {
_push(`<span class="text-xs text-slate-300" data-v-b47e60f8>加载产品中...</span>`);
} else if (!productGroups.value.length) {
_push(`<span class="text-xs text-slate-300" data-v-b47e60f8>无产品</span>`);
} else {
_push(`<!--[-->`);
ssrRenderList(productGroups.value, (g) => {
_push(`<div class="mb-2 last:mb-0" data-v-b47e60f8><div class="text-[11px] font-semibold text-slate-500 mb-1 sticky top-0 bg-white py-0.5" data-v-b47e60f8>🏭 ${ssrInterpolate(g.label)}</div><div class="flex flex-wrap gap-2" data-v-b47e60f8><!--[-->`);
ssrRenderList(g.products, (p) => {
_push(`<label class="chk" data-v-b47e60f8><input${ssrIncludeBooleanAttr(Array.isArray(sel.products) ? ssrLooseContain(sel.products, String(p.id)) : sel.products) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", String(p.id))} data-v-b47e60f8>${ssrInterpolate((p.devicename || "产品") + " #" + p.id)}</label>`);
});
_push(`<!--]--></div></div>`);
});
_push(`<!--]-->`);
}
_push(`</div></div></div><div class="flex gap-3 justify-end mt-6" data-v-b47e60f8><button class="btn btn-ghost btn-sm" data-v-b47e60f8>取消</button><button class="btn btn-primary btn-sm text-white"${ssrIncludeBooleanAttr(submitting.value) ? " disabled" : ""} data-v-b47e60f8>保存</button></div></div></div><dialog class="modal" data-v-b47e60f8><div class="modal-box max-w-md" data-v-b47e60f8><h3 class="font-bold text-lg mb-1" data-v-b47e60f8>充值 / 调整资源点</h3><p class="text-xs text-slate-400 mb-3" data-v-b47e60f8>代理:<span class="font-medium text-slate-600" data-v-b47e60f8>${ssrInterpolate(topup.name)}</span>。填增量(可填负数下调),当前余额:<span class="text-emerald-600" data-v-b47e60f8>${ssrInterpolate(topup.cur)}</span></p><div class="grid grid-cols-3 gap-3" data-v-b47e60f8><div data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>VIP天数</label><input${ssrRenderAttr("value", topup.vipday)} type="number" class="input input-bordered input-sm w-full" data-v-b47e60f8></div><div data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>翻译分钟</label><input${ssrRenderAttr("value", topup.trademin)} type="number" class="input input-bordered input-sm w-full" data-v-b47e60f8></div><div data-v-b47e60f8><label class="text-xs text-slate-500" data-v-b47e60f8>会议分钟</label><input${ssrRenderAttr("value", topup.meetmin)} type="number" class="input input-bordered input-sm w-full" data-v-b47e60f8></div></div><div class="modal-action" data-v-b47e60f8><button class="btn btn-ghost btn-sm" data-v-b47e60f8>取消</button><button class="btn btn-primary btn-sm text-white" data-v-b47e60f8>确认</button></div></div><form method="dialog" class="modal-backdrop" data-v-b47e60f8><button data-v-b47e60f8>close</button></form></dialog></div>`);
};
}
});
const _sfc_setup = _sfc_main.setup;
_sfc_main.setup = (props, ctx) => {
const ssrContext = useSSRContext();
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("pages/accounts.vue");
return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
};
const accounts = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-b47e60f8"]]);
export { accounts as default };
//# sourceMappingURL=accounts-CampayFP.mjs.map

1
apps/admin/.output/server/chunks/build/accounts-CampayFP.mjs.map

@ -1 +0,0 @@
{"version":3,"file":"accounts-CampayFP.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/accounts-CampayFP.js"],"names":[],"mappings":"","x_google_ignoreList":[0]}

8
apps/admin/.output/server/chunks/build/accounts-styles.B912aimJ.mjs

@ -1,8 +0,0 @@
const accounts_vue_vue_type_style_index_0_scoped_b47e60f8_lang = ".chk[data-v-b47e60f8]{display:flex;align-items:center;gap:6px;padding:5px 9px;border:1px solid #e2e8f0;border-radius:8px;font-size:12px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chk[data-v-b47e60f8]:hover{background:#f8fafc}.chk input[data-v-b47e60f8]{width:14px;height:14px}";
const accountsStyles_B912aimJ = [
accounts_vue_vue_type_style_index_0_scoped_b47e60f8_lang
];
export { accountsStyles_B912aimJ as default };
//# sourceMappingURL=accounts-styles.B912aimJ.mjs.map

1
apps/admin/.output/server/chunks/build/accounts-styles.B912aimJ.mjs.map

@ -1 +0,0 @@
{"version":3,"file":"accounts-styles.B912aimJ.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/accounts-styles-1.mjs-BUD0U4Q9.js","../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/accounts-styles.B912aimJ.mjs"],"names":["style_0"],"mappings":"","x_google_ignoreList":[0,1]}

8
apps/admin/.output/server/chunks/build/accounts-styles.Bwl6sYRz.mjs

@ -0,0 +1,8 @@
const accounts_vue_vue_type_style_index_0_scoped_a2832f1b_lang = ".chk[data-v-a2832f1b]{display:flex;align-items:center;gap:6px;padding:5px 9px;border:1px solid #e2e8f0;border-radius:8px;font-size:12px;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.chk[data-v-a2832f1b]:hover{background:#f8fafc}.chk input[data-v-a2832f1b]{width:14px;height:14px}";
const accountsStyles_Bwl6sYRz = [
accounts_vue_vue_type_style_index_0_scoped_a2832f1b_lang
];
export { accountsStyles_Bwl6sYRz as default };
//# sourceMappingURL=accounts-styles.Bwl6sYRz.mjs.map

1
apps/admin/.output/server/chunks/build/accounts-styles.Bwl6sYRz.mjs.map

@ -0,0 +1 @@
{"version":3,"file":"accounts-styles.Bwl6sYRz.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/accounts-styles-1.mjs-BqkDag56.js","../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/accounts-styles.Bwl6sYRz.mjs"],"names":["style_0"],"mappings":"","x_google_ignoreList":[0,1]}

2
apps/admin/.output/server/chunks/build/client.precomputed.mjs

File diff suppressed because one or more lines are too long

1
apps/admin/.output/server/chunks/build/dashboard-C7m4n3tj.mjs.map

@ -1 +0,0 @@
{"version":3,"file":"dashboard-C7m4n3tj.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/dashboard-C7m4n3tj.js"],"names":[],"mappings":"","x_google_ignoreList":[0]}

56
apps/admin/.output/server/chunks/build/dashboard-C7m4n3tj.mjs → apps/admin/.output/server/chunks/build/dashboard-Y8255DFm.mjs

@ -310,76 +310,76 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
} }
return (_ctx, _push, _parent, _attrs) => { return (_ctx, _push, _parent, _attrs) => {
const _component_SvcAlertBanner = __nuxt_component_0; const _component_SvcAlertBanner = __nuxt_component_0;
_push(`<div${ssrRenderAttrs(_attrs)} data-v-fb791e6a>`); _push(`<div${ssrRenderAttrs(_attrs)} data-v-449e8f97>`);
_push(ssrRenderComponent(_component_SvcAlertBanner, null, null, _parent)); _push(ssrRenderComponent(_component_SvcAlertBanner, null, null, _parent));
_push(`<div class="panel p-4 mb-5" data-v-fb791e6a><div class="flex flex-wrap items-end gap-3" data-v-fb791e6a>`); _push(`<div class="panel p-4 mb-5" data-v-449e8f97><div class="flex flex-wrap items-end gap-3" data-v-449e8f97>`);
if (!IS_SCOPED.value) { if (!IS_SCOPED.value || appOptions.value.length) {
_push(`<div class="form-control" data-v-fb791e6a><label class="label py-1" data-v-fb791e6a><span class="label-text text-xs text-slate-500" data-v-fb791e6a>应用</span></label><select class="select select-bordered select-sm w-40" data-v-fb791e6a><option value="" data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.app) ? ssrLooseContain(filters.app, "") : ssrLooseEqual(filters.app, "")) ? " selected" : ""}>全部应用</option><!--[-->`); _push(`<div class="form-control" data-v-449e8f97><label class="label py-1" data-v-449e8f97><span class="label-text text-xs text-slate-500" data-v-449e8f97>应用</span></label><select class="select select-bordered select-sm w-40" data-v-449e8f97><option value="" data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.app) ? ssrLooseContain(filters.app, "") : ssrLooseEqual(filters.app, "")) ? " selected" : ""}>全部应用</option><!--[-->`);
ssrRenderList(appOptions.value, (a) => { ssrRenderList(appOptions.value, (a) => {
_push(`<option${ssrRenderAttr("value", a.value)} data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.app) ? ssrLooseContain(filters.app, a.value) : ssrLooseEqual(filters.app, a.value)) ? " selected" : ""}>${ssrInterpolate(a.label)}</option>`); _push(`<option${ssrRenderAttr("value", a.value)} data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.app) ? ssrLooseContain(filters.app, a.value) : ssrLooseEqual(filters.app, a.value)) ? " selected" : ""}>${ssrInterpolate(a.label)}</option>`);
}); });
_push(`<!--]--></select></div>`); _push(`<!--]--></select></div>`);
} else { } else {
_push(`<!---->`); _push(`<!---->`);
} }
if (!IS_SCOPED.value) { if (!IS_SCOPED.value) {
_push(`<div class="form-control" data-v-fb791e6a><label class="label py-1" data-v-fb791e6a><span class="label-text text-xs text-slate-500" data-v-fb791e6a>区域</span></label><select class="select select-bordered select-sm w-32" data-v-fb791e6a><option value="" data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.region) ? ssrLooseContain(filters.region, "") : ssrLooseEqual(filters.region, "")) ? " selected" : ""}>全部区域</option><!--[-->`); _push(`<div class="form-control" data-v-449e8f97><label class="label py-1" data-v-449e8f97><span class="label-text text-xs text-slate-500" data-v-449e8f97>区域</span></label><select class="select select-bordered select-sm w-32" data-v-449e8f97><option value="" data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.region) ? ssrLooseContain(filters.region, "") : ssrLooseEqual(filters.region, "")) ? " selected" : ""}>全部区域</option><!--[-->`);
ssrRenderList(regionOptions.value, (r) => { ssrRenderList(regionOptions.value, (r) => {
_push(`<option${ssrRenderAttr("value", r.value)} data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.region) ? ssrLooseContain(filters.region, r.value) : ssrLooseEqual(filters.region, r.value)) ? " selected" : ""}>${ssrInterpolate(r.label)}</option>`); _push(`<option${ssrRenderAttr("value", r.value)} data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.region) ? ssrLooseContain(filters.region, r.value) : ssrLooseEqual(filters.region, r.value)) ? " selected" : ""}>${ssrInterpolate(r.label)}</option>`);
}); });
_push(`<!--]--></select></div>`); _push(`<!--]--></select></div>`);
} else { } else {
_push(`<!---->`); _push(`<!---->`);
} }
_push(`<div class="form-control" data-v-fb791e6a><label class="label py-1" data-v-fb791e6a><span class="label-text text-xs text-slate-500" data-v-fb791e6a>产品</span></label><select class="select select-bordered select-sm w-48" data-v-fb791e6a><option value="" data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.product) ? ssrLooseContain(filters.product, "") : ssrLooseEqual(filters.product, "")) ? " selected" : ""}>全部产品</option><!--[-->`); _push(`<div class="form-control" data-v-449e8f97><label class="label py-1" data-v-449e8f97><span class="label-text text-xs text-slate-500" data-v-449e8f97>产品</span></label><select class="select select-bordered select-sm w-48" data-v-449e8f97><option value="" data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.product) ? ssrLooseContain(filters.product, "") : ssrLooseEqual(filters.product, "")) ? " selected" : ""}>全部产品</option><!--[-->`);
ssrRenderList(productOptions.value, (p) => { ssrRenderList(productOptions.value, (p) => {
_push(`<option${ssrRenderAttr("value", p.value)} data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.product) ? ssrLooseContain(filters.product, p.value) : ssrLooseEqual(filters.product, p.value)) ? " selected" : ""}>${ssrInterpolate(p.label)}</option>`); _push(`<option${ssrRenderAttr("value", p.value)} data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.product) ? ssrLooseContain(filters.product, p.value) : ssrLooseEqual(filters.product, p.value)) ? " selected" : ""}>${ssrInterpolate(p.label)}</option>`);
}); });
_push(`<!--]--></select></div>`); _push(`<!--]--></select></div>`);
if (!unref(auth).isDealer) { if (!unref(auth).isDealer) {
_push(`<div class="form-control" data-v-fb791e6a><label class="label py-1" data-v-fb791e6a><span class="label-text text-xs text-slate-500" data-v-fb791e6a>渠道商</span></label><select class="select select-bordered select-sm w-48" data-v-fb791e6a><option value="" data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.channel) ? ssrLooseContain(filters.channel, "") : ssrLooseEqual(filters.channel, "")) ? " selected" : ""}>全部渠道商</option><option value="__none__" data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.channel) ? ssrLooseContain(filters.channel, "__none__") : ssrLooseEqual(filters.channel, "__none__")) ? " selected" : ""}>未分配渠道</option><!--[-->`); _push(`<div class="form-control" data-v-449e8f97><label class="label py-1" data-v-449e8f97><span class="label-text text-xs text-slate-500" data-v-449e8f97>渠道商</span></label><select class="select select-bordered select-sm w-48" data-v-449e8f97><option value="" data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.channel) ? ssrLooseContain(filters.channel, "") : ssrLooseEqual(filters.channel, "")) ? " selected" : ""}>全部渠道商</option><option value="__none__" data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.channel) ? ssrLooseContain(filters.channel, "__none__") : ssrLooseEqual(filters.channel, "__none__")) ? " selected" : ""}>未分配渠道</option><!--[-->`);
ssrRenderList(channelOptions.value, (ch) => { ssrRenderList(channelOptions.value, (ch) => {
_push(`<option${ssrRenderAttr("value", ch.value)} data-v-fb791e6a${ssrIncludeBooleanAttr(Array.isArray(filters.channel) ? ssrLooseContain(filters.channel, ch.value) : ssrLooseEqual(filters.channel, ch.value)) ? " selected" : ""}>${ssrInterpolate(ch.label)}</option>`); _push(`<option${ssrRenderAttr("value", ch.value)} data-v-449e8f97${ssrIncludeBooleanAttr(Array.isArray(filters.channel) ? ssrLooseContain(filters.channel, ch.value) : ssrLooseEqual(filters.channel, ch.value)) ? " selected" : ""}>${ssrInterpolate(ch.label)}</option>`);
}); });
_push(`<!--]--></select></div>`); _push(`<!--]--></select></div>`);
} else { } else {
_push(`<!---->`); _push(`<!---->`);
} }
_push(`<button class="btn btn-primary btn-sm text-white" data-v-fb791e6a>查询</button><span class="text-xs text-slate-400 ml-auto self-center" data-v-fb791e6a>顶部为全量总览;各版面右上角可单独选时间周期</span></div></div><div class="sec-title muted" data-v-fb791e6a><span class="bar" style="${ssrRenderStyle({ "background": "#cbd5e1" })}" data-v-fb791e6a></span><h2 data-v-fb791e6a>累计数据</h2><span class="sub" data-v-fb791e6a>全量累计 · 随筛选条件变化</span></div><div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-8" data-v-fb791e6a><!--[-->`); _push(`<button class="btn btn-primary btn-sm text-white" data-v-449e8f97>查询</button><span class="text-xs text-slate-400 ml-auto self-center" data-v-449e8f97>顶部为全量总览;各版面右上角可单独选时间周期</span></div></div><div class="sec-title muted" data-v-449e8f97><span class="bar" style="${ssrRenderStyle({ "background": "#cbd5e1" })}" data-v-449e8f97></span><h2 data-v-449e8f97>累计数据</h2><span class="sub" data-v-449e8f97>全量累计 · 随筛选条件变化</span></div><div class="grid grid-cols-2 md:grid-cols-4 gap-3 mb-8" data-v-449e8f97><!--[-->`);
ssrRenderList(globalCards.value, (c) => { ssrRenderList(globalCards.value, (c) => {
_push(`<div class="cum-card" data-v-fb791e6a><span class="ico" style="${ssrRenderStyle({ background: cardStyle(c[0])[1] })}" data-v-fb791e6a>${ssrInterpolate(cardStyle(c[0])[0])}</span><div class="body" data-v-fb791e6a><div class="lbl" data-v-fb791e6a>${ssrInterpolate(c[1])}</div><div class="val" data-v-fb791e6a>${ssrInterpolate(globalVal(c))}</div></div></div>`); _push(`<div class="cum-card" data-v-449e8f97><span class="ico" style="${ssrRenderStyle({ background: cardStyle(c[0])[1] })}" data-v-449e8f97>${ssrInterpolate(cardStyle(c[0])[0])}</span><div class="body" data-v-449e8f97><div class="lbl" data-v-449e8f97>${ssrInterpolate(c[1])}</div><div class="val" data-v-449e8f97>${ssrInterpolate(globalVal(c))}</div></div></div>`);
}); });
_push(`<!--]--></div><div class="today-wrap mb-8" data-v-fb791e6a><div class="sec-title hero" style="${ssrRenderStyle({ "margin-bottom": "16px" })}" data-v-fb791e6a><span class="bar" style="${ssrRenderStyle({ "background": "linear-gradient(180deg,#0EA5E9,#22D3EE)" })}" data-v-fb791e6a></span><h2 data-v-fb791e6a>今日数据</h2><span class="tag" style="${ssrRenderStyle({ "color": "#0369a1", "background": "#dbeafe" })}" data-v-fb791e6a>${ssrInterpolate(todayTag.value)}</span><span class="sub" data-v-fb791e6a>今日 0 点至现在 · 含较昨日同比(设备类无日期维度,仅见累计)</span></div><div class="grid grid-cols-2 md:grid-cols-4 gap-4" data-v-fb791e6a><!--[-->`); _push(`<!--]--></div><div class="today-wrap mb-8" data-v-449e8f97><div class="sec-title hero" style="${ssrRenderStyle({ "margin-bottom": "16px" })}" data-v-449e8f97><span class="bar" style="${ssrRenderStyle({ "background": "linear-gradient(180deg,#0EA5E9,#22D3EE)" })}" data-v-449e8f97></span><h2 data-v-449e8f97>今日数据</h2><span class="tag" style="${ssrRenderStyle({ "color": "#0369a1", "background": "#dbeafe" })}" data-v-449e8f97>${ssrInterpolate(todayTag.value)}</span><span class="sub" data-v-449e8f97>今日 0 点至现在 · 含较昨日同比(设备类无日期维度,仅见累计)</span></div><div class="grid grid-cols-2 md:grid-cols-4 gap-4" data-v-449e8f97><!--[-->`);
ssrRenderList(todayCards.value, (c) => { ssrRenderList(todayCards.value, (c) => {
_push(`<div class="today-card" data-v-fb791e6a><span class="accent" style="${ssrRenderStyle({ background: cardStyle(c[0])[2] })}" data-v-fb791e6a></span><div class="today-card-top" data-v-fb791e6a><span class="lbl" data-v-fb791e6a>${ssrInterpolate(c[1])}</span><span class="ico" style="${ssrRenderStyle({ background: cardStyle(c[0])[1] })}" data-v-fb791e6a>${ssrInterpolate(cardStyle(c[0])[0])}</span></div><div class="val" data-v-fb791e6a>${ssrInterpolate(todayVal(c))}</div><div class="foot" data-v-fb791e6a>`); _push(`<div class="today-card" data-v-449e8f97><span class="accent" style="${ssrRenderStyle({ background: cardStyle(c[0])[2] })}" data-v-449e8f97></span><div class="today-card-top" data-v-449e8f97><span class="lbl" data-v-449e8f97>${ssrInterpolate(c[1])}</span><span class="ico" style="${ssrRenderStyle({ background: cardStyle(c[0])[1] })}" data-v-449e8f97>${ssrInterpolate(cardStyle(c[0])[0])}</span></div><div class="val" data-v-449e8f97>${ssrInterpolate(todayVal(c))}</div><div class="foot" data-v-449e8f97>`);
if (todayDelta(c).type === "new") { if (todayDelta(c).type === "new") {
_push(`<span class="delta up" data-v-fb791e6a>新</span>`); _push(`<span class="delta up" data-v-449e8f97>新</span>`);
} else if (todayDelta(c).type !== "none") { } else if (todayDelta(c).type !== "none") {
_push(`<span class="${ssrRenderClass([todayDelta(c).type, "delta"])}" data-v-fb791e6a>${ssrInterpolate(todayDelta(c).arrow)} ${ssrInterpolate(todayDelta(c).abs)}%</span>`); _push(`<span class="${ssrRenderClass([todayDelta(c).type, "delta"])}" data-v-449e8f97>${ssrInterpolate(todayDelta(c).arrow)} ${ssrInterpolate(todayDelta(c).abs)}%</span>`);
} else { } else {
_push(`<!---->`); _push(`<!---->`);
} }
_push(`<span data-v-fb791e6a>较昨日</span></div></div>`); _push(`<span data-v-449e8f97>较昨日</span></div></div>`);
}); });
_push(`<!--]--></div></div><div class="sec-title" data-v-fb791e6a><span class="bar" style="${ssrRenderStyle({ "background": "linear-gradient(180deg,#10B981,#22D3EE)" })}" data-v-fb791e6a></span><h2 data-v-fb791e6a>趋势分析</h2><span class="sub" data-v-fb791e6a>各版面右上角可独立选择时间周期</span></div><div class="grid grid-cols-1 xl:grid-cols-2 gap-6" data-v-fb791e6a><!--[-->`); _push(`<!--]--></div></div><div class="sec-title" data-v-449e8f97><span class="bar" style="${ssrRenderStyle({ "background": "linear-gradient(180deg,#10B981,#22D3EE)" })}" data-v-449e8f97></span><h2 data-v-449e8f97>趋势分析</h2><span class="sub" data-v-449e8f97>各版面右上角可独立选择时间周期</span></div><div class="grid grid-cols-1 xl:grid-cols-2 gap-6" data-v-449e8f97><!--[-->`);
ssrRenderList(panels.value, (p) => { ssrRenderList(panels.value, (p) => {
_push(`<div class="panel" data-v-fb791e6a><div class="panel-head" data-v-fb791e6a><span class="panel-dot" style="${ssrRenderStyle({ background: p.tint })}" data-v-fb791e6a><svg width="17" height="17" fill="none" viewBox="0 0 24 24"${ssrRenderAttr("stroke", p.color)} data-v-fb791e6a><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"${ssrRenderAttr("d", p.icon)} data-v-fb791e6a></path></svg></span><span class="font-semibold text-slate-700 text-sm" data-v-fb791e6a>${ssrInterpolate(p.title)}</span>`); _push(`<div class="panel" data-v-449e8f97><div class="panel-head" data-v-449e8f97><span class="panel-dot" style="${ssrRenderStyle({ background: p.tint })}" data-v-449e8f97><svg width="17" height="17" fill="none" viewBox="0 0 24 24"${ssrRenderAttr("stroke", p.color)} data-v-449e8f97><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"${ssrRenderAttr("d", p.icon)} data-v-449e8f97></path></svg></span><span class="font-semibold text-slate-700 text-sm" data-v-449e8f97>${ssrInterpolate(p.title)}</span>`);
if (p.key === "device") { if (p.key === "device") {
_push(`<span class="ml-auto text-xs text-slate-400" data-v-fb791e6a>当前累计 · 无日期维度</span>`); _push(`<span class="ml-auto text-xs text-slate-400" data-v-449e8f97>当前累计 · 无日期维度</span>`);
} else { } else {
_push(`<div class="ml-auto flex items-center gap-1" data-v-fb791e6a><!--[-->`); _push(`<div class="ml-auto flex items-center gap-1" data-v-449e8f97><!--[-->`);
ssrRenderList(rangeBtns, (d) => { ssrRenderList(rangeBtns, (d) => {
_push(`<button class="${ssrRenderClass([{ "tbtn-on": d[0] === panelDays[p.key] }, "tbtn"])}" data-v-fb791e6a>${ssrInterpolate(d[1])}</button>`); _push(`<button class="${ssrRenderClass([{ "tbtn-on": d[0] === panelDays[p.key] }, "tbtn"])}" data-v-449e8f97>${ssrInterpolate(d[1])}</button>`);
}); });
_push(`<!--]--></div>`); _push(`<!--]--></div>`);
} }
_push(`</div><div class="px-5 py-4" data-v-fb791e6a><div class="grid grid-cols-2 sm:grid-cols-3 gap-2.5" data-v-fb791e6a><!--[-->`); _push(`</div><div class="px-5 py-4" data-v-449e8f97><div class="grid grid-cols-2 sm:grid-cols-3 gap-2.5" data-v-449e8f97><!--[-->`);
ssrRenderList(p.stats, (s) => { ssrRenderList(p.stats, (s) => {
_push(`<div class="stat-box" data-v-fb791e6a><div class="stat-label" data-v-fb791e6a>${ssrInterpolate(s[1])}</div><div class="stat-val" data-v-fb791e6a>${ssrInterpolate(panelStatVal(p, s))}</div></div>`); _push(`<div class="stat-box" data-v-449e8f97><div class="stat-label" data-v-449e8f97>${ssrInterpolate(s[1])}</div><div class="stat-val" data-v-449e8f97>${ssrInterpolate(panelStatVal(p, s))}</div></div>`);
}); });
_push(`<!--]--></div>`); _push(`<!--]--></div>`);
if (p.key !== "device") { if (p.key !== "device") {
_push(`<div style="${ssrRenderStyle({ "height": "170px", "margin-top": "1rem" })}" data-v-fb791e6a><canvas data-v-fb791e6a></canvas></div>`); _push(`<div style="${ssrRenderStyle({ "height": "170px", "margin-top": "1rem" })}" data-v-449e8f97><canvas data-v-449e8f97></canvas></div>`);
} else { } else {
_push(`<!---->`); _push(`<!---->`);
} }
@ -395,7 +395,7 @@ _sfc_main.setup = (props, ctx) => {
(ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("pages/dashboard.vue"); (ssrContext.modules || (ssrContext.modules = /* @__PURE__ */ new Set())).add("pages/dashboard.vue");
return _sfc_setup ? _sfc_setup(props, ctx) : void 0; return _sfc_setup ? _sfc_setup(props, ctx) : void 0;
}; };
const dashboard = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-fb791e6a"]]); const dashboard = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-449e8f97"]]);
export { dashboard as default }; export { dashboard as default };
//# sourceMappingURL=dashboard-C7m4n3tj.mjs.map //# sourceMappingURL=dashboard-Y8255DFm.mjs.map

1
apps/admin/.output/server/chunks/build/dashboard-Y8255DFm.mjs.map

@ -0,0 +1 @@
{"version":3,"file":"dashboard-Y8255DFm.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/dashboard-Y8255DFm.js"],"names":[],"mappings":"","x_google_ignoreList":[0]}

11
apps/admin/.output/server/chunks/build/dashboard-styles.CnnmNtqM.mjs

@ -1,11 +0,0 @@
import { S as SvcAlertBanner_vue_vue_type_style_index_0_scoped_3dd2fb7c_lang } from './dashboard-styles-1.mjs-CFxtv9Pt.mjs';
const dashboard_vue_vue_type_style_index_0_scoped_fb791e6a_lang = ".panel[data-v-fb791e6a]{background:#fff;border:1px solid #f1f5f9;border-radius:16px;box-shadow:0 1px 2px #0000000a;overflow:hidden}.panel-head[data-v-fb791e6a]{padding:12px 18px;gap:10px;border-bottom:1px solid #f8fafc;flex-wrap:wrap}.panel-dot[data-v-fb791e6a],.panel-head[data-v-fb791e6a]{display:flex;align-items:center}.panel-dot[data-v-fb791e6a]{width:30px;height:30px;border-radius:9px;justify-content:center;flex-shrink:0}.stat-box[data-v-fb791e6a]{padding:10px 12px;border-radius:10px;background:#fafbfc}.stat-label[data-v-fb791e6a]{font-size:11px;color:#94a3b8;margin-bottom:3px}.stat-val[data-v-fb791e6a]{font-size:20px;font-weight:700;color:#1e293b;line-height:1.1;letter-spacing:-.02em}.sec-title[data-v-fb791e6a]{display:flex;align-items:center;gap:10px;margin:0 0 14px}.sec-title .bar[data-v-fb791e6a]{width:4px;height:18px;border-radius:3px}.sec-title h2[data-v-fb791e6a]{font-size:15px;font-weight:700;color:#0f172a;letter-spacing:-.01em}.sec-title .sub[data-v-fb791e6a]{font-size:12px;color:#94a3b8}.sec-title .tag[data-v-fb791e6a]{font-size:11px;font-weight:600;padding:2px 9px;border-radius:999px}.sec-title.muted .bar[data-v-fb791e6a]{height:14px;opacity:.6}.sec-title.muted h2[data-v-fb791e6a]{font-size:13px;font-weight:600;color:#94a3b8}.sec-title.hero .bar[data-v-fb791e6a]{width:5px;height:22px}.sec-title.hero h2[data-v-fb791e6a]{font-size:18px;font-weight:800;color:#0f172a}.cum-card[data-v-fb791e6a]{gap:11px;background:#f8fafc;border:1px solid #eef2f7;border-radius:12px;padding:10px 13px}.cum-card[data-v-fb791e6a],.cum-card .ico[data-v-fb791e6a]{display:flex;align-items:center}.cum-card .ico[data-v-fb791e6a]{width:30px;height:30px;border-radius:9px;justify-content:center;flex-shrink:0;font-size:14px;filter:saturate(.65);opacity:.85}.cum-card .body[data-v-fb791e6a]{min-width:0}.cum-card .lbl[data-v-fb791e6a]{font-size:11.5px;color:#94a3b8;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cum-card .val[data-v-fb791e6a]{font-size:17px;font-weight:700;color:#64748b;line-height:1.3;letter-spacing:-.01em;margin-top:1px}.today-wrap[data-v-fb791e6a]{background:linear-gradient(180deg,#e8f1ff,#f5f9ff);border:1px solid #d6e4ff;border-radius:22px;padding:20px;box-shadow:0 1px 3px #0d6efd0d}.today-card[data-v-fb791e6a]{position:relative;background:#fff;border:1px solid #e6eefb;border-radius:18px;padding:17px 19px;box-shadow:0 6px 18px #0d6efd14;transition:transform .18s ease,box-shadow .18s ease;overflow:hidden}.today-card[data-v-fb791e6a]:hover{transform:translateY(-3px);box-shadow:0 14px 32px #0d6efd26}.today-card .accent[data-v-fb791e6a]{position:absolute;left:0;top:0;bottom:0;width:5px}.today-card-top[data-v-fb791e6a]{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.today-card .lbl[data-v-fb791e6a]{font-size:13px;color:#475569;font-weight:600}.today-card .ico[data-v-fb791e6a]{width:42px;height:42px;border-radius:13px;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:20px}.today-card .val[data-v-fb791e6a]{font-size:31px;font-weight:800;color:#0f172a;line-height:1.05;letter-spacing:-.02em}.today-card .foot[data-v-fb791e6a]{margin-top:9px;font-size:12px;color:#94a3b8;display:flex;align-items:center;gap:6px}.delta[data-v-fb791e6a]{display:inline-flex;align-items:center;gap:2px;font-weight:700;padding:2px 7px;border-radius:7px;font-size:11.5px}.delta.up[data-v-fb791e6a]{color:#059669;background:#ecfdf5}.delta.down[data-v-fb791e6a]{color:#dc2626;background:#fef2f2}.delta.flat[data-v-fb791e6a],.tbtn[data-v-fb791e6a]{color:#64748b;background:#f1f5f9}.tbtn[data-v-fb791e6a]{font-size:11px;padding:3px 9px;border-radius:7px;line-height:1.4}.tbtn[data-v-fb791e6a]:hover{background:#e2e8f0}.tbtn-on[data-v-fb791e6a]{background:#1e293b;color:#fff}";
const dashboardStyles_CnnmNtqM = [
SvcAlertBanner_vue_vue_type_style_index_0_scoped_3dd2fb7c_lang,
dashboard_vue_vue_type_style_index_0_scoped_fb791e6a_lang
];
export { dashboardStyles_CnnmNtqM as default };
//# sourceMappingURL=dashboard-styles.CnnmNtqM.mjs.map

1
apps/admin/.output/server/chunks/build/dashboard-styles.CnnmNtqM.mjs.map

@ -1 +0,0 @@
{"version":3,"file":"dashboard-styles.CnnmNtqM.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/dashboard-styles-2.mjs-D9QGJGGw.js","../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/dashboard-styles.CnnmNtqM.mjs"],"names":["style_0","style_1"],"mappings":"","x_google_ignoreList":[0,1]}

11
apps/admin/.output/server/chunks/build/dashboard-styles.DHIbN8CY.mjs

@ -0,0 +1,11 @@
import { S as SvcAlertBanner_vue_vue_type_style_index_0_scoped_3dd2fb7c_lang } from './dashboard-styles-1.mjs-CFxtv9Pt.mjs';
const dashboard_vue_vue_type_style_index_0_scoped_449e8f97_lang = ".panel[data-v-449e8f97]{background:#fff;border:1px solid #f1f5f9;border-radius:16px;box-shadow:0 1px 2px #0000000a;overflow:hidden}.panel-head[data-v-449e8f97]{padding:12px 18px;gap:10px;border-bottom:1px solid #f8fafc;flex-wrap:wrap}.panel-dot[data-v-449e8f97],.panel-head[data-v-449e8f97]{display:flex;align-items:center}.panel-dot[data-v-449e8f97]{width:30px;height:30px;border-radius:9px;justify-content:center;flex-shrink:0}.stat-box[data-v-449e8f97]{padding:10px 12px;border-radius:10px;background:#fafbfc}.stat-label[data-v-449e8f97]{font-size:11px;color:#94a3b8;margin-bottom:3px}.stat-val[data-v-449e8f97]{font-size:20px;font-weight:700;color:#1e293b;line-height:1.1;letter-spacing:-.02em}.sec-title[data-v-449e8f97]{display:flex;align-items:center;gap:10px;margin:0 0 14px}.sec-title .bar[data-v-449e8f97]{width:4px;height:18px;border-radius:3px}.sec-title h2[data-v-449e8f97]{font-size:15px;font-weight:700;color:#0f172a;letter-spacing:-.01em}.sec-title .sub[data-v-449e8f97]{font-size:12px;color:#94a3b8}.sec-title .tag[data-v-449e8f97]{font-size:11px;font-weight:600;padding:2px 9px;border-radius:999px}.sec-title.muted .bar[data-v-449e8f97]{height:14px;opacity:.6}.sec-title.muted h2[data-v-449e8f97]{font-size:13px;font-weight:600;color:#94a3b8}.sec-title.hero .bar[data-v-449e8f97]{width:5px;height:22px}.sec-title.hero h2[data-v-449e8f97]{font-size:18px;font-weight:800;color:#0f172a}.cum-card[data-v-449e8f97]{gap:11px;background:#f8fafc;border:1px solid #eef2f7;border-radius:12px;padding:10px 13px}.cum-card[data-v-449e8f97],.cum-card .ico[data-v-449e8f97]{display:flex;align-items:center}.cum-card .ico[data-v-449e8f97]{width:30px;height:30px;border-radius:9px;justify-content:center;flex-shrink:0;font-size:14px;filter:saturate(.65);opacity:.85}.cum-card .body[data-v-449e8f97]{min-width:0}.cum-card .lbl[data-v-449e8f97]{font-size:11.5px;color:#94a3b8;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.cum-card .val[data-v-449e8f97]{font-size:17px;font-weight:700;color:#64748b;line-height:1.3;letter-spacing:-.01em;margin-top:1px}.today-wrap[data-v-449e8f97]{background:linear-gradient(180deg,#e8f1ff,#f5f9ff);border:1px solid #d6e4ff;border-radius:22px;padding:20px;box-shadow:0 1px 3px #0d6efd0d}.today-card[data-v-449e8f97]{position:relative;background:#fff;border:1px solid #e6eefb;border-radius:18px;padding:17px 19px;box-shadow:0 6px 18px #0d6efd14;transition:transform .18s ease,box-shadow .18s ease;overflow:hidden}.today-card[data-v-449e8f97]:hover{transform:translateY(-3px);box-shadow:0 14px 32px #0d6efd26}.today-card .accent[data-v-449e8f97]{position:absolute;left:0;top:0;bottom:0;width:5px}.today-card-top[data-v-449e8f97]{display:flex;align-items:center;justify-content:space-between;margin-bottom:12px}.today-card .lbl[data-v-449e8f97]{font-size:13px;color:#475569;font-weight:600}.today-card .ico[data-v-449e8f97]{width:42px;height:42px;border-radius:13px;display:flex;align-items:center;justify-content:center;flex-shrink:0;font-size:20px}.today-card .val[data-v-449e8f97]{font-size:31px;font-weight:800;color:#0f172a;line-height:1.05;letter-spacing:-.02em}.today-card .foot[data-v-449e8f97]{margin-top:9px;font-size:12px;color:#94a3b8;display:flex;align-items:center;gap:6px}.delta[data-v-449e8f97]{display:inline-flex;align-items:center;gap:2px;font-weight:700;padding:2px 7px;border-radius:7px;font-size:11.5px}.delta.up[data-v-449e8f97]{color:#059669;background:#ecfdf5}.delta.down[data-v-449e8f97]{color:#dc2626;background:#fef2f2}.delta.flat[data-v-449e8f97],.tbtn[data-v-449e8f97]{color:#64748b;background:#f1f5f9}.tbtn[data-v-449e8f97]{font-size:11px;padding:3px 9px;border-radius:7px;line-height:1.4}.tbtn[data-v-449e8f97]:hover{background:#e2e8f0}.tbtn-on[data-v-449e8f97]{background:#1e293b;color:#fff}";
const dashboardStyles_DHIbN8CY = [
SvcAlertBanner_vue_vue_type_style_index_0_scoped_3dd2fb7c_lang,
dashboard_vue_vue_type_style_index_0_scoped_449e8f97_lang
];
export { dashboardStyles_DHIbN8CY as default };
//# sourceMappingURL=dashboard-styles.DHIbN8CY.mjs.map

1
apps/admin/.output/server/chunks/build/dashboard-styles.DHIbN8CY.mjs.map

@ -0,0 +1 @@
{"version":3,"file":"dashboard-styles.DHIbN8CY.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/dashboard-styles-2.mjs-5w42oV-z.js","../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/dashboard-styles.DHIbN8CY.mjs"],"names":["style_0","style_1"],"mappings":"","x_google_ignoreList":[0,1]}

37
apps/admin/.output/server/chunks/build/product-CDTf1lTs.mjs → apps/admin/.output/server/chunks/build/product-3h7bsXRI.mjs

@ -48,6 +48,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
const rows = ref([]); const rows = ref([]);
const brands = ref({}); const brands = ref({});
const brandOptions = ref([]); const brandOptions = ref([]);
const appOptions = ref([]);
const loading = ref(false); const loading = ref(false);
const submitting = ref(false); const submitting = ref(false);
const isEditing = ref(false); const isEditing = ref(false);
@ -67,6 +68,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
devicecodecount: 1, devicecodecount: 1,
productimage: "", productimage: "",
channel: "official", channel: "official",
appnames: [],
bindrewardvpitime: 0, bindrewardvpitime: 0,
bindrewardtranslate: 0, bindrewardtranslate: 0,
bindrewardmeeting: 0, bindrewardmeeting: 0,
@ -76,6 +78,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
function hexId(id) { function hexId(id) {
return id ? Number(id).toString(16).toUpperCase() : ""; return id ? Number(id).toString(16).toUpperCase() : "";
} }
function appNamesOf(p) {
return String(p.appnames || "").split(",").map((s) => s.trim()).filter(Boolean);
}
function featureCount(p) { function featureCount(p) {
return toggleFields.filter((t) => !!p[t.key]).length; return toggleFields.filter((t) => !!p[t.key]).length;
} }
@ -91,11 +96,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
return !!currentProduct.value?.versionid && v.id === currentProduct.value.versionid; return !!currentProduct.value?.versionid && v.id === currentProduct.value.versionid;
} }
return (_ctx, _push, _parent, _attrs) => { return (_ctx, _push, _parent, _attrs) => {
_push(`<div${ssrRenderAttrs(_attrs)}><div style="${ssrRenderStyle(view.value === "list" ? null : { display: "none" })}"><div class="flex items-center justify-between mb-5"><h2 class="text-lg font-semibold text-slate-800">产品列表</h2><button class="btn btn-primary btn-sm text-white">+ 新增产品</button></div><div class="bg-white rounded-xl shadow-sm border border-slate-100"><div class="overflow-x-auto"><table class="table table-zebra text-sm"><thead><tr><th>ID</th><th>图片</th><th>名称</th><th>品牌商</th><th>类型</th><th>版本</th><th>功能</th><th>操作</th></tr></thead><tbody>`); _push(`<div${ssrRenderAttrs(_attrs)}><div style="${ssrRenderStyle(view.value === "list" ? null : { display: "none" })}"><div class="flex items-center justify-between mb-5"><h2 class="text-lg font-semibold text-slate-800">产品列表</h2><button class="btn btn-primary btn-sm text-white">+ 新增产品</button></div><div class="bg-white rounded-xl shadow-sm border border-slate-100"><div class="overflow-x-auto"><table class="table table-zebra text-sm"><thead><tr><th>ID</th><th>图片</th><th>名称</th><th>品牌商</th><th>绑定应用</th><th>类型</th><th>版本</th><th>功能</th><th>操作</th></tr></thead><tbody>`);
if (loading.value) { if (loading.value) {
_push(`<tr><td colspan="8" class="text-center py-8"><span class="loading loading-spinner loading-sm"></span></td></tr>`); _push(`<tr><td colspan="9" class="text-center py-8"><span class="loading loading-spinner loading-sm"></span></td></tr>`);
} else if (!rows.value.length) { } else if (!rows.value.length) {
_push(`<tr><td colspan="8" class="text-center text-slate-400 py-8">暂无数据</td></tr>`); _push(`<tr><td colspan="9" class="text-center text-slate-400 py-8">暂无数据</td></tr>`);
} else { } else {
_push(`<!---->`); _push(`<!---->`);
} }
@ -107,7 +112,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
} else { } else {
_push(`<div class="w-10 h-10 rounded bg-slate-100 flex items-center justify-center text-slate-300"><svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg></div>`); _push(`<div class="w-10 h-10 rounded bg-slate-100 flex items-center justify-center text-slate-300"><svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path></svg></div>`);
} }
_push(`</td><td class="font-medium">${ssrInterpolate(p.devicename)}</td><td>${ssrInterpolate(brands.value[p.brandid] || "")}</td><td><span class="badge badge-outline badge-sm">${ssrInterpolate(deviceTypes[p.devicetype] || p.devicetype)}</span></td><td class="text-sm">`); _push(`</td><td class="font-medium">${ssrInterpolate(p.devicename)}</td><td>${ssrInterpolate(brands.value[p.brandid] || "")}</td><td>`);
if (appNamesOf(p).length) {
_push(`<div class="flex flex-wrap gap-1"><!--[-->`);
ssrRenderList(appNamesOf(p), (n) => {
_push(`<span class="badge badge-ghost badge-sm">${ssrInterpolate(n)}</span>`);
});
_push(`<!--]--></div>`);
} else {
_push(`<span class="text-slate-300 text-xs">未绑定</span>`);
}
_push(`</td><td><span class="badge badge-outline badge-sm">${ssrInterpolate(deviceTypes[p.devicetype] || p.devicetype)}</span></td><td class="text-sm">`);
if (p.version) { if (p.version) {
_push(`<span>${ssrInterpolate(p.version)}</span>`); _push(`<span>${ssrInterpolate(p.version)}</span>`);
} else { } else {
@ -123,7 +138,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
ssrRenderList(deviceTypeOptions, (label, val) => { ssrRenderList(deviceTypeOptions, (label, val) => {
_push(`<option${ssrRenderAttr("value", Number(val))}${ssrIncludeBooleanAttr(Array.isArray(form.devicetype) ? ssrLooseContain(form.devicetype, Number(val)) : ssrLooseEqual(form.devicetype, Number(val))) ? " selected" : ""}>${ssrInterpolate(label)}</option>`); _push(`<option${ssrRenderAttr("value", Number(val))}${ssrIncludeBooleanAttr(Array.isArray(form.devicetype) ? ssrLooseContain(form.devicetype, Number(val)) : ssrLooseEqual(form.devicetype, Number(val))) ? " selected" : ""}>${ssrInterpolate(label)}</option>`);
}); });
_push(`<!--]--></select></div></div><div class="grid grid-cols-2 gap-4 mb-4"><div class="form-control"><label class="label"><span class="label-text font-medium">扫描UUID</span></label><input${ssrRenderAttr("value", form.scanuuid)} type="text" class="input input-bordered w-full"></div><div class="form-control"><label class="label"><span class="label-text font-medium">设备码数量(每副)</span></label><select class="select select-bordered w-full"><option${ssrRenderAttr("value", 1)}${ssrIncludeBooleanAttr(Array.isArray(form.devicecodecount) ? ssrLooseContain(form.devicecodecount, 1) : ssrLooseEqual(form.devicecodecount, 1)) ? " selected" : ""}>单份 (1个/副)</option><option${ssrRenderAttr("value", 2)}${ssrIncludeBooleanAttr(Array.isArray(form.devicecodecount) ? ssrLooseContain(form.devicecodecount, 2) : ssrLooseEqual(form.devicecodecount, 2)) ? " selected" : ""}>双份 (2个/副)</option></select></div></div><div class="grid grid-cols-2 gap-4 mb-4"><div class="form-control"><label class="label"><span class="label-text font-medium">渠道方</span></label><select class="select select-bordered w-full"><option value="official"${ssrIncludeBooleanAttr(Array.isArray(form.channel) ? ssrLooseContain(form.channel, "official") : ssrLooseEqual(form.channel, "official")) ? " selected" : ""}>官方</option><option value="mobile"${ssrIncludeBooleanAttr(Array.isArray(form.channel) ? ssrLooseContain(form.channel, "mobile") : ssrLooseEqual(form.channel, "mobile")) ? " selected" : ""}>移动</option></select></div></div><div class="mb-4" style="${ssrRenderStyle(form.channel === "mobile" ? null : { display: "none" })}"><div class="grid grid-cols-3 gap-4"><div class="form-control"><label class="label"><span class="label-text font-medium">移动平台ID</span></label><input${ssrRenderAttr("value", mobileExtra.platform_id)} type="text" class="input input-bordered w-full" placeholder="移动平台分配的 ID"></div><div class="form-control"><label class="label"><span class="label-text font-medium">移动平台KEY</span></label><input${ssrRenderAttr("value", mobileExtra.platform_key)} type="text" class="input input-bordered w-full" placeholder="移动平台分配的 KEY"></div><div class="form-control"><label class="label"><span class="label-text font-medium">TUI(8位)</span></label><input${ssrRenderAttr("value", mobileExtra.tui)} type="text" maxlength="8" class="input input-bordered w-full" placeholder="CMEI 前缀,如 11113396"></div></div></div><div class="form-control mb-4"><label class="label"><span class="label-text font-medium">产品图片</span></label><div class="flex items-start gap-4"><div class="flex-1"><input${ssrRenderAttr("value", form.productimage)} type="text" class="input input-bordered w-full input-sm mb-2" placeholder="图片URL(可手动输入或上传)"><div class="flex items-center gap-2"><input type="file" accept="image/*" class="file-input file-input-bordered file-input-sm flex-1"><button type="button" class="btn btn-outline btn-sm btn-primary"${ssrIncludeBooleanAttr(imgUploading.value) ? " disabled" : ""}>`); _push(`<!--]--></select></div></div><div class="form-control mb-4"><label class="label"><span class="label-text font-medium">绑定应用</span><span class="label-text-alt text-slate-400">可多选;品牌商/渠道商账号的「应用」下拉只列出其产品绑定过的应用</span></label>`);
if (!appOptions.value.length) {
_push(`<div class="text-xs text-slate-400 border border-dashed border-slate-200 rounded-lg px-3 py-2"> 暂无可选应用,请先到【SaaS 管理 → 应用中心】新建应用 </div>`);
} else {
_push(`<div class="flex flex-wrap gap-2 border border-slate-200 rounded-lg px-3 py-2"><!--[-->`);
ssrRenderList(appOptions.value, (n) => {
_push(`<label class="label cursor-pointer gap-2 py-1"><input${ssrIncludeBooleanAttr(Array.isArray(form.appnames) ? ssrLooseContain(form.appnames, n) : form.appnames) ? " checked" : ""} type="checkbox"${ssrRenderAttr("value", n)} class="checkbox checkbox-sm checkbox-primary"><span class="label-text">${ssrInterpolate(n)}</span></label>`);
});
_push(`<!--]--></div>`);
}
_push(`</div><div class="grid grid-cols-2 gap-4 mb-4"><div class="form-control"><label class="label"><span class="label-text font-medium">扫描UUID</span></label><input${ssrRenderAttr("value", form.scanuuid)} type="text" class="input input-bordered w-full"></div><div class="form-control"><label class="label"><span class="label-text font-medium">设备码数量(每副)</span></label><select class="select select-bordered w-full"><option${ssrRenderAttr("value", 1)}${ssrIncludeBooleanAttr(Array.isArray(form.devicecodecount) ? ssrLooseContain(form.devicecodecount, 1) : ssrLooseEqual(form.devicecodecount, 1)) ? " selected" : ""}>单份 (1个/副)</option><option${ssrRenderAttr("value", 2)}${ssrIncludeBooleanAttr(Array.isArray(form.devicecodecount) ? ssrLooseContain(form.devicecodecount, 2) : ssrLooseEqual(form.devicecodecount, 2)) ? " selected" : ""}>双份 (2个/副)</option></select></div></div><div class="grid grid-cols-2 gap-4 mb-4"><div class="form-control"><label class="label"><span class="label-text font-medium">渠道方</span></label><select class="select select-bordered w-full"><option value="official"${ssrIncludeBooleanAttr(Array.isArray(form.channel) ? ssrLooseContain(form.channel, "official") : ssrLooseEqual(form.channel, "official")) ? " selected" : ""}>官方</option><option value="mobile"${ssrIncludeBooleanAttr(Array.isArray(form.channel) ? ssrLooseContain(form.channel, "mobile") : ssrLooseEqual(form.channel, "mobile")) ? " selected" : ""}>移动</option></select></div></div><div class="mb-4" style="${ssrRenderStyle(form.channel === "mobile" ? null : { display: "none" })}"><div class="grid grid-cols-3 gap-4"><div class="form-control"><label class="label"><span class="label-text font-medium">移动平台ID</span></label><input${ssrRenderAttr("value", mobileExtra.platform_id)} type="text" class="input input-bordered w-full" placeholder="移动平台分配的 ID"></div><div class="form-control"><label class="label"><span class="label-text font-medium">移动平台KEY</span></label><input${ssrRenderAttr("value", mobileExtra.platform_key)} type="text" class="input input-bordered w-full" placeholder="移动平台分配的 KEY"></div><div class="form-control"><label class="label"><span class="label-text font-medium">TUI(8位)</span></label><input${ssrRenderAttr("value", mobileExtra.tui)} type="text" maxlength="8" class="input input-bordered w-full" placeholder="CMEI 前缀,如 11113396"></div></div></div><div class="form-control mb-4"><label class="label"><span class="label-text font-medium">产品图片</span></label><div class="flex items-start gap-4"><div class="flex-1"><input${ssrRenderAttr("value", form.productimage)} type="text" class="input input-bordered w-full input-sm mb-2" placeholder="图片URL(可手动输入或上传)"><div class="flex items-center gap-2"><input type="file" accept="image/*" class="file-input file-input-bordered file-input-sm flex-1"><button type="button" class="btn btn-outline btn-sm btn-primary"${ssrIncludeBooleanAttr(imgUploading.value) ? " disabled" : ""}>`);
if (imgUploading.value) { if (imgUploading.value) {
_push(`<span class="loading loading-spinner loading-xs"></span>`); _push(`<span class="loading loading-spinner loading-xs"></span>`);
} else { } else {
@ -191,4 +216,4 @@ _sfc_main.setup = (props, ctx) => {
}; };
export { _sfc_main as default }; export { _sfc_main as default };
//# sourceMappingURL=product-CDTf1lTs.mjs.map //# sourceMappingURL=product-3h7bsXRI.mjs.map

1
apps/admin/.output/server/chunks/build/product-3h7bsXRI.mjs.map

@ -0,0 +1 @@
{"version":3,"file":"product-3h7bsXRI.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/product-3h7bsXRI.js"],"names":[],"mappings":"","x_google_ignoreList":[0]}

1
apps/admin/.output/server/chunks/build/product-CDTf1lTs.mjs.map

@ -1 +0,0 @@
{"version":3,"file":"product-CDTf1lTs.mjs","sources":["../../../../node_modules/.cache/nuxt/.nuxt/dist/server/_nuxt/product-CDTf1lTs.js"],"names":[],"mappings":"","x_google_ignoreList":[0]}

21
apps/admin/.output/server/chunks/build/server.mjs

@ -1956,7 +1956,7 @@ const _routes = [
name: "accounts", name: "accounts",
path: "/accounts", path: "/accounts",
meta: __nuxt_page_meta$o || {}, meta: __nuxt_page_meta$o || {},
component: () => import('./accounts-CampayFP.mjs') component: () => import('./accounts-CM5YEJ4p.mjs')
}, },
{ {
name: "agents", name: "agents",
@ -1998,7 +1998,7 @@ const _routes = [
name: "dashboard", name: "dashboard",
path: "/dashboard", path: "/dashboard",
meta: __nuxt_page_meta$h || {}, meta: __nuxt_page_meta$h || {},
component: () => import('./dashboard-C7m4n3tj.mjs') component: () => import('./dashboard-Y8255DFm.mjs')
}, },
{ {
name: "dealers", name: "dealers",
@ -2052,7 +2052,7 @@ const _routes = [
name: "product", name: "product",
path: "/product", path: "/product",
meta: __nuxt_page_meta$8 || {}, meta: __nuxt_page_meta$8 || {},
component: () => import('./product-CDTf1lTs.mjs') component: () => import('./product-3h7bsXRI.mjs')
}, },
{ {
name: "provider", name: "provider",
@ -2888,10 +2888,14 @@ const MENU_GROUPS = [
] ]
} }
]; ];
MENU_GROUPS.flatMap((g) => g.items.map((m) => m.id)); const ALL_MENU_IDS = MENU_GROUPS.flatMap((g) => g.items.map((m) => m.id));
const DEFAULT_ADMIN_ACCESS = MENU_GROUPS.filter((g) => !g.restricted).flatMap((g) => g.items.map((m) => m.id)); const DEFAULT_ADMIN_ACCESS = MENU_GROUPS.filter((g) => !g.restricted).flatMap((g) => g.items.map((m) => m.id));
const DEFAULT_BRAND_ACCESS = ["dashboard", "channel", "user", "settlement"]; const DEFAULT_BRAND_ACCESS = ["dashboard", "channel", "user", "settlement"];
const DEFAULT_DEALER_ACCESS = ["dashboard", "user", "settlement"]; const DEFAULT_DEALER_ACCESS = ["dashboard", "user", "settlement"];
const ROLE_ACCESS_CEILING = {
3: DEFAULT_BRAND_ACCESS,
5: DEFAULT_DEALER_ACCESS
};
const IDENTITY_LABELS = { const IDENTITY_LABELS = {
1: "超管", 1: "超管",
2: "管理员", 2: "管理员",
@ -3034,9 +3038,10 @@ const useAuthStore = defineStore("auth", {
if (this.identity === IDENTITY_MANAGER && this.access.length === 0) { if (this.identity === IDENTITY_MANAGER && this.access.length === 0) {
return DEFAULT_ADMIN_ACCESS.includes(pageId); return DEFAULT_ADMIN_ACCESS.includes(pageId);
} }
if (this.access.length === 0) { const ceiling = ROLE_ACCESS_CEILING[this.identity];
if (this.identity === IDENTITY_BRAND) return DEFAULT_BRAND_ACCESS.includes(pageId); if (ceiling) {
if (this.identity === IDENTITY_DEALER) return DEFAULT_DEALER_ACCESS.includes(pageId); if (!ceiling.includes(pageId)) return false;
if (this.access.length === 0) return true;
} }
return this.access.includes(pageId); return this.access.includes(pageId);
} }
@ -4198,5 +4203,5 @@ let entry;
} }
const entry_default = ((ssrContext) => entry(ssrContext)); const entry_default = ((ssrContext) => entry(ssrContext));
export { DEFAULT_ADMIN_ACCESS as D, MENU_GROUPS as M, _export_sfc as _, useAuthStore as a, useRouter as b, useRoute$1 as c, useRuntimeConfig as d, entry_default as default, encodeRoutePath as e, nuxtLinkDefaults as f, navigateTo as n, resolveRouteObject as r, useNuxtApp as u }; export { ALL_MENU_IDS as A, DEFAULT_ADMIN_ACCESS as D, MENU_GROUPS as M, ROLE_ACCESS_CEILING as R, _export_sfc as _, useAuthStore as a, useRouter as b, useRoute$1 as c, useRuntimeConfig as d, entry_default as default, encodeRoutePath as e, nuxtLinkDefaults as f, navigateTo as n, resolveRouteObject as r, useNuxtApp as u };
//# sourceMappingURL=server.mjs.map //# sourceMappingURL=server.mjs.map

14
apps/admin/.output/server/chunks/build/styles.mjs

@ -2,22 +2,22 @@ const interopDefault = r => r.default || r || [];
const styles = { const styles = {
"../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/app/components/error-500.vue": () => import('./error-500-styles.CsxdYB__.mjs').then(interopDefault), "../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/app/components/error-500.vue": () => import('./error-500-styles.CsxdYB__.mjs').then(interopDefault),
"../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/app/components/error-404.vue": () => import('./error-404-styles.Dw8OeZuk.mjs').then(interopDefault), "../node_modules/.pnpm/nuxt@4.4.8_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7__@babel+plugin-syntax-typ_25b4a4016600149c0331b87503aafc6b/node_modules/nuxt/dist/app/components/error-404.vue": () => import('./error-404-styles.Dw8OeZuk.mjs').then(interopDefault),
"pages/agents.vue": () => import('./agents-styles.CKxmVBlz.mjs').then(interopDefault),
"pages/calltranslate.vue": () => import('./calltranslate-styles.DejCdNUq.mjs').then(interopDefault),
"pages/apps/[name].vue": () => import('./_name_-styles.CveqLyYu.mjs').then(interopDefault), "pages/apps/[name].vue": () => import('./_name_-styles.CveqLyYu.mjs').then(interopDefault),
"pages/accounts.vue": () => import('./accounts-styles.B912aimJ.mjs').then(interopDefault),
"pages/channels.vue": () => import('./channels-styles.YMd5B91-.mjs').then(interopDefault),
"components/AppDeployTab.vue": () => import('./AppDeployTab-styles.4FdVYf2u.mjs').then(interopDefault), "components/AppDeployTab.vue": () => import('./AppDeployTab-styles.4FdVYf2u.mjs').then(interopDefault),
"components/AppModuleTab.vue": () => import('./AppModuleTab-styles._m-oVrlE.mjs').then(interopDefault), "components/AppModuleTab.vue": () => import('./AppModuleTab-styles._m-oVrlE.mjs').then(interopDefault),
"pages/accounts.vue": () => import('./accounts-styles.Bwl6sYRz.mjs').then(interopDefault),
"pages/calltranslate.vue": () => import('./calltranslate-styles.DejCdNUq.mjs').then(interopDefault),
"pages/agents.vue": () => import('./agents-styles.CKxmVBlz.mjs').then(interopDefault),
"pages/apps/index.vue": () => import('./index-styles.DdwLJn9K.mjs').then(interopDefault), "pages/apps/index.vue": () => import('./index-styles.DdwLJn9K.mjs').then(interopDefault),
"pages/dashboard.vue": () => import('./dashboard-styles.CnnmNtqM.mjs').then(interopDefault), "pages/channels.vue": () => import('./channels-styles.YMd5B91-.mjs').then(interopDefault),
"pages/dashboard.vue": () => import('./dashboard-styles.DHIbN8CY.mjs').then(interopDefault),
"components/SvcAlertBanner.vue": () => import('./SvcAlertBanner-styles.C9CJuYwV.mjs').then(interopDefault), "components/SvcAlertBanner.vue": () => import('./SvcAlertBanner-styles.C9CJuYwV.mjs').then(interopDefault),
"pages/serviceconfig.vue": () => import('./serviceconfig-styles.BoVuqbov.mjs').then(interopDefault), "pages/serviceconfig.vue": () => import('./serviceconfig-styles.BoVuqbov.mjs').then(interopDefault),
"pages/meettemplates.vue": () => import('./meettemplates-styles.BmUIUT9b.mjs').then(interopDefault),
"pages/meetingsvc.vue": () => import('./meetingsvc-styles.CJmYxbsV.mjs').then(interopDefault), "pages/meetingsvc.vue": () => import('./meetingsvc-styles.CJmYxbsV.mjs').then(interopDefault),
"pages/meettemplates.vue": () => import('./meettemplates-styles.BmUIUT9b.mjs').then(interopDefault),
"pages/svcinspect.vue": () => import('./svcinspect-styles.DpDXXkHn.mjs').then(interopDefault),
"pages/statlog.vue": () => import('./statlog-styles.tckJcIlw.mjs').then(interopDefault), "pages/statlog.vue": () => import('./statlog-styles.tckJcIlw.mjs').then(interopDefault),
"pages/index.vue": () => import('./index-styles.D3jm1SfB.mjs').then(interopDefault), "pages/index.vue": () => import('./index-styles.D3jm1SfB.mjs').then(interopDefault),
"pages/svcinspect.vue": () => import('./svcinspect-styles.DpDXXkHn.mjs').then(interopDefault),
"pages/systemconfig.vue": () => import('./systemconfig-styles.DqxAqW2L.mjs').then(interopDefault), "pages/systemconfig.vue": () => import('./systemconfig-styles.DqxAqW2L.mjs').then(interopDefault),
"layouts/default.vue": () => import('./default-styles.BZwnP0YX.mjs').then(interopDefault), "layouts/default.vue": () => import('./default-styles.BZwnP0YX.mjs').then(interopDefault),
"components/AppLoading.vue": () => import('./default-styles.BZwnP0YX.mjs').then(interopDefault), "components/AppLoading.vue": () => import('./default-styles.BZwnP0YX.mjs').then(interopDefault),

472
apps/admin/.output/server/chunks/nitro/nitro.mjs

@ -4028,7 +4028,7 @@ function _expandFromEnv(value) {
const _inlineRuntimeConfig = { const _inlineRuntimeConfig = {
"app": { "app": {
"baseURL": "/", "baseURL": "/",
"buildId": "12df8bde-c7e1-423a-8c26-514d561b95ec", "buildId": "15e7ab28-16d6-4f4e-8edd-c6a8122f81cf",
"buildAssetsDir": "/_nuxt/", "buildAssetsDir": "/_nuxt/",
"cdnURL": "" "cdnURL": ""
}, },
@ -4507,432 +4507,432 @@ const plugins = [
]; ];
const assets = { const assets = {
"/_nuxt/32rNuZwS.js": { "/_nuxt/0CGOegeu.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"161c-xrBRvvJwitKtFm4ME6kMTCb03hE\"", "etag": "\"ab0b-wAJPKXaWnrvjHTqLtlGbAz+PRKE\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 5660, "size": 43787,
"path": "../public/_nuxt/32rNuZwS.js" "path": "../public/_nuxt/0CGOegeu.js"
},
"/_nuxt/32XpWsQL.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"4420-LhxpNO174+u66d/0bCnOmaSgxdY\"",
"mtime": "2026-08-15T09:07:20.777Z",
"size": 17440,
"path": "../public/_nuxt/32XpWsQL.js"
}, },
"/_nuxt/7m3DvxFn.js": { "/_nuxt/7m3DvxFn.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"124-bioeqTegIgwu2Bt0lWW2BhznYbU\"", "etag": "\"124-bioeqTegIgwu2Bt0lWW2BhznYbU\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 292, "size": 292,
"path": "../public/_nuxt/7m3DvxFn.js" "path": "../public/_nuxt/7m3DvxFn.js"
}, },
"/_nuxt/B8hrjpgL.js": { "/_nuxt/AeilnnXP.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"2f77-hGRLgkxIGfWL9wqwhnMqjKZUu0U\"", "etag": "\"2c52-OdHTXFka+nnPeUxhe/5ocyfP8jY\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 12151, "size": 11346,
"path": "../public/_nuxt/B8hrjpgL.js" "path": "../public/_nuxt/AeilnnXP.js"
}, },
"/_nuxt/BAkLwAvM.js": { "/_nuxt/6O01ZZML.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"4269-pjr/t3p/PskUq8oVk9kaHBiHnxg\"", "etag": "\"327eb-oqot1YXk9lpL65TtwlVVYt1ghLE\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 17001, "size": 206827,
"path": "../public/_nuxt/BAkLwAvM.js" "path": "../public/_nuxt/6O01ZZML.js"
}, },
"/_nuxt/B9UHsPCY.js": { "/_nuxt/B-G7qD0T.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"4a85-XB/BiHyyeyTsvecuDXZV5W/5NpU\"", "etag": "\"1a6d-xzOJBDbjNaaynzrgGaMwGiVQwTg\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 19077, "size": 6765,
"path": "../public/_nuxt/B9UHsPCY.js" "path": "../public/_nuxt/B-G7qD0T.js"
}, },
"/_nuxt/BDDumZok.js": { "/_nuxt/BCmMvQNl.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"3a63-Jrrxhzd+FXdpDhIIh8PhVeBKc3c\"", "etag": "\"2251-2NxC8ZFe6tWCCMQfVQwI6qx6G24\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 14947, "size": 8785,
"path": "../public/_nuxt/BDDumZok.js" "path": "../public/_nuxt/BCmMvQNl.js"
}, },
"/_nuxt/BFjsaYIf.js": { "/_nuxt/BIYq6SKh.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"3921-D+OPwLN6nNNQJHYigEISPaUXE94\"", "etag": "\"df-zpDDeFq+60nJM+yIrE+WmIc/9YA\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 14625, "size": 223,
"path": "../public/_nuxt/BFjsaYIf.js" "path": "../public/_nuxt/BIYq6SKh.js"
}, },
"/_nuxt/BKXYxnNU.js": { "/_nuxt/BNW9rRgN.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"b1f-T0SCITQ9vojZhdzmltYlixS8XH0\"", "etag": "\"443e-UmGAG8AB7MTn0RBZdFShaV+MQtg\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 2847, "size": 17470,
"path": "../public/_nuxt/BKXYxnNU.js" "path": "../public/_nuxt/BNW9rRgN.js"
}, },
"/_nuxt/BSO50kj0.js": { "/_nuxt/BSXoR6Yx.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"1a6d-ijJpGHwGc5JfTjehpr+zcNsa+8k\"", "etag": "\"2f77-6EZnQyDqAv5Z4yJZN6f+j9uqXLc\"",
"mtime": "2026-08-14T08:52:10.251Z", "mtime": "2026-08-15T09:07:20.777Z",
"size": 6765, "size": 12151,
"path": "../public/_nuxt/BSO50kj0.js" "path": "../public/_nuxt/BSXoR6Yx.js"
}, },
"/_nuxt/Bad2XFSd.js": { "/_nuxt/BZR1IKC1.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"585c-i9gNA+Lz6/+GzcR98xDe8eJEX6I\"", "etag": "\"585c-9LtGrJOBN7UG/lqEHB9G9H7XocY\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 22620, "size": 22620,
"path": "../public/_nuxt/Bad2XFSd.js" "path": "../public/_nuxt/BZR1IKC1.js"
},
"/_nuxt/Bm2Gu08J.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"ecf-IrKRWzaW+yoGSCYmqYJ1J6ASNmA\"",
"mtime": "2026-08-14T08:52:10.252Z",
"size": 3791,
"path": "../public/_nuxt/Bm2Gu08J.js"
}, },
"/_nuxt/Bp86Q8ON.js": { "/_nuxt/BgasD__e.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"2c52-Okm3EPDQqdhbKZSoYRrALTH4Za4\"", "etag": "\"82a-RYPbil64oSIg22v2eoLkq0eJmLA\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 11346, "size": 2090,
"path": "../public/_nuxt/Bp86Q8ON.js" "path": "../public/_nuxt/BgasD__e.js"
},
"/_nuxt/Bs6lDwyi.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"3234-Cwm9RQ5AxP/1La0jug5n0cT7j9U\"",
"mtime": "2026-08-14T08:52:10.252Z",
"size": 12852,
"path": "../public/_nuxt/Bs6lDwyi.js"
}, },
"/_nuxt/C9zSjFPi.js": { "/_nuxt/BqBJfKQo.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"4d74-7WqzcJl7PLfQS2x/OCRCem35xtY\"", "etag": "\"3361-mjphjVfC2YnFQWqE0tPxoqaLxNE\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 19828, "size": 13153,
"path": "../public/_nuxt/C9zSjFPi.js" "path": "../public/_nuxt/BqBJfKQo.js"
}, },
"/_nuxt/CLee_yMD.js": { "/_nuxt/BrJ9pewm.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"9918-qI9LxWAxYeI8zxNeedt4EGcTC/o\"", "etag": "\"868-X2nf5ZmgrLsvdSRE/1gzdne7MpI\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 39192, "size": 2152,
"path": "../public/_nuxt/CLee_yMD.js" "path": "../public/_nuxt/BrJ9pewm.js"
}, },
"/_nuxt/BZKwWPxz.js": { "/_nuxt/BvvkbLjV.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"2052-wnn0WEU+27sKP3SZQqxe4vsO7Nk\"", "etag": "\"146-RCzFlMQqBdtAO+nbTGxc2OEyWgw\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 8274, "size": 326,
"path": "../public/_nuxt/BZKwWPxz.js" "path": "../public/_nuxt/BvvkbLjV.js"
}, },
"/_nuxt/CUR2rcGX.js": { "/_nuxt/C8kc9IUa.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"ab0b-E4R9IhdQAdk5AeMaurqAhUAFHv8\"", "etag": "\"4d37-xlx31LlyrHG41nhgvi2cluBeL4M\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 43787, "size": 19767,
"path": "../public/_nuxt/CUR2rcGX.js" "path": "../public/_nuxt/C8kc9IUa.js"
}, },
"/_nuxt/ChqjEN2N.js": { "/_nuxt/CAhwHUW5.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"4376-vHiSqf3pf8EM2IRApPC4z8vzXXk\"", "etag": "\"1c22-iRpsqMBZ/lKvQ1ZLFTdXJj+CxZg\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 17270, "size": 7202,
"path": "../public/_nuxt/ChqjEN2N.js" "path": "../public/_nuxt/CAhwHUW5.js"
}, },
"/_nuxt/Cy52Ecc0.js": { "/_nuxt/CDB8L8go.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"1bc4-xBCYPvI5gv6mE7Yl/aqkMoqlJOM\"", "etag": "\"161d-8vTFhQeAhu0iwZiVsbiORqBk33o\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 7108, "size": 5661,
"path": "../public/_nuxt/Cy52Ecc0.js" "path": "../public/_nuxt/CDB8L8go.js"
}, },
"/_nuxt/D4Um3zt0.js": { "/_nuxt/CEFq2Pq9.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"868-tvHe4V2VBT2qFlTNG2ybuXr9i5E\"", "etag": "\"2224-LzFXmuuqoPrIY+0cZdXYpv3GpPU\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 2152, "size": 8740,
"path": "../public/_nuxt/D4Um3zt0.js" "path": "../public/_nuxt/CEFq2Pq9.js"
}, },
"/_nuxt/D5EVRMZE.js": { "/_nuxt/CPoAe5lL.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"185e-l27fNSlC0ZrgHjirXS6gdQ09ZK0\"", "etag": "\"185e-p7spm3znOFfjN5nsnJBNcL8zeB4\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 6238, "size": 6238,
"path": "../public/_nuxt/D5EVRMZE.js" "path": "../public/_nuxt/CPoAe5lL.js"
}, },
"/_nuxt/D5UrQ7F3.js": { "/_nuxt/CS9TbzfM.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"df-Vpe6+w4O37bZbRfKwkmhV/5uJ/0\"", "etag": "\"2801-JJYulw9B7TEJQH1pUflxEBXtIUk\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 223, "size": 10241,
"path": "../public/_nuxt/D5UrQ7F3.js" "path": "../public/_nuxt/CS9TbzfM.js"
}, },
"/_nuxt/D8jvJLAX.js": { "/_nuxt/CkLfApYf.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"d96-MQjqcLH6rrs5z/JBKqZTc2pky4I\"", "etag": "\"d96-g9HYKIqCFAy/mMRN2MIzovAnK8A\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 3478, "size": 3478,
"path": "../public/_nuxt/D8jvJLAX.js" "path": "../public/_nuxt/CkLfApYf.js"
},
"/_nuxt/DAaIRqev.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"b4f7-htOh1yrKjWatpHK70CxXvGFprSc\"",
"mtime": "2026-08-14T08:52:10.252Z",
"size": 46327,
"path": "../public/_nuxt/DAaIRqev.js"
}, },
"/_nuxt/DBJku-16.js": { "/_nuxt/CasIUDzx.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"1a5-JM0kJjeh2BCFcL9bJnPZoSalMHo\"", "etag": "\"1bc4-5ID5s+IqRJr+nGxzzhd9T0KQ7zk\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 421, "size": 7108,
"path": "../public/_nuxt/DBJku-16.js" "path": "../public/_nuxt/CasIUDzx.js"
}, },
"/_nuxt/DBzpctzV.js": { "/_nuxt/DC2vBYza.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"2224-hFH6p9RkJNoBHW1/2i3gQ6Tnr6k\"", "etag": "\"3a63-Twcfgh0ozaiODvKx4+2hSN+2uVQ\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 8740, "size": 14947,
"path": "../public/_nuxt/DBzpctzV.js" "path": "../public/_nuxt/DC2vBYza.js"
}, },
"/_nuxt/DD3V9C6_.js": { "/_nuxt/DD3V9C6_.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"6dc-zzPSx3jvZqwehMMA49ruje/F1NI\"", "etag": "\"6dc-zzPSx3jvZqwehMMA49ruje/F1NI\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 1756, "size": 1756,
"path": "../public/_nuxt/DD3V9C6_.js" "path": "../public/_nuxt/DD3V9C6_.js"
}, },
"/_nuxt/DVest5s8.js": { "/_nuxt/DDe4k6KN.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"b1f-A3pbG2HA1ApBxaVza6eBjgp6v8c\"",
"mtime": "2026-08-15T09:07:20.778Z",
"size": 2847,
"path": "../public/_nuxt/DDe4k6KN.js"
},
"/_nuxt/DPKLCcBs.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"79c-kv9yX8M0p8L1+kS2HfRlQvaTNyU\"", "etag": "\"79c-HKz+gDp6JpgfUZSgWKSoQXH/C2o\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.778Z",
"size": 1948, "size": 1948,
"path": "../public/_nuxt/DVest5s8.js" "path": "../public/_nuxt/DPKLCcBs.js"
}, },
"/_nuxt/DhKR78CK.js": { "/_nuxt/DQ6zmqs4.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"2251-jM3FqC+OzQ4UfDhKHF4yzQLMVFw\"", "etag": "\"3921-Ta27EmPx1a1zPCDhLBfK47aqKHA\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 8785, "size": 14625,
"path": "../public/_nuxt/DhKR78CK.js" "path": "../public/_nuxt/DQ6zmqs4.js"
}, },
"/_nuxt/DlgycG-C.js": { "/_nuxt/DRVBzPRY.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"1c22-5kRKn+HliLndZwWyJpR0S30/jeM\"", "etag": "\"9918-Z957wioFQ0IUV5O9QL9irHxU9iI\"",
"mtime": "2026-08-14T08:52:10.252Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 7202, "size": 39192,
"path": "../public/_nuxt/DlgycG-C.js" "path": "../public/_nuxt/DRVBzPRY.js"
}, },
"/_nuxt/EeX3zgoF.js": { "/_nuxt/DT3lD2sm.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"17a-z+W6VxS3hfxBETeBUy7Cf49z/kg\"", "etag": "\"2284-3B3SW8oYDuX/iiWCCywYaG6SyEc\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 378, "size": 8836,
"path": "../public/_nuxt/EeX3zgoF.js" "path": "../public/_nuxt/DT3lD2sm.js"
}, },
"/_nuxt/GUJrhX2S.js": { "/_nuxt/DTVoyhwb.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"224a-bpuN0R00By1R+d+6CqDpIKReyK4\"", "etag": "\"537a-HqFQGz4Kmm2jhEwPsMFj+u5BgvA\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 8778, "size": 21370,
"path": "../public/_nuxt/GUJrhX2S.js" "path": "../public/_nuxt/DTVoyhwb.js"
},
"/_nuxt/DZfr_EfO.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"3234-E1FakbFo6nQGKpgjXYnI0zoxcdU\"",
"mtime": "2026-08-15T09:07:20.779Z",
"size": 12852,
"path": "../public/_nuxt/DZfr_EfO.js"
},
"/_nuxt/Dehik56a.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"2052-ZdMoECmaaJB0MlZMDcSQIrWKWwo\"",
"mtime": "2026-08-15T09:07:20.779Z",
"size": 8274,
"path": "../public/_nuxt/Dehik56a.js"
},
"/_nuxt/DlMn1R4f.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"4556-T7X/kR9Cl+QOLvBuDrthhR4bAC8\"",
"mtime": "2026-08-15T09:07:20.779Z",
"size": 17750,
"path": "../public/_nuxt/DlMn1R4f.js"
}, },
"/_nuxt/LangSelect.Dkm6e8RK.css": { "/_nuxt/LangSelect.Dkm6e8RK.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"5c3-C4SkCgblTC2eBbJlNpFMUPfZZW8\"", "etag": "\"5c3-C4SkCgblTC2eBbJlNpFMUPfZZW8\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 1475, "size": 1475,
"path": "../public/_nuxt/LangSelect.Dkm6e8RK.css" "path": "../public/_nuxt/LangSelect.Dkm6e8RK.css"
}, },
"/_nuxt/DSy_gLdM.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"327e8-ofXh22atukXGgO3BK8kUSnn4Hz8\"",
"mtime": "2026-08-14T08:52:10.252Z",
"size": 206824,
"path": "../public/_nuxt/DSy_gLdM.js"
},
"/_nuxt/NtXZuCUg.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"820-JFINM6U1uIlZATaPNOMh0nubmak\"",
"mtime": "2026-08-14T08:52:10.253Z",
"size": 2080,
"path": "../public/_nuxt/NtXZuCUg.js"
},
"/_nuxt/PN667bHc.js": { "/_nuxt/PN667bHc.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"58d-Ep7a34IW34moz3HCr5MkNYgtj58\"", "etag": "\"58d-Ep7a34IW34moz3HCr5MkNYgtj58\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 1421, "size": 1421,
"path": "../public/_nuxt/PN667bHc.js" "path": "../public/_nuxt/PN667bHc.js"
}, },
"/_nuxt/VxS1tujf.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"b4f7-VJxykOevVbS6bBdjvWEwDX6cBFQ\"",
"mtime": "2026-08-15T09:07:20.779Z",
"size": 46327,
"path": "../public/_nuxt/VxS1tujf.js"
},
"/_nuxt/_name_.Dk1VjRtn.css": { "/_nuxt/_name_.Dk1VjRtn.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"1a66-1dxYeVhpWEHP4N42J8xWTbXC/O0\"", "etag": "\"1a66-1dxYeVhpWEHP4N42J8xWTbXC/O0\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 6758, "size": 6758,
"path": "../public/_nuxt/_name_.Dk1VjRtn.css" "path": "../public/_nuxt/_name_.Dk1VjRtn.css"
}, },
"/_nuxt/accounts.maMJCEm_.css": { "/_nuxt/_yKEhqk3.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"1a5-1vBo/bnCh6VM/9ZUiAImesQfgZ0\"",
"mtime": "2026-08-15T09:07:20.779Z",
"size": 421,
"path": "../public/_nuxt/_yKEhqk3.js"
},
"/_nuxt/accounts.B-g1r2A7.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"13a-JufS/36sDSbUlUvboAenUt1gceo\"", "etag": "\"13a-SYvdtlrmLyFcIi8v0JfmEZ1t3DI\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 314, "size": 314,
"path": "../public/_nuxt/accounts.maMJCEm_.css" "path": "../public/_nuxt/accounts.B-g1r2A7.css"
}, },
"/_nuxt/agents.DyZqnyeq.css": { "/_nuxt/agents.DyZqnyeq.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"ddf-1zDtq4utyLScKyjKpP5Vl0kGrH0\"", "etag": "\"ddf-1zDtq4utyLScKyjKpP5Vl0kGrH0\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 3551, "size": 3551,
"path": "../public/_nuxt/agents.DyZqnyeq.css" "path": "../public/_nuxt/agents.DyZqnyeq.css"
}, },
"/_nuxt/PbGQRI_R.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"4556-5M15W7wQigCpY5s0KAT/XoDNOFU\"",
"mtime": "2026-08-14T08:52:10.253Z",
"size": 17750,
"path": "../public/_nuxt/PbGQRI_R.js"
},
"/_nuxt/calltranslate.blzoinPN.css": { "/_nuxt/calltranslate.blzoinPN.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"12bf-B3jQjoB9OO2WOeybQnvfI4S0Nko\"", "etag": "\"12bf-B3jQjoB9OO2WOeybQnvfI4S0Nko\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 4799, "size": 4799,
"path": "../public/_nuxt/calltranslate.blzoinPN.css" "path": "../public/_nuxt/calltranslate.blzoinPN.css"
}, },
"/_nuxt/channels.DbnY_8Am.css": { "/_nuxt/channels.DbnY_8Am.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"fab-YPcS9+hI/kVgbpM78C7NfxKXxDw\"", "etag": "\"fab-YPcS9+hI/kVgbpM78C7NfxKXxDw\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.779Z",
"size": 4011, "size": 4011,
"path": "../public/_nuxt/channels.DbnY_8Am.css" "path": "../public/_nuxt/channels.DbnY_8Am.css"
}, },
"/_nuxt/dashboard.BgaEnlue.css": { "/_nuxt/dashboard.CuNO2Lt5.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"1674-ggQ76Yns/VcHCLK1Vkz0Fy6jv9E\"", "etag": "\"1674-SCKd3O2ku8SyyCDj+QxFT1o+LCU\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 5748, "size": 5748,
"path": "../public/_nuxt/dashboard.BgaEnlue.css" "path": "../public/_nuxt/dashboard.CuNO2Lt5.css"
}, },
"/_nuxt/default.miyQHb0v.css": { "/_nuxt/default.miyQHb0v.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"b2-O1zVvoAVcFlJDT9d+8Mq5HKgSwA\"", "etag": "\"b2-O1zVvoAVcFlJDT9d+8Mq5HKgSwA\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 178, "size": 178,
"path": "../public/_nuxt/default.miyQHb0v.css" "path": "../public/_nuxt/default.miyQHb0v.css"
}, },
"/_nuxt/error-404.Dm-MYrAh.css": { "/_nuxt/error-404.Dm-MYrAh.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"97e-/v6mv+rmcBtKGiHr88cRdQNod1s\"", "etag": "\"97e-/v6mv+rmcBtKGiHr88cRdQNod1s\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 2430, "size": 2430,
"path": "../public/_nuxt/error-404.Dm-MYrAh.css" "path": "../public/_nuxt/error-404.Dm-MYrAh.css"
}, },
"/_nuxt/entry.CF8jJHbs.css": { "/_nuxt/entry.B1mQ-Tl2.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"187cd-vRyzLqoJe81wEX3PvtPjQxByzu4\"", "etag": "\"187f0-/271PGRih2x01/rPrhvJSidiSQw\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 100301, "size": 100336,
"path": "../public/_nuxt/entry.CF8jJHbs.css" "path": "../public/_nuxt/entry.B1mQ-Tl2.css"
}, },
"/_nuxt/error-500.DM8oqBl3.css": { "/_nuxt/error-500.DM8oqBl3.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"773-fnDg7l3rvJ5f8Hx4TwZqMlSCEdI\"", "etag": "\"773-fnDg7l3rvJ5f8Hx4TwZqMlSCEdI\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 1907, "size": 1907,
"path": "../public/_nuxt/error-500.DM8oqBl3.css" "path": "../public/_nuxt/error-500.DM8oqBl3.css"
}, },
"/_nuxt/index.B6hNDrw5.css": { "/_nuxt/index.B6hNDrw5.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"9bb-/UiGUQ9ZySUPo+TfZxQFmRAajvk\"", "etag": "\"9bb-/UiGUQ9ZySUPo+TfZxQFmRAajvk\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 2491, "size": 2491,
"path": "../public/_nuxt/index.B6hNDrw5.css" "path": "../public/_nuxt/index.B6hNDrw5.css"
}, },
"/_nuxt/index.dJfvJhMb.css": { "/_nuxt/index.dJfvJhMb.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"c9d-Q0Ilc9TjkNvm89dRCjMxXNLi/MA\"", "etag": "\"c9d-Q0Ilc9TjkNvm89dRCjMxXNLi/MA\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 3229, "size": 3229,
"path": "../public/_nuxt/index.dJfvJhMb.css" "path": "../public/_nuxt/index.dJfvJhMb.css"
}, },
"/_nuxt/meetingsvc.DgYSEQUA.css": { "/_nuxt/meetingsvc.DgYSEQUA.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"15b5-ihBIWfyVoCoSGDt99wujE0L7L7g\"", "etag": "\"15b5-ihBIWfyVoCoSGDt99wujE0L7L7g\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 5557, "size": 5557,
"path": "../public/_nuxt/meetingsvc.DgYSEQUA.css" "path": "../public/_nuxt/meetingsvc.DgYSEQUA.css"
}, },
"/_nuxt/meettemplates.DBfDdqB2.css": { "/_nuxt/meettemplates.DBfDdqB2.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"d49-TVYcNFQzlREsqQOJGNzA07JhwmQ\"", "etag": "\"d49-TVYcNFQzlREsqQOJGNzA07JhwmQ\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 3401, "size": 3401,
"path": "../public/_nuxt/meettemplates.DBfDdqB2.css" "path": "../public/_nuxt/meettemplates.DBfDdqB2.css"
}, },
"/_nuxt/obp34o1K.js": { "/_nuxt/oWVa2rll.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"146-vZ+Lzqk947J/xG6zkYNonHoix/o\"",
"mtime": "2026-08-14T08:52:10.253Z",
"size": 326,
"path": "../public/_nuxt/obp34o1K.js"
},
"/_nuxt/rUi_Q6ng.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"2801-6guWmyoUWx7UZbs69v6PRm3gLe8\"", "etag": "\"ecf-YtgrGMbys5HvNT/kO4skO5kDP0k\"",
"mtime": "2026-08-14T08:52:10.253Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 10241, "size": 3791,
"path": "../public/_nuxt/rUi_Q6ng.js" "path": "../public/_nuxt/oWVa2rll.js"
}, },
"/_nuxt/serviceconfig.UIJazB1z.css": { "/_nuxt/serviceconfig.UIJazB1z.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"1e79-kEtx7BtNj5nG/cCNlmQ0QQVPn38\"", "etag": "\"1e79-kEtx7BtNj5nG/cCNlmQ0QQVPn38\"",
"mtime": "2026-08-14T08:52:10.254Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 7801, "size": 7801,
"path": "../public/_nuxt/serviceconfig.UIJazB1z.css" "path": "../public/_nuxt/serviceconfig.UIJazB1z.css"
}, },
"/_nuxt/q-Oqovwl.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"4a85-O8hCUtX7PWtlxgqVEH/PmO9285Y\"",
"mtime": "2026-08-15T09:07:20.780Z",
"size": 19077,
"path": "../public/_nuxt/q-Oqovwl.js"
},
"/_nuxt/statlog.DNW5XZ2N.css": { "/_nuxt/statlog.DNW5XZ2N.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"4f1-Yqyu5jOcireqWKtZ+4omiemN9AU\"", "etag": "\"4f1-Yqyu5jOcireqWKtZ+4omiemN9AU\"",
"mtime": "2026-08-14T08:52:10.254Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 1265, "size": 1265,
"path": "../public/_nuxt/statlog.DNW5XZ2N.css" "path": "../public/_nuxt/statlog.DNW5XZ2N.css"
}, },
"/_nuxt/svcinspect.H9TdRqZ5.css": { "/_nuxt/svcinspect.H9TdRqZ5.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"709-X1szhhs8D9fMma7X8BsLOY0a31w\"", "etag": "\"709-X1szhhs8D9fMma7X8BsLOY0a31w\"",
"mtime": "2026-08-14T08:52:10.254Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 1801, "size": 1801,
"path": "../public/_nuxt/svcinspect.H9TdRqZ5.css" "path": "../public/_nuxt/svcinspect.H9TdRqZ5.css"
}, },
"/_nuxt/systemconfig.MaL8_AEr.css": { "/_nuxt/systemconfig.MaL8_AEr.css": {
"type": "text/css; charset=utf-8", "type": "text/css; charset=utf-8",
"etag": "\"5f6-qMlVehTadQhvspNSgWfTP18KCiE\"", "etag": "\"5f6-qMlVehTadQhvspNSgWfTP18KCiE\"",
"mtime": "2026-08-14T08:52:10.254Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 1526, "size": 1526,
"path": "../public/_nuxt/systemconfig.MaL8_AEr.css" "path": "../public/_nuxt/systemconfig.MaL8_AEr.css"
}, },
"/_nuxt/w_7nuVJ9.js": { "/_nuxt/xsgK-Nup.js": {
"type": "text/javascript; charset=utf-8", "type": "text/javascript; charset=utf-8",
"etag": "\"4d37-uI6WtYyte9RrNfP2CqG0a3Dfkxs\"", "etag": "\"17a-aXb9bGYs9ZSofA1WpznR9+wq6n8\"",
"mtime": "2026-08-14T08:52:10.254Z", "mtime": "2026-08-15T09:07:20.780Z",
"size": 19767, "size": 378,
"path": "../public/_nuxt/w_7nuVJ9.js" "path": "../public/_nuxt/xsgK-Nup.js"
},
"/_nuxt/yis2MfHE.js": {
"type": "text/javascript; charset=utf-8",
"etag": "\"3361-zoc94hknJ/vh8V1IAnn1tSOmBl8\"",
"mtime": "2026-08-14T08:52:10.254Z",
"size": 13153,
"path": "../public/_nuxt/yis2MfHE.js"
}, },
"/_nuxt/builds/latest.json": { "/_nuxt/builds/latest.json": {
"type": "application/json", "type": "application/json",
"etag": "\"47-yuldLdByJUJ9lY60/tuyaHtw01M\"", "etag": "\"47-hDZp+IYLjka2s44fydU68+BM9Ak\"",
"mtime": "2026-08-14T08:52:10.244Z", "mtime": "2026-08-15T09:07:20.771Z",
"size": 71, "size": 71,
"path": "../public/_nuxt/builds/latest.json" "path": "../public/_nuxt/builds/latest.json"
}, },
"/_nuxt/builds/meta/12df8bde-c7e1-423a-8c26-514d561b95ec.json": { "/_nuxt/builds/meta/15e7ab28-16d6-4f4e-8edd-c6a8122f81cf.json": {
"type": "application/json", "type": "application/json",
"etag": "\"58-VsfNIFumgAfownB62g17vvIcau8\"", "etag": "\"58-4dAoyvoGi+EJ91UGjlvVnME+sFI\"",
"mtime": "2026-08-14T08:52:10.241Z", "mtime": "2026-08-15T09:07:20.769Z",
"size": 88, "size": 88,
"path": "../public/_nuxt/builds/meta/12df8bde-c7e1-423a-8c26-514d561b95ec.json" "path": "../public/_nuxt/builds/meta/15e7ab28-16d6-4f4e-8edd-c6a8122f81cf.json"
} }
}; };

26
apps/admin/app/pages/accounts.vue

@ -104,13 +104,14 @@
<div class="flex items-center justify-between mb-1"> <div class="flex items-center justify-between mb-1">
<div class="text-sm font-semibold text-slate-600">菜单权限</div> <div class="text-sm font-semibold text-slate-600">菜单权限</div>
<div class="flex gap-1"> <div class="flex gap-1">
<button type="button" class="btn btn-ghost btn-xs" @click="sel.access = DEFAULT_ADMIN_ACCESS.slice()">管理员默认</button> <button v-if="!roleCeiling" type="button" class="btn btn-ghost btn-xs" @click="sel.access = DEFAULT_ADMIN_ACCESS.slice()">管理员默认</button>
<button type="button" class="btn btn-ghost btn-xs" @click="sel.access = ALL_MENU_IDS.slice()">全选</button> <button type="button" class="btn btn-ghost btn-xs" @click="sel.access = allowedMenuIds.slice()">全选</button>
<button type="button" class="btn btn-ghost btn-xs" @click="sel.access = []">清空</button> <button type="button" class="btn btn-ghost btn-xs" @click="sel.access = []">清空</button>
</div> </div>
</div> </div>
<p class="text-xs text-slate-400 mb-3">管理员默认开放除「SaaS 管理 / 系统管理」以外的全部菜单(权限留空时按默认生效);代理/运营需显式勾选。</p> <p v-if="roleCeiling" class="text-xs text-slate-400 mb-3">该角色为外部账号,可见页面固定在下列范围内(留空即全部开放这些页面)。</p>
<div v-for="g in MENU_GROUPS" :key="g.label" class="mb-2.5"> <p v-else class="text-xs text-slate-400 mb-3">管理员默认开放除「SaaS 管理 / 系统管理」以外的全部菜单(权限留空时按默认生效);代理/运营需显式勾选。</p>
<div v-for="g in menuGroupsForRole" :key="g.label" class="mb-2.5">
<div class="text-xs text-slate-500 mb-1.5">{{ g.label }}<span v-if="g.restricted" class="text-amber-500 ml-1">(管理员默认不开放)</span></div> <div class="text-xs text-slate-500 mb-1.5">{{ g.label }}<span v-if="g.restricted" class="text-amber-500 ml-1">(管理员默认不开放)</span></div>
<div class="flex flex-wrap gap-2"> <div class="flex flex-wrap gap-2">
<label v-for="m in g.items" :key="m.id" class="chk"> <label v-for="m in g.items" :key="m.id" class="chk">
@ -218,7 +219,7 @@
import { ref, reactive, computed, watch, onMounted } from 'vue' import { ref, reactive, computed, watch, onMounted } from 'vue'
import { useApi } from '~/composables/useApi' import { useApi } from '~/composables/useApi'
import { useToast } from '~/composables/useToast' import { useToast } from '~/composables/useToast'
import { MENU_GROUPS, ALL_MENU_IDS, DEFAULT_ADMIN_ACCESS } from '~/utils/menus' import { MENU_GROUPS, ALL_MENU_IDS, DEFAULT_ADMIN_ACCESS, ROLE_ACCESS_CEILING } from '~/utils/menus'
import { REGION_OPTIONS } from '~/utils/regions' import { REGION_OPTIONS } from '~/utils/regions'
definePageMeta({ title: '后台账号' }) definePageMeta({ title: '后台账号' })
@ -273,6 +274,16 @@ const form = reactive({
brandid: 0, brandid: 0,
channelid: '', channelid: '',
}) })
// 角色菜单上限(品牌商/渠道商):编辑器只呈现该角色允许的页面,勾了上限外的也不会生效(见 stores/auth hasAccess)。
const roleCeiling = computed<string[] | null>(() => ROLE_ACCESS_CEILING[form.identity] ?? null)
const allowedMenuIds = computed<string[]>(() => roleCeiling.value ?? ALL_MENU_IDS)
const menuGroupsForRole = computed(() => {
const ceiling = roleCeiling.value
if (!ceiling) return MENU_GROUPS
return MENU_GROUPS
.map((g) => ({ ...g, items: g.items.filter((m) => ceiling.includes(m.id)) }))
.filter((g) => g.items.length > 0)
})
// 全量渠道商(含未启用),按所选品牌商过滤出下拉项 // 全量渠道商(含未启用),按所选品牌商过滤出下拉项
const channels = ref<ChannelItem[]>([]) const channels = ref<ChannelItem[]>([])
const accountChannelOptions = computed(() => const accountChannelOptions = computed(() =>
@ -380,9 +391,12 @@ function openEdit(a?: Account) {
view.value = 'form' view.value = 'form'
} }
// 切换角色时联动权限勾选:切到管理员且未勾选任何页面 → 预填默认集 // 切换角色时联动权限勾选:切到管理员且未勾选任何页面 → 预填默认集;
// 切到品牌商/渠道商 → 把已勾选项裁到该角色上限内(超出的勾了也不生效,留着只会误导)。
watch(() => form.identity, (idt) => { watch(() => form.identity, (idt) => {
if (idt === 2 && sel.access.length === 0) sel.access = DEFAULT_ADMIN_ACCESS.slice() if (idt === 2 && sel.access.length === 0) sel.access = DEFAULT_ADMIN_ACCESS.slice()
const ceiling = ROLE_ACCESS_CEILING[idt]
if (ceiling) sel.access = sel.access.filter((id) => ceiling.includes(id))
}) })
function closeEdit() { function closeEdit() {

12
apps/admin/app/pages/dashboard.vue

@ -6,7 +6,7 @@
<!-- 全局筛选条(应用/区域/产品,时间由各版面单独控制)--> <!-- 全局筛选条(应用/区域/产品,时间由各版面单独控制)-->
<div class="panel p-4 mb-5"> <div class="panel p-4 mb-5">
<div class="flex flex-wrap items-end gap-3"> <div class="flex flex-wrap items-end gap-3">
<div v-if="!IS_SCOPED" class="form-control"> <div v-if="!IS_SCOPED || appOptions.length" class="form-control">
<label class="label py-1"><span class="label-text text-xs text-slate-500">应用</span></label> <label class="label py-1"><span class="label-text text-xs text-slate-500">应用</span></label>
<select v-model="filters.app" class="select select-bordered select-sm w-40"> <select v-model="filters.app" class="select select-bordered select-sm w-40">
<option value="">全部应用</option> <option value="">全部应用</option>
@ -444,8 +444,14 @@ function renderChart(p: Panel, rows: any[]) {
async function initFilters() { async function initFilters() {
// 应用 // 应用
if (IS_SCOPED.value) { if (IS_SCOPED.value) {
// 品牌商/渠道商账号无权读应用注册表,也不按应用维度收敛——留「全部应用」即可。 // 品牌商/渠道商账号无权读应用注册表,改走 api_getmyapps:只列出「本品牌产品绑定过的应用」。
appOptions.value = [] // 产品一个都没绑应用时返回空 → 下拉整体隐藏,等同于「不按应用维度筛选」。
try {
const d = await webApi<{ apps: { name: string; app_name?: string }[] }>('getmyapps', {})
const list: { name: string; app_name?: string }[] = d?.apps ?? []
const names: string[] = [...new Set(list.map((a) => a.app_name || a.name).filter(Boolean))]
appOptions.value = names.map((n) => ({ value: n, label: n }))
} catch { appOptions.value = [] }
} else if (IS_AGENT.value) { } else if (IS_AGENT.value) {
// 代理只列绑定应用;"全部应用"复用模板里固定的空值项(选它=不传过滤,后端按账号绑定自动收敛为"我的全部") // 代理只列绑定应用;"全部应用"复用模板里固定的空值项(选它=不传过滤,后端按账号绑定自动收敛为"我的全部")
appOptions.value = BOUND_APPS.value.map((name) => ({ value: name, label: name })) appOptions.value = BOUND_APPS.value.map((name) => ({ value: name, label: name }))

51
apps/admin/app/pages/product.vue

@ -10,11 +10,11 @@
<div class="overflow-x-auto"> <div class="overflow-x-auto">
<table class="table table-zebra text-sm"> <table class="table table-zebra text-sm">
<thead> <thead>
<tr><th>ID</th><th>图片</th><th>名称</th><th>品牌商</th><th>类型</th><th>版本</th><th>功能</th><th>操作</th></tr> <tr><th>ID</th><th>图片</th><th>名称</th><th>品牌商</th><th>绑定应用</th><th>类型</th><th>版本</th><th>功能</th><th>操作</th></tr>
</thead> </thead>
<tbody> <tbody>
<tr v-if="loading"><td colspan="8" class="text-center py-8"><span class="loading loading-spinner loading-sm"></span></td></tr> <tr v-if="loading"><td colspan="9" class="text-center py-8"><span class="loading loading-spinner loading-sm"></span></td></tr>
<tr v-else-if="!rows.length"><td colspan="8" class="text-center text-slate-400 py-8">暂无数据</td></tr> <tr v-else-if="!rows.length"><td colspan="9" class="text-center text-slate-400 py-8">暂无数据</td></tr>
<tr v-for="p in rows" :key="p.id"> <tr v-for="p in rows" :key="p.id">
<td class="font-mono text-sm">{{ hexId(p.id) }}</td> <td class="font-mono text-sm">{{ hexId(p.id) }}</td>
<td> <td>
@ -25,6 +25,12 @@
</td> </td>
<td class="font-medium">{{ p.devicename }}</td> <td class="font-medium">{{ p.devicename }}</td>
<td>{{ brands[p.brandid] || '' }}</td> <td>{{ brands[p.brandid] || '' }}</td>
<td>
<div v-if="appNamesOf(p).length" class="flex flex-wrap gap-1">
<span v-for="n in appNamesOf(p)" :key="n" class="badge badge-ghost badge-sm">{{ n }}</span>
</div>
<span v-else class="text-slate-300 text-xs">未绑定</span>
</td>
<td><span class="badge badge-outline badge-sm">{{ deviceTypes[p.devicetype] || p.devicetype }}</span></td> <td><span class="badge badge-outline badge-sm">{{ deviceTypes[p.devicetype] || p.devicetype }}</span></td>
<td class="text-sm"><span v-if="p.version">{{ p.version }}</span><span v-else class="text-slate-300">-</span></td> <td class="text-sm"><span v-if="p.version">{{ p.version }}</span><span v-else class="text-slate-300">-</span></td>
<td><span class="text-xs text-slate-500">{{ featureCount(p) }}/14</span></td> <td><span class="text-xs text-slate-500">{{ featureCount(p) }}/14</span></td>
@ -70,6 +76,23 @@
</select> </select>
</div> </div>
</div> </div>
<!-- 绑定应用:决定该产品的数据算在哪个应用下,也决定品牌商/渠道商账号能选到哪些应用 -->
<div class="form-control mb-4">
<label class="label">
<span class="label-text font-medium">绑定应用</span>
<span class="label-text-alt text-slate-400">可多选;品牌商/渠道商账号的「应用」下拉只列出其产品绑定过的应用</span>
</label>
<div v-if="!appOptions.length" class="text-xs text-slate-400 border border-dashed border-slate-200 rounded-lg px-3 py-2">
暂无可选应用,请先到【SaaS 管理 → 应用中心】新建应用
</div>
<div v-else class="flex flex-wrap gap-2 border border-slate-200 rounded-lg px-3 py-2">
<label v-for="n in appOptions" :key="n" class="label cursor-pointer gap-2 py-1">
<input v-model="form.appnames" type="checkbox" :value="n" class="checkbox checkbox-sm checkbox-primary" />
<span class="label-text">{{ n }}</span>
</label>
</div>
</div>
<div class="grid grid-cols-2 gap-4 mb-4"> <div class="grid grid-cols-2 gap-4 mb-4">
<div class="form-control"> <div class="form-control">
<label class="label"><span class="label-text font-medium">扫描UUID</span></label> <label class="label"><span class="label-text font-medium">扫描UUID</span></label>
@ -235,13 +258,14 @@ interface Product {
id: number; devicename: string; brandid: number; devicetype: number id: number; devicename: string; brandid: number; devicetype: number
scanuuid: string; devicecodecount: number; productimage: string scanuuid: string; devicecodecount: number; productimage: string
channel: string; channelextra: string channel: string; channelextra: string
appnames?: string // 绑定应用名 CSV(空=未绑定)
bindrewardvpitime: number; bindrewardtranslate: number; bindrewardmeeting: number bindrewardvpitime: number; bindrewardtranslate: number; bindrewardmeeting: number
version?: string; versionid?: number; updatepackageaddress?: string version?: string; versionid?: number; updatepackageaddress?: string
[key: string]: unknown [key: string]: unknown
} }
interface Version { id: number; version: string; description: string; updatepackageaddress: string; productid: number } interface Version { id: number; version: string; description: string; updatepackageaddress: string; productid: number }
const { webApi, uploadFile } = useApi() const { webApi, consoleApi, uploadFile } = useApi()
const { success, error, warn } = useToast() const { success, error, warn } = useToast()
const deviceTypes: Record<number, string> = { 0: '未知', 1: '经典蓝牙', 2: 'BLE双端', 3: 'BLE单端', 4: '录音笔', 5: '智能眼镜', 6: '激活码卡片' } const deviceTypes: Record<number, string> = { 0: '未知', 1: '经典蓝牙', 2: 'BLE双端', 3: 'BLE单端', 4: '录音笔', 5: '智能眼镜', 6: '激活码卡片' }
@ -268,6 +292,8 @@ const view = ref<'list' | 'form' | 'version'>('list')
const rows = ref<Product[]>([]) const rows = ref<Product[]>([])
const brands = ref<Record<number, string>>({}) const brands = ref<Record<number, string>>({})
const brandOptions = ref<{ id: number; brand: string }[]>([]) const brandOptions = ref<{ id: number; brand: string }[]>([])
// 可绑定的应用名(应用中心 app_product.name);只有超管/管理员进得来产品页,直接调注册表接口取。
const appOptions = ref<string[]>([])
const loading = ref(false) const loading = ref(false)
const submitting = ref(false) const submitting = ref(false)
const isEditing = ref(false) const isEditing = ref(false)
@ -280,13 +306,16 @@ function emptyToggles(): Record<string, boolean> {
const form = reactive({ const form = reactive({
id: 0, devicename: '', brandid: 0, devicetype: 0, scanuuid: '', devicecodecount: 1, id: 0, devicename: '', brandid: 0, devicetype: 0, scanuuid: '', devicecodecount: 1,
productimage: '', channel: 'official', productimage: '', channel: 'official', appnames: [] as string[],
bindrewardvpitime: 0, bindrewardtranslate: 0, bindrewardmeeting: 0, bindrewardvpitime: 0, bindrewardtranslate: 0, bindrewardmeeting: 0,
toggles: emptyToggles() as Record<string, boolean>, toggles: emptyToggles() as Record<string, boolean>,
}) })
const mobileExtra = reactive({ platform_id: '', platform_key: '', tui: '' }) const mobileExtra = reactive({ platform_id: '', platform_key: '', tui: '' })
function hexId(id: number) { return id ? Number(id).toString(16).toUpperCase() : '' } function hexId(id: number) { return id ? Number(id).toString(16).toUpperCase() : '' }
function appNamesOf(p: Product): string[] {
return String(p.appnames || '').split(',').map((s) => s.trim()).filter(Boolean)
}
function featureCount(p: Product) { return toggleFields.filter((t) => !!p[t.key]).length } function featureCount(p: Product) { return toggleFields.filter((t) => !!p[t.key]).length }
// ── 列表 ── // ── 列表 ──
@ -314,10 +343,19 @@ async function loadBrands() {
} catch { brandOptions.value = [] } } catch { brandOptions.value = [] }
} }
// 应用候选取自应用中心(console/api/products/list,即 app_product 表),与部署无关,只按应用名绑。
async function loadAppOptions() {
try {
const list = await consoleApi<{ name: string; enabled?: boolean }[]>('products/list', {})
appOptions.value = (list ?? []).map((a) => a.name).filter(Boolean)
} catch { appOptions.value = [] }
}
function showList() { view.value = 'list'; loadData() } function showList() { view.value = 'list'; loadData() }
function showForm(p?: Product) { function showForm(p?: Product) {
loadBrands() loadBrands()
loadAppOptions()
if (p) { if (p) {
isEditing.value = true isEditing.value = true
form.id = p.id form.id = p.id
@ -328,6 +366,7 @@ function showForm(p?: Product) {
form.devicecodecount = p.devicecodecount === 2 ? 2 : 1 form.devicecodecount = p.devicecodecount === 2 ? 2 : 1
form.productimage = p.productimage || '' form.productimage = p.productimage || ''
form.channel = p.channel || 'official' form.channel = p.channel || 'official'
form.appnames = appNamesOf(p)
form.bindrewardvpitime = p.bindrewardvpitime || 0 form.bindrewardvpitime = p.bindrewardvpitime || 0
form.bindrewardtranslate = p.bindrewardtranslate || 0 form.bindrewardtranslate = p.bindrewardtranslate || 0
form.bindrewardmeeting = p.bindrewardmeeting || 0 form.bindrewardmeeting = p.bindrewardmeeting || 0
@ -347,6 +386,7 @@ function showForm(p?: Product) {
form.devicecodecount = 1 form.devicecodecount = 1
form.productimage = '' form.productimage = ''
form.channel = 'official' form.channel = 'official'
form.appnames = []
form.bindrewardvpitime = 0 form.bindrewardvpitime = 0
form.bindrewardtranslate = 0 form.bindrewardtranslate = 0
form.bindrewardmeeting = 0 form.bindrewardmeeting = 0
@ -374,6 +414,7 @@ async function saveProduct() {
productimage: form.productimage, productimage: form.productimage,
channel: form.channel, channel: form.channel,
channelextra, channelextra,
appnames: form.appnames.join(','),
bindrewardvpitime: Number(form.bindrewardvpitime) || 0, bindrewardvpitime: Number(form.bindrewardvpitime) || 0,
bindrewardtranslate: Number(form.bindrewardtranslate) || 0, bindrewardtranslate: Number(form.bindrewardtranslate) || 0,
bindrewardmeeting: Number(form.bindrewardmeeting) || 0, bindrewardmeeting: Number(form.bindrewardmeeting) || 0,

17
apps/admin/app/pages/users.vue

@ -273,11 +273,18 @@ function buildAppSelect() {
// ---- 初始化:加载启用的注册应用 ---- // ---- 初始化:加载启用的注册应用 ----
async function loadApps() { async function loadApps() {
// 代理无权调 apps/list(403),用登录下发的绑定应用(含注册 id/region) // 超管/管理员之外的角色(代理/运营/品牌商/渠道商)无权调 apps/list(403),改走 api_getmyapps:
if (auth.identity === 3) { // 后端按账号绑定下发可选部署——品牌商/渠道商即「名下产品绑定过的应用」。
apps.value = (auth.appbinds || []).map((a) => ({ // 接口失败时退回登录时下发的 appbinds(同源,只是不含产品绑定的最新变化)。
id: a.id, name: a.name, app_name: a.app_name, region: a.region, enabled: true, if (!auth.isAdmin) {
})) try {
const d = await webApi<{ apps: AppItem[] }>('getmyapps', {})
apps.value = d?.apps ?? []
} catch {
apps.value = (auth.appbinds || []).map((a) => ({
id: a.id, name: a.name, app_name: a.app_name, region: a.region, enabled: true,
}))
}
buildAppSelect() buildAppSelect()
return return
} }

13
apps/admin/app/stores/auth.ts

@ -1,5 +1,5 @@
import { defineStore } from 'pinia' import { defineStore } from 'pinia'
import { DEFAULT_ADMIN_ACCESS, DEFAULT_BRAND_ACCESS, DEFAULT_DEALER_ACCESS } from '~/utils/menus' import { DEFAULT_ADMIN_ACCESS, ROLE_ACCESS_CEILING } from '~/utils/menus'
export const IDENTITY_LABELS: Record<number, string> = { export const IDENTITY_LABELS: Record<number, string> = {
1: '超管', 1: '超管',
@ -209,11 +209,12 @@ export const useAuthStore = defineStore('auth', {
if (this.identity === IDENTITY_MANAGER && this.access.length === 0) { if (this.identity === IDENTITY_MANAGER && this.access.length === 0) {
return DEFAULT_ADMIN_ACCESS.includes(pageId) return DEFAULT_ADMIN_ACCESS.includes(pageId)
} }
// 品牌商/渠道商账号未显式配置权限时,按各自的默认页面集放行, // 品牌商/渠道商账号:可见页面不允许超出角色上限(品牌商=仪表盘/渠道商管理/用户查询/月结算,
// 免得新开的账号忘了勾权限就空白一片。 // 渠道商=仪表盘/用户查询/月结算)。未显式勾权限时上限即默认集,免得新开的账号空白一片。
if (this.access.length === 0) { const ceiling = ROLE_ACCESS_CEILING[this.identity]
if (this.identity === IDENTITY_BRAND) return DEFAULT_BRAND_ACCESS.includes(pageId) if (ceiling) {
if (this.identity === IDENTITY_DEALER) return DEFAULT_DEALER_ACCESS.includes(pageId) if (!ceiling.includes(pageId)) return false
if (this.access.length === 0) return true
} }
return this.access.includes(pageId) return this.access.includes(pageId)
}, },

8
apps/admin/app/utils/menus.ts

@ -94,6 +94,14 @@ export const DEFAULT_BRAND_ACCESS: string[] = ['dashboard', 'channel', 'user', '
// 渠道商账号(identity=5)默认页面集:只看自己渠道的数据与结算单,不含渠道商管理。 // 渠道商账号(identity=5)默认页面集:只看自己渠道的数据与结算单,不含渠道商管理。
export const DEFAULT_DEALER_ACCESS: string[] = ['dashboard', 'user', 'settlement'] export const DEFAULT_DEALER_ACCESS: string[] = ['dashboard', 'user', 'settlement']
// 角色菜单上限:品牌商/渠道商账号是外部角色,可见页面不允许超出各自默认集——
// 即便账号里存了更多 access(历史数据或误勾),也一律按上限收敛。
// 未列出的角色(管理员/运营)不设上限,按显式勾选生效。
export const ROLE_ACCESS_CEILING: Record<number, string[]> = {
3: DEFAULT_BRAND_ACCESS,
5: DEFAULT_DEALER_ACCESS,
}
// 按路由路径反查菜单项(前缀匹配,取最长命中,供路由守卫用)。 // 按路由路径反查菜单项(前缀匹配,取最长命中,供路由守卫用)。
export function menuItemByPath(path: string): MenuItem | null { export function menuItemByPath(path: string): MenuItem | null {
let best: MenuItem | null = null let best: MenuItem | null = null

2
apps/admin/.output/public/_nuxt/CUR2rcGX.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/0CGOegeu.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/ChqjEN2N.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/32XpWsQL.js

File diff suppressed because one or more lines are too long

1
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/32rNuZwS.js

File diff suppressed because one or more lines are too long

6
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/DSy_gLdM.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/6O01ZZML.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/Bp86Q8ON.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/AeilnnXP.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BSO50kj0.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/B-G7qD0T.js

File diff suppressed because one or more lines are too long

1
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BAkLwAvM.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/DhKR78CK.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BCmMvQNl.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/D5UrQ7F3.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BIYq6SKh.js

@ -1 +1 @@
import{_ as t,o,c as s,R as c}from"./DSy_gLdM.js";const r={},a={class:"min-h-screen","data-theme":"corporate"};function n(e,_){return o(),s("div",a,[c(e.$slots,"default")])}const l=t(r,[["render",n]]);export{l as default}; import{_ as t,o,c as s,S as c}from"./6O01ZZML.js";const r={},a={class:"min-h-screen","data-theme":"corporate"};function n(e,_){return o(),s("div",a,[c(e.$slots,"default")])}const l=t(r,[["render",n]]);export{l as default};

1
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BNW9rRgN.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/B8hrjpgL.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BSXoR6Yx.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/Bad2XFSd.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BZR1IKC1.js

File diff suppressed because one or more lines are too long

1
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BgasD__e.js

@ -0,0 +1 @@
import{e as y,aa as h,ab as w,A as g,j as d,k as b}from"./6O01ZZML.js";const k="$s";function A(...t){const s=typeof t[t.length-1]=="string"?t.pop():void 0;typeof t[0]!="string"&&t.unshift(s);const[a,o]=t;if(!a||typeof a!="string")throw new TypeError("[nuxt] [useState] key must be a string: "+a);if(o!==void 0&&typeof o!="function")throw new Error("[nuxt] [useState] init must be a function: "+o);const i=k+a,r=y(),n=h(r.payload.state,i);if(o&&(r._state[i]??={_default:o}),n.value===void 0&&o){const e=o();if(w(e))return r.payload.state[i]=e,e;n.value=e}return n}function m(){const t=A("app:loading",()=>0),s=g(()=>t.value>0);function a(){t.value++}function o(){t.value=Math.max(0,t.value-1)}return{count:t,loading:s,begin:a,end:o}}async function f(t,s,a){const o=d(),i=b(),r={"Content-Type":"application/json"};o.token&&(r.Authorization=o.token),a&&Object.assign(r,a);const n=await fetch(t,{method:"POST",headers:r,body:JSON.stringify(s)});if(!n.ok)throw new Error(`HTTP error: ${n.status}`);const e=await n.json();if(e.code===18)throw o.logout(),i.push("/"),new Error(e.msg||"Unauthorized");if(e.code!==0)throw new Error(e.msg||"Unknown error");return e.data}const S=/^(get|list|load|query|fetch|search|count|stat|export|check)/i;function v(t){return!S.test(t)}function x(){const t=d(),{begin:s,end:a}=m();async function o(n,e){const u={};if(t.currentAppId&&(u["X-App-Id"]=String(t.currentAppId)),!v(n))return f(`/web/api/api_${n}`,e??{},u);s();try{return await f(`/web/api/api_${n}`,e??{},u)}finally{a()}}async function i(n,e){return f(`/console/api/${n}`,e??{})}async function r(n,e){const u=n.type||"application/octet-stream",c=await o("getcostoken",{path:e,filename:n.name,content_type:u}),p=c.upload_url||c.url||"";if(!p)throw new Error("未获取到上传地址:请确认已在【第三方服务配置→存储】配置并启用「阿里云 OSS」");const l=await fetch(p,{method:"PUT",headers:{"Content-Type":u},body:n});if(!l.ok)throw new Error(`Upload failed: ${l.status}`);return c.url||p.split("?")[0]}return{webApi:o,consoleApi:i,uploadFile:r}}export{m as a,A as b,x as u};

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/yis2MfHE.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BqBJfKQo.js

File diff suppressed because one or more lines are too long

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/D4Um3zt0.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BrJ9pewm.js

@ -1 +1 @@
import{L as y,l as x}from"./DD3V9C6_.js";import{g as V,c as t,F as u,a as l,n as C,r,l as g,t as o,A as h,o as s,d as B,_ as N}from"./DSy_gLdM.js";const L={class:"lang-select"},O={class:"lang-chip-name"},S=["onClick"],j={key:0,class:"lang-empty"},A={key:0,class:"lang-dd"},F={class:"lang-dd-sum"},I={class:"lang-dd-panel"},T=["checked","onChange"],$={class:"lang-opt-code"},w={class:"lang-opt-name"},z=["value","disabled"],D=["value"],E=V({__name:"LangSelect",props:{modelValue:{},multiple:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},options:{default:void 0}},emits:["update:modelValue"],setup(c,{emit:f}){const d=c,m=f,p=h(()=>d.options&&d.options.length?d.options:y),i=h(()=>(d.modelValue||"").split(",").map(a=>a.trim()).filter(Boolean));function v(a){return x(a)}function _(a){if(d.disabled)return;const n=i.value.slice(),e=n.indexOf(a);e>=0?n.splice(e,1):n.push(a),m("update:modelValue",n.join(","))}function b(a){m("update:modelValue",a.target.value)}return(a,n)=>(s(),t("div",L,[c.multiple?(s(),t(u,{key:0},[l("div",{class:C(["lang-chips",{"lang-disabled":c.disabled}])},[(s(!0),t(u,null,r(i.value,e=>(s(),t("span",{key:e,class:"lang-chip"},[B(o(e),1),l("span",O,o(v(e)),1),l("button",{type:"button",class:"lang-x",onClick:k=>_(e)},"×",8,S)]))),128)),i.value.length?g("",!0):(s(),t("span",j,"未选择语言"))],2),c.disabled?g("",!0):(s(),t("details",A,[l("summary",F,"+ 选择语言(已选 "+o(i.value.length)+")",1),l("div",I,[(s(!0),t(u,null,r(p.value,e=>(s(),t("label",{key:e.code,class:"lang-opt"},[l("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary",checked:i.value.includes(e.code),onChange:k=>_(e.code)},null,40,T),l("span",$,o(e.code),1),l("span",w,o(e.name),1)]))),128))])]))],64)):(s(),t("select",{key:1,class:"select select-bordered select-sm w-full text-xs",value:c.modelValue,disabled:c.disabled,onChange:b},[n[0]||(n[0]=l("option",{value:""},"(未设置)",-1)),(s(!0),t(u,null,r(p.value,e=>(s(),t("option",{key:e.code,value:e.code},o(e.code)+" · "+o(e.name),9,D))),128))],40,z))]))}}),q=Object.assign(N(E,[["__scopeId","data-v-4903af59"]]),{__name:"LangSelect"});export{q as _}; import{L as y,l as x}from"./DD3V9C6_.js";import{g as V,c as t,F as u,a as l,n as C,r,l as g,t as o,A as h,o as s,d as B,_ as N}from"./6O01ZZML.js";const L={class:"lang-select"},O={class:"lang-chip-name"},S=["onClick"],j={key:0,class:"lang-empty"},A={key:0,class:"lang-dd"},F={class:"lang-dd-sum"},I={class:"lang-dd-panel"},T=["checked","onChange"],$={class:"lang-opt-code"},w={class:"lang-opt-name"},z=["value","disabled"],D=["value"],E=V({__name:"LangSelect",props:{modelValue:{},multiple:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},options:{default:void 0}},emits:["update:modelValue"],setup(c,{emit:f}){const d=c,m=f,p=h(()=>d.options&&d.options.length?d.options:y),i=h(()=>(d.modelValue||"").split(",").map(a=>a.trim()).filter(Boolean));function v(a){return x(a)}function _(a){if(d.disabled)return;const n=i.value.slice(),e=n.indexOf(a);e>=0?n.splice(e,1):n.push(a),m("update:modelValue",n.join(","))}function b(a){m("update:modelValue",a.target.value)}return(a,n)=>(s(),t("div",L,[c.multiple?(s(),t(u,{key:0},[l("div",{class:C(["lang-chips",{"lang-disabled":c.disabled}])},[(s(!0),t(u,null,r(i.value,e=>(s(),t("span",{key:e,class:"lang-chip"},[B(o(e),1),l("span",O,o(v(e)),1),l("button",{type:"button",class:"lang-x",onClick:k=>_(e)},"×",8,S)]))),128)),i.value.length?g("",!0):(s(),t("span",j,"未选择语言"))],2),c.disabled?g("",!0):(s(),t("details",A,[l("summary",F,"+ 选择语言(已选 "+o(i.value.length)+")",1),l("div",I,[(s(!0),t(u,null,r(p.value,e=>(s(),t("label",{key:e.code,class:"lang-opt"},[l("input",{type:"checkbox",class:"checkbox checkbox-xs checkbox-primary",checked:i.value.includes(e.code),onChange:k=>_(e.code)},null,40,T),l("span",$,o(e.code),1),l("span",w,o(e.name),1)]))),128))])]))],64)):(s(),t("select",{key:1,class:"select select-bordered select-sm w-full text-xs",value:c.modelValue,disabled:c.disabled,onChange:b},[n[0]||(n[0]=l("option",{value:""},"(未设置)",-1)),(s(!0),t(u,null,r(p.value,e=>(s(),t("option",{key:e.code,value:e.code},o(e.code)+" · "+o(e.name),9,D))),128))],40,z))]))}}),q=Object.assign(N(E,[["__scopeId","data-v-4903af59"]]),{__name:"LangSelect"});export{q as _};

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/obp34o1K.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/BvvkbLjV.js

@ -1 +1 @@
import{u as a,e as s,h as u,i as r,f as h}from"./DSy_gLdM.js";function i(t){const e=t||s();return e.ssrContext?.head||e.runWithContext(()=>{if(u()){const n=r(h);if(!n)throw new Error("[nuxt] [unhead] Missing Unhead instance.");return n}})}function d(t,e={}){const n=e.head||i(e.nuxt);return a(t,{head:n,...e})}export{d as u}; import{u as a,e as s,h as u,i as r,f as h}from"./6O01ZZML.js";function i(t){const e=t||s();return e.ssrContext?.head||e.runWithContext(()=>{if(u()){const n=r(h);if(!n)throw new Error("[nuxt] [unhead] Missing Unhead instance.");return n}})}function d(t,e={}){const n=e.head||i(e.nuxt);return a(t,{head:n,...e})}export{d as u};

2
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/w_7nuVJ9.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/C8kc9IUa.js

File diff suppressed because one or more lines are too long

1
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/C9zSjFPi.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/DlgycG-C.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/CAhwHUW5.js

@ -1,4 +1,4 @@
import{g as G,C as K,Q as P,c as a,a as e,d as u,q as g,s as U,F as f,r as B,v as Q,x as Y,t as n,y as i,A as E,o,n as F,l as A,_ as Z}from"./DSy_gLdM.js";import{u as J}from"./NtXZuCUg.js";import{u as W}from"./EeX3zgoF.js";const X=globalThis.setInterval,$={class:"flex items-center justify-between mb-4 flex-wrap gap-3"},tt={class:"flex items-center gap-2 flex-wrap"},et=["value"],st={class:"flex items-center gap-1 text-xs text-slate-500 cursor-pointer"},lt={class:"flex items-center gap-4 mb-3 text-xs text-slate-500"},nt={class:"text-slate-700"},at={class:"text-slate-700"},ot={class:"text-slate-700"},rt={class:"muted"},ut={class:"panel overflow-hidden"},it={id:"logBody",style:{"max-height":"calc(100vh - 230px)","overflow-y":"auto"}},ct={key:0,class:"text-center text-slate-400 py-10"},dt={key:1,class:"text-center text-red-400 py-10"},vt={key:2,class:"text-center text-slate-400 py-10"},pt={class:"t"},mt={class:"app-name"},ft={key:0,class:"unreg",title:"该应用名未在 console 注册,快照已收到但不会写入统计库"},_t={key:1,class:"muted"},gt={class:"muted"},xt={class:"muted"},yt={class:"muted"},bt={class:"muted"},ht={key:0,class:"muted"},wt={class:"t"},kt={key:0,class:"late"},Ct=G({__name:"statlog",setup(Tt){const{webApi:I}=J(),{success:O,error:R}=W(),H={cn:"中国",us:"美国",ea:"东亚",sea:"东南亚",sa:"南亚",me:"中东",eu:"欧洲",ru:"俄罗斯",af:"非洲",sam:"南美",nam:"北美",oc:"大洋洲",br:"巴西",in:"印度"};function D(l){return l?H[l]||l:"-"}const c=i([]),x=i(!1),_=i(""),L=i("-"),N=i("-"),y=i(""),v=i(0),b=i(""),h=i(""),w=i(!1);let d=null;function p(l=0){const s=new Date(Date.now()+l*864e5),t=new Intl.DateTimeFormat("en-CA",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit"}).format(s);return parseInt(t.replace(/-/g,""),10)}function k(l){const s=""+l;return s.length===8?s.slice(0,4)+"-"+s.slice(4,6)+"-"+s.slice(6,8):s}function C(l){if(!l)return"--";const s=new Date(l*1e3),t=r=>r<10?"0"+r:""+r;return t(s.getHours())+":"+t(s.getMinutes())+":"+t(s.getSeconds())}function S(l){return l?"0x"+(l>>>0).toString(16).toUpperCase():"全部"}const V=E(()=>[{value:p(0),label:"今天 "+k(p(0))},{value:p(-1),label:"昨天 "+k(p(-1))}]);function M(l){return l==="error"?{cls:"lv-error",txt:"解析失败"}:l==="warn"?{cls:"lv-warn",txt:"未落库"}:{cls:"lv-info",txt:"已落库"}}function j(l){return!!(l.snap_ts&&l.ts&&l.ts-l.snap_ts>120)}const T=E(()=>{const l=b.value,s=h.value.trim().toLowerCase();return c.value.filter(t=>!(l&&t.level!==l||s&&((t.app||"")+" "+(t.region||"")+" "+D(t.region)+" "+(t.product_id||"")+" "+S(t.product_id)+" "+(t.channel_id||"")+" "+(t.stat_day||"")).toLowerCase().indexOf(s)<0))});async function m(){x.value=!0,_.value="";try{const l=await I("getstatlogs",{day:v.value||0});c.value=l?.entries||[],L.value=l?.total!=null?l.total:c.value.length,N.value=c.value.length?C(c.value[0].ts):"--"}catch(l){_.value=l?.message||"网络异常"}finally{x.value=!1}}async function q(){const l=v.value||0,s=V.value.find(r=>r.value===l),t=s?s.label:""+l;if(window.confirm("确定清空「"+t+`」的接收流水吗? import{g as G,C as K,Q as P,c as a,a as e,d as u,q as g,s as U,F as f,r as B,v as Q,x as Y,t as n,y as i,A as E,o,n as F,l as A,_ as Z}from"./6O01ZZML.js";import{u as J}from"./BgasD__e.js";import{u as W}from"./xsgK-Nup.js";const X=globalThis.setInterval,$={class:"flex items-center justify-between mb-4 flex-wrap gap-3"},tt={class:"flex items-center gap-2 flex-wrap"},et=["value"],st={class:"flex items-center gap-1 text-xs text-slate-500 cursor-pointer"},lt={class:"flex items-center gap-4 mb-3 text-xs text-slate-500"},nt={class:"text-slate-700"},at={class:"text-slate-700"},ot={class:"text-slate-700"},rt={class:"muted"},ut={class:"panel overflow-hidden"},it={id:"logBody",style:{"max-height":"calc(100vh - 230px)","overflow-y":"auto"}},ct={key:0,class:"text-center text-slate-400 py-10"},dt={key:1,class:"text-center text-red-400 py-10"},vt={key:2,class:"text-center text-slate-400 py-10"},pt={class:"t"},mt={class:"app-name"},ft={key:0,class:"unreg",title:"该应用名未在 console 注册,快照已收到但不会写入统计库"},_t={key:1,class:"muted"},gt={class:"muted"},xt={class:"muted"},yt={class:"muted"},bt={class:"muted"},ht={key:0,class:"muted"},wt={class:"t"},kt={key:0,class:"late"},Ct=G({__name:"statlog",setup(Tt){const{webApi:I}=J(),{success:O,error:R}=W(),H={cn:"中国",us:"美国",ea:"东亚",sea:"东南亚",sa:"南亚",me:"中东",eu:"欧洲",ru:"俄罗斯",af:"非洲",sam:"南美",nam:"北美",oc:"大洋洲",br:"巴西",in:"印度"};function D(l){return l?H[l]||l:"-"}const c=i([]),x=i(!1),_=i(""),L=i("-"),N=i("-"),y=i(""),v=i(0),b=i(""),h=i(""),w=i(!1);let d=null;function p(l=0){const s=new Date(Date.now()+l*864e5),t=new Intl.DateTimeFormat("en-CA",{timeZone:"Asia/Shanghai",year:"numeric",month:"2-digit",day:"2-digit"}).format(s);return parseInt(t.replace(/-/g,""),10)}function k(l){const s=""+l;return s.length===8?s.slice(0,4)+"-"+s.slice(4,6)+"-"+s.slice(6,8):s}function C(l){if(!l)return"--";const s=new Date(l*1e3),t=r=>r<10?"0"+r:""+r;return t(s.getHours())+":"+t(s.getMinutes())+":"+t(s.getSeconds())}function S(l){return l?"0x"+(l>>>0).toString(16).toUpperCase():"全部"}const V=E(()=>[{value:p(0),label:"今天 "+k(p(0))},{value:p(-1),label:"昨天 "+k(p(-1))}]);function M(l){return l==="error"?{cls:"lv-error",txt:"解析失败"}:l==="warn"?{cls:"lv-warn",txt:"未落库"}:{cls:"lv-info",txt:"已落库"}}function j(l){return!!(l.snap_ts&&l.ts&&l.ts-l.snap_ts>120)}const T=E(()=>{const l=b.value,s=h.value.trim().toLowerCase();return c.value.filter(t=>!(l&&t.level!==l||s&&((t.app||"")+" "+(t.region||"")+" "+D(t.region)+" "+(t.product_id||"")+" "+S(t.product_id)+" "+(t.channel_id||"")+" "+(t.stat_day||"")).toLowerCase().indexOf(s)<0))});async function m(){x.value=!0,_.value="";try{const l=await I("getstatlogs",{day:v.value||0});c.value=l?.entries||[],L.value=l?.total!=null?l.total:c.value.length,N.value=c.value.length?C(c.value[0].ts):"--"}catch(l){_.value=l?.message||"网络异常"}finally{x.value=!1}}async function q(){const l=v.value||0,s=V.value.find(r=>r.value===l),t=s?s.label:""+l;if(window.confirm("确定清空「"+t+`」的接收流水吗?
只清除本核对面板的记录,不影响已落库的统计数据。 只清除本核对面板的记录,不影响已落库的统计数据。
清空后可重新触发埋点,观察是否正常进来。`))try{const r=await I("clearstatlogs",{day:l});O("已清空 "+(r&&r.cleared!=null?r.cleared:0)+" 条"),m()}catch(r){R("清空失败:"+(r?.message||"网络异常"))}}function z(){w.value?(d=X(m,15e3),y.value="· 每 15 秒自动刷新"):(d&&clearInterval(d),d=null,y.value="")}return K(()=>{v.value=p(0),m()}),P(()=>{d&&clearInterval(d)}),(l,s)=>(o(),a("div",null,[e("div",$,[s[6]||(s[6]=e("div",null,[e("h2",{class:"text-lg font-bold text-slate-700"},"统计日志"),e("p",{class:"text-xs text-slate-400 mt-0.5"},[u("console 从 NATS 收到的「当日统计快照」接收流水(最新在前,按接收时间分天存 Redis)。各业务部署每个同步周期/启动时/0点 推送一次当日绝对快照,console 收到后覆盖落库。用于核对每个部署是否在正常汇报;带 "),e("span",{class:"unreg"},"未注册"),u(" 的应用快照已收到但"),e("b",null,"不会落库"),u("(应用名需与 console 注册表完全一致)。")])],-1)),e("div",tt,[g(e("select",{"onUpdate:modelValue":s[0]||(s[0]=t=>v.value=t),class:"select select-bordered select-sm",onChange:m},[(o(!0),a(f,null,B(V.value,t=>(o(),a("option",{key:t.value,value:t.value},n(t.label),9,et))),128))],544),[[U,v.value,void 0,{number:!0}]]),g(e("select",{"onUpdate:modelValue":s[1]||(s[1]=t=>b.value=t),class:"select select-bordered select-sm"},[...s[4]||(s[4]=[e("option",{value:""},"全部级别",-1),e("option",{value:"info"},"已落库",-1),e("option",{value:"warn"},"未落库",-1),e("option",{value:"error"},"解析失败",-1)])],512),[[U,b.value]]),g(e("input",{"onUpdate:modelValue":s[2]||(s[2]=t=>h.value=t),class:"input input-bordered input-sm w-44",placeholder:"筛选 应用/区域/产品/渠道商"},null,512),[[Q,h.value]]),e("label",st,[g(e("input",{"onUpdate:modelValue":s[3]||(s[3]=t=>w.value=t),type:"checkbox",class:"checkbox checkbox-xs",onChange:z},null,544),[[Y,w.value]]),s[5]||(s[5]=u(" 自动刷新 ",-1))]),e("button",{class:"btn btn-primary btn-sm text-white",onClick:m},"刷新"),e("button",{class:"btn btn-outline btn-error btn-sm",title:"清空本日核对流水(不影响已落库的统计数据),清空后可重新观察埋点是否正常进来",onClick:q},"清空本日")])]),e("div",lt,[e("span",null,[s[7]||(s[7]=u("该日保留 ",-1)),e("b",nt,n(L.value),1),s[8]||(s[8]=u(" 条",-1))]),e("span",null,[s[9]||(s[9]=u("当前显示 ",-1)),e("b",at,n(T.value.length),1),s[10]||(s[10]=u(" 条",-1))]),e("span",null,[s[11]||(s[11]=u("最近接收 ",-1)),e("b",ot,n(N.value),1)]),e("span",rt,n(y.value),1)]),e("div",ut,[s[12]||(s[12]=e("div",{id:"logHead"},[e("div",null,"接收时间"),e("div",null,"级别"),e("div",null,"应用 · 区域 · 产品 · 渠道商"),e("div",null,"统计日"),e("div",null,"指标摘要 / 说明"),e("div",null,"快照时间")],-1)),e("div",it,[x.value?(o(),a("div",ct,"加载中...")):_.value?(o(),a("div",dt,"加载失败:"+n(_.value),1)):T.value.length?(o(!0),a(f,{key:3},B(T.value,(t,r)=>(o(),a("div",{key:r,class:"logrow"},[e("div",pt,n(C(t.ts)),1),e("div",null,[e("span",{class:F(["lv",M(t.level).cls])},n(M(t.level).txt),3)]),e("div",null,[t.app?(o(),a(f,{key:0},[e("span",mt,n(t.app),1),t.registered?A("",!0):(o(),a("span",ft,"未注册"))],64)):(o(),a("span",_t,"(无应用名)")),e("span",gt," · "+n(D(t.region)),1),e("span",xt," · "+n(S(t.product_id)),1),e("span",yt," · "+n(t.channel_id||"未分配渠道"),1)]),e("div",bt,n(t.stat_day?k(t.stat_day):"-"),1),e("div",null,[t.msg?(o(),a(f,{key:0},[e("span",{class:F(t.level==="error"?"text-red-600":"text-amber-600")},n(t.msg),3),t.summary?(o(),a("span",ht," · "+n(t.summary),1)):A("",!0)],64)):(o(),a(f,{key:1},[u(n(t.summary||"无增量"),1)],64))]),e("div",wt,[u(n(C(t.snap_ts)),1),j(t)?(o(),a("span",kt,"迟到"+n(t.ts-t.snap_ts)+"s",1)):A("",!0)])]))),128)):(o(),a("div",vt,n(c.value.length?"无匹配记录":"该日暂无接收记录"),1))])])]))}}),Lt=Z(Ct,[["__scopeId","data-v-e7a3debc"]]);export{Lt as default}; 清空后可重新触发埋点,观察是否正常进来。`))try{const r=await I("clearstatlogs",{day:l});O("已清空 "+(r&&r.cleared!=null?r.cleared:0)+" 条"),m()}catch(r){R("清空失败:"+(r?.message||"网络异常"))}}function z(){w.value?(d=X(m,15e3),y.value="· 每 15 秒自动刷新"):(d&&clearInterval(d),d=null,y.value="")}return K(()=>{v.value=p(0),m()}),P(()=>{d&&clearInterval(d)}),(l,s)=>(o(),a("div",null,[e("div",$,[s[6]||(s[6]=e("div",null,[e("h2",{class:"text-lg font-bold text-slate-700"},"统计日志"),e("p",{class:"text-xs text-slate-400 mt-0.5"},[u("console 从 NATS 收到的「当日统计快照」接收流水(最新在前,按接收时间分天存 Redis)。各业务部署每个同步周期/启动时/0点 推送一次当日绝对快照,console 收到后覆盖落库。用于核对每个部署是否在正常汇报;带 "),e("span",{class:"unreg"},"未注册"),u(" 的应用快照已收到但"),e("b",null,"不会落库"),u("(应用名需与 console 注册表完全一致)。")])],-1)),e("div",tt,[g(e("select",{"onUpdate:modelValue":s[0]||(s[0]=t=>v.value=t),class:"select select-bordered select-sm",onChange:m},[(o(!0),a(f,null,B(V.value,t=>(o(),a("option",{key:t.value,value:t.value},n(t.label),9,et))),128))],544),[[U,v.value,void 0,{number:!0}]]),g(e("select",{"onUpdate:modelValue":s[1]||(s[1]=t=>b.value=t),class:"select select-bordered select-sm"},[...s[4]||(s[4]=[e("option",{value:""},"全部级别",-1),e("option",{value:"info"},"已落库",-1),e("option",{value:"warn"},"未落库",-1),e("option",{value:"error"},"解析失败",-1)])],512),[[U,b.value]]),g(e("input",{"onUpdate:modelValue":s[2]||(s[2]=t=>h.value=t),class:"input input-bordered input-sm w-44",placeholder:"筛选 应用/区域/产品/渠道商"},null,512),[[Q,h.value]]),e("label",st,[g(e("input",{"onUpdate:modelValue":s[3]||(s[3]=t=>w.value=t),type:"checkbox",class:"checkbox checkbox-xs",onChange:z},null,544),[[Y,w.value]]),s[5]||(s[5]=u(" 自动刷新 ",-1))]),e("button",{class:"btn btn-primary btn-sm text-white",onClick:m},"刷新"),e("button",{class:"btn btn-outline btn-error btn-sm",title:"清空本日核对流水(不影响已落库的统计数据),清空后可重新观察埋点是否正常进来",onClick:q},"清空本日")])]),e("div",lt,[e("span",null,[s[7]||(s[7]=u("该日保留 ",-1)),e("b",nt,n(L.value),1),s[8]||(s[8]=u(" 条",-1))]),e("span",null,[s[9]||(s[9]=u("当前显示 ",-1)),e("b",at,n(T.value.length),1),s[10]||(s[10]=u(" 条",-1))]),e("span",null,[s[11]||(s[11]=u("最近接收 ",-1)),e("b",ot,n(N.value),1)]),e("span",rt,n(y.value),1)]),e("div",ut,[s[12]||(s[12]=e("div",{id:"logHead"},[e("div",null,"接收时间"),e("div",null,"级别"),e("div",null,"应用 · 区域 · 产品 · 渠道商"),e("div",null,"统计日"),e("div",null,"指标摘要 / 说明"),e("div",null,"快照时间")],-1)),e("div",it,[x.value?(o(),a("div",ct,"加载中...")):_.value?(o(),a("div",dt,"加载失败:"+n(_.value),1)):T.value.length?(o(!0),a(f,{key:3},B(T.value,(t,r)=>(o(),a("div",{key:r,class:"logrow"},[e("div",pt,n(C(t.ts)),1),e("div",null,[e("span",{class:F(["lv",M(t.level).cls])},n(M(t.level).txt),3)]),e("div",null,[t.app?(o(),a(f,{key:0},[e("span",mt,n(t.app),1),t.registered?A("",!0):(o(),a("span",ft,"未注册"))],64)):(o(),a("span",_t,"(无应用名)")),e("span",gt," · "+n(D(t.region)),1),e("span",xt," · "+n(S(t.product_id)),1),e("span",yt," · "+n(t.channel_id||"未分配渠道"),1)]),e("div",bt,n(t.stat_day?k(t.stat_day):"-"),1),e("div",null,[t.msg?(o(),a(f,{key:0},[e("span",{class:F(t.level==="error"?"text-red-600":"text-amber-600")},n(t.msg),3),t.summary?(o(),a("span",ht," · "+n(t.summary),1)):A("",!0)],64)):(o(),a(f,{key:1},[u(n(t.summary||"无增量"),1)],64))]),e("div",wt,[u(n(C(t.snap_ts)),1),j(t)?(o(),a("span",kt,"迟到"+n(t.ts-t.snap_ts)+"s",1)):A("",!0)])]))),128)):(o(),a("div",vt,n(c.value.length?"无匹配记录":"该日暂无接收记录"),1))])])]))}}),Lt=Z(Ct,[["__scopeId","data-v-e7a3debc"]]);export{Lt as default};

1
apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/CDB8L8go.js

File diff suppressed because one or more lines are too long

2
apps/admin/.output/public/_nuxt/DBzpctzV.js → apps/admin/node_modules/.cache/nuxt/.nuxt/dist/client/_nuxt/CEFq2Pq9.js

File diff suppressed because one or more lines are too long

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

Loading…
Cancel
Save