Commit 478c4876 authored by luwei's avatar luwei

修改

parent 36e2cc19
...@@ -14,6 +14,13 @@ from app.services.data_management_service import DataManagementService ...@@ -14,6 +14,13 @@ from app.services.data_management_service import DataManagementService
class EvalService: class EvalService:
def __init__(self) -> None: def __init__(self) -> None:
self._dm = DataManagementService() self._dm = DataManagementService()
self._base_dir = Path(__file__).resolve().parents[2]
def _resolve_model_path(self, file_path: str) -> Path:
p = Path(file_path)
if p.is_absolute():
return p
return self._base_dir / p
# ── dropdown data ───────────────────────────────────────────────────────── # ── dropdown data ─────────────────────────────────────────────────────────
...@@ -39,7 +46,7 @@ class EvalService: ...@@ -39,7 +46,7 @@ class EvalService:
if not pkg: if not pkg:
raise ValueError('数据包不存在') raise ValueError('数据包不存在')
model_path = Path(model.file_path) model_path = self._resolve_model_path(model.file_path)
model_name = model.model_name model_name = model.model_name
package_name = pkg.name package_name = pkg.name
......
...@@ -23,7 +23,8 @@ _registry_lock = threading.Lock() ...@@ -23,7 +23,8 @@ _registry_lock = threading.Lock()
class TrainService: class TrainService:
def __init__(self) -> None: def __init__(self) -> None:
self._dm = DataManagementService() self._dm = DataManagementService()
self._models_dir = Path(__file__).resolve().parents[2] / 'saved_models' self._base_dir = Path(__file__).resolve().parents[2]
self._models_dir = self._base_dir / 'saved_models'
self._models_dir.mkdir(parents=True, exist_ok=True) self._models_dir.mkdir(parents=True, exist_ok=True)
# ── packages (for dropdown) ────────────────────────────────────────────── # ── packages (for dropdown) ──────────────────────────────────────────────
...@@ -147,7 +148,7 @@ class TrainService: ...@@ -147,7 +148,7 @@ class TrainService:
package_id=task.package_id, package_id=task.package_id,
package_name=task.package_name, package_name=task.package_name,
params=task.params, params=task.params,
file_path=str(model_path), file_path=model_path.relative_to(self._base_dir).as_posix(),
train_loss=task.train_loss, train_loss=task.train_loss,
val_loss=task.val_loss, val_loss=task.val_loss,
test_loss=task.test_loss, test_loss=task.test_loss,
...@@ -177,7 +178,7 @@ class TrainService: ...@@ -177,7 +178,7 @@ class TrainService:
task.is_saved = 0 task.is_saved = 0
# Delete the .pt file only if nothing else references it # Delete the .pt file only if nothing else references it
model_path = Path(model.file_path) model_path = self._resolve_model_path(model.file_path)
if model_path.exists(): if model_path.exists():
model_path.unlink(missing_ok=True) model_path.unlink(missing_ok=True)
...@@ -186,6 +187,12 @@ class TrainService: ...@@ -186,6 +187,12 @@ class TrainService:
# ── private helpers ─────────────────────────────────────────────────────── # ── private helpers ───────────────────────────────────────────────────────
def _resolve_model_path(self, file_path: str) -> Path:
"""Return absolute Path whether file_path is relative or absolute."""
p = Path(file_path)
if p.is_absolute():
return p
return self._base_dir / p
def _launch_thread(self, task_id: int, package_id: int, params: dict) -> None: def _launch_thread(self, task_id: int, package_id: int, params: dict) -> None:
cancel_event = threading.Event() cancel_event = threading.Event()
with _registry_lock: with _registry_lock:
......
import{A as e,D as t,Ht as n,I as r,N as i,X as a,d as o,m as s,st as c,t as l,u}from"./_plugin-vue_export-helper-D1RKUtCV.js";import{t as d}from"./echarts-B4btcaVd.js";var f={class:`curve-box`},p={class:`stats-row`},m={class:`stat-card`},h={class:`stat-value`},g={class:`stat-card`},_={class:`stat-value`},v={class:`stat-card`},y={class:`stat-value`},b=l({__name:`DataCurve`,props:{records:{type:Array,default:()=>[]}},setup(l){let b=l,x=c(null),S=null,C=u(()=>(Array.isArray(b.records)?b.records:[]).map((e,t)=>({idx:t,time:e.time||`第${t+1}条`,current:Number(e.current),voltage:Number(e.voltage),actual_temperature:Number(e.actual_temperature)})).filter(e=>Number.isFinite(e.current)||Number.isFinite(e.voltage)||Number.isFinite(e.actual_temperature))),w=u(()=>{let e=C.value.map(e=>e.actual_temperature).filter(e=>Number.isFinite(e));return{count:C.value.length,max:e.length?Math.max(...e):0,min:e.length?Math.min(...e):0}}),T=e=>Number.isFinite(e)?Number(e).toFixed(2):`--`,E=e=>C.value.map(t=>Number.isFinite(t[e])?t[e]:null),D=()=>{if(!x.value)return;S||=d(x.value);let e=C.value.length>0;S.setOption({animation:!0,color:[`#409EFF`,`#67C23A`,`#FF6B6B`],tooltip:{trigger:`axis`,backgroundColor:`rgba(255,255,255,0.96)`,borderColor:`#e2e8f0`,borderWidth:1,textStyle:{color:`#334155`},extraCssText:`box-shadow: 0 10px 30px rgba(15,23,42,0.16); border-radius: 12px;`,formatter(e){if(!e?.length)return``;let t=[`<div style="margin-bottom:6px;font-weight:600;">${e[0].axisValue}</div>`];return e.forEach(e=>{t.push(`<div style="display:flex;align-items:center;gap:6px;min-width:160px;justify-content:space-between;">
<span>${e.marker}${e.seriesName}</span>
<strong>${T(e.data)}</strong>
</div>`)}),t.join(``)}},legend:{bottom:0,itemWidth:18,itemHeight:10,textStyle:{color:`#475569`},data:[`电流(A)`,`电压(V)`,`温度(℃)`]},grid:{top:24,left:24,right:24,bottom:56,containLabel:!0},xAxis:{type:`category`,boundaryGap:!1,data:C.value.map(e=>e.time),axisLabel:{color:`#64748b`,rotate:35},axisLine:{lineStyle:{color:`#94a3b8`}}},yAxis:{type:`value`,axisLabel:{color:`#64748b`},splitLine:{lineStyle:{type:`dashed`,color:`rgba(148, 163, 184, 0.45)`}}},series:[{name:`电流(A)`,type:`line`,smooth:!0,symbol:`circle`,symbolSize:7,data:E(`current`)},{name:`电压(V)`,type:`line`,smooth:!0,symbol:`circle`,symbolSize:7,data:E(`voltage`)},{name:`温度(℃)`,type:`line`,smooth:!0,symbol:`circle`,symbolSize:7,data:E(`actual_temperature`)}],graphic:e?[]:[{type:`text`,left:`center`,top:`middle`,style:{text:`暂无足够数据生成曲线`,fill:`#64748b`,fontSize:14}}]},!0)},O=()=>{S?.resize()};return i(async()=>{await t(),D(),window.addEventListener(`resize`,O)}),a(()=>b.records,async()=>{await t(),D()},{deep:!0}),e(()=>{window.removeEventListener(`resize`,O),S?.dispose(),S=null}),(e,t)=>(r(),s(`div`,f,[o(`div`,p,[o(`div`,m,[t[0]||=o(`div`,{class:`stat-label`},`总条数`,-1),o(`div`,h,n(w.value.count),1)]),o(`div`,g,[t[1]||=o(`div`,{class:`stat-label`},`最高温度`,-1),o(`div`,_,n(T(w.value.max))+` °C`,1)]),o(`div`,v,[t[2]||=o(`div`,{class:`stat-label`},`最低温度`,-1),o(`div`,y,n(T(w.value.min))+` °C`,1)])]),o(`div`,{ref_key:`chartRef`,ref:x,class:`echarts-box`},null,512)]))}},[[`__scopeId`,`data-v-7c9af9ab`]]);export{b as t};
\ No newline at end of file
.curve-box[data-v-7c9af9ab]{flex-direction:column;gap:14px;height:100%;display:flex}.stats-row[data-v-7c9af9ab]{grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;display:grid}.stat-card[data-v-7c9af9ab]{background:#f3f6fb;border-radius:14px;padding:14px 16px}.stat-label[data-v-7c9af9ab]{color:#64748b;margin-bottom:8px;font-size:13px}.stat-value[data-v-7c9af9ab]{color:#0f172a;font-size:18px;font-weight:700}.echarts-box[data-v-7c9af9ab]{background:linear-gradient(#fff,#f8fafc);border:1px solid #0f172a1a;border-radius:14px;flex:1;min-height:360px}
import{a as e,c as t,f as n,h as r,n as i,o as ee,r as a,s as te}from"./es-DCOtnflc.js";import{$ as ne,A as o,B as s,H as re,Ht as ie,I as c,N as l,Q as u,R as ae,V as oe,Vt as d,_ as f,a as se,at as p,d as m,f as h,ht as g,m as _,p as ce,st as v,t as y,u as b,v as x,zt as le}from"./_plugin-vue_export-helper-D1RKUtCV.js";import{t as S}from"./request-D8DwihSV.js";import{t as ue}from"./DataCurve--Vg_Op5b.js";function C(){return S.get(`/data/categories`)}function w(e){return S.post(`/data/categories`,e)}function T(e,t){return S.put(`/data/categories/${e}`,t)}function E(e){return S.delete(`/data/categories/${e}`)}function de(e){return S.get(`/data/files`,{params:e})}function fe(e){return S.post(`/data/files/upload`,e,{headers:{"Content-Type":`multipart/form-data`}})}function pe(e){return S.delete(`/data/files/${e}`)}function me(e,t){return S.get(`/data/files/${e}/records`,{params:t})}function he(){return S.get(`/data/files/template`,{responseType:`blob`})}var ge={class:`pane-header`},_e={class:`tree-node`},ve={class:`tree-main`},ye={class:`tree-name`},be={key:0,class:`tree-actions`},xe={class:`pane-header`},Se={key:0,class:`file-title`},Ce={class:`content-wrap`},D=`data-management-layout-v1`,O=12,we=24,k=30,Te=56,A=24,j=y({__name:`index`,setup(y){let S=v([]),j=v(`all`),M=p({filename:``}),Ee=v([]),N=v(!1),P=v(null),F=v([]),I=v(!1),L=v(`table`),R=v(!1),z=v(`create`),B=v(``),V=p({name:``}),H=v(!1),U=p({categoryId:``}),W=v(null),G=v(16),K=v(38),q=v(null),J=v(null),Y=0,De=b(()=>{let e=100-G.value-K.value;return Number(e.toFixed(2))}),Oe=b(()=>z.value===`create`?`新增分类`:`编辑分类`),ke=b(()=>(S.value.find(e=>String(e.id)===`all`)?.children||[]).map(e=>({label:e.name,value:String(e.id)}))),Ae=e=>[{id:`all`,name:`全部`,parent_id:null,children:(Array.isArray(e)?e:[]).filter(e=>String(e?.id)!==`all`).map(e=>({id:e.id,name:e.name,parent_id:e.parent_id,children:[]}))}],X=(e,t,n=`left`)=>{let r=Math.min(Math.max(e,O),we),i=Math.min(Math.max(t,k),Te);100-r-i<A&&(n===`left`?(r=100-i-A,r<O&&(r=O,i=100-r-A)):(i=100-r-A,i<k&&(i=k,r=100-i-A))),G.value=Number(r.toFixed(2)),K.value=Number(i.toFixed(2))},je=()=>{let e=localStorage.getItem(D);if(e)try{let t=JSON.parse(e);typeof t.left==`number`&&typeof t.middle==`number`&&X(t.left,t.middle,`middle`)}catch{localStorage.removeItem(D)}},Me=()=>{localStorage.setItem(D,JSON.stringify({left:G.value,middle:K.value}))},Ne=e=>{if(!q.value)return;let t=(e-q.value.startX)/q.value.layoutWidth*100;q.value.target===`left`?X(q.value.startLeft+t,q.value.startMiddle,`left`):X(q.value.startLeft,q.value.startMiddle+t,`middle`)},Pe=()=>{Y=0,J.value!==null&&Ne(J.value)},Z=()=>{window.removeEventListener(`mousemove`,Fe),window.removeEventListener(`mouseup`,Z),window.removeEventListener(`mouseleave`,Z),window.removeEventListener(`blur`,Z),document.body.style.userSelect=``,document.body.style.cursor=``,Y&&=(cancelAnimationFrame(Y),0),J.value=null,q.value&&Me(),q.value=null},Fe=e=>{q.value&&(J.value=e.clientX,Y||=requestAnimationFrame(Pe))},Ie=(e,t)=>{window.innerWidth<=980||!W.value||(t.preventDefault(),Z(),q.value={target:e,startX:t.clientX,startLeft:G.value,startMiddle:K.value,layoutWidth:W.value.clientWidth},document.body.style.userSelect=`none`,document.body.style.cursor=`col-resize`,window.addEventListener(`mousemove`,Fe),window.addEventListener(`mouseup`,Z),window.addEventListener(`mouseleave`,Z),window.addEventListener(`blur`,Z))},Q=async()=>{S.value=Ae(await C()),[...S.value.map(e=>String(e.id)),...S.value.flatMap(e=>(e.children||[]).map(e=>String(e.id)))].includes(String(j.value))||(j.value=`all`)},$=async()=>{N.value=!0;try{Ee.value=await de({category_id:j.value&&j.value!==`all`?j.value:``,filename:M.filename.trim()})}finally{N.value=!1}},Le=async e=>{j.value=e.id,P.value=null,F.value=[],await $()},Re=()=>{z.value=`create`,B.value=``,V.name=``,R.value=!0},ze=e=>{z.value=`edit`,B.value=e.id,V.name=e.name,R.value=!0},Be=async()=>{let e=V.name.trim();if(!e){a.warning(`请输入分类名称`);return}z.value===`create`?await w({name:e,parent_id:null}):await T(B.value,{name:e}),R.value=!1,a.success(`分类保存成功`),await Q()},Ve=async e=>{try{await i.confirm(`确定删除分类“${e.name}”吗?`,`提示`,{type:`warning`}),await E(e.id),a.success(`分类已删除`),j.value===e.id&&(j.value=`all`),await Q(),await $()}catch{}},He=async()=>{await $()},Ue=async()=>{M.filename=``,await $()},We=()=>{U.categoryId=j.value&&j.value!==`all`?String(j.value):``,H.value=!0},Ge=e=>{if(!U.categoryId)return a.warning(`请先在弹窗中选择分类`),!1;let t=e.name.toLowerCase(),n=t.endsWith(`.xlsx`)||t.endsWith(`.xls`)||t.endsWith(`.csv`);return n||a.warning(`仅支持数据文件(.xlsx/.xls/.csv)`),n},Ke=async e=>{if(!U.categoryId){a.warning(`请先选择分类后再上传`),e.onError(Error(`未选择分类`));return}let t=new FormData;t.append(`file`,e.file),t.append(`category_id`,String(U.categoryId));try{await fe(t),j.value=String(U.categoryId),H.value=!1,a.success(`上传成功`),await $(),e.onSuccess()}catch(t){e.onError(t)}},qe=async()=>{let e=await he(),t=window.URL.createObjectURL(e),n=document.createElement(`a`);n.href=t,n.download=`data_template.xlsx`,document.body.appendChild(n),n.click(),n.remove(),window.URL.revokeObjectURL(t)},Je=async e=>{P.value=e,I.value=!0;try{F.value=(await me(e.id,{limit:500})).records}finally{I.value=!1}},Ye=async e=>{try{await i.confirm(`确定删除文件“${e.filename}”吗?`,`提示`,{type:`warning`}),await pe(e.id),a.success(`文件已删除`),P.value?.id===e.id&&(P.value=null,F.value=[]),await $()}catch{}};return l(async()=>{je(),await Q(),j.value=j.value||`all`,await $()}),o(()=>{Z()}),(i,a)=>{let o=s(`el-button`),l=s(`el-icon`),p=s(`el-tree`),v=s(`el-card`),y=s(`el-input`),b=s(`el-form-item`),C=s(`el-form`),w=s(`el-table-column`),T=s(`el-table`),E=s(`el-radio-button`),de=s(`el-radio-group`),fe=s(`el-empty`),pe=s(`el-option`),me=s(`el-select`),he=s(`el-upload`),D=s(`el-dialog`),O=oe(`loading`);return c(),_(`section`,{class:le([`data-page`,{dragging:!!q.value}])},[m(`div`,{ref_key:`layoutRef`,ref:W,class:`data-layout`},[x(v,{class:`pane-card pane-card--tree`,shadow:`hover`,style:d({width:`${G.value}%`})},{header:u(()=>[m(`div`,ge,[a[11]||=m(`div`,null,[m(`span`,null,`分类树`)],-1),x(o,{type:`primary`,plain:``,size:`small`,onClick:Re},{default:u(()=>[...a[10]||=[f(` 新增 `,-1)]]),_:1})])]),default:u(()=>[x(p,{data:S.value,"node-key":`id`,"highlight-current":``,"default-expand-all":``,"current-node-key":j.value||void 0,"expand-on-click-node":!1,onNodeClick:Le},{default:u(({data:n})=>[m(`div`,_e,[m(`div`,ve,[x(l,{class:`tree-icon`},{default:u(()=>[(c(),h(re(n.id===`all`?g(t):g(te))))]),_:2},1024),m(`span`,ye,ie(n.name),1)]),n.id===`all`?ce(``,!0):(c(),_(`span`,be,[x(o,{link:``,type:`primary`,icon:g(ee),onClick:r(e=>ze(n),[`stop`])},null,8,[`icon`,`onClick`]),x(o,{link:``,type:`danger`,icon:g(e),onClick:r(e=>Ve(n),[`stop`])},null,8,[`icon`,`onClick`])]))])]),_:1},8,[`data`,`current-node-key`])]),_:1},8,[`style`]),m(`div`,{class:`pane-divider`,onMousedown:a[0]||=r(e=>Ie(`left`,e),[`prevent`])},null,32),x(v,{class:`pane-card`,shadow:`hover`,style:d({width:`${K.value}%`})},{header:u(()=>[...a[12]||=[m(`div`,{class:`pane-header`},[m(`span`,null,`文件列表`)],-1)]]),default:u(()=>[x(C,{inline:!0,class:`search-form`},{default:u(()=>[x(b,null,{default:u(()=>[x(y,{modelValue:M.filename,"onUpdate:modelValue":a[1]||=e=>M.filename=e,placeholder:`文件名`,clearable:``},null,8,[`modelValue`])]),_:1}),x(b,null,{default:u(()=>[x(o,{type:`primary`,onClick:He},{default:u(()=>[...a[13]||=[f(`搜索`,-1)]]),_:1}),x(o,{onClick:Ue},{default:u(()=>[...a[14]||=[f(`重置`,-1)]]),_:1}),x(o,{type:`info`,plain:``,onClick:qe},{default:u(()=>[...a[15]||=[f(`下载模板`,-1)]]),_:1}),x(o,{type:`primary`,icon:g(n),onClick:We},{default:u(()=>[...a[16]||=[f(`上传文件`,-1)]]),_:1},8,[`icon`])]),_:1})]),_:1}),ne((c(),h(T,{data:Ee.value,border:``,stripe:``,height:`calc(100vh - 250px)`},{default:u(()=>[x(w,{prop:`filename`,label:`文件名`,"min-width":`160`}),x(w,{prop:`uploaded_at`,label:`上传时间`,"min-width":`170`}),x(w,{prop:`data_count`,label:`数据量`,width:`90`}),x(w,{label:`操作`,width:`150`,fixed:`right`},{default:u(({row:e})=>[x(o,{link:``,type:`primary`,onClick:t=>Je(e)},{default:u(()=>[...a[17]||=[f(`查看`,-1)]]),_:1},8,[`onClick`]),x(o,{link:``,type:`danger`,onClick:t=>Ye(e)},{default:u(()=>[...a[18]||=[f(`删除`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`])),[[O,N.value]])]),_:1},8,[`style`]),m(`div`,{class:`pane-divider`,onMousedown:a[2]||=r(e=>Ie(`middle`,e),[`prevent`])},null,32),x(v,{class:`pane-card`,shadow:`hover`,style:d({width:`${De.value}%`})},{header:u(()=>[m(`div`,xe,[m(`span`,null,[a[19]||=f(` 文件内容 `,-1),P.value?(c(),_(`span`,Se,`- `+ie(P.value.filename),1)):ce(``,!0)]),x(de,{modelValue:L.value,"onUpdate:modelValue":a[3]||=e=>L.value=e,size:`small`},{default:u(()=>[x(E,{value:`table`},{default:u(()=>[...a[20]||=[f(`表格`,-1)]]),_:1}),x(E,{value:`curve`},{default:u(()=>[...a[21]||=[f(`曲线`,-1)]]),_:1})]),_:1},8,[`modelValue`])])]),default:u(()=>[ne((c(),_(`div`,Ce,[P.value?L.value===`table`?(c(),h(T,{key:1,data:F.value,border:``,stripe:``,height:`calc(100vh - 250px)`},{default:u(()=>[x(w,{prop:`time`,label:`时间`,"min-width":`140`}),x(w,{prop:`current`,label:`电流`,"min-width":`100`}),x(w,{prop:`voltage`,label:`电压`,"min-width":`100`}),x(w,{prop:`set_temperature`,label:`设定温度`,"min-width":`100`}),x(w,{prop:`actual_temperature`,label:`实际温度`,"min-width":`100`})]),_:1},8,[`data`])):(c(),h(ue,{key:2,records:F.value},null,8,[`records`])):(c(),h(fe,{key:0,description:`请选择并查看一个文件`}))])),[[O,I.value]])]),_:1},8,[`style`])],512),x(D,{modelValue:H.value,"onUpdate:modelValue":a[6]||=e=>H.value=e,title:`上传数据文件`,width:`460px`},{footer:u(()=>[x(o,{onClick:a[5]||=e=>H.value=!1},{default:u(()=>[...a[24]||=[f(`关闭`,-1)]]),_:1})]),default:u(()=>[x(C,{"label-position":`top`},{default:u(()=>[x(b,{label:`选择分类`,required:``},{default:u(()=>[x(me,{modelValue:U.categoryId,"onUpdate:modelValue":a[4]||=e=>U.categoryId=e,placeholder:`请选择要上传到的分类`,style:{width:`100%`}},{default:u(()=>[(c(!0),_(se,null,ae(ke.value,e=>(c(),h(pe,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`])]),_:1}),x(b,{label:`上传文件`,required:``},{default:u(()=>[x(he,{class:`upload-panel`,drag:``,"show-file-list":!1,"http-request":Ke,"before-upload":Ge,accept:`.xlsx,.xls,.csv`},{tip:u(()=>[...a[22]||=[m(`div`,{class:`el-upload__tip`},`支持 .xlsx / .xls / .csv,上传前请先选择分类`,-1)]]),default:u(()=>[x(l,{class:`upload-panel__icon`},{default:u(()=>[x(g(n))]),_:1}),a[23]||=m(`div`,{class:`el-upload__text`},`拖拽文件到此处,或点击选择 Excel / CSV 文件`,-1)]),_:1})]),_:1})]),_:1})]),_:1},8,[`modelValue`]),x(D,{modelValue:R.value,"onUpdate:modelValue":a[9]||=e=>R.value=e,title:Oe.value,width:`420px`},{footer:u(()=>[x(o,{onClick:a[8]||=e=>R.value=!1},{default:u(()=>[...a[25]||=[f(`取消`,-1)]]),_:1}),x(o,{type:`primary`,onClick:Be},{default:u(()=>[...a[26]||=[f(`保存`,-1)]]),_:1})]),default:u(()=>[x(C,{"label-position":`top`},{default:u(()=>[x(b,{label:`分类名称`,required:``},{default:u(()=>[x(y,{modelValue:V.name,"onUpdate:modelValue":a[7]||=e=>V.name=e,maxlength:`100`,"show-word-limit":``},null,8,[`modelValue`])]),_:1})]),_:1})]),_:1},8,[`modelValue`,`title`])],2)}}},[[`__scopeId`,`data-v-7089f2ac`]]);export{j as default};
\ No newline at end of file
.train-page[data-v-fea158ef]{background:var(--bg-page);flex-direction:column;gap:12px;height:100%;display:flex;overflow-y:auto}.config-card[data-v-fea158ef],.tasks-card[data-v-fea158ef]{border:1px solid var(--border-color);border-radius:4px;flex-shrink:0;box-shadow:var(--shadow-card)!important}.config-card[data-v-fea158ef] .el-card__header,.tasks-card[data-v-fea158ef] .el-card__header{border-bottom:1px solid var(--border-color);background:#f7f8fa;align-items:center;height:44px;padding:0 20px;display:flex}.config-card[data-v-fea158ef] .el-card__body,.tasks-card[data-v-fea158ef] .el-card__body{padding:16px 20px}.tasks-card[data-v-fea158ef]{flex:1;min-height:0;overflow:hidden}.card-title[data-v-fea158ef]{color:var(--text-primary);font-size:14px;font-weight:600}.card-header-row[data-v-fea158ef]{justify-content:space-between;align-items:center;width:100%;display:flex}.train-form .form-row[data-v-fea158ef]{flex-wrap:wrap;gap:24px;margin-bottom:4px;display:flex}.train-form .form-item-wide[data-v-fea158ef]{flex:1;min-width:220px}.train-form .form-item-wide[data-v-fea158ef] .el-form-item__content{display:block}.params-section[data-v-fea158ef]{border-top:1px solid var(--border-color);margin-bottom:8px;padding-top:12px}.params-label[data-v-fea158ef]{color:var(--text-secondary);margin-bottom:12px;font-size:13px;font-weight:600;display:block}.params-grid[data-v-fea158ef]{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px 24px;display:grid}.params-grid[data-v-fea158ef] .el-form-item{margin-bottom:0}.form-action[data-v-fea158ef]{border-top:1px solid var(--border-color);text-align:right;padding-top:16px}.params-cell[data-v-fea158ef]{color:var(--text-secondary);white-space:nowrap;text-overflow:ellipsis;font-size:12px;display:block;overflow:hidden}.muted[data-v-fea158ef]{color:var(--text-tertiary)}.err-text[data-v-fea158ef]{color:#f53f3f;white-space:nowrap;text-overflow:ellipsis;font-size:12px;display:block;overflow:hidden}
import{n as e,r as t,u as n}from"./es-DCOtnflc.js";import{$ as ee,A as r,B as i,Ht as a,I as o,N as s,Q as c,R as l,V as u,_ as d,a as f,at as p,d as m,f as h,ht as g,m as _,st as v,t as y,u as b,v as x}from"./_plugin-vue_export-helper-D1RKUtCV.js";import{c as S,i as C,l as w,n as T,o as E,s as D,t as O}from"./trainManagement-TFX-G3Jl.js";var k={class:`train-page`},A={class:`form-row`},j={class:`params-section`},M={class:`params-grid`},N={class:`form-action`},P={class:`card-header-row`},F={class:`params-cell`},I={key:2,class:`muted`},L={key:0,class:`err-text`},R={key:1},z=`calc(100vh - 520px)`,B=y(Object.assign({},{__name:`index`,setup(y){let B=p({model_name:``,package_id:``,params:{seq_len:20,hidden_size:64,num_layers:2,epochs:50,batch_size:32,learning_rate:.001,train_ratio:.8}}),V=v([]),H=v(!1),U=v([]),W=v(!1),G=null,K=b(()=>U.value.some(e=>e.status===`pending`||e.status===`running`)),q=()=>{G||=setInterval(Y,3e3)},J=()=>{G&&=(clearInterval(G),null)},Y=async()=>{try{U.value=await D(),K.value?q():J()}catch{}},te=async()=>{if(!B.model_name.trim()){t.warning(`请输入模型名称`);return}if(!B.package_id){t.warning(`请选择数据包`);return}H.value=!0;try{await T({model_name:B.model_name.trim(),package_id:B.package_id,params:{...B.params}}),t.success(`训练任务已提交`),B.model_name=``,await Y()}finally{H.value=!1}},ne=async e=>{try{await O(e.id),t.success(`已发送取消请求`),await Y()}catch(e){t.error(e?.message||`取消失败`)}},X=async e=>{try{await S(e.id),t.success(`重新训练已启动`),await Y()}catch(e){t.error(e?.message||`重启失败`)}},re=async e=>{try{await w(e.id),t.success(`模型已保存,可在模型列表中查看`),await Y()}catch(e){t.error(e?.message||`保存失败`)}},Z=async n=>{try{await e.confirm(`确定删除训练任务"${n.model_name}"吗?`,`提示`,{type:`warning`}),await C(n.id),t.success(`已删除`),await Y()}catch{}},ie={pending:{type:`info`,text:`等待中`},running:{type:`warning`,text:`训练中`},completed:{type:`success`,text:`已完成`},failed:{type:`danger`,text:`失败`},cancelled:{type:``,text:`已取消`}},Q=e=>ie[e]||{type:`info`,text:e},$=e=>e?[`序列长度 ${e.seq_len}`,`隐藏层 ${e.hidden_size}`,`层数 ${e.num_layers}`,`轮数 ${e.epochs}`,`批次 ${e.batch_size}`,`学习率 ${e.learning_rate}`,`训练比 ${e.train_ratio}`].join(` / `):`-`,ae=e=>e.train_loss==null?`-`:`训练: ${Number(e.train_loss).toFixed(5)}`+(e.val_loss==null?``:` / 验证: ${Number(e.val_loss).toFixed(5)}`);return s(async()=>{W.value=!0;try{await Promise.all([E().then(e=>V.value=e),Y()])}finally{W.value=!1}}),r(J),(e,t)=>{let r=i(`el-option`),s=i(`el-select`),p=i(`el-form-item`),v=i(`el-input`),y=i(`el-input-number`),b=i(`el-button`),S=i(`el-form`),C=i(`el-card`),w=i(`el-table-column`),T=i(`el-tooltip`),E=i(`el-tag`),D=i(`el-progress`),O=i(`el-table`),G=u(`loading`);return o(),_(`div`,k,[x(C,{class:`config-card`,shadow:`hover`},{header:c(()=>[...t[9]||=[m(`span`,{class:`card-title`},`训练配置`,-1)]]),default:c(()=>[x(S,{model:B,"label-position":`top`,class:`train-form`},{default:c(()=>[m(`div`,A,[x(p,{label:`选择数据包`,required:``,class:`form-item-wide`},{default:c(()=>[x(s,{modelValue:B.package_id,"onUpdate:modelValue":t[0]||=e=>B.package_id=e,placeholder:`请选择数据包`,filterable:``,style:{width:`100%`}},{default:c(()=>[(o(!0),_(f,null,l(V.value,e=>(o(),h(r,{key:e.id,label:`${e.name}${e.data_count} 条)`,value:e.id},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`])]),_:1}),x(p,{label:`模型名称`,required:``,class:`form-item-wide`},{default:c(()=>[x(v,{modelValue:B.model_name,"onUpdate:modelValue":t[1]||=e=>B.model_name=e,placeholder:`请输入模型名称`,maxlength:`100`,"show-word-limit":``},null,8,[`modelValue`])]),_:1})]),m(`div`,j,[t[10]||=m(`span`,{class:`params-label`},`LSTM 超参数`,-1),m(`div`,M,[x(p,{label:`序列长度`},{default:c(()=>[x(y,{modelValue:B.params.seq_len,"onUpdate:modelValue":t[2]||=e=>B.params.seq_len=e,min:5,max:500,step:5,"controls-position":`right`,style:{width:`100%`}},null,8,[`modelValue`])]),_:1}),x(p,{label:`隐藏层大小`},{default:c(()=>[x(y,{modelValue:B.params.hidden_size,"onUpdate:modelValue":t[3]||=e=>B.params.hidden_size=e,min:8,max:1024,step:8,"controls-position":`right`,style:{width:`100%`}},null,8,[`modelValue`])]),_:1}),x(p,{label:`LSTM 层数`},{default:c(()=>[x(y,{modelValue:B.params.num_layers,"onUpdate:modelValue":t[4]||=e=>B.params.num_layers=e,min:1,max:8,"controls-position":`right`,style:{width:`100%`}},null,8,[`modelValue`])]),_:1}),x(p,{label:`训练轮数 (Epochs)`},{default:c(()=>[x(y,{modelValue:B.params.epochs,"onUpdate:modelValue":t[5]||=e=>B.params.epochs=e,min:1,max:2e3,step:10,"controls-position":`right`,style:{width:`100%`}},null,8,[`modelValue`])]),_:1}),x(p,{label:`批次大小 (Batch)`},{default:c(()=>[x(y,{modelValue:B.params.batch_size,"onUpdate:modelValue":t[6]||=e=>B.params.batch_size=e,min:1,max:512,step:8,"controls-position":`right`,style:{width:`100%`}},null,8,[`modelValue`])]),_:1}),x(p,{label:`学习率`},{default:c(()=>[x(y,{modelValue:B.params.learning_rate,"onUpdate:modelValue":t[7]||=e=>B.params.learning_rate=e,min:1e-5,max:1,step:1e-4,precision:5,"controls-position":`right`,style:{width:`100%`}},null,8,[`modelValue`])]),_:1}),x(p,{label:`训练集比例`},{default:c(()=>[x(y,{modelValue:B.params.train_ratio,"onUpdate:modelValue":t[8]||=e=>B.params.train_ratio=e,min:.5,max:.99,step:.05,precision:2,"controls-position":`right`,style:{width:`100%`}},null,8,[`modelValue`])]),_:1})])]),m(`div`,N,[x(b,{type:`primary`,size:`large`,loading:H.value,onClick:te},{default:c(()=>[...t[11]||=[d(` 开始训练 `,-1)]]),_:1},8,[`loading`])])]),_:1},8,[`model`])]),_:1}),x(C,{class:`tasks-card`,shadow:`hover`},{header:c(()=>[m(`div`,P,[t[13]||=m(`span`,{class:`card-title`},`训练记录`,-1),x(b,{icon:g(n),size:`small`,plain:``,loading:W.value,onClick:Y},{default:c(()=>[...t[12]||=[d(` 刷新 `,-1)]]),_:1},8,[`icon`,`loading`])])]),default:c(()=>[ee((o(),h(O,{data:U.value,border:``,stripe:``,height:z},{default:c(()=>[x(w,{prop:`model_name`,label:`模型名称`,"min-width":`140`,"show-overflow-tooltip":``}),x(w,{prop:`package_name`,label:`数据包`,"min-width":`130`,"show-overflow-tooltip":``}),x(w,{label:`参数`,"min-width":`180`,"show-overflow-tooltip":``},{default:c(({row:e})=>[x(T,{content:$(e.params),placement:`top`},{default:c(()=>[m(`span`,F,a($(e.params)),1)]),_:2},1032,[`content`])]),_:1}),x(w,{label:`状态`,width:`100`,align:`center`},{default:c(({row:e})=>[x(E,{type:Q(e.status).type,size:`small`},{default:c(()=>[d(a(Q(e.status).text),1)]),_:2},1032,[`type`])]),_:1}),x(w,{label:`进度`,width:`150`,align:`center`},{default:c(({row:e})=>[e.status===`running`?(o(),h(D,{key:0,percentage:e.progress,"stroke-width":6,"show-text":!0,style:{width:`120px`}},null,8,[`percentage`])):e.status===`completed`?(o(),h(D,{key:1,percentage:100,status:`success`,"stroke-width":6,style:{width:`120px`}})):(o(),_(`span`,I,`—`))]),_:1}),x(w,{label:`损失`,"min-width":`200`,"show-overflow-tooltip":``},{default:c(({row:e})=>[e.status===`failed`?(o(),_(`span`,L,a(e.error_msg||`未知错误`),1)):(o(),_(`span`,R,a(ae(e)),1))]),_:1}),x(w,{prop:`created_at`,label:`创建时间`,width:`160`}),x(w,{label:`操作`,width:`210`,fixed:`right`},{default:c(({row:e})=>[e.status===`running`||e.status===`pending`?(o(),h(b,{key:0,link:``,type:`warning`,onClick:t=>ne(e)},{default:c(()=>[...t[14]||=[d(`取消`,-1)]]),_:1},8,[`onClick`])):e.status===`completed`?(o(),_(f,{key:1},[e.is_saved?(o(),h(E,{key:1,type:`success`,size:`small`,style:{"margin-right":`6px`}},{default:c(()=>[...t[16]||=[d(`已保存`,-1)]]),_:1})):(o(),h(b,{key:0,link:``,type:`primary`,onClick:t=>re(e)},{default:c(()=>[...t[15]||=[d(` 保存模型 `,-1)]]),_:1},8,[`onClick`])),x(b,{link:``,type:`info`,onClick:t=>X(e)},{default:c(()=>[...t[17]||=[d(`重新训练`,-1)]]),_:1},8,[`onClick`]),x(b,{link:``,type:`danger`,onClick:t=>Z(e)},{default:c(()=>[...t[18]||=[d(`删除`,-1)]]),_:1},8,[`onClick`])],64)):(o(),_(f,{key:2},[x(b,{link:``,type:`info`,onClick:t=>X(e)},{default:c(()=>[...t[19]||=[d(`重新训练`,-1)]]),_:1},8,[`onClick`]),x(b,{link:``,type:`danger`,onClick:t=>Z(e)},{default:c(()=>[...t[20]||=[d(`删除`,-1)]]),_:1},8,[`onClick`])],64))]),_:1})]),_:1},8,[`data`])),[[G,W.value]])]),_:1})])}}}),[[`__scopeId`,`data-v-fea158ef`]]);export{B as default};
\ No newline at end of file
.pane-card[data-v-bbcd2093]{border:none;border-right:1px solid var(--border-color);background:var(--bg-white);border-radius:0;flex-direction:column;height:100%;display:flex;overflow:hidden;box-shadow:none!important}.pane-card[data-v-bbcd2093] .el-card__header{border-bottom:1px solid var(--border-color);background:#f7f8fa;align-items:center;height:44px;padding:0 16px;display:flex}.pane-card[data-v-bbcd2093] .el-card__body{flex:1;padding:8px 0;overflow-y:auto}.pane-header[data-v-bbcd2093]{width:100%;color:var(--text-primary);justify-content:space-between;align-items:center;font-size:14px;font-weight:600;display:flex}.tree-node[data-v-bbcd2093]{justify-content:space-between;align-items:center;width:100%;min-width:0;padding-right:4px;display:flex}.tree-main[data-v-bbcd2093]{align-items:center;gap:6px;min-width:0;display:flex}.tree-icon[data-v-bbcd2093]{color:var(--primary);flex-shrink:0;font-size:14px}.tree-name[data-v-bbcd2093]{text-overflow:ellipsis;white-space:nowrap;color:var(--text-primary);font-size:13px;overflow:hidden}.tree-actions[data-v-bbcd2093]{flex-shrink:0;gap:0;display:none}.tree-actions .el-button[data-v-bbcd2093]{color:var(--text-tertiary);padding:0 3px;font-size:13px}.tree-actions .el-button[data-v-bbcd2093]:hover{color:var(--primary)}.tree-node:hover .tree-actions[data-v-bbcd2093]{display:inline-flex}.pane-card[data-v-8f5781ed]{border:none;border-right:1px solid var(--border-color);background:var(--bg-white);border-radius:0;flex-direction:column;height:100%;display:flex;overflow:hidden;box-shadow:none!important}.pane-card[data-v-8f5781ed] .el-card__header{border-bottom:1px solid var(--border-color);background:#f7f8fa;align-items:center;height:44px;padding:0 16px;display:flex}.pane-card[data-v-8f5781ed] .el-card__body{flex:1;padding:12px 16px;overflow:hidden}.pane-header[data-v-8f5781ed]{width:100%;color:var(--text-primary);justify-content:space-between;align-items:center;font-size:14px;font-weight:600;display:flex}.search-bar[data-v-8f5781ed]{gap:8px;margin-bottom:12px;display:flex}.search-bar .el-input[data-v-8f5781ed]{flex:1}[data-v-8f5781ed] .el-table .current-row>td{background:var(--primary-light)!important}[data-v-8f5781ed] .el-table .el-button.is-link{height:auto;padding:0 4px;font-size:13px;line-height:1}.pane-card[data-v-6b2fedfc]{background:var(--bg-white);border:none;border-radius:0;flex-direction:column;height:100%;display:flex;overflow:hidden;box-shadow:none!important}.pane-card[data-v-6b2fedfc] .el-card__header{border-bottom:1px solid var(--border-color);background:#f7f8fa;align-items:center;height:44px;padding:0 16px;display:flex}.pane-card[data-v-6b2fedfc] .el-card__body{flex:1;padding:0;overflow:hidden}.pane-header[data-v-6b2fedfc]{width:100%;color:var(--text-primary);justify-content:space-between;align-items:center;font-size:14px;font-weight:600;display:flex}.pkg-title[data-v-6b2fedfc]{color:var(--text-secondary);margin-left:4px;font-size:13px;font-weight:400}.content-wrap[data-v-6b2fedfc]{height:100%;padding:0 16px 12px}[data-v-6b2fedfc] .el-radio-group .el-radio-button__inner{color:var(--text-secondary);border-color:var(--border-color);background:0 0;padding:4px 12px;font-size:13px}[data-v-6b2fedfc] .el-radio-group .el-radio-button__original-radio:checked+.el-radio-button__inner{color:#fff;background:var(--primary)!important;border-color:var(--primary)!important;box-shadow:none!important}.add-pkg-page[data-v-03a732e5]{flex-direction:column;gap:0;height:100%;display:flex;overflow:hidden}.add-pkg-header[data-v-03a732e5]{background:#ffffffe6;border-bottom:1px solid #e8edf3;flex-shrink:0;align-items:center;gap:16px;padding:12px 20px;display:flex}.add-pkg-title[data-v-03a732e5]{color:#0f172a;font-size:16px;font-weight:600}.section-card[data-v-03a732e5]{background:#fff;border:1px solid #e8edf3;border-radius:8px;padding:16px;overflow:hidden}.section-title[data-v-03a732e5]{color:#0f172a;align-items:center;gap:8px;margin-bottom:12px;font-size:14px;font-weight:600;display:flex}.section-hint[data-v-03a732e5]{color:#64748b;font-size:12px;font-weight:400}.file-search-bar[data-v-03a732e5]{margin-bottom:10px}.file-section[data-v-03a732e5]{flex-shrink:0;margin:12px 12px 0}.section-bottom[data-v-03a732e5]{flex:1;gap:12px;min-height:0;padding:12px;display:flex;overflow:hidden}.form-section[data-v-03a732e5]{flex-shrink:0;width:320px;overflow-y:auto}.preview-section[data-v-03a732e5]{flex-direction:column;flex:1;min-width:0;display:flex;overflow:hidden}.preview-section .section-title[data-v-03a732e5]{flex-shrink:0}.preview-content[data-v-03a732e5]{flex:1;min-height:0;overflow:hidden}.pkg-form[data-v-03a732e5] .el-form-item{margin-bottom:16px}.pkg-page[data-v-bc327363]{background:var(--bg-page);height:100%}.pkg-page.dragging[data-v-bc327363]{-webkit-user-select:none;user-select:none;cursor:col-resize}.pkg-layout[data-v-bc327363]{background:var(--bg-white);border:1px solid var(--border-color);height:100%;box-shadow:var(--shadow-card);align-items:stretch;gap:0;display:flex}.pane-divider[data-v-bc327363]{background:var(--border-color);cursor:col-resize;flex-shrink:0;width:4px;transition:background .15s;position:relative}.pane-divider[data-v-bc327363]:after{content:"";position:absolute;inset:0 -2px}.pane-divider[data-v-bc327363]:hover,.dragging .pane-divider[data-v-bc327363]{background:var(--primary-border)}
import{a as e,c as t,d as n,h as r,i,l as a,m as o,n as s,o as c,r as l,s as u}from"./es-DCOtnflc.js";import{$ as d,A as f,B as p,H as m,Ht as h,I as g,N as _,Q as v,R as y,V as b,Vt as x,X as S,_ as C,a as w,at as T,d as E,f as D,ht as O,m as k,p as A,st as j,t as M,u as N,v as P,zt as F}from"./_plugin-vue_export-helper-D1RKUtCV.js";import{t as I}from"./request-D8DwihSV.js";import{t as L}from"./DataCurve--Vg_Op5b.js";function R(){return I.get(`/packages/categories`)}function z(e){return I.post(`/packages/categories`,e)}function B(e,t){return I.put(`/packages/categories/${e}`,t)}function V(e){return I.delete(`/packages/categories/${e}`)}function H(){return I.get(`/packages/data-files`)}function U(e){return I.get(`/packages`,{params:e})}function W(e){return I.post(`/packages`,e)}function G(e){return I.delete(`/packages/${e}`)}function ee(e,t){return I.get(`/packages/${e}/records`,{params:t})}function te(e,t){return I.post(`/packages/preview`,e,{params:t})}var ne={class:`pane-header`},re={class:`tree-node`},ie={class:`tree-main`},K={class:`tree-name`},q={key:0,class:`tree-actions`},J=M({__name:`PkgCategoryTree`,props:{modelValue:{type:[String,Number],default:`all`},style:{type:Object,default:()=>({})}},emits:[`update:modelValue`,`select`],setup(n,{emit:i}){let a=n,o=i,d=j([]),f=j(!1),y=j(`create`),b=j(``),S=T({name:``}),M=N(()=>y.value===`create`?`新增分类`:`编辑分类`),F=e=>[{id:`all`,name:`全部`,parent_id:null,children:(Array.isArray(e)?e:[]).filter(e=>String(e?.id)!==`all`).map(e=>({id:e.id,name:e.name,parent_id:e.parent_id,children:[]}))}],I=async()=>{d.value=F(await R()),[...d.value.map(e=>String(e.id)),...d.value.flatMap(e=>(e.children||[]).map(e=>String(e.id)))].includes(String(a.modelValue))||(o(`update:modelValue`,`all`),o(`select`,`all`))},L=e=>{o(`update:modelValue`,e.id),o(`select`,e.id)},H=()=>{y.value=`create`,b.value=``,S.name=``,f.value=!0},U=e=>{y.value=`edit`,b.value=e.id,S.name=e.name,f.value=!0},W=async()=>{let e=S.name.trim();if(!e){l.warning(`请输入分类名称`);return}y.value===`create`?await z({name:e,parent_id:null}):await B(b.value,{name:e}),f.value=!1,l.success(`分类保存成功`),await I()},G=async e=>{try{await s.confirm(`确定删除分类"${e.name}"吗?`,`提示`,{type:`warning`}),await V(e.id),l.success(`分类已删除`),String(a.modelValue)===String(e.id)&&(o(`update:modelValue`,`all`),o(`select`,`all`)),await I()}catch{}};return _(I),(i,o)=>{let s=p(`el-button`),l=p(`el-icon`),_=p(`el-tree`),y=p(`el-card`),b=p(`el-input`),T=p(`el-form-item`),j=p(`el-form`),N=p(`el-dialog`);return g(),k(w,null,[P(y,{class:`pane-card`,shadow:`hover`,style:x(a.style)},{header:v(()=>[E(`div`,ne,[o[4]||=E(`span`,null,`分类树`,-1),P(s,{type:`primary`,plain:``,size:`small`,onClick:H},{default:v(()=>[...o[3]||=[C(`新增`,-1)]]),_:1})])]),default:v(()=>[P(_,{data:d.value,"node-key":`id`,"highlight-current":``,"default-expand-all":``,"current-node-key":n.modelValue||void 0,"expand-on-click-node":!1,onNodeClick:L},{default:v(({data:n})=>[E(`div`,re,[E(`div`,ie,[P(l,{class:`tree-icon`},{default:v(()=>[(g(),D(m(n.id===`all`?O(t):O(u))))]),_:2},1024),E(`span`,K,h(n.name),1)]),n.id===`all`?A(``,!0):(g(),k(`span`,q,[P(s,{link:``,type:`primary`,icon:O(c),onClick:r(e=>U(n),[`stop`])},null,8,[`icon`,`onClick`]),P(s,{link:``,type:`danger`,icon:O(e),onClick:r(e=>G(n),[`stop`])},null,8,[`icon`,`onClick`])]))])]),_:1},8,[`data`,`current-node-key`])]),_:1},8,[`style`]),P(N,{modelValue:f.value,"onUpdate:modelValue":o[2]||=e=>f.value=e,title:M.value,width:`420px`},{footer:v(()=>[P(s,{onClick:o[1]||=e=>f.value=!1},{default:v(()=>[...o[5]||=[C(`取消`,-1)]]),_:1}),P(s,{type:`primary`,onClick:W},{default:v(()=>[...o[6]||=[C(`保存`,-1)]]),_:1})]),default:v(()=>[P(j,{"label-position":`top`},{default:v(()=>[P(T,{label:`分类名称`,required:``},{default:v(()=>[P(b,{modelValue:S.name,"onUpdate:modelValue":o[0]||=e=>S.name=e,maxlength:`100`,"show-word-limit":``},null,8,[`modelValue`])]),_:1})]),_:1})]),_:1},8,[`modelValue`,`title`])],64)}}},[[`__scopeId`,`data-v-bbcd2093`]]),ae={class:`pane-header`},oe={class:`search-bar`},se=M({__name:`PkgList`,props:{categoryId:{type:[String,Number],default:`all`},refreshKey:{type:Number,default:0},style:{type:Object,default:()=>({})}},emits:[`view`,`add`],setup(e,{emit:t}){let r=e,i=t,c=j(!1),u=j([]),f=j(``),m=j(null),h=async()=>{c.value=!0;try{u.value=await U({category_id:r.categoryId&&String(r.categoryId)!==`all`?String(r.categoryId):``,name:f.value.trim()})}finally{c.value=!1}},y=()=>h(),w=()=>{f.value=``,h()},T=e=>{m.value=e,i(`view`,e)},k=async e=>{try{await s.confirm(`确定删除数据包"${e.name}"吗?`,`提示`,{type:`warning`}),await G(e.id),l.success(`数据包已删除`),m.value?.id===e.id&&(m.value=null),await h()}catch{}};return S(()=>r.categoryId,h),S(()=>r.refreshKey,()=>{m.value=null,h()}),_(h),(e,t)=>{let s=p(`el-button`),l=p(`el-input`),h=p(`el-table-column`),_=p(`el-table`),S=p(`el-card`),A=b(`loading`);return g(),D(S,{class:`pane-card`,shadow:`hover`,style:x(r.style)},{header:v(()=>[E(`div`,ae,[t[3]||=E(`span`,null,`数据包列表`,-1),P(s,{type:`primary`,icon:O(a),size:`small`,onClick:t[0]||=e=>i(`add`)},{default:v(()=>[...t[2]||=[C(`新增数据包`,-1)]]),_:1},8,[`icon`])])]),default:v(()=>[E(`div`,oe,[P(l,{modelValue:f.value,"onUpdate:modelValue":t[1]||=e=>f.value=e,placeholder:`数据包名称`,clearable:``,"prefix-icon":O(n),onKeyup:o(y,[`enter`]),onClear:w},null,8,[`modelValue`,`prefix-icon`]),P(s,{type:`primary`,onClick:y},{default:v(()=>[...t[4]||=[C(`搜索`,-1)]]),_:1}),P(s,{onClick:w},{default:v(()=>[...t[5]||=[C(`重置`,-1)]]),_:1})]),d((g(),D(_,{data:u.value,border:``,stripe:``,"highlight-current-row":``,height:`calc(100vh - 265px)`,"row-class-name":({row:e})=>m.value?.id===e.id?`current-row`:``},{default:v(()=>[P(h,{prop:`name`,label:`数据包名称`,"min-width":`150`,"show-overflow-tooltip":``}),P(h,{prop:`created_at`,label:`创建时间`,"min-width":`160`}),P(h,{prop:`data_count`,label:`数据量`,width:`80`,align:`center`}),P(h,{label:`操作`,width:`130`,fixed:`right`},{default:v(({row:e})=>[P(s,{link:``,type:`primary`,onClick:t=>T(e)},{default:v(()=>[...t[6]||=[C(`查看`,-1)]]),_:1},8,[`onClick`]),P(s,{link:``,type:`danger`,onClick:t=>k(e)},{default:v(()=>[...t[7]||=[C(`删除`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`,`row-class-name`])),[[A,c.value]])]),_:1},8,[`style`])}}},[[`__scopeId`,`data-v-8f5781ed`]]),ce={class:`pane-header`},le={key:0,class:`pkg-title`},ue={class:`content-wrap`},de=M({__name:`PkgDetail`,props:{package:{type:Object,default:null},style:{type:Object,default:()=>({})}},setup(e){let t=e,n=j(!1),r=j([]),i=j(`table`),a=async e=>{if(!e){r.value=[];return}n.value=!0;try{r.value=(await ee(e.id,{limit:500})).records}finally{n.value=!1}};return S(()=>t.package,e=>{i.value=`table`,a(e)},{immediate:!0}),(e,a)=>{let o=p(`el-radio-button`),s=p(`el-radio-group`),c=p(`el-empty`),l=p(`el-table-column`),u=p(`el-table`),f=p(`el-card`),m=b(`loading`);return g(),D(f,{class:`pane-card`,shadow:`hover`,style:x(t.style)},{header:v(()=>[E(`div`,ce,[E(`span`,null,[a[1]||=C(` 数据包内容 `,-1),t.package?(g(),k(`span`,le,`— `+h(t.package.name),1)):A(``,!0)]),P(s,{modelValue:i.value,"onUpdate:modelValue":a[0]||=e=>i.value=e,size:`small`},{default:v(()=>[P(o,{value:`table`},{default:v(()=>[...a[2]||=[C(`表格`,-1)]]),_:1}),P(o,{value:`curve`},{default:v(()=>[...a[3]||=[C(`曲线`,-1)]]),_:1})]),_:1},8,[`modelValue`])])]),default:v(()=>[d((g(),k(`div`,ue,[t.package?i.value===`table`?(g(),D(u,{key:1,data:r.value,border:``,stripe:``,height:`calc(100vh - 250px)`},{default:v(()=>[P(l,{prop:`time`,label:`时间`,"min-width":`140`}),P(l,{prop:`current`,label:`电流`,"min-width":`90`}),P(l,{prop:`voltage`,label:`电压`,"min-width":`90`}),P(l,{prop:`set_temperature`,label:`设定温度`,"min-width":`100`}),P(l,{prop:`actual_temperature`,label:`实际温度`,"min-width":`100`})]),_:1},8,[`data`])):(g(),D(L,{key:2,records:r.value},null,8,[`records`])):(g(),D(c,{key:0,description:`请选择一个数据包查看`}))])),[[m,n.value]])]),_:1},8,[`style`])}}},[[`__scopeId`,`data-v-6b2fedfc`]]),fe={class:`add-pkg-page`},pe={class:`add-pkg-header`},me={class:`section-card file-section`},he={class:`section-title`},ge={class:`section-hint`},_e={class:`file-search-bar`},ve={class:`section-bottom`},ye={class:`section-card form-section`},be={class:`section-card preview-section`},xe={class:`section-title`},Y={key:0,class:`section-hint`},Se={class:`preview-content`},Ce=M({__name:`AddPackage`,emits:[`cancel`,`saved`],setup(e,{emit:t}){let n=t,r=j([]),a=j([]),o=j(null),s=j(``),c=N(()=>{let e=s.value.trim().toLowerCase();return e?r.value.filter(t=>t.filename.toLowerCase().includes(e)||(t.category_name||``).toLowerCase().includes(e)):r.value}),u=e=>{a.value=e.map(e=>e.id)},f=j([]),m=async()=>{let e=await R();f.value=(Array.isArray(e)?e:[]).filter(e=>String(e?.id)!==`all`).map(e=>({label:e.name,value:String(e.id)}))},x=T({categoryId:``,name:``,remark:``}),M=j(!1),F=j([]),I=j(0),z=j(`table`),B=null;S(a,()=>{if(clearTimeout(B),!a.value.length){F.value=[],I.value=0;return}B=setTimeout(async()=>{M.value=!0;try{let e=await te({file_ids:a.value},{limit:300});F.value=e.records,I.value=e.count}finally{M.value=!1}},600)},{deep:!0});let V=j(!1),U=async()=>{if(!x.name.trim()){l.warning(`请输入数据包名称`);return}if(!a.value.length){l.warning(`请至少选择一个数据文件`);return}V.value=!0;try{await W({name:x.name.trim(),category_id:x.categoryId||null,remark:x.remark.trim()||null,file_ids:a.value}),l.success(`数据包创建成功`),n(`saved`)}finally{V.value=!1}};return _(async()=>{let[e]=await Promise.all([H(),m()]);r.value=e}),(e,t)=>{let r=p(`el-button`),l=p(`el-input`),m=p(`el-table-column`),_=p(`el-table`),S=p(`el-option`),T=p(`el-select`),j=p(`el-form-item`),N=p(`el-form`),R=p(`el-radio-button`),B=p(`el-radio-group`),H=p(`el-empty`),W=b(`loading`);return g(),k(`div`,fe,[E(`div`,pe,[P(r,{icon:O(i),plain:``,onClick:t[0]||=e=>n(`cancel`)},{default:v(()=>[...t[6]||=[C(`返回列表`,-1)]]),_:1},8,[`icon`]),t[7]||=E(`span`,{class:`add-pkg-title`},`新增数据包`,-1)]),E(`div`,me,[E(`div`,he,[t[8]||=C(` 选择数据文件 `,-1),E(`span`,ge,`已选 `+h(a.value.length)+` 个文件`,1)]),E(`div`,_e,[P(l,{modelValue:s.value,"onUpdate:modelValue":t[1]||=e=>s.value=e,placeholder:`按文件名或分类搜索`,clearable:``,style:{width:`280px`}},null,8,[`modelValue`])]),P(_,{ref_key:`fileTableRef`,ref:o,data:c.value,border:``,stripe:``,height:`220`,onSelectionChange:u},{default:v(()=>[P(m,{type:`selection`,width:`46`}),P(m,{prop:`filename`,label:`文件名`,"min-width":`200`,"show-overflow-tooltip":``}),P(m,{prop:`category_name`,label:`所属分类`,width:`130`,"show-overflow-tooltip":``}),P(m,{prop:`data_count`,label:`数据量`,width:`80`,align:`center`}),P(m,{prop:`uploaded_at`,label:`上传时间`,width:`160`})]),_:1},8,[`data`])]),E(`div`,ve,[E(`div`,ye,[t[10]||=E(`div`,{class:`section-title`},`生成数据包`,-1),P(N,{"label-position":`top`,class:`pkg-form`},{default:v(()=>[P(j,{label:`数据包分类`},{default:v(()=>[P(T,{modelValue:x.categoryId,"onUpdate:modelValue":t[2]||=e=>x.categoryId=e,placeholder:`请选择(可选)`,clearable:``,style:{width:`100%`}},{default:v(()=>[(g(!0),k(w,null,y(f.value,e=>(g(),D(S,{key:e.value,label:e.label,value:e.value},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`])]),_:1}),P(j,{label:`数据包名称`,required:``},{default:v(()=>[P(l,{modelValue:x.name,"onUpdate:modelValue":t[3]||=e=>x.name=e,maxlength:`100`,"show-word-limit":``,placeholder:`请输入数据包名称`},null,8,[`modelValue`])]),_:1}),P(j,{label:`备注`},{default:v(()=>[P(l,{modelValue:x.remark,"onUpdate:modelValue":t[4]||=e=>x.remark=e,type:`textarea`,rows:3,maxlength:`500`,"show-word-limit":``,placeholder:`备注(可选)`},null,8,[`modelValue`])]),_:1}),P(j,null,{default:v(()=>[P(r,{type:`primary`,loading:V.value,style:{width:`100%`},onClick:U},{default:v(()=>[...t[9]||=[C(` 生成数据包 `,-1)]]),_:1},8,[`loading`])]),_:1})]),_:1})]),E(`div`,be,[E(`div`,xe,[t[13]||=C(` 生成结果预览 `,-1),I.value?(g(),k(`span`,Y,`共 `+h(I.value)+` 条(展示前 300 条)`,1)):A(``,!0),P(B,{modelValue:z.value,"onUpdate:modelValue":t[5]||=e=>z.value=e,size:`small`,style:{"margin-left":`auto`}},{default:v(()=>[P(R,{value:`table`},{default:v(()=>[...t[11]||=[C(`表格`,-1)]]),_:1}),P(R,{value:`curve`},{default:v(()=>[...t[12]||=[C(`曲线`,-1)]]),_:1})]),_:1},8,[`modelValue`])]),d((g(),k(`div`,Se,[!M.value&&!F.value.length?(g(),D(H,{key:0,description:`请在上方选择数据文件,预览将自动更新`,"image-size":80})):z.value===`table`?(g(),D(_,{key:1,data:F.value,border:``,stripe:``,height:`100%`},{default:v(()=>[P(m,{prop:`time`,label:`时间`,"min-width":`140`}),P(m,{prop:`current`,label:`电流`,"min-width":`80`}),P(m,{prop:`voltage`,label:`电压`,"min-width":`80`}),P(m,{prop:`set_temperature`,label:`设定温度`,"min-width":`100`}),P(m,{prop:`actual_temperature`,label:`实际温度`,"min-width":`100`})]),_:1},8,[`data`])):(g(),D(L,{key:2,records:F.value},null,8,[`records`]))])),[[W,M.value]])])])])}}},[[`__scopeId`,`data-v-03a732e5`]]),X=`pkg-management-layout-v1`,Z=12,we=24,Q=30,Te=56,$=24,Ee=M({__name:`index`,setup(e){let t=j(`list`),n=j(`all`),i=j(null),a=j(0),o=e=>{n.value=e,i.value=null},s=e=>{i.value=e},c=()=>{t.value=`add`},l=()=>{t.value=`list`,a.value++,i.value=null},u=()=>{t.value=`list`},d=j(null),p=j(16),m=j(38),h=j(null),v=j(null),y=0,b=N(()=>Number((100-p.value-m.value).toFixed(2))),S=(e,t,n=`left`)=>{let r=Math.min(Math.max(e,Z),we),i=Math.min(Math.max(t,Q),Te);100-r-i<$&&(n===`left`?(r=100-i-$,r<Z&&(r=Z,i=100-r-$)):(i=100-r-$,i<Q&&(i=Q,r=100-i-$))),p.value=Number(r.toFixed(2)),m.value=Number(i.toFixed(2))},C=()=>{let e=localStorage.getItem(X);if(e)try{let t=JSON.parse(e);typeof t.left==`number`&&typeof t.middle==`number`&&S(t.left,t.middle,`middle`)}catch{localStorage.removeItem(X)}},w=()=>{localStorage.setItem(X,JSON.stringify({left:p.value,middle:m.value}))},T=e=>{if(!h.value)return;let t=(e-h.value.startX)/h.value.layoutWidth*100;h.value.target===`left`?S(h.value.startLeft+t,h.value.startMiddle,`left`):S(h.value.startLeft,h.value.startMiddle+t,`middle`)},O=()=>{y=0,v.value!==null&&T(v.value)},A=()=>{window.removeEventListener(`mousemove`,M),window.removeEventListener(`mouseup`,A),window.removeEventListener(`mouseleave`,A),window.removeEventListener(`blur`,A),document.body.style.userSelect=``,document.body.style.cursor=``,y&&=(cancelAnimationFrame(y),0),v.value=null,h.value&&w(),h.value=null},M=e=>{h.value&&(v.value=e.clientX,y||=requestAnimationFrame(O))},I=(e,t)=>{window.innerWidth<=980||!d.value||(t.preventDefault(),A(),h.value={target:e,startX:t.clientX,startLeft:p.value,startMiddle:m.value,layoutWidth:d.value.clientWidth},document.body.style.userSelect=`none`,document.body.style.cursor=`col-resize`,window.addEventListener(`mousemove`,M),window.addEventListener(`mouseup`,A),window.addEventListener(`mouseleave`,A),window.addEventListener(`blur`,A))};return _(C),f(A),(e,f)=>(g(),k(`section`,{class:F([`pkg-page`,{dragging:!!h.value}])},[t.value===`add`?(g(),D(Ce,{key:0,onSaved:l,onCancel:u})):(g(),k(`div`,{key:1,ref_key:`layoutRef`,ref:d,class:`pkg-layout`},[P(J,{"model-value":n.value,style:x({width:`${p.value}%`}),"onUpdate:modelValue":f[0]||=e=>n.value=e,onSelect:o},null,8,[`model-value`,`style`]),E(`div`,{class:`pane-divider`,onMousedown:f[1]||=r(e=>I(`left`,e),[`prevent`])},null,32),P(se,{"category-id":n.value,"refresh-key":a.value,style:x({width:`${m.value}%`}),onView:s,onAdd:c},null,8,[`category-id`,`refresh-key`,`style`]),E(`div`,{class:`pane-divider`,onMousedown:f[2]||=r(e=>I(`middle`,e),[`prevent`])},null,32),P(de,{package:i.value,style:x({width:`${b.value}%`})},null,8,[`package`,`style`])],512))],2))}},[[`__scopeId`,`data-v-bc327363`]]);export{Ee as default};
\ No newline at end of file
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>热实验温度控制系统</title> <title>热实验温度控制系统</title>
<script type="module" crossorigin src="/assets/index-D5S_ELZm.js"></script> <script type="module" crossorigin src="/assets/index-CvdqK_rU.js"></script>
<link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-D1RKUtCV.js"> <link rel="modulepreload" crossorigin href="/assets/_plugin-vue_export-helper-D1RKUtCV.js">
<link rel="modulepreload" crossorigin href="/assets/es-DCOtnflc.js"> <link rel="modulepreload" crossorigin href="/assets/es-DCOtnflc.js">
<link rel="stylesheet" crossorigin href="/assets/index-BrwBxauG.css"> <link rel="stylesheet" crossorigin href="/assets/index-pfQxyObg.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment