4 lines
16 KiB
JavaScript
4 lines
16 KiB
JavaScript
import{_ as he,r as h,N as be,u as we,o as xe,m as b,f as e,w as t,b as ke,l as Ee,a as q,E as x,d as i,e as Ce,c as y,M as S,A as Me,y as De,z as Ve,B as Fe,C as Ae,F as Pe,D as Te,G as Ne,O as Se,H as ze,j as Ie,k as r,P as Re,I as _,Q as Ue,R as $,n as o,q as Z,h as Le,i as Ye,J as $e,K as n,S as Be,T as Oe,p as je,v as qe,U as Ke,V as Ge,W as B,X as He,Y as Je,Z as Qe,$ as We,a0 as Xe,a1 as Ze,a2 as et,a3 as tt,a4 as at,a5 as lt}from"./index-CtyWzmh7.js";/* empty css *//* empty css *//* empty css *//* empty css *//* empty css *//* empty css */const st={class:"prediction-view"},ot={class:"card-header"},dt={style:{"margin-left":"8px"}},nt={class:"metrics-display"},rt={class:"metric-item"},it={class:"metric-value"},ut={class:"metric-item"},_t={class:"metric-value"},ct={class:"metric-item"},pt={class:"metric-value"},ft={class:"metric-item"},mt={class:"metric-value"},vt={class:"pagination-container"},yt={key:1,class:"loading-container"},gt={key:2,class:"result-container"},ht={class:"chart-container"},bt={class:"chart-container"},wt={key:1,class:"chart-placeholder",style:{height:"300px"}},xt={key:0,class:"prediction-dialog-content"},kt={class:"prediction-summary"},Et={class:"prediction-chart-container"},Ct={key:1,class:"chart-placeholder",style:{height:"400px"}},Mt={class:"prediction-chart-container"},Dt={key:1,class:"chart-placeholder",style:{height:"400px"}},Vt={class:"stat-cards"},Ft={class:"stat-value"},At={class:"stat-value"},Pt={class:"stat-value"},Tt={key:0},Nt={key:1},St={class:"dialog-footer"},zt={__name:"PredictionView",setup(It){const O=h([]),M=h(!1),z=h(!1),k=h(!1),D=h([]),d=h(null),K=h(""),j=h(""),I=h(""),V=h(1),T=h(10),ee=be(()=>{const s=(V.value-1)*T.value,a=s+T.value;return D.value.slice(s,a)}),c=we({product_id:"",model_type:"",start_date:new Date().toISOString().split("T")[0],future_days:7}),te=async()=>{try{const s=await q.get("/api/products");s.data.status==="success"&&(O.value=s.data.data)}catch(s){x.error("获取产品列表失败"),console.error(s)}},G=async()=>{z.value=!0,D.value=[],V.value=1;try{const s={};c.product_id&&(s.product_id=c.product_id),c.model_type&&(s.model_type=c.model_type);const a=await q.get("/api/models",{params:s});a.data.status==="success"&&(D.value=a.data.data,D.value.length===0&&x.info("没有找到符合条件的模型,请先训练模型或修改筛选条件"))}catch(s){x.error("获取可用模型列表失败"),console.error(s)}finally{z.value=!1}},ae=()=>{d.value=null},le=()=>{d.value=null},se=s=>{T.value=s,V.value=1},oe=s=>{V.value=s},de=async s=>{var a,f;K.value=s.model_id,j.value=s.model_type,I.value=s.product_id,M.value=!0,d.value=null;try{console.log(`开始预测,起始日期: ${c.start_date}`);const p=await q.post("/api/prediction",{product_id:s.product_id,model_type:s.model_type,future_days:c.future_days,start_date:c.start_date,include_visualization:!0});p.data.status==="success"?(d.value=p.data,x.success("预测成功!"),k.value=!0):x.error(p.data.error||"预测失败")}catch(p){x.error(((f=(a=p.response)==null?void 0:a.data)==null?void 0:f.error)||"预测请求失败"),console.error(p)}finally{M.value=!1}},ne=()=>{k.value=!1},H=s=>s?new Date(s).toLocaleString():"N/A",F=s=>s?new Date(s).toLocaleDateString():"N/A",J=s=>({mlstm:"primary",transformer:"success",kan:"warning"})[s]||"info",Q=s=>{const a=O.value.find(f=>f.product_id===s);return a?a.product_name:s},re=s=>!s||s.length===0?0:s.reduce((a,f)=>a+f.sales,0)/s.length,ie=s=>!s||s.length===0?0:Math.max(...s.map(a=>a.sales)),ue=s=>!s||s.length===0?0:Math.min(...s.map(a=>a.sales)),_e=()=>{if(d.value)try{let s=`日期,销量,数据类型
|
||
`;d.value.data.forEach(w=>{s+=`${new Date(w.date).toLocaleDateString()},${w.sales.toFixed(2)},${w.data_type}
|
||
`});const a=new Blob([s],{type:"text/csv;charset=utf-8;"}),f=URL.createObjectURL(a),p=document.createElement("a");p.href=f;const A=c.start_date.replace(/-/g,""),R=c.future_days;p.setAttribute("download",`预测结果_${I.value}_${A}_days${R}.csv`),document.body.appendChild(p),p.click(),document.body.removeChild(p),x.success("预测结果已导出")}catch(s){console.error("导出预测结果失败",s),x.error("导出预测结果失败")}};return xe(()=>{te(),G()}),(s,a)=>{const f=Re,p=Be,A=Ne,R=Ae,w=Fe,v=Ve,ce=Se,pe=ze,N=Ie,E=De,fe=Me,U=$e,u=Ye,C=Le,me=je,W=He,P=Qe,X=Je,L=ke,Y=Ze,ve=Xe,ye=Ee,ge=qe;return i(),b("div",st,[e(L,null,{header:t(()=>[o("div",ot,[a[9]||(a[9]=o("span",null,"模型预测",-1)),e(p,{content:"在这里可以使用已训练好的模型进行销售预测"},{default:t(()=>[e(f,null,{default:t(()=>[e(_(We))]),_:1})]),_:1})])]),default:t(()=>[e(fe,{model:c,class:"prediction-form","label-width":"120px"},{default:t(()=>[e(E,{gutter:20},{default:t(()=>[e(v,{sm:24,md:12,lg:8},{default:t(()=>[e(w,{label:"产品"},{default:t(()=>[e(R,{modelValue:c.product_id,"onUpdate:modelValue":a[0]||(a[0]=l=>c.product_id=l),placeholder:"选择产品",filterable:"",onChange:ae,style:{width:"100%"}},{default:t(()=>[(i(!0),b(Pe,null,Te(O.value,l=>(i(),y(A,{key:l.product_id,label:l.product_name,value:l.product_id},null,8,["label","value"]))),128))]),_:1},8,["modelValue"])]),_:1})]),_:1}),e(v,{sm:24,md:12,lg:8},{default:t(()=>[e(w,{label:"模型类型"},{default:t(()=>[e(R,{modelValue:c.model_type,"onUpdate:modelValue":a[1]||(a[1]=l=>c.model_type=l),placeholder:"选择模型类型",onChange:le,style:{width:"100%"}},{default:t(()=>[e(A,{label:"mLSTM",value:"mlstm"}),e(A,{label:"Transformer",value:"transformer"}),e(A,{label:"KAN",value:"kan"})]),_:1},8,["modelValue"])]),_:1})]),_:1}),e(v,{sm:24,md:12,lg:8},{default:t(()=>[e(w,{label:"预测起始日期"},{default:t(()=>[e(ce,{modelValue:c.start_date,"onUpdate:modelValue":a[2]||(a[2]=l=>c.start_date=l),type:"date",placeholder:"选择日期",format:"YYYY-MM-DD","value-format":"YYYY-MM-DD",style:{width:"100%"},clearable:!1},null,8,["modelValue"])]),_:1})]),_:1}),e(v,{sm:24,md:12,lg:8},{default:t(()=>[e(w,{label:"预测天数"},{default:t(()=>[e(pe,{modelValue:c.future_days,"onUpdate:modelValue":a[3]||(a[3]=l=>c.future_days=l),min:1,max:30,size:"default"},null,8,["modelValue"])]),_:1})]),_:1}),e(v,{sm:24,md:12,lg:8},{default:t(()=>[e(w,null,{default:t(()=>[e(N,{type:"primary",onClick:G},{default:t(()=>[e(f,null,{default:t(()=>[e(_(Ue))]),_:1}),a[10]||(a[10]=r(" 查询可用模型 "))]),_:1,__:[10]})]),_:1})]),_:1})]),_:1})]),_:1},8,["model"]),e(_($),{"content-position":"left"},{default:t(()=>a[11]||(a[11]=[r("可用模型列表")])),_:1,__:[11]}),Ce((i(),b("div",null,[D.value.length===0&&!z.value?(i(),y(_(Z),{key:0,description:"没有找到可用的模型,请先训练模型或修改筛选条件"})):(i(),y(C,{key:1,data:ee.value,border:"",stripe:"",style:{width:"100%"},"highlight-current-row":!0},{default:t(()=>[e(u,{prop:"model_id",label:"模型ID","min-width":"120"},{default:t(({row:l})=>[e(U,{size:"small",type:J(l.model_type)},{default:t(()=>[r(n(l.model_type),1)]),_:2},1032,["type"]),o("span",dt,n(l.model_id),1)]),_:1}),e(u,{prop:"product_id",label:"产品","min-width":"100"},{default:t(({row:l})=>[r(n(Q(l.product_id)),1)]),_:1}),e(u,{prop:"created_at",label:"创建时间","min-width":"160"},{default:t(({row:l})=>[r(n(H(l.created_at)),1)]),_:1}),e(u,{label:"评估指标","min-width":"200"},{default:t(({row:l})=>[o("div",nt,[e(p,{effect:"dark",content:"R平方值,越接近1表示模型越好",placement:"top"},{default:t(()=>{var m,g;return[o("div",rt,[a[12]||(a[12]=o("span",{class:"metric-label"},"R²:",-1)),o("span",it,n(((g=(m=l.metrics)==null?void 0:m.R2)==null?void 0:g.toFixed(4))||"N/A"),1)])]}),_:2},1024),e(p,{effect:"dark",content:"均方根误差,越小表示模型越准确",placement:"top"},{default:t(()=>{var m,g;return[o("div",ut,[a[13]||(a[13]=o("span",{class:"metric-label"},"RMSE:",-1)),o("span",_t,n(((g=(m=l.metrics)==null?void 0:m.RMSE)==null?void 0:g.toFixed(4))||"N/A"),1)])]}),_:2},1024),e(p,{effect:"dark",content:"平均绝对误差,越小表示模型越准确",placement:"top"},{default:t(()=>{var m,g;return[o("div",ct,[a[14]||(a[14]=o("span",{class:"metric-label"},"MAE:",-1)),o("span",pt,n(((g=(m=l.metrics)==null?void 0:m.MAE)==null?void 0:g.toFixed(4))||"N/A"),1)])]}),_:2},1024),e(p,{effect:"dark",content:"平均绝对百分比误差,越小表示模型越准确",placement:"top"},{default:t(()=>{var m,g;return[o("div",ft,[a[15]||(a[15]=o("span",{class:"metric-label"},"MAPE:",-1)),o("span",mt,n(((g=(m=l.metrics)==null?void 0:m.MAPE)==null?void 0:g.toFixed(2))||"N/A")+"%",1)])]}),_:2},1024)])]),_:1}),e(u,{label:"操作",width:"150",fixed:"right"},{default:t(({row:l})=>[e(N,{type:"primary",size:"small",onClick:m=>de(l),loading:M.value&&K.value===l.model_id},{default:t(()=>[e(f,null,{default:t(()=>[e(_(Oe))]),_:1}),a[16]||(a[16]=r(" 执行预测 "))]),_:2,__:[16]},1032,["onClick","loading"])]),_:1})]),_:1},8,["data"])),o("div",vt,[e(me,{"current-page":V.value,"page-size":T.value,"page-sizes":[5,10,20,50],layout:"total, sizes, prev, pager, next, jumper",total:D.value.length,onSizeChange:se,onCurrentChange:oe,"onUpdate:pageSize":a[4]||(a[4]=l=>T.value=l),"onUpdate:currentPage":a[5]||(a[5]=l=>V.value=l)},null,8,["current-page","page-size","total"])])])),[[ge,z.value]]),M.value?(i(),y(_($),{key:0})):S("",!0),M.value?(i(),b("div",yt,[e(_(Ke),{rows:5,animated:""})])):S("",!0),d.value&&!k.value?(i(),b("div",gt,[e(E,{gutter:20},{default:t(()=>[e(v,{span:24,style:{"text-align":"center","margin-bottom":"15px"}},{default:t(()=>[e(N,{type:"success",onClick:a[6]||(a[6]=l=>k.value=!0)},{default:t(()=>[e(f,null,{default:t(()=>[e(_(Ge))]),_:1}),a[17]||(a[17]=r(" 全屏查看预测结果 "))]),_:1,__:[17]})]),_:1})]),_:1}),e(E,{gutter:20},{default:t(()=>[e(v,{xs:24,sm:12},{default:t(()=>[o("div",ht,[a[18]||(a[18]=o("h4",null,"预测趋势图",-1)),d.value.image_url?(i(),y(_(B),{key:0,src:d.value.image_url,fit:"contain",style:{width:"100%",height:"300px"},"preview-src-list":[d.value.image_url]},null,8,["src","preview-src-list"])):S("",!0)])]),_:1}),e(v,{xs:24,sm:12},{default:t(()=>[o("div",bt,[a[19]||(a[19]=o("h4",null,"同期销量对比",-1)),d.value.history_image_url?(i(),y(_(B),{key:0,src:d.value.history_image_url,fit:"contain",style:{width:"100%",height:"300px"},"preview-src-list":[d.value.history_image_url]},null,8,["src","preview-src-list"])):(i(),b("div",wt,[e(W,{title:"同期数据对比图暂时无法显示",type:"warning",description:"可能的原因:1) 历史数据不足,无法找到同期数据;2) 服务器处理图表时发生错误;3) 预测日期设置不正确。","show-icon":"",closable:!1})]))])]),_:1})]),_:1}),e(E,{gutter:20,style:{"margin-top":"20px"}},{default:t(()=>[e(v,{span:24},{default:t(()=>[a[20]||(a[20]=o("h3",null,"预测结果数据",-1)),e(X,null,{default:t(()=>[e(P,{label:"预测数据"},{default:t(()=>[e(C,{data:d.value.prediction_data,stripe:"",height:"400"},{default:t(()=>[e(u,{prop:"date",label:"日期",width:"150"},{default:t(({row:l})=>[r(n(F(l.date)),1)]),_:1}),e(u,{prop:"sales",label:"预测销量"},{default:t(({row:l})=>[r(n(l.sales.toFixed(2)),1)]),_:1})]),_:1},8,["data"])]),_:1}),e(P,{label:"历史数据"},{default:t(()=>[e(C,{data:d.value.history_data,stripe:"",height:"400"},{default:t(()=>[e(u,{prop:"date",label:"日期",width:"150"},{default:t(({row:l})=>[r(n(F(l.date)),1)]),_:1}),e(u,{prop:"sales",label:"历史销量"},{default:t(({row:l})=>[r(n(l.sales.toFixed(2)),1)]),_:1})]),_:1},8,["data"])]),_:1}),e(P,{label:"全部数据"},{default:t(()=>[e(C,{data:d.value.data,stripe:"",height:"400"},{default:t(()=>[e(u,{prop:"date",label:"日期",width:"150"},{default:t(({row:l})=>[r(n(F(l.date)),1)]),_:1}),e(u,{prop:"sales",label:"销量"},{default:t(({row:l})=>[r(n(l.sales.toFixed(2)),1)]),_:1}),e(u,{prop:"data_type",label:"数据类型"},{default:t(({row:l})=>[e(U,{type:l.data_type==="历史销量"?"info":"success"},{default:t(()=>[r(n(l.data_type),1)]),_:2},1032,["type"])]),_:1})]),_:1},8,["data"])]),_:1})]),_:1})]),_:1,__:[20]})]),_:1})])):M.value?S("",!0):(i(),y(_(Z),{key:3,description:"请选择产品和模型后执行预测"}))]),_:1}),e(ye,{modelValue:k.value,"onUpdate:modelValue":a[8]||(a[8]=l=>k.value=l),title:"预测结果详情",fullscreen:"","destroy-on-close":!1,"before-close":ne},{footer:t(()=>[o("span",St,[e(N,{onClick:a[7]||(a[7]=l=>k.value=!1)},{default:t(()=>a[29]||(a[29]=[r("关闭")])),_:1,__:[29]}),e(N,{type:"primary",onClick:_e},{default:t(()=>[e(f,null,{default:t(()=>[e(_(lt))]),_:1}),a[30]||(a[30]=r(" 导出预测结果 "))]),_:1,__:[30]})])]),default:t(()=>[d.value?(i(),b("div",xt,[e(E,{gutter:20},{default:t(()=>[e(v,{span:24},{default:t(()=>[o("div",kt,[e(ve,{column:4,border:""},{default:t(()=>[e(Y,{label:"产品名称"},{default:t(()=>[r(n(Q(I.value)),1)]),_:1}),e(Y,{label:"产品ID"},{default:t(()=>[r(n(I.value),1)]),_:1}),e(Y,{label:"模型类型"},{default:t(()=>[e(U,{type:J(j.value)},{default:t(()=>[r(n(j.value),1)]),_:1},8,["type"])]),_:1}),e(Y,{label:"预测时间"},{default:t(()=>[r(n(H(new Date)),1)]),_:1})]),_:1})])]),_:1})]),_:1}),e(_($)),e(E,{gutter:20},{default:t(()=>[e(v,{xs:24,md:12},{default:t(()=>[o("div",Et,[a[22]||(a[22]=o("h3",null,"预测趋势图",-1)),d.value.image_url?(i(),y(_(B),{key:0,src:d.value.image_url,fit:"contain",style:{width:"100%",height:"400px"},"preview-src-list":[d.value.image_url]},null,8,["src","preview-src-list"])):(i(),b("div",Ct,a[21]||(a[21]=[o("p",null,"预测图表生成失败或不可用。",-1)])))])]),_:1}),e(v,{xs:24,md:12},{default:t(()=>[o("div",Mt,[a[24]||(a[24]=o("h3",null,"同期销量对比",-1)),d.value.history_image_url?(i(),y(_(B),{key:0,src:d.value.history_image_url,fit:"contain",style:{width:"100%",height:"400px"},"preview-src-list":[d.value.history_image_url]},null,8,["src","preview-src-list"])):(i(),b("div",Dt,[e(W,{title:"同期数据对比图暂时无法显示",type:"warning",description:"可能的原因:1) 历史数据不足,无法找到同期数据;2) 服务器处理图表时发生错误;3) 预测日期设置不正确。","show-icon":"",closable:!1,style:{"margin-bottom":"20px"}}),a[23]||(a[23]=o("p",null,"请尝试选择其他预测日期,或确保历史数据中存在相应的同期记录。",-1))]))])]),_:1})]),_:1}),e(_($)),e(E,{gutter:20},{default:t(()=>[e(v,{span:24},{default:t(()=>[a[28]||(a[28]=o("h3",null,"数据详情",-1)),e(X,{type:"border-card"},{default:t(()=>[e(P,{label:"预测数据"},{default:t(()=>[o("div",Vt,[e(L,{shadow:"hover"},{header:t(()=>a[25]||(a[25]=[o("div",{class:"stat-header"},[o("span",null,"平均预测销量")],-1)])),default:t(()=>[o("div",Ft,n(re(d.value.prediction_data).toFixed(2)),1)]),_:1}),e(L,{shadow:"hover"},{header:t(()=>a[26]||(a[26]=[o("div",{class:"stat-header"},[o("span",null,"最高预测销量")],-1)])),default:t(()=>[o("div",At,n(ie(d.value.prediction_data).toFixed(2)),1)]),_:1}),e(L,{shadow:"hover"},{header:t(()=>a[27]||(a[27]=[o("div",{class:"stat-header"},[o("span",null,"最低预测销量")],-1)])),default:t(()=>[o("div",Pt,n(ue(d.value.prediction_data).toFixed(2)),1)]),_:1})]),e(C,{data:d.value.prediction_data,stripe:"",height:"330",border:""},{default:t(()=>[e(u,{prop:"date",label:"日期",width:"150"},{default:t(({row:l})=>[r(n(F(l.date)),1)]),_:1}),e(u,{prop:"sales",label:"预测销量",sortable:""},{default:t(({row:l})=>[r(n(l.sales.toFixed(2)),1)]),_:1}),e(u,{label:"趋势"},{default:t(({row:l,$index:m})=>[m>0?(i(),b("div",Tt,[l.sales>d.value.prediction_data[m-1].sales?(i(),y(f,{key:0,color:"#67C23A"},{default:t(()=>[e(_(et))]),_:1})):l.sales<d.value.prediction_data[m-1].sales?(i(),y(f,{key:1,color:"#F56C6C"},{default:t(()=>[e(_(tt))]),_:1})):(i(),y(f,{key:2,color:"#909399"},{default:t(()=>[e(_(at))]),_:1})),r(" "+n(Math.abs(l.sales-d.value.prediction_data[m-1].sales).toFixed(2)),1)])):(i(),b("span",Nt,"-"))]),_:1})]),_:1},8,["data"])]),_:1}),e(P,{label:"历史数据"},{default:t(()=>[e(C,{data:d.value.history_data,stripe:"",height:"400",border:""},{default:t(()=>[e(u,{prop:"date",label:"日期",width:"150"},{default:t(({row:l})=>[r(n(F(l.date)),1)]),_:1}),e(u,{prop:"sales",label:"历史销量",sortable:""},{default:t(({row:l})=>[r(n(l.sales.toFixed(2)),1)]),_:1})]),_:1},8,["data"])]),_:1}),e(P,{label:"全部数据"},{default:t(()=>[e(C,{data:d.value.data,stripe:"",height:"400",border:""},{default:t(()=>[e(u,{prop:"date",label:"日期",width:"150"},{default:t(({row:l})=>[r(n(F(l.date)),1)]),_:1}),e(u,{prop:"sales",label:"销量",sortable:""},{default:t(({row:l})=>[r(n(l.sales.toFixed(2)),1)]),_:1}),e(u,{prop:"data_type",label:"数据类型",width:"120"},{default:t(({row:l})=>[e(U,{type:l.data_type==="历史销量"?"info":"success"},{default:t(()=>[r(n(l.data_type),1)]),_:2},1032,["type"])]),_:1})]),_:1},8,["data"])]),_:1})]),_:1})]),_:1,__:[28]})]),_:1})])):S("",!0)]),_:1},8,["modelValue"])])}}},jt=he(zt,[["__scopeId","data-v-5202f57d"]]);export{jt as default};
|