feat(v3): Web 界面视觉升级(全局设计令牌 + 深色侧边栏壳 + 页面细节打磨)

- style.css 重写为设计系统:色板/圆角/阴影/统一滚动条/焦点环/卡片质感,main.ts 引入
- App.vue:深色渐变侧边栏替换顶部条(品牌区/图标导航/激活高亮/网关状态脚注)
- 六个视图页面背景令牌化,卡片统一阴影;index.html 标题与语言修正
- 功能零改动,纯视觉层
This commit is contained in:
tzt
2026-09-01 19:09:29 +08:00
parent 43e2bceae7
commit 1ae9ffb159
31 changed files with 284 additions and 365 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
.metrics-view[data-v-079e4daf]{height:100%;padding:20px 24px;overflow-y:auto}.by-model[data-v-079e4daf]{border-collapse:collapse;width:100%;font-size:12px}.by-model th[data-v-079e4daf],.by-model td[data-v-079e4daf]{text-align:left;border-bottom:1px solid #f3f4f6;padding:4px 8px}.by-model th[data-v-079e4daf]{color:#6b7280;font-weight:600}.by-model td.mono[data-v-079e4daf]{font-family:ui-monospace,Consolas,monospace}.hint[data-v-079e4daf]{color:#9ca3af;margin-top:8px;font-size:11px}.metrics-header[data-v-079e4daf]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.metrics-header h2[data-v-079e4daf]{margin:0;font-size:20px}.refresh[data-v-079e4daf]{cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:6px;padding:6px 14px}.loading[data-v-079e4daf],.error[data-v-079e4daf]{text-align:center;color:#9ca3af;padding:40px}.error[data-v-079e4daf]{color:#dc2626}.card-grid[data-v-079e4daf]{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px;margin-bottom:24px;display:grid}.metric-card[data-v-079e4daf]{background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:16px}.metric-card.highlight[data-v-079e4daf]{background:#eff6ff;border-color:#2563eb}.metric-card h3[data-v-079e4daf]{color:#374151;margin:0 0 12px;font-size:14px}.kv-list[data-v-079e4daf]{grid-template-columns:1fr 1fr;gap:6px 12px;font-size:13px;display:grid}.kv-list span[data-v-079e4daf]{color:#6b7280}.kv-list b[data-v-079e4daf]{color:#111;text-align:right}.review-card[data-v-079e4daf]{grid-column:span 2}.review-stats[data-v-079e4daf]{gap:24px;margin-bottom:12px;display:flex}.stat-item[data-v-079e4daf]{flex-direction:column;align-items:center;display:flex}.stat-num[data-v-079e4daf]{color:#2563eb;font-size:28px;font-weight:700}.stat-label[data-v-079e4daf]{color:#6b7280;font-size:12px}.progress-wrap[data-v-079e4daf]{background:#e5e7eb;border-radius:99px;height:8px;margin-bottom:6px;overflow:hidden}.reviewed-bar[data-v-079e4daf]{background:#16a34a;height:100%;transition:width .5s}.review-rate[data-v-079e4daf]{color:#6b7280;margin:0;font-size:13px}.raw-json[data-v-079e4daf]{background:var(--c-bg);border:1px solid #e5e7eb;border-radius:8px}.raw-json summary[data-v-079e4daf]{cursor:pointer;color:#6b7280;padding:10px 14px;font-size:13px}.raw-json pre[data-v-079e4daf]{white-space:pre-wrap;border-top:1px solid #e5e7eb;margin:0;padding:10px 14px;font-size:12px}
@@ -1 +0,0 @@
.metrics-view[data-v-ba641559]{height:100%;padding:20px 24px;overflow-y:auto}.by-model[data-v-ba641559]{border-collapse:collapse;width:100%;font-size:12px}.by-model th[data-v-ba641559],.by-model td[data-v-ba641559]{text-align:left;border-bottom:1px solid #f3f4f6;padding:4px 8px}.by-model th[data-v-ba641559]{color:#6b7280;font-weight:600}.by-model td.mono[data-v-ba641559]{font-family:ui-monospace,Consolas,monospace}.hint[data-v-ba641559]{color:#9ca3af;margin-top:8px;font-size:11px}.metrics-header[data-v-ba641559]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.metrics-header h2[data-v-ba641559]{margin:0;font-size:20px}.refresh[data-v-ba641559]{cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:6px;padding:6px 14px}.loading[data-v-ba641559],.error[data-v-ba641559]{text-align:center;color:#9ca3af;padding:40px}.error[data-v-ba641559]{color:#dc2626}.card-grid[data-v-ba641559]{grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px;margin-bottom:24px;display:grid}.metric-card[data-v-ba641559]{background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:16px}.metric-card.highlight[data-v-ba641559]{background:#eff6ff;border-color:#2563eb}.metric-card h3[data-v-ba641559]{color:#374151;margin:0 0 12px;font-size:14px}.kv-list[data-v-ba641559]{grid-template-columns:1fr 1fr;gap:6px 12px;font-size:13px;display:grid}.kv-list span[data-v-ba641559]{color:#6b7280}.kv-list b[data-v-ba641559]{color:#111;text-align:right}.review-card[data-v-ba641559]{grid-column:span 2}.review-stats[data-v-ba641559]{gap:24px;margin-bottom:12px;display:flex}.stat-item[data-v-ba641559]{flex-direction:column;align-items:center;display:flex}.stat-num[data-v-ba641559]{color:#2563eb;font-size:28px;font-weight:700}.stat-label[data-v-ba641559]{color:#6b7280;font-size:12px}.progress-wrap[data-v-ba641559]{background:#e5e7eb;border-radius:99px;height:8px;margin-bottom:6px;overflow:hidden}.reviewed-bar[data-v-ba641559]{background:#16a34a;height:100%;transition:width .5s}.review-rate[data-v-ba641559]{color:#6b7280;margin:0;font-size:13px}.raw-json[data-v-ba641559]{background:#f9fafb;border:1px solid #e5e7eb;border-radius:8px}.raw-json summary[data-v-ba641559]{cursor:pointer;color:#6b7280;padding:10px 14px;font-size:13px}.raw-json pre[data-v-ba641559]{white-space:pre-wrap;border-top:1px solid #e5e7eb;margin:0;padding:10px 14px;font-size:12px}
@@ -1 +1 @@
import{A as e,D as t,G as n,I as r,L as i,N as a,O as o,P as s,V as c,W as l,j as u,k as d,s as f,t as p}from"./index-DtjeaX4S.js";var m={class:`metrics-view`},h={key:0,class:`loading`},g={key:1,class:`error`},_={class:`card-grid`},v={class:`metric-card`},y={class:`kv-list`},b={class:`metric-card`},x={class:`kv-list`},S={key:0,class:`metric-card highlight`},C={class:`kv-list`},w={key:0},T={key:1},E={key:1,class:`metric-card`},D={class:`by-model`},O={class:`mono`},k={key:2,class:`metric-card review-card`},A={class:`review-stats`},j={class:`stat-item`},M={class:`stat-num`},N={class:`stat-item`},P={class:`stat-num`},F={key:0,class:`progress-wrap`},I={class:`review-rate`},L={class:`raw-json`},R=p(a({__name:`MetricsView`,setup(a){let p=c(null),R=c(!1),z=c(``),B=o(()=>p.value?.v2?.by_model||null);async function V(){R.value=!0,z.value=``;try{p.value=await f()}catch(e){z.value=e instanceof Error?e.message:`指标加载失败,请检查后端服务`}finally{R.value=!1}}return s(V),(a,o)=>(r(),u(`div`,m,[d(`header`,{class:`metrics-header`},[o[0]||=d(`h2`,null,`系统指标`,-1),d(`button`,{class:`refresh`,onClick:V},`🔄 刷新`)]),R.value?(r(),u(`div`,h,`加载中…`)):z.value?(r(),u(`div`,g,n(z.value),1)):p.value?(r(),u(t,{key:2},[d(`div`,_,[d(`div`,v,[o[1]||=d(`h3`,null,`路由器(v1`,-1),d(`div`,y,[(r(!0),u(t,null,i(p.value.router,(e,i)=>(r(),u(t,{key:i},[d(`span`,null,n(i),1),d(`b`,null,n(e),1)],64))),128))])]),d(`div`,b,[o[2]||=d(`h3`,null,`缓存`,-1),d(`div`,x,[(r(!0),u(t,null,i(p.value.cache,(e,i)=>(r(),u(t,{key:i},[d(`span`,null,n(i),1),d(`b`,null,n(e),1)],64))),128))])]),p.value.v2?(r(),u(`div`,S,[o[3]||=d(`h3`,null,`协作管线(v2`,-1),d(`div`,C,[(r(!0),u(t,null,i(p.value.v2,(i,a)=>(r(),u(t,{key:a},[a===`by_model`?e(``,!0):(r(),u(`span`,w,n(a),1)),a===`by_model`?e(``,!0):(r(),u(`b`,T,n(i),1))],64))),128))])])):e(``,!0),B.value&&Object.keys(B.value).length?(r(),u(`div`,E,[o[5]||=d(`h3`,null,`按模型分账(token / 成本)`,-1),d(`table`,D,[o[4]||=d(`thead`,null,[d(`tr`,null,[d(`th`,null,`模型`),d(`th`,null,`次数`),d(`th`,null,``),d(`th`,null,``),d(`th`,null,`成本 $`)])],-1),d(`tbody`,null,[(r(!0),u(t,null,i(B.value,(e,t)=>(r(),u(`tr`,{key:t},[d(`td`,O,n(t),1),d(`td`,null,n(e.requests),1),d(`td`,null,n(e.input_tokens),1),d(`td`,null,n(e.output_tokens),1),d(`td`,null,n(e.cost_est_usd),1)]))),128))])]),o[6]||=d(`p`,{class:`hint`},`单价来自模型池条目($/1M tokens);经典设置下的模型成本不计入。`,-1)])):e(``,!0),p.value.review?(r(),u(`div`,k,[o[9]||=d(`h3`,null,`人工检验`,-1),d(`div`,A,[d(`div`,j,[d(`span`,M,n(p.value.review.pending),1),o[7]||=d(`span`,{class:`stat-label`},`待审核`,-1)]),d(`div`,N,[d(`span`,P,n(p.value.review.total),1),o[8]||=d(`span`,{class:`stat-label`},`总提交`,-1)])]),p.value.review.total>0?(r(),u(`div`,F,[d(`div`,{class:`reviewed-bar`,style:l({width:`${(p.value.review.total-p.value.review.pending)/p.value.review.total*100}%`})},null,4)])):e(``,!0),d(`p`,I,` 通过率: `+n(((p.value.review.total-p.value.review.pending)/p.value.review.total*100).toFixed(1))+`% `,1)])):e(``,!0)]),d(`details`,L,[o[10]||=d(`summary`,null,`原始 JSON`,-1),d(`pre`,null,n(JSON.stringify(p.value,null,2)),1)])],64)):e(``,!0)]))}}),[[`__scopeId`,`data-v-ba641559`]]);export{R as default};
import{A as e,D as t,G as n,I as r,L as i,N as a,O as o,P as s,V as c,W as l,j as u,k as d,s as f,t as p}from"./index-D70fN-oL.js";var m={class:`metrics-view`},h={key:0,class:`loading`},g={key:1,class:`error`},_={class:`card-grid`},v={class:`metric-card`},y={class:`kv-list`},b={class:`metric-card`},x={class:`kv-list`},S={key:0,class:`metric-card highlight`},C={class:`kv-list`},w={key:0},T={key:1},E={key:1,class:`metric-card`},D={class:`by-model`},O={class:`mono`},k={key:2,class:`metric-card review-card`},A={class:`review-stats`},j={class:`stat-item`},M={class:`stat-num`},N={class:`stat-item`},P={class:`stat-num`},F={key:0,class:`progress-wrap`},I={class:`review-rate`},L={class:`raw-json`},R=p(a({__name:`MetricsView`,setup(a){let p=c(null),R=c(!1),z=c(``),B=o(()=>p.value?.v2?.by_model||null);async function V(){R.value=!0,z.value=``;try{p.value=await f()}catch(e){z.value=e instanceof Error?e.message:`指标加载失败,请检查后端服务`}finally{R.value=!1}}return s(V),(a,o)=>(r(),u(`div`,m,[d(`header`,{class:`metrics-header`},[o[0]||=d(`h2`,null,`系统指标`,-1),d(`button`,{class:`refresh`,onClick:V},`🔄 刷新`)]),R.value?(r(),u(`div`,h,`加载中…`)):z.value?(r(),u(`div`,g,n(z.value),1)):p.value?(r(),u(t,{key:2},[d(`div`,_,[d(`div`,v,[o[1]||=d(`h3`,null,`路由器(v1`,-1),d(`div`,y,[(r(!0),u(t,null,i(p.value.router,(e,i)=>(r(),u(t,{key:i},[d(`span`,null,n(i),1),d(`b`,null,n(e),1)],64))),128))])]),d(`div`,b,[o[2]||=d(`h3`,null,`缓存`,-1),d(`div`,x,[(r(!0),u(t,null,i(p.value.cache,(e,i)=>(r(),u(t,{key:i},[d(`span`,null,n(i),1),d(`b`,null,n(e),1)],64))),128))])]),p.value.v2?(r(),u(`div`,S,[o[3]||=d(`h3`,null,`协作管线(v2`,-1),d(`div`,C,[(r(!0),u(t,null,i(p.value.v2,(i,a)=>(r(),u(t,{key:a},[a===`by_model`?e(``,!0):(r(),u(`span`,w,n(a),1)),a===`by_model`?e(``,!0):(r(),u(`b`,T,n(i),1))],64))),128))])])):e(``,!0),B.value&&Object.keys(B.value).length?(r(),u(`div`,E,[o[5]||=d(`h3`,null,`按模型分账(token / 成本)`,-1),d(`table`,D,[o[4]||=d(`thead`,null,[d(`tr`,null,[d(`th`,null,`模型`),d(`th`,null,`次数`),d(`th`,null,``),d(`th`,null,``),d(`th`,null,`成本 $`)])],-1),d(`tbody`,null,[(r(!0),u(t,null,i(B.value,(e,t)=>(r(),u(`tr`,{key:t},[d(`td`,O,n(t),1),d(`td`,null,n(e.requests),1),d(`td`,null,n(e.input_tokens),1),d(`td`,null,n(e.output_tokens),1),d(`td`,null,n(e.cost_est_usd),1)]))),128))])]),o[6]||=d(`p`,{class:`hint`},`单价来自模型池条目($/1M tokens);经典设置下的模型成本不计入。`,-1)])):e(``,!0),p.value.review?(r(),u(`div`,k,[o[9]||=d(`h3`,null,`人工检验`,-1),d(`div`,A,[d(`div`,j,[d(`span`,M,n(p.value.review.pending),1),o[7]||=d(`span`,{class:`stat-label`},`待审核`,-1)]),d(`div`,N,[d(`span`,P,n(p.value.review.total),1),o[8]||=d(`span`,{class:`stat-label`},`总提交`,-1)])]),p.value.review.total>0?(r(),u(`div`,F,[d(`div`,{class:`reviewed-bar`,style:l({width:`${(p.value.review.total-p.value.review.pending)/p.value.review.total*100}%`})},null,4)])):e(``,!0),d(`p`,I,` 通过率: `+n(((p.value.review.total-p.value.review.pending)/p.value.review.total*100).toFixed(1))+`% `,1)])):e(``,!0)]),d(`details`,L,[o[10]||=d(`summary`,null,`原始 JSON`,-1),d(`pre`,null,n(JSON.stringify(p.value,null,2)),1)])],64)):e(``,!0)]))}}),[[`__scopeId`,`data-v-079e4daf`]]);export{R as default};
@@ -1 +0,0 @@
.review-view[data-v-19c16eff]{height:100%;padding:20px 24px;overflow-y:auto}.review-header[data-v-19c16eff]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.review-header h2[data-v-19c16eff]{margin:0;font-size:20px}.controls[data-v-19c16eff]{gap:8px;display:flex}button[data-v-19c16eff]{cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:6px;padding:6px 14px;font-size:13px}button.active[data-v-19c16eff]{color:#fff;background:#2563eb;border-color:#2563eb}.refresh-btn[data-v-19c16eff]{margin-left:auto}.loading[data-v-19c16eff],.error[data-v-19c16eff],.empty[data-v-19c16eff]{text-align:center;color:#9ca3af;padding:40px}.error[data-v-19c16eff]{color:#dc2626}.queue-list[data-v-19c16eff]{flex-direction:column;gap:16px;display:flex}.review-card[data-v-19c16eff]{background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:16px}.card-header[data-v-19c16eff]{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:10px;display:flex}.card-id[data-v-19c16eff]{color:#6b7280;font-family:monospace;font-size:12px}.verdict-badge[data-v-19c16eff]{border-radius:99px;padding:2px 8px;font-size:12px;font-weight:600}.verdict-badge.pending[data-v-19c16eff]{color:#92400e;background:#fef3c7}.verdict-badge.approved[data-v-19c16eff]{color:#16a34a;background:#dcfce7}.verdict-badge.rejected[data-v-19c16eff]{color:#dc2626;background:#fee2e2}.tags[data-v-19c16eff]{gap:4px;display:flex}.tag[data-v-19c16eff]{color:#3730a3;background:#e0e7ff;border-radius:4px;padding:1px 6px;font-size:11px}.date[data-v-19c16eff]{color:#9ca3af;margin-left:auto;font-size:11px}.query-block[data-v-19c16eff],.response-block[data-v-19c16eff]{margin-bottom:8px;font-size:13px;line-height:1.6}.query-block pre[data-v-19c16eff],.response-block pre[data-v-19c16eff]{white-space:pre-wrap;background:#f9fafb;border:1px solid #e5e7eb;border-radius:4px;margin:4px 0 0;padding:6px 10px;font-size:13px}.actions[data-v-19c16eff]{flex-direction:column;gap:8px;margin-top:10px;display:flex}textarea[data-v-19c16eff]{resize:vertical;box-sizing:border-box;border:1px solid #d1d5db;border-radius:6px;width:100%;padding:8px 10px;font-family:inherit;font-size:13px}.btn-row[data-v-19c16eff]{gap:8px;display:flex}.approve[data-v-19c16eff]{color:#16a34a;background:#dcfce7;border-color:#86efac}.reject[data-v-19c16eff]{color:#dc2626;background:#fee2e2;border-color:#fca5a5}.correction[data-v-19c16eff]{background:#fffbeb;border:1px solid #fcd34d;border-radius:4px;margin-top:8px;padding:6px 10px;font-size:13px}
@@ -1 +1 @@
import{A as e,D as t,E as n,G as r,I as i,L as a,M as o,N as s,O as c,P as l,U as u,V as d,f,j as p,k as m,t as h,v as g,z as _}from"./index-DtjeaX4S.js";var v={class:`review-view`},y={class:`review-header`},b={class:`controls`},x={key:0,class:`loading`},S={key:1,class:`error`},C={key:2,class:`queue-list`},w={key:0,class:`empty`},T={class:`card-header`},E={class:`card-id`},D={class:`tags`},O={class:`date`},k={class:`query-block`},A={class:`response-block`},j={key:0,class:`actions`},M=[`onUpdate:modelValue`],N={class:`btn-row`},P=[`onClick`],F=[`onClick`],I={key:1,class:`correction`},L=h(s({__name:`ReviewView`,setup(s){let h=d([]),L=d(!1),R=d(``),z=d(`pending`),B=d({}),V=c(()=>z.value===`all`?h.value:h.value.filter(e=>e.verdict===z.value));async function H(){L.value=!0,R.value=``;try{h.value=await f()}catch(e){R.value=e instanceof Error?e.message:String(e)}finally{L.value=!1}}async function U(e,t){try{await g(e,t,B.value[e]||void 0),await H()}catch(e){R.value=e instanceof Error?e.message:String(e)}}return l(H),(s,c)=>(i(),p(`div`,v,[m(`header`,y,[c[4]||=m(`h2`,null,`人工检验队列`,-1),m(`div`,b,[m(`button`,{class:u({active:z.value===`all`}),onClick:c[0]||=e=>z.value=`all`},`全部`,2),m(`button`,{class:u({active:z.value===`pending`}),onClick:c[1]||=e=>z.value=`pending`},`待审核`,2),m(`button`,{class:u({active:z.value===`approved`}),onClick:c[2]||=e=>z.value=`approved`},`已通过`,2),m(`button`,{class:u({active:z.value===`rejected`}),onClick:c[3]||=e=>z.value=`rejected`},`已拒绝`,2),m(`button`,{class:`refresh-btn`,onClick:H},`🔄 刷新`)])]),L.value?(i(),p(`div`,x,`加载中…`)):R.value?(i(),p(`div`,S,r(R.value),1)):(i(),p(`div`,C,[V.value.length?e(``,!0):(i(),p(`div`,w,`队列为空。`)),(i(!0),p(t,null,a(V.value,s=>(i(),p(`div`,{key:s.id,class:`review-card`},[m(`div`,T,[m(`span`,E,`#`+r(s.id),1),m(`span`,{class:u([`verdict-badge`,s.verdict])},r(s.verdict),3),m(`span`,D,[(i(!0),p(t,null,a(s.tags,e=>(i(),p(`span`,{key:e,class:`tag`},r(e),1))),128))]),m(`span`,O,r(s.created_at),1)]),m(`div`,k,[c[5]||=m(`strong`,null,`Query`,-1),o(r(s.query),1)]),m(`div`,A,[c[6]||=m(`strong`,null,`Response`,-1),m(`pre`,null,r(s.response),1)]),s.verdict===`pending`?(i(),p(`div`,j,[_(m(`textarea`,{"onUpdate:modelValue":e=>B.value[s.id]=e,placeholder:`修正意见(可选)`,rows:`2`},null,8,M),[[n,B.value[s.id]]]),m(`div`,N,[m(`button`,{class:`approve`,onClick:e=>U(s.id,`approved`)},`✅ 通过`,8,P),m(`button`,{class:`reject`,onClick:e=>U(s.id,`rejected`)},`❌ 拒绝`,8,F)])])):s.correction?(i(),p(`div`,I,[c[7]||=m(`strong`,null,`修正:`,-1),o(r(s.correction),1)])):e(``,!0)]))),128))]))]))}}),[[`__scopeId`,`data-v-19c16eff`]]);export{L as default};
import{A as e,D as t,E as n,G as r,I as i,L as a,M as o,N as s,O as c,P as l,U as u,V as d,f,j as p,k as m,t as h,v as g,z as _}from"./index-D70fN-oL.js";var v={class:`review-view`},y={class:`review-header`},b={class:`controls`},x={key:0,class:`loading`},S={key:1,class:`error`},C={key:2,class:`queue-list`},w={key:0,class:`empty`},T={class:`card-header`},E={class:`card-id`},D={class:`tags`},O={class:`date`},k={class:`query-block`},A={class:`response-block`},j={key:0,class:`actions`},M=[`onUpdate:modelValue`],N={class:`btn-row`},P=[`onClick`],F=[`onClick`],I={key:1,class:`correction`},L=h(s({__name:`ReviewView`,setup(s){let h=d([]),L=d(!1),R=d(``),z=d(`pending`),B=d({}),V=c(()=>z.value===`all`?h.value:h.value.filter(e=>e.verdict===z.value));async function H(){L.value=!0,R.value=``;try{h.value=await f()}catch(e){R.value=e instanceof Error?e.message:String(e)}finally{L.value=!1}}async function U(e,t){try{await g(e,t,B.value[e]||void 0),await H()}catch(e){R.value=e instanceof Error?e.message:String(e)}}return l(H),(s,c)=>(i(),p(`div`,v,[m(`header`,y,[c[4]||=m(`h2`,null,`人工检验队列`,-1),m(`div`,b,[m(`button`,{class:u({active:z.value===`all`}),onClick:c[0]||=e=>z.value=`all`},`全部`,2),m(`button`,{class:u({active:z.value===`pending`}),onClick:c[1]||=e=>z.value=`pending`},`待审核`,2),m(`button`,{class:u({active:z.value===`approved`}),onClick:c[2]||=e=>z.value=`approved`},`已通过`,2),m(`button`,{class:u({active:z.value===`rejected`}),onClick:c[3]||=e=>z.value=`rejected`},`已拒绝`,2),m(`button`,{class:`refresh-btn`,onClick:H},`🔄 刷新`)])]),L.value?(i(),p(`div`,x,`加载中…`)):R.value?(i(),p(`div`,S,r(R.value),1)):(i(),p(`div`,C,[V.value.length?e(``,!0):(i(),p(`div`,w,`队列为空。`)),(i(!0),p(t,null,a(V.value,s=>(i(),p(`div`,{key:s.id,class:`review-card`},[m(`div`,T,[m(`span`,E,`#`+r(s.id),1),m(`span`,{class:u([`verdict-badge`,s.verdict])},r(s.verdict),3),m(`span`,D,[(i(!0),p(t,null,a(s.tags,e=>(i(),p(`span`,{key:e,class:`tag`},r(e),1))),128))]),m(`span`,O,r(s.created_at),1)]),m(`div`,k,[c[5]||=m(`strong`,null,`Query`,-1),o(r(s.query),1)]),m(`div`,A,[c[6]||=m(`strong`,null,`Response`,-1),m(`pre`,null,r(s.response),1)]),s.verdict===`pending`?(i(),p(`div`,j,[_(m(`textarea`,{"onUpdate:modelValue":e=>B.value[s.id]=e,placeholder:`修正意见(可选)`,rows:`2`},null,8,M),[[n,B.value[s.id]]]),m(`div`,N,[m(`button`,{class:`approve`,onClick:e=>U(s.id,`approved`)},`✅ 通过`,8,P),m(`button`,{class:`reject`,onClick:e=>U(s.id,`rejected`)},`❌ 拒绝`,8,F)])])):s.correction?(i(),p(`div`,I,[c[7]||=m(`strong`,null,`修正:`,-1),o(r(s.correction),1)])):e(``,!0)]))),128))]))]))}}),[[`__scopeId`,`data-v-c4b0ce4d`]]);export{L as default};
@@ -0,0 +1 @@
.review-view[data-v-c4b0ce4d]{height:100%;padding:20px 24px;overflow-y:auto}.review-header[data-v-c4b0ce4d]{justify-content:space-between;align-items:center;margin-bottom:20px;display:flex}.review-header h2[data-v-c4b0ce4d]{margin:0;font-size:20px}.controls[data-v-c4b0ce4d]{gap:8px;display:flex}button[data-v-c4b0ce4d]{cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:6px;padding:6px 14px;font-size:13px}button.active[data-v-c4b0ce4d]{color:#fff;background:#2563eb;border-color:#2563eb}.refresh-btn[data-v-c4b0ce4d]{margin-left:auto}.loading[data-v-c4b0ce4d],.error[data-v-c4b0ce4d],.empty[data-v-c4b0ce4d]{text-align:center;color:#9ca3af;padding:40px}.error[data-v-c4b0ce4d]{color:#dc2626}.queue-list[data-v-c4b0ce4d]{flex-direction:column;gap:16px;display:flex}.review-card[data-v-c4b0ce4d]{background:#fff;border:1px solid #e5e7eb;border-radius:10px;padding:16px}.card-header[data-v-c4b0ce4d]{flex-wrap:wrap;align-items:center;gap:10px;margin-bottom:10px;display:flex}.card-id[data-v-c4b0ce4d]{color:#6b7280;font-family:monospace;font-size:12px}.verdict-badge[data-v-c4b0ce4d]{border-radius:99px;padding:2px 8px;font-size:12px;font-weight:600}.verdict-badge.pending[data-v-c4b0ce4d]{color:#92400e;background:#fef3c7}.verdict-badge.approved[data-v-c4b0ce4d]{color:#16a34a;background:#dcfce7}.verdict-badge.rejected[data-v-c4b0ce4d]{color:#dc2626;background:#fee2e2}.tags[data-v-c4b0ce4d]{gap:4px;display:flex}.tag[data-v-c4b0ce4d]{color:#3730a3;background:#e0e7ff;border-radius:4px;padding:1px 6px;font-size:11px}.date[data-v-c4b0ce4d]{color:#9ca3af;margin-left:auto;font-size:11px}.query-block[data-v-c4b0ce4d],.response-block[data-v-c4b0ce4d]{margin-bottom:8px;font-size:13px;line-height:1.6}.query-block pre[data-v-c4b0ce4d],.response-block pre[data-v-c4b0ce4d]{background:var(--c-bg);white-space:pre-wrap;border:1px solid #e5e7eb;border-radius:4px;margin:4px 0 0;padding:6px 10px;font-size:13px}.actions[data-v-c4b0ce4d]{flex-direction:column;gap:8px;margin-top:10px;display:flex}textarea[data-v-c4b0ce4d]{resize:vertical;box-sizing:border-box;border:1px solid #d1d5db;border-radius:6px;width:100%;padding:8px 10px;font-family:inherit;font-size:13px}.btn-row[data-v-c4b0ce4d]{gap:8px;display:flex}.approve[data-v-c4b0ce4d]{color:#16a34a;background:#dcfce7;border-color:#86efac}.reject[data-v-c4b0ce4d]{color:#dc2626;background:#fee2e2;border-color:#fca5a5}.correction[data-v-c4b0ce4d]{background:#fffbeb;border:1px solid #fcd34d;border-radius:4px;margin-top:8px;padding:6px 10px;font-size:13px}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -1,12 +1,12 @@
<!doctype html>
<html lang="en">
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>webapp</title>
<script type="module" crossorigin src="/static/assets/index-DtjeaX4S.js"></script>
<link rel="stylesheet" crossorigin href="/static/assets/index-DPz6YNpx.css">
<title>端云协同 LLM 协作系统</title>
<script type="module" crossorigin src="/static/assets/index-D70fN-oL.js"></script>
<link rel="stylesheet" crossorigin href="/static/assets/index-BVpeNfYt.css">
</head>
<body>
<div id="app"></div>
@@ -0,0 +1 @@
{"touched":[],"bashMutation":true,"reportedFindings":[],"findingEvents":[],"baseline":null,"stateErrors":[],"omittedReportedFindings":0,"omittedFindingEvents":0,"processing":null,"updatedAt":"2026-09-01T11:06:08.696Z"}
@@ -0,0 +1,14 @@
{
"schemaVersion": "mimosa-hook-status/v1",
"recordedAt": "2026-09-01T11:06:34.610Z",
"sessionId": "sess_e50d4f25-3ac6-43f2-b2f3-8833b3150465",
"event": "PostToolUse",
"toolName": "Edit",
"file": "src/style.css",
"outcome": "clear",
"coverage": "complete",
"findingCount": 0,
"durationMs": 3,
"hostState": "hook_complete",
"reportHint": ".mimosa/reports/"
}
+2 -2
View File
@@ -1,10 +1,10 @@
<!doctype html>
<html lang="en">
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>webapp</title>
<title>端云协同 LLM 协作系统</title>
</head>
<body>
<div id="app"></div>
@@ -0,0 +1 @@
{"touched":[],"bashMutation":true,"reportedFindings":[],"findingEvents":[],"baseline":null,"stateErrors":[],"omittedReportedFindings":0,"omittedFindingEvents":0,"processing":null,"updatedAt":"2026-09-01T11:06:00.142Z"}
+123 -52
View File
@@ -1,85 +1,156 @@
<template>
<div class="app">
<!-- 顶部导航 -->
<nav class="topbar">
<span class="brand">🤖 端云协同 LLM 系统</span>
<div class="nav-links">
<router-link to="/chat">💬 对话</router-link>
<router-link to="/collaboration">🔄 协作</router-link>
<router-link to="/agent">🤖 智能体</router-link>
<router-link to="/review">🔍 检验</router-link>
<router-link to="/metrics">📊 指标</router-link>
<router-link to="/settings"> 设置</router-link>
<!-- 深色侧边导航 -->
<aside class="side">
<div class="brand">
<div class="brand-logo">🤖</div>
<div class="brand-text">
<b>端云协同</b>
<span>LLM 协作系统</span>
</div>
</div>
</nav>
<!-- 路由视图 -->
<router-view class="content" />
<nav class="nav">
<router-link v-for="item in NAV" :key="item.to" :to="item.to" class="nav-item">
<span class="nav-icon">{{ item.icon }}</span>
<span class="nav-label">{{ item.label }}</span>
</router-link>
</nav>
<div class="side-foot">
<div class="foot-dot" />
<span>本地网关 · :8000</span>
</div>
</aside>
<!-- 内容区 -->
<div class="main-col">
<router-view class="content" />
</div>
</div>
</template>
<script setup lang="ts">
// App.vue — 根布局,导航栏 + 路由出口
// App.vue — 深色侧边栏壳 + 路由出口
const NAV = [
{ to: '/chat', icon: '💬', label: '对话' },
{ to: '/collaboration', icon: '🔄', label: '协作过程' },
{ to: '/agent', icon: '🤖', label: '智能体' },
{ to: '/review', icon: '🔍', label: '人工检验' },
{ to: '/metrics', icon: '📊', label: '指标' },
{ to: '/settings', icon: '⚙️', label: '设置' },
]
</script>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body, #app {
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
font-size: 14px;
color: #111;
background: #fff;
}
.app {
display: flex;
flex-direction: column;
height: 100%;
}
.topbar {
display: flex;
align-items: center;
gap: 24px;
padding: 0 24px;
height: 52px;
border-bottom: 1px solid #e5e7eb;
background: #fff;
/* ---------- 侧边栏 ---------- */
.side {
width: 208px;
flex-shrink: 0;
display: flex;
flex-direction: column;
background: linear-gradient(180deg, var(--c-side-bg) 0%, var(--c-side-bg-2) 100%);
color: var(--c-side-text);
padding: 18px 12px 14px;
user-select: none;
}
.brand {
font-size: 16px;
font-weight: 700;
color: #1e40af;
white-space: nowrap;
}
.nav-links {
display: flex;
gap: 4px;
align-items: center;
gap: 10px;
padding: 4px 8px 18px;
border-bottom: 1px solid rgba(255, 255, 255, 0.07);
margin-bottom: 14px;
}
.brand-logo {
width: 38px;
height: 38px;
display: grid;
place-items: center;
font-size: 20px;
background: linear-gradient(135deg, #4f6ef7, #7c5cf5);
border-radius: 11px;
box-shadow: 0 4px 14px rgba(79, 110, 247, 0.45);
}
.brand-text { display: flex; flex-direction: column; line-height: 1.25; }
.brand-text b { color: #fff; font-size: 15px; letter-spacing: 0.5px; }
.brand-text span { font-size: 11px; color: var(--c-side-text); }
.nav-links a {
padding: 6px 14px;
border-radius: 6px;
.nav { display: flex; flex-direction: column; gap: 3px; flex: 1; }
.nav-item {
display: flex;
align-items: center;
gap: 11px;
padding: 9px 12px;
border-radius: 9px;
text-decoration: none;
color: #374151;
font-size: 14px;
color: var(--c-side-text);
font-size: 13.5px;
font-weight: 500;
transition: background 0.15s;
position: relative;
transition: background 0.15s, color 0.15s;
}
.nav-links a:hover { background: #f3f4f6; }
.nav-links a.router-link-active {
background: #eff6ff;
color: #2563eb;
.nav-item:hover { background: rgba(255, 255, 255, 0.055); color: #e6eaf4; }
.nav-item.router-link-active {
background: var(--c-side-active);
color: var(--c-side-text-active);
}
.nav-item.router-link-active::before {
content: '';
position: absolute;
left: -12px;
top: 8px;
bottom: 8px;
width: 3px;
border-radius: 0 3px 3px 0;
background: var(--c-primary);
}
.nav-icon {
width: 26px;
height: 26px;
display: grid;
place-items: center;
font-size: 15px;
background: rgba(255, 255, 255, 0.06);
border-radius: 7px;
}
.nav-item.router-link-active .nav-icon { background: rgba(79, 110, 247, 0.35); }
.side-foot {
display: flex;
align-items: center;
gap: 7px;
padding: 10px 8px 2px;
border-top: 1px solid rgba(255, 255, 255, 0.07);
font-size: 11px;
color: #7d879e;
}
.foot-dot {
width: 7px;
height: 7px;
border-radius: 50%;
background: #34d399;
box-shadow: 0 0 6px #34d399;
}
/* ---------- 内容区 ---------- */
.main-col {
flex: 1;
min-width: 0;
height: 100%;
display: flex;
flex-direction: column;
}
.content {
flex: 1;
overflow: hidden; /* 限制自己高度,不被子内容撑开 */
overflow: hidden;
display: flex;
flex-direction: column;
min-height: 0;
+1
View File
@@ -2,6 +2,7 @@ import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
import './style.css'
const app = createApp(App)
app.use(createPinia())
+98 -275
View File
@@ -1,296 +1,119 @@
/* ============================================================
端云协同 LLM 系统 · 全局设计令牌与基础样式
(浅色主题;深色侧边栏壳见 App.vue)
============================================================ */
:root {
--text: #6b6375;
--text-h: #08060d;
--bg: #fff;
--border: #e5e4e7;
--code-bg: #f4f3ec;
--accent: #aa3bff;
--accent-bg: rgba(170, 59, 255, 0.1);
--accent-border: rgba(170, 59, 255, 0.5);
--social-bg: rgba(244, 243, 236, 0.5);
--shadow:
rgba(0, 0, 0, 0.1) 0 10px 15px -3px, rgba(0, 0, 0, 0.05) 0 4px 6px -2px;
/* 色板 */
--c-bg: #f4f6fb; /* 页面底 */
--c-surface: #ffffff; /* 卡片/面板 */
--c-border: #e6e9f2;
--c-border-soft: #eef1f7;
--sans: system-ui, 'Segoe UI', Roboto, sans-serif;
--heading: system-ui, 'Segoe UI', Roboto, sans-serif;
--mono: ui-monospace, Consolas, monospace;
--c-text: #1a2233;
--c-text-2: #5b6478;
--c-text-3: #9aa3b5;
font: 18px/145% var(--sans);
letter-spacing: 0.18px;
color-scheme: light dark;
color: var(--text);
background: var(--bg);
font-synthesis: none;
text-rendering: optimizeLegibility;
--c-primary: #4f6ef7;
--c-primary-strong: #3d5cf5;
--c-primary-soft: #eef1fe;
--c-primary-ring: rgba(79, 110, 247, 0.16);
--c-ok: #16a34a;
--c-ok-soft: #dcfce7;
--c-warn: #d97706;
--c-warn-soft: #fef3c7;
--c-err: #dc2626;
--c-err-soft: #fee2e2;
/* 侧边栏(深色) */
--c-side-bg: #151b2c;
--c-side-bg-2: #1b2338;
--c-side-text: #aeb7cd;
--c-side-text-active: #ffffff;
--c-side-active: rgba(255, 255, 255, 0.09);
/* 形状与影 */
--radius: 10px;
--radius-sm: 7px;
--shadow-card: 0 1px 2px rgba(16, 24, 40, 0.04), 0 4px 16px rgba(16, 24, 40, 0.06);
--shadow-pop: 0 10px 40px rgba(16, 24, 40, 0.16);
--font-mono: ui-monospace, Consolas, "Courier New", monospace;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body, #app {
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
"Microsoft YaHei", Roboto, sans-serif;
font-size: 14px;
color: var(--c-text);
background: var(--c-bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@media (max-width: 1024px) {
font-size: 16px;
}
}
@media (prefers-color-scheme: dark) {
:root {
--text: #9ca3af;
--text-h: #f3f4f6;
--bg: #16171d;
--border: #2e303a;
--code-bg: #1f2028;
--accent: #c084fc;
--accent-bg: rgba(192, 132, 252, 0.15);
--accent-border: rgba(192, 132, 252, 0.5);
--social-bg: rgba(47, 48, 58, 0.5);
--shadow:
rgba(0, 0, 0, 0.4) 0 10px 15px -3px, rgba(0, 0, 0, 0.25) 0 4px 6px -2px;
}
#social .button-icon {
filter: invert(1) brightness(2);
}
}
body {
margin: 0;
}
h1,
h2 {
font-family: var(--heading);
font-weight: 500;
color: var(--text-h);
}
h1 {
font-size: 56px;
letter-spacing: -1.68px;
margin: 32px 0;
@media (max-width: 1024px) {
font-size: 36px;
margin: 20px 0;
}
}
h2 {
font-size: 24px;
line-height: 118%;
letter-spacing: -0.24px;
margin: 0 0 8px;
@media (max-width: 1024px) {
font-size: 20px;
}
}
p {
margin: 0;
}
code,
.counter {
font-family: var(--mono);
display: inline-flex;
border-radius: 4px;
color: var(--text-h);
}
code {
font-size: 15px;
line-height: 135%;
padding: 4px 8px;
background: var(--code-bg);
}
.counter {
font-size: 16px;
padding: 5px 10px;
border-radius: 5px;
color: var(--accent);
background: var(--accent-bg);
/* ---------- 统一滚动条 ---------- */
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-thumb {
background: #c9cfdd;
border-radius: 8px;
border: 2px solid transparent;
transition: border-color 0.3s;
margin-bottom: 24px;
background-clip: content-box;
}
::-webkit-scrollbar-thumb:hover { background-color: #aab2c5; }
::-webkit-scrollbar-track { background: transparent; }
&:hover {
border-color: var(--accent-border);
}
&:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
/* ---------- 基础元素统一 ---------- */
button, input, select, textarea { font-family: inherit; color: inherit; }
h2 { font-size: 19px; font-weight: 700; letter-spacing: 0.2px; }
a { color: var(--c-primary); }
code, pre { font-family: var(--font-mono); }
/* 焦点环统一 */
input:focus-visible, select:focus-visible, textarea:focus-visible, button:focus-visible {
outline: none;
box-shadow: 0 0 0 3px var(--c-primary-ring);
}
.hero {
position: relative;
.base,
.framework,
.vite {
inset-inline: 0;
margin: 0 auto;
}
.base {
width: 170px;
position: relative;
z-index: 0;
}
.framework,
.vite {
position: absolute;
}
.framework {
z-index: 1;
top: 34px;
height: 28px;
transform: perspective(2000px) rotateZ(300deg) rotateX(44deg) rotateY(39deg)
scale(1.4);
}
.vite {
z-index: 0;
top: 107px;
height: 26px;
width: auto;
transform: perspective(2000px) rotateZ(300deg) rotateX(40deg) rotateY(39deg)
scale(0.8);
}
/* ---------- 通用卡片质感(供各页复用) ---------- */
.surface {
background: var(--c-surface);
border: 1px solid var(--c-border);
border-radius: var(--radius);
box-shadow: var(--shadow-card);
}
#app {
width: 1126px;
max-width: 100%;
margin: 0 auto;
text-align: center;
border-inline: 1px solid var(--border);
min-height: 100svh;
display: flex;
flex-direction: column;
box-sizing: border-box;
/* 各页卡片统一阴影(配合各自 scoped 样式) */
.settings-section,
.metric-card,
.ev-card {
box-shadow: var(--shadow-card);
border-radius: var(--radius);
}
#center {
display: flex;
flex-direction: column;
gap: 25px;
place-content: center;
place-items: center;
flex-grow: 1;
@media (max-width: 1024px) {
padding: 32px 20px 24px;
gap: 18px;
}
}
#next-steps {
display: flex;
border-top: 1px solid var(--border);
text-align: left;
& > div {
flex: 1 1 0;
padding: 32px;
@media (max-width: 1024px) {
padding: 24px 20px;
}
}
.icon {
margin-bottom: 16px;
width: 22px;
height: 22px;
}
@media (max-width: 1024px) {
flex-direction: column;
text-align: center;
}
}
#docs {
border-right: 1px solid var(--border);
@media (max-width: 1024px) {
border-right: none;
border-bottom: 1px solid var(--border);
}
}
#next-steps ul {
list-style: none;
padding: 0;
/* 页面通用头 */
.page-head h2 {
display: flex;
align-items: center;
gap: 8px;
margin: 32px 0 0;
}
.page-head .sub { margin-top: 3px; }
.logo {
height: 18px;
}
/* 细节:数字/代码味道 */
.mono { font-family: var(--font-mono); }
a {
color: var(--text-h);
font-size: 16px;
border-radius: 6px;
background: var(--social-bg);
display: flex;
padding: 6px 12px;
align-items: center;
gap: 8px;
text-decoration: none;
transition: box-shadow 0.3s;
&:hover {
box-shadow: var(--shadow);
}
.button-icon {
height: 18px;
width: 18px;
}
}
@media (max-width: 1024px) {
margin-top: 20px;
flex-wrap: wrap;
justify-content: center;
li {
flex: 1 1 calc(50% - 8px);
}
a {
width: 100%;
justify-content: center;
box-sizing: border-box;
}
/* 平滑出现 */
@media (prefers-reduced-motion: no-preference) {
.ev-card, .metric-card, .settings-section {
animation: fade-up 0.18s ease both;
}
}
#spacer {
height: 88px;
border-top: 1px solid var(--border);
@media (max-width: 1024px) {
height: 48px;
}
}
.ticks {
position: relative;
width: 100%;
&::before,
&::after {
content: '';
position: absolute;
top: -4.5px;
border: 5px solid transparent;
}
&::before {
left: 0;
border-left-color: var(--border);
}
&::after {
right: 0;
border-right-color: var(--border);
}
@keyframes fade-up {
from { opacity: 0; transform: translateY(4px); }
to { opacity: 1; transform: translateY(0); }
}
+5 -5
View File
@@ -352,7 +352,7 @@ onMounted(async () => {
.agent-view {
display: flex;
height: 100%;
background: #f9fafb;
background: var(--c-bg);
}
/* 左侧工作区 */
@@ -377,7 +377,7 @@ onMounted(async () => {
padding: 6px 14px;
font-size: 11px;
color: #6b7280;
background: #f9fafb;
background: var(--c-bg);
border-bottom: 1px solid #f3f4f6;
white-space: nowrap;
overflow: hidden;
@@ -411,7 +411,7 @@ onMounted(async () => {
justify-content: space-between;
align-items: center;
padding: 8px 14px;
background: #f9fafb;
background: var(--c-bg);
font-size: 12px;
font-weight: 600;
color: #374151;
@@ -623,7 +623,7 @@ onMounted(async () => {
.crumb {
font-size: 12px;
color: #6b7280;
background: #f9fafb;
background: var(--c-bg);
border: 1px solid #f3f4f6;
border-radius: 6px;
padding: 6px 10px;
@@ -666,7 +666,7 @@ onMounted(async () => {
.recent-label { font-size: 12px; color: #9ca3af; }
.recent-chip {
border: 1px solid #e5e7eb;
background: #f9fafb;
background: var(--c-bg);
border-radius: 12px;
padding: 2px 10px;
font-size: 12px;
+1 -1
View File
@@ -178,7 +178,7 @@ async function handleSend() {
.sidebar {
width: 240px;
border-right: 1px solid #e5e7eb;
background: #f9fafb;
background: var(--c-bg);
display: flex;
flex-direction: column;
overflow: hidden;
+1 -1
View File
@@ -245,7 +245,7 @@ function getDecision(issueId: string) {
.collab-sidebar {
width: 260px;
border-right: 1px solid #e5e7eb;
background: #f9fafb;
background: var(--c-bg);
display: flex;
flex-direction: column;
overflow: hidden;
+1 -1
View File
@@ -194,7 +194,7 @@ onMounted(load)
.review-rate { font-size: 13px; color: #6b7280; margin: 0; }
.raw-json {
background: #f9fafb;
background: var(--c-bg);
border: 1px solid #e5e7eb;
border-radius: 8px;
}
+1 -1
View File
@@ -162,7 +162,7 @@ button.active { background: #2563eb; color: #fff; border-color: #2563eb; }
}
.query-block pre, .response-block pre {
margin: 4px 0 0;
background: #f9fafb;
background: var(--c-bg);
border: 1px solid #e5e7eb;
border-radius: 4px;
padding: 6px 10px;
+3 -3
View File
@@ -960,7 +960,7 @@ onUnmounted(() => { _dlSSE?.close() })
height: 100%;
overflow-y: auto;
padding: 24px;
background: #f9fafb;
background: var(--c-bg);
box-sizing: border-box;
/* 覆盖 router-view 注入的 .content 的 display:flexflex 列布局会把
overflow:hidden 的子项压缩截断而非撑出滚动条,导致页面无法滚动 */
@@ -1063,7 +1063,7 @@ onUnmounted(() => { _dlSSE?.close() })
justify-content: space-between;
align-items: center;
padding: 8px 12px;
background: #f9fafb;
background: var(--c-bg);
border-bottom: 1px solid #f3f4f6;
font-size: 13px;
font-weight: 500;
@@ -1273,7 +1273,7 @@ onUnmounted(() => { _dlSSE?.close() })
.btn-inline { font-size: 12px; }
.btn-ping {
background: #f9fafb;
background: var(--c-bg);
border: 1px solid #d1d5db;
border-radius: 6px;
padding: 6px 10px;
+8
View File
@@ -134,3 +134,11 @@
(备份/恢复),并向用户说明需重配 key。
- **运维提醒**:网关用 taskkill /T 停止会连带杀掉其启动的 llama-server 子进程;
重启网关后需在设置页重新启动 llama-server。
### 5.6 增补(同日):Web 界面视觉升级
- 全局设计系统 `webapp/src/style.css`(设计令牌:色板/圆角/阴影/统一滚动条/焦点环),
main.ts 正式引入(原为未使用的脚手架残留)。
- App.vue 重设计:顶部条 → 深色侧边栏壳(渐变 Logo、图标导航、激活态高亮条、网关状态脚注)。
- 各页浅层打磨:页面背景令牌化、卡片统一阴影、浏览器标题/lang 修正(原为"webapp"/en)。
- 功能零改动;构建产物同步。