fix(frontend)+chore(deploy): 修复明细表格渲染 + static/ 改服务器构建

- SalesOrdersTab/PurchaseOrdersTab/MaterialsTab/ProductsTab: t-table 明细行不渲染(push/splice 改新数组引用)+ Decimal 算术类型错误(Number() 包裹)
- static/ 不再进 git(.gitignore),改为 deploy.sh 在服务器 npm run build
- 新增 deploy.sh:拉取 + 构建前端 + 重启后端
This commit is contained in:
2026-08-03 16:12:34 +08:00
parent 4ec6f98f10
commit eab4137c0a
39 changed files with 55 additions and 173 deletions
+3
View File
@@ -23,6 +23,9 @@ logs/
uploads/ uploads/
html_output/ html_output/
# 前端构建产物(由 deploy.sh 在部署时 npm run build 生成,不进 git)
static/
# 不再需要在 src/ 下跟踪这些 # 不再需要在 src/ 下跟踪这些
src/uploads/ src/uploads/
src/html_output/ src/html_output/
+37
View File
@@ -0,0 +1,37 @@
#!/bin/bash
# 部署脚本:拉取代码 + 构建前端 + 重启后端
# 用法:./deploy.sh
# 前提:服务器已安装 Node.js(node --version 能输出版本)
set -e
cd "$(dirname "$0")"
# ── 1. 检查 Node.js ──
if ! command -v node &> /dev/null; then
echo "❌ 服务器未安装 Node.js,无法构建前端"
echo " 安装(Debian/Ubuntu):"
echo " curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -"
echo " sudo apt-get install -y nodejs"
exit 1
fi
echo "✅ Node.js: $(node --version)"
# ── 2. 拉取最新代码 ──
echo "=== 拉取最新代码 ==="
git pull
# ── 3. 构建前端(产物输出到 ../static/)──
echo "=== 构建前端 ==="
cd frontend
npm install
npm run build
cd ..
# ── 4. 重启后端服务 ──
echo "=== 重启后端服务 ==="
sudo systemctl restart gemoldinsight
sleep 2
sudo systemctl status gemoldinsight --no-pager | head -8
echo ""
echo "=== 部署完成 ==="
echo "前端已构建到 static/,后端已重启。"
@@ -98,16 +98,16 @@ async function openRestockModal() {
} }
function addRestockItem() { function addRestockItem() {
restockItems.value.push({ restockItems.value = [...restockItems.value, {
material_id: state.materials[0]?.id || null, material_id: state.materials[0]?.id || null,
quantity: 1, quantity: 1,
unit_price: 0, unit_price: 0,
remark: '' remark: ''
}) }]
} }
function removeRestockItem(index: number) { function removeRestockItem(index: number) {
restockItems.value.splice(index, 1) restockItems.value = restockItems.value.filter((_, i) => i !== index)
} }
const restockTotalAmount = computed(() => { const restockTotalAmount = computed(() => {
@@ -51,14 +51,14 @@ async function editProduct(product: any) {
} }
function addBomItem() { function addBomItem() {
bomItems.value.push({ bomItems.value = [...bomItems.value, {
material_id: state.materials[0]?.id || null, material_id: state.materials[0]?.id || null,
quantity: 1 quantity: 1
}) }]
} }
function removeBomItem(index: number) { function removeBomItem(index: number) {
bomItems.value.splice(index, 1) bomItems.value = bomItems.value.filter((_, i) => i !== index)
} }
async function saveProduct() { async function saveProduct() {
@@ -101,15 +101,15 @@ function openCreateOrder() {
} }
function addOrderItem() { function addOrderItem() {
orderItems.value.push({ orderItems.value = [...orderItems.value, {
product_id: state.materials[0]?.id || null, product_id: state.materials[0]?.id || null,
quantity: 1, quantity: 1,
remark: '' remark: ''
}) }]
} }
function removeOrderItem(index: number) { function removeOrderItem(index: number) {
orderItems.value.splice(index, 1) orderItems.value = orderItems.value.filter((_, i) => i !== index)
} }
const orderTotalAmount = computed(() => { const orderTotalAmount = computed(() => {
@@ -66,7 +66,7 @@ function openCreateOrder() {
} }
function addMoldItem() { function addMoldItem() {
moldItems.value.push({ moldItems.value = [...moldItems.value, {
mold_mode: 'new', mold_mode: 'new',
mold_sku: '', mold_sku: '',
mold_name: '', mold_name: '',
@@ -74,11 +74,11 @@ function addMoldItem() {
quantity: 1, quantity: 1,
unit_price: 0, unit_price: 0,
remark: '' remark: ''
}) }]
} }
function removeMoldItem(index: number) { function removeMoldItem(index: number) {
moldItems.value.splice(index, 1) moldItems.value = moldItems.value.filter((_, i) => i !== index)
} }
const orderTotalAmount = computed(() => { const orderTotalAmount = computed(() => {
@@ -263,15 +263,15 @@ function openConsumptionModal() {
} }
function addConsumptionItem() { function addConsumptionItem() {
consumptionItems.value.push({ consumptionItems.value = [...consumptionItems.value, {
material_id: state.materials[0]?.id || null, material_id: state.materials[0]?.id || null,
quantity: 1, quantity: 1,
remark: '' remark: ''
}) }]
} }
function removeConsumptionItem(index: number) { function removeConsumptionItem(index: number) {
consumptionItems.value.splice(index, 1) consumptionItems.value = consumptionItems.value.filter((_, i) => i !== index)
} }
const consumptionTotalAmount = computed(() => { const consumptionTotalAmount = computed(() => {
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
.batch-file-list[data-v-167d79eb]{margin-top:var(--space-3);border:1px solid var(--border-color);border-radius:var(--radius-sm);padding:var(--space-2)}.batch-file-header[data-v-167d79eb]{margin-bottom:var(--space-2);justify-content:space-between;align-items:center;font-weight:600;display:flex}.batch-file-item[data-v-167d79eb]{align-items:center;gap:var(--space-2);padding:var(--space-1) 0;border-bottom:1px solid var(--border-light);display:flex}.batch-file-item .file-name[data-v-167d79eb]{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.batch-file-item .file-size[data-v-167d79eb]{color:var(--text-secondary);white-space:nowrap;font-size:.85rem}.batch-dashboard[data-v-167d79eb]{margin-top:var(--space-4)}.batch-progress-header[data-v-167d79eb]{margin-bottom:var(--space-2);justify-content:space-between;align-items:flex-start;display:flex}.batch-progress-info h2[data-v-167d79eb]{margin:0 0 var(--space-1)}.batch-progress-info p[data-v-167d79eb]{align-items:center;gap:var(--space-2);margin:0;display:flex}
-1
View File
@@ -1 +0,0 @@
.customers-tab[data-v-36237339]{padding:0}.table-header[data-v-36237339]{margin-bottom:16px}
-1
View File
@@ -1 +0,0 @@
import{C as e,D as t,F as n,N as r,P as i,R as a,S as o,T as s,g as c,i as l,j as u,k as d,n as f,r as p,s as m,x as h,y as g}from"./index-Dngmm__P.js";import{t as _}from"./useInventory-CrXJ8kdd.js";var v={class:`customers-tab`},y={class:`table-header`},b=f(e({__name:`CustomersTab`,setup(e){let{state:f,loadCustomers:b}=_(),x=i(!1),S=i(null),C=i(!1),w=r({name:``,contact_person:``,phone:``,email:``,address:``});function T(){S.value=null,w.name=``,w.contact_person=``,w.phone=``,w.email=``,w.address=``,x.value=!0}function E(e){S.value=e,w.name=e.name??``,w.contact_person=e.contact_person??``,w.phone=e.phone??``,w.email=e.email??``,w.address=e.address??``,x.value=!0}async function D(){if(!C.value){if(!w.name||!w.name.trim()){p(`请输入客户名称`,`warning`);return}C.value=!0;try{let e={name:w.name,contact_person:w.contact_person||null,phone:w.phone||null,email:w.email||null,address:w.address||null};S.value?(await m(`/api/customers/${S.value.id}`,{method:`PUT`,body:JSON.stringify(e)}),p(`客户更新成功`,`success`)):(await m(`/api/customers`,{method:`POST`,body:JSON.stringify(e)}),p(`客户已创建`,`success`)),x.value=!1,b()}catch(e){l(e,`保存客户`)}finally{C.value=!1}}}async function O(e){if(confirm(`确定要删除这个客户吗?`))try{await m(`/api/customers/${e}`,{method:`DELETE`}),p(`客户已删除`,`success`),b()}catch(e){l(e,`删除客户`)}}return s(()=>{b()}),(e,r)=>{let i=d(`t-button`),s=d(`t-table-column`),l=d(`t-table`),p=d(`t-input`),m=d(`t-form-item`),_=d(`t-form`),b=d(`t-dialog`);return t(),g(`div`,v,[c(`div`,y,[o(i,{type:`primary`,onClick:T},{default:u(()=>[...r[7]||=[h(`+ 新增客户`,-1)]]),_:1})]),o(l,{data:n(f).customers,style:{width:`100%`},loading:n(f).loading,"empty-text":`暂无客户数据`},{default:u(()=>[o(s,{prop:`code`,label:`编码`}),o(s,{prop:`name`,label:`名称`}),o(s,{prop:`contact_person`,label:`联系人`},{default:u(({row:e})=>[h(a(e.contact_person||`-`),1)]),_:1}),o(s,{prop:`phone`,label:`电话`},{default:u(({row:e})=>[h(a(e.phone||`-`),1)]),_:1}),o(s,{prop:`email`,label:`邮箱`},{default:u(({row:e})=>[h(a(e.email||`-`),1)]),_:1}),o(s,{label:`操作`,width:`180`},{default:u(({row:e})=>[o(i,{size:`small`,onClick:t=>E(e)},{default:u(()=>[...r[8]||=[h(`编辑`,-1)]]),_:1},8,[`onClick`]),o(i,{size:`small`,type:`danger`,onClick:t=>O(e.id)},{default:u(()=>[...r[9]||=[h(`删除`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`,`loading`]),o(b,{modelValue:x.value,"onUpdate:modelValue":r[6]||=e=>x.value=e,title:S.value?`编辑客户`:`新增客户`,width:`520px`,"close-on-click-modal":!1},{footer:u(()=>[o(i,{onClick:r[5]||=e=>x.value=!1,disabled:C.value},{default:u(()=>[...r[10]||=[h(`取消`,-1)]]),_:1},8,[`disabled`]),o(i,{type:`primary`,loading:C.value,disabled:C.value,onClick:D},{default:u(()=>[...r[11]||=[h(`保存`,-1)]]),_:1},8,[`loading`,`disabled`])]),default:u(()=>[o(_,{model:w,"label-width":`80px`},{default:u(()=>[o(m,{label:`名称`,required:``},{default:u(()=>[o(p,{modelValue:w.name,"onUpdate:modelValue":r[0]||=e=>w.name=e,placeholder:`请输入客户名称`},null,8,[`modelValue`])]),_:1}),o(m,{label:`联系人`},{default:u(()=>[o(p,{modelValue:w.contact_person,"onUpdate:modelValue":r[1]||=e=>w.contact_person=e,placeholder:`请输入联系人`},null,8,[`modelValue`])]),_:1}),o(m,{label:`电话`},{default:u(()=>[o(p,{modelValue:w.phone,"onUpdate:modelValue":r[2]||=e=>w.phone=e,placeholder:`请输入电话`},null,8,[`modelValue`])]),_:1}),o(m,{label:`邮箱`},{default:u(()=>[o(p,{modelValue:w.email,"onUpdate:modelValue":r[3]||=e=>w.email=e,type:`email`,placeholder:`请输入邮箱`},null,8,[`modelValue`])]),_:1}),o(m,{label:`地址`},{default:u(()=>[o(p,{modelValue:w.address,"onUpdate:modelValue":r[4]||=e=>w.address=e,placeholder:`请输入地址`},null,8,[`modelValue`])]),_:1})]),_:1},8,[`model`])]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-36237339`]]);export{b as default};
-1
View File
@@ -1 +0,0 @@
import{C as e,D as t,F as n,O as r,R as i,S as a,_ as o,g as s,j as c,k as l,m as u,y as d}from"./index-Dngmm__P.js";import{t as f}from"./useInventory-CrXJ8kdd.js";var p={style:{display:`flex`,"align-items":`center`,gap:`12px`}},m={style:{"font-size":`32px`}},h={style:{"font-size":`24px`,"font-weight":`700`}},g={style:{color:`var(--text-tertiary)`,"font-size":`13px`}},_=e({__name:`DashboardTab`,setup(e){let{state:_,formatCurrency:v}=f();return(e,f)=>{let y=l(`t-card`),b=l(`t-col`),x=l(`t-row`);return t(),o(x,{gutter:16},{default:c(()=>[(t(!0),d(u,null,r([{icon:`📦`,value:n(_).dashboard?.finished_product_count||0,label:`成品数量`},{icon:`📊`,value:n(_).dashboard?.total_stock||0,label:`物料库存总量`},{icon:`💰`,value:n(v)(n(_).dashboard?.total_value||0),label:`库存价值`},{icon:`🏭`,value:n(_).dashboard?.supplier_count||0,label:`供应商`},{icon:`👥`,value:n(_).dashboard?.customer_count||0,label:`客户`},{icon:`🏪`,value:n(_).dashboard?.warehouse_count||0,label:`仓库`}],e=>(t(),o(b,{span:8,key:e.label,style:{"margin-bottom":`16px`}},{default:c(()=>[a(y,{shadow:`hover`},{default:c(()=>[s(`div`,p,[s(`span`,m,i(e.icon),1),s(`div`,null,[s(`div`,h,i(e.value),1),s(`div`,g,i(e.label),1)])])]),_:2},1024)]),_:2},1024))),128))]),_:1})}}});export{_ as default};
@@ -1 +0,0 @@
import{D as e,g as t,n,y as r}from"./index-Dngmm__P.js";var i={};function a(n,i){return e(),r(`div`,null,[...i[0]||=[t(`div`,{class:`page-header`},[t(`h1`,{class:`page-title`},`设计体系`),t(`p`,{class:`page-subtitle`},`迁移中...`)],-1)]])}var o=n(i,[[`render`,a]]);export{o as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
.hero-section[data-v-dc82ceb2]{text-align:center;padding:var(--space-16) 0}.hero-title[data-v-dc82ceb2]{font-size:var(--text-4xl);font-weight:var(--font-bold);color:var(--text-primary);margin-bottom:var(--space-4)}.hero-subtitle[data-v-dc82ceb2]{font-size:var(--text-lg);color:var(--text-tertiary);max-width:600px;margin:0 auto var(--space-8)}.features-grid[data-v-dc82ceb2]{gap:var(--space-6);margin-top:var(--space-12);grid-template-columns:repeat(auto-fit,minmax(280px,1fr));display:grid}.feature-card[data-v-dc82ceb2]{background:var(--bg-primary);border:1px solid var(--border-light);border-radius:var(--radius-xl);padding:var(--space-6);text-align:left}.feature-card[style*=cursor][data-v-dc82ceb2]:hover{border-color:var(--primary-200);box-shadow:var(--shadow-md);transition:all .2s;transform:translateY(-2px)}.feature-icon[data-v-dc82ceb2]{background:var(--primary-50);border-radius:var(--radius-lg);width:40px;height:40px;color:var(--primary-500);font-size:var(--text-lg);margin-bottom:var(--space-4);justify-content:center;align-items:center;display:flex}.feature-title[data-v-dc82ceb2]{font-size:var(--text-base);font-weight:var(--font-semibold);color:var(--text-primary);margin-bottom:var(--space-2)}.feature-desc[data-v-dc82ceb2]{font-size:var(--text-sm);color:var(--text-tertiary);line-height:1.6}
-1
View File
@@ -1 +0,0 @@
.inventory-tab[data-v-37ecfc85]{padding:0}.table-header[data-v-37ecfc85]{margin-bottom:16px}
-1
View File
@@ -1 +0,0 @@
import{C as e,D as t,F as n,N as r,O as i,P as a,S as o,T as s,_ as c,g as l,i as u,j as d,k as f,m as p,n as m,r as h,s as g,x as _,y as v}from"./index-Dngmm__P.js";import{t as y}from"./useInventory-CrXJ8kdd.js";var b={class:`inventory-tab`},x={class:`table-header`},S=m(e({__name:`InventoryTab`,setup(e){let{state:m,loadInventory:S,ensureStockBaseData:C}=y(),w=a(!1),T=a(null),E=a(!1),D=r({product_id:null,warehouse_id:null,quantity:0,locked_quantity:0,batch_no:``,location:``});function O(){C(),T.value=null,D.product_id=null,D.warehouse_id=null,D.quantity=0,D.locked_quantity=0,D.batch_no=``,D.location=``,w.value=!0}function k(e){C(),T.value=e,D.product_id=e.product_id??null,D.warehouse_id=e.warehouse_id??null,D.quantity=e.quantity??0,D.locked_quantity=e.locked_quantity??0,D.batch_no=e.batch_no??``,D.location=e.location??``,w.value=!0}async function A(){if(!E.value){if(!D.product_id){h(`请选择物料`,`warning`);return}if(!D.warehouse_id){h(`请选择仓库`,`warning`);return}if(D.quantity<0){h(`数量不能为负数`,`warning`);return}if(D.locked_quantity>D.quantity){h(`锁定数量不能大于库存数量`,`warning`);return}E.value=!0;try{let e={product_id:D.product_id,warehouse_id:D.warehouse_id,quantity:D.quantity,locked_quantity:D.locked_quantity,batch_no:D.batch_no||null,location:D.location||null};T.value?(await g(`/api/inventory/${T.value.id}`,{method:`PUT`,body:JSON.stringify(e)}),h(`物料库存更新成功`,`success`)):(await g(`/api/inventory`,{method:`POST`,body:JSON.stringify(e)}),h(`物料库存已创建`,`success`)),w.value=!1,S()}catch(e){u(e,`保存物料库存`)}finally{E.value=!1}}}async function j(e){if(confirm(`确定要删除这个物料库存记录吗?`))try{await g(`/api/inventory/${e}`,{method:`DELETE`}),h(`物料库存已删除`,`success`),S()}catch(e){u(e,`删除物料库存`)}}return s(()=>{S()}),(e,r)=>{let a=f(`t-button`),s=f(`t-table-column`),u=f(`t-table`),h=f(`t-option`),g=f(`t-select`),y=f(`t-form-item`),S=f(`t-input-number`),C=f(`t-input`),M=f(`t-form`),N=f(`t-dialog`);return t(),v(`div`,b,[l(`div`,x,[o(a,{type:`primary`,onClick:O},{default:d(()=>[...r[8]||=[_(`+ 新增物料库存`,-1)]]),_:1})]),o(u,{data:n(m).inventory,style:{width:`100%`},loading:n(m).loading,"empty-text":`暂无库存数据`},{default:d(()=>[o(s,{prop:`product_sku`,label:`SKU`}),o(s,{prop:`product_name`,label:`物料`}),o(s,{prop:`warehouse_name`,label:`仓库`}),o(s,{prop:`quantity`,label:`数量`}),o(s,{prop:`available_quantity`,label:`可用`}),o(s,{label:`操作`,width:`180`},{default:d(({row:e})=>[o(a,{size:`small`,onClick:t=>k(e)},{default:d(()=>[...r[9]||=[_(`编辑`,-1)]]),_:1},8,[`onClick`]),o(a,{size:`small`,type:`danger`,onClick:t=>j(e.id)},{default:d(()=>[...r[10]||=[_(`删除`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`,`loading`]),o(N,{modelValue:w.value,"onUpdate:modelValue":r[7]||=e=>w.value=e,title:T.value?`编辑物料库存`:`新增物料库存`,width:`520px`,"close-on-click-modal":!1},{footer:d(()=>[o(a,{onClick:r[6]||=e=>w.value=!1,disabled:E.value},{default:d(()=>[...r[11]||=[_(`取消`,-1)]]),_:1},8,[`disabled`]),o(a,{type:`primary`,loading:E.value,disabled:E.value,onClick:A},{default:d(()=>[...r[12]||=[_(`保存`,-1)]]),_:1},8,[`loading`,`disabled`])]),default:d(()=>[o(M,{model:D,"label-width":`80px`},{default:d(()=>[o(y,{label:`物料`,required:``},{default:d(()=>[o(g,{modelValue:D.product_id,"onUpdate:modelValue":r[0]||=e=>D.product_id=e,placeholder:`请选择物料`,style:{width:`100%`}},{default:d(()=>[(t(!0),v(p,null,i(n(m).materials,e=>(t(),c(h,{key:e.id,label:e.name+(e.sku?` (`+e.sku+`)`:``),value:e.id},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`])]),_:1}),o(y,{label:`仓库`,required:``},{default:d(()=>[o(g,{modelValue:D.warehouse_id,"onUpdate:modelValue":r[1]||=e=>D.warehouse_id=e,placeholder:`请选择仓库`,style:{width:`100%`}},{default:d(()=>[(t(!0),v(p,null,i(n(m).warehouses,e=>(t(),c(h,{key:e.id,label:e.name,value:e.id},null,8,[`label`,`value`]))),128))]),_:1},8,[`modelValue`])]),_:1}),o(y,{label:`数量`,required:``},{default:d(()=>[o(S,{modelValue:D.quantity,"onUpdate:modelValue":r[2]||=e=>D.quantity=e,min:0,style:{width:`100%`}},null,8,[`modelValue`])]),_:1}),o(y,{label:`锁定数量`},{default:d(()=>[o(S,{modelValue:D.locked_quantity,"onUpdate:modelValue":r[3]||=e=>D.locked_quantity=e,min:0,style:{width:`100%`}},null,8,[`modelValue`])]),_:1}),o(y,{label:`批次号`},{default:d(()=>[o(C,{modelValue:D.batch_no,"onUpdate:modelValue":r[4]||=e=>D.batch_no=e,placeholder:`请输入批次号`},null,8,[`modelValue`])]),_:1}),o(y,{label:`库位`},{default:d(()=>[o(C,{modelValue:D.location,"onUpdate:modelValue":r[5]||=e=>D.location=e,placeholder:`请输入库位`},null,8,[`modelValue`])]),_:1})]),_:1},8,[`model`])]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-37ecfc85`]]);export{S as default};
-1
View File
@@ -1 +0,0 @@
.sidebar-nav[data-v-80d71466]{background:var(--bg-primary);border:1px solid var(--border-light);border-radius:var(--radius-lg);padding:var(--space-2)}.sidebar-group[data-v-80d71466]{margin-bottom:var(--space-2)}.sidebar-group[data-v-80d71466]:last-child{margin-bottom:0}.sidebar-group-title[data-v-80d71466]{padding:var(--space-2) var(--space-3);font-size:var(--text-xs);font-weight:var(--font-semibold);color:var(--text-tertiary);text-transform:uppercase;cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:var(--radius-sm);justify-content:space-between;align-items:center;transition:background .15s;display:flex}.sidebar-group-title[data-v-80d71466]:hover{background:var(--bg-tertiary)}.group-arrow[data-v-80d71466]{font-size:10px;transition:transform .2s}.sidebar-item[data-v-80d71466]{height:36px;padding:0 var(--space-3) 0 var(--space-6);margin:1px var(--space-1);font-size:var(--text-sm);color:var(--text-secondary);border-radius:var(--radius-md);cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;transition:all .15s;display:flex}.sidebar-item[data-v-80d71466]:hover{background:var(--bg-tertiary);color:var(--text-primary)}.sidebar-item.active[data-v-80d71466]{background:var(--primary-50);color:var(--primary-600);font-weight:var(--font-medium)}.page-container[data-v-c950e09f]{padding:0}.page-header[data-v-c950e09f]{margin-bottom:var(--space-6)}.page-header h1[data-v-c950e09f]{font-size:var(--text-2xl);font-weight:var(--font-bold);color:var(--text-primary);margin:0}.page-header p[data-v-c950e09f]{color:var(--text-tertiary);margin:var(--space-1) 0 0;font-size:var(--text-sm)}.inventory-layout[data-v-c950e09f]{gap:var(--space-6);align-items:flex-start;display:flex}.inventory-sidebar-wrapper[data-v-c950e09f]{flex-shrink:0;width:200px;position:sticky;top:80px}.inventory-content[data-v-c950e09f]{flex:1;min-width:0}.inventory-content-header[data-v-c950e09f]{margin-bottom:var(--space-4)}.inventory-breadcrumb[data-v-c950e09f]{font-size:var(--text-sm);color:var(--text-tertiary)}.inventory-breadcrumb .sep[data-v-c950e09f]{margin:0 var(--space-2)}.inventory-breadcrumb .current[data-v-c950e09f]{color:var(--text-primary);font-weight:var(--font-medium)}
-1
View File
@@ -1 +0,0 @@
import{A as e,C as t,D as n,E as r,F as i,I as a,O as o,R as s,S as c,T as l,_ as u,c as d,g as f,j as p,k as m,l as h,m as g,n as _,r as v,u as y,v as b,y as x}from"./index-Dngmm__P.js";import{t as S}from"./inventory-BFlQBLDI.js";var C={class:`sidebar-nav`},w=[`onClick`],T={class:`group-arrow`},E=[`onClick`],D=_(t({__name:`InventorySidebar`,setup(e){let t=y(),r=S(),{menuGroups:c,openGroups:l,toggleGroup:u}=r,d=e=>{r.activeTab=e,t.push(`/inventory/${e}`)};return(e,t)=>(n(),x(`nav`,C,[(n(!0),x(g,null,o(i(c),e=>(n(),x(`div`,{key:e.key,class:`sidebar-group`},[f(`div`,{class:`sidebar-group-title`,onClick:t=>i(u)(e.key)},[f(`span`,null,s(e.title),1),f(`span`,T,s(i(l)[e.key]?`▾`:`▸`),1)],8,w),i(l)[e.key]?(n(!0),x(g,{key:0},o(e.items,e=>(n(),x(`div`,{key:e.key,class:a([`sidebar-item`,{active:i(r).activeTab===e.key}]),onClick:t=>d(e.key)},s(e.label),11,E))),128)):b(``,!0)]))),128))]))}}),[[`__scopeId`,`data-v-80d71466`]]),O={class:`page-container`},k={class:`inventory-layout`},A={class:`inventory-sidebar-wrapper`},j={class:`inventory-content`},M={class:`inventory-content-header`},N={class:`inventory-breadcrumb`},P={class:`current`},F=_(t({__name:`InventoryView`,setup(t){let a=S(),o=d(),g=y(),_=h(),C=()=>{let e=_.path.split(`/`);return e[e.length-1]||`dashboard`};return e(()=>_.path,()=>{a.activeTab=C()},{immediate:!0}),l(()=>{if(!o.user){g.push(`/login`);return}a.activeTab=C(),a.checkBackendHealth().then(()=>{if(!a.backendDbReady){v(a.backendDbMessage||`业务服务不可用`,`warning`);return}a.loadDashboard()})}),r(()=>{a.destroyPickers()}),(e,t)=>{let r=m(`t-alert`),o=m(`router-view`),l=m(`t-loading`);return n(),x(`div`,O,[t[1]||=f(`div`,{class:`page-header`},[f(`h1`,null,`进销存管理`),f(`p`,null,`库存、采购、销售管理`)],-1),f(`div`,k,[f(`aside`,A,[c(D)]),f(`section`,j,[f(`div`,M,[f(`div`,N,[f(`span`,null,s(i(a).activeMenu?.group?.title||`进销存`),1),t[0]||=f(`span`,{class:`sep`},`/`,-1),f(`span`,P,s(i(a).activeMenu?.item?.label||``),1)])]),i(a).backendDbReady?b(``,!0):(n(),u(r,{key:0,title:i(a).backendDbMessage,theme:`warning`,"show-icon":``,closable:!1,style:{"margin-bottom":`16px`}},null,8,[`title`])),c(l,{loading:i(a).loading},{default:p(()=>[c(o)]),_:1},8,[`loading`])])])])}}}),[[`__scopeId`,`data-v-c950e09f`]]);export{F as default};
-1
View File
@@ -1 +0,0 @@
.login-container[data-v-c91bfbf2]{background:var(--bg-secondary);min-height:100vh;padding:var(--space-6);justify-content:center;align-items:center;display:flex}.login-card[data-v-c91bfbf2]{background:var(--bg-primary);border:1px solid var(--border-light);border-radius:var(--radius-xl);width:100%;max-width:400px;padding:var(--space-8)}.login-header[data-v-c91bfbf2]{text-align:center;margin-bottom:var(--space-8)}.login-logo[data-v-c91bfbf2]{background:var(--primary-500);border-radius:var(--radius-lg);color:#fff;width:48px;height:48px;font-size:var(--text-xl);font-weight:var(--font-bold);margin:0 auto var(--space-4);justify-content:center;align-items:center;display:flex}.login-title[data-v-c91bfbf2]{font-size:var(--text-2xl);font-weight:var(--font-bold);color:var(--text-primary);margin-bottom:var(--space-2)}.login-subtitle[data-v-c91bfbf2]{font-size:var(--text-sm);color:var(--text-tertiary)}
-1
View File
@@ -1 +0,0 @@
import{C as e,D as t,N as n,R as r,S as i,_ as a,g as o,j as s,k as c,n as l,o as u,r as d,s as f,u as p,v as m,x as h,y as g}from"./index-Dngmm__P.js";var _={class:`login-container`},v={class:`login-card`},y=l(e({__name:`LoginView`,setup(e){let l=p(),y=n({username:``,password:``,error:``,loading:!1}),b=async()=>{y.error=``,y.loading=!0;try{let e=await f(`/api/auth/login/json`,{method:`POST`,body:JSON.stringify({username:y.username,password:y.password})});u(e.access_token,e.user),d(`登录成功`,`success`),l.push(`/`)}catch(e){y.error=e.message||`登录失败`}finally{y.loading=!1}};return(e,n)=>{let l=c(`t-input`),u=c(`t-form-item`),d=c(`t-alert`),f=c(`t-button`),p=c(`t-form`);return t(),g(`div`,_,[o(`div`,v,[n[2]||=o(`div`,{class:`login-header`},[o(`div`,{class:`login-logo`},`G`),o(`h1`,{class:`login-title`},`Gemold`),o(`p`,{class:`login-subtitle`},`模具制造管理系统`)],-1),i(p,{onSubmit:b},{default:s(()=>[i(u,{label:`用户名`},{default:s(()=>[i(l,{modelValue:y.username,"onUpdate:modelValue":n[0]||=e=>y.username=e,placeholder:`请输入用户名`,clearable:``},null,8,[`modelValue`])]),_:1}),i(u,{label:`密码`},{default:s(()=>[i(l,{modelValue:y.password,"onUpdate:modelValue":n[1]||=e=>y.password=e,type:`password`,placeholder:`请输入密码`,clearable:``},null,8,[`modelValue`])]),_:1}),y.error?(t(),a(d,{key:0,theme:`error`,message:y.error,style:{"margin-bottom":`16px`}},null,8,[`message`])):m(``,!0),i(f,{theme:`primary`,block:``,type:`submit`,loading:y.loading},{default:s(()=>[h(r(y.loading?`登录中...`:`登录`),1)]),_:1},8,[`loading`])]),_:1})])])}}}),[[`__scopeId`,`data-v-c91bfbf2`]]);export{y as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
.movements-tab[data-v-79f8d5e3]{padding:0}
-1
View File
@@ -1 +0,0 @@
import{C as e,D as t,F as n,R as r,S as i,T as a,j as o,k as s,n as c,x as l,y as u}from"./index-Dngmm__P.js";import{t as d}from"./useInventory-CrXJ8kdd.js";var f={class:`movements-tab`},p=c(e({__name:`MovementsTab`,setup(e){let{state:c,loadMovements:p,getMovementTypeLabel:m,getMovementBadgeClass:h,formatDateTime:g}=d(),_=e=>{let t=h(e);return t===`badge-success`?`success`:t===`badge-error`?`danger`:t===`badge-warning`?`warning`:`info`};return a(()=>{p()}),(e,a)=>{let d=s(`t-table-column`),p=s(`t-tag`),h=s(`t-table`);return t(),u(`div`,f,[i(h,{data:n(c).movements,style:{width:`100%`},loading:n(c).loading,"empty-text":`暂无库存变动记录`},{default:o(()=>[i(d,{label:`物料`},{default:o(({row:e})=>[l(r(e.product_name)+r(e.product_sku?` (`+e.product_sku+`)`:``),1)]),_:1}),i(d,{label:`类型`,width:`140`},{default:o(({row:e})=>[i(p,{type:_(e.movement_type),size:`small`},{default:o(()=>[l(r(n(m)(e.movement_type)),1)]),_:2},1032,[`type`])]),_:1}),i(d,{prop:`quantity`,label:`数量`,width:`80`}),i(d,{prop:`before_quantity`,label:`变动前`,width:`80`}),i(d,{prop:`after_quantity`,label:`变动后`,width:`80`}),i(d,{label:`时间`,width:`180`},{default:o(({row:e})=>[l(r(n(g)(e.created_at)),1)]),_:1})]),_:1},8,[`data`,`loading`])])}}}),[[`__scopeId`,`data-v-79f8d5e3`]]);export{p as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
import{D as e,g as t,n,y as r}from"./index-Dngmm__P.js";var i={};function a(n,i){return e(),r(`div`,null,[...i[0]||=[t(`div`,{class:`page-header`},[t(`h1`,{class:`page-title`},`灰度发布与回滚`),t(`p`,{class:`page-subtitle`},`迁移中...`)],-1)]])}var o=n(i,[[`render`,a]]);export{o as default};
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
-1
View File
@@ -1 +0,0 @@
.suppliers-tab[data-v-e8c22e24]{padding:0}.table-header[data-v-e8c22e24]{margin-bottom:16px}
-1
View File
@@ -1 +0,0 @@
import{C as e,D as t,F as n,N as r,P as i,R as a,S as o,T as s,g as c,i as l,j as u,k as d,n as f,r as p,s as m,x as h,y as g}from"./index-Dngmm__P.js";import{t as _}from"./useInventory-CrXJ8kdd.js";var v={class:`suppliers-tab`},y={class:`table-header`},b=f(e({__name:`SuppliersTab`,setup(e){let{state:f,loadSuppliers:b}=_(),x=i(!1),S=i(null),C=i(!1),w=r({name:``,contact_person:``,phone:``,email:``,address:``});function T(){S.value=null,w.name=``,w.contact_person=``,w.phone=``,w.email=``,w.address=``,x.value=!0}function E(e){S.value=e,w.name=e.name??``,w.contact_person=e.contact_person??``,w.phone=e.phone??``,w.email=e.email??``,w.address=e.address??``,x.value=!0}async function D(){if(!C.value){if(!w.name||!w.name.trim()){p(`请输入供应商名称`,`warning`);return}C.value=!0;try{let e={name:w.name,contact_person:w.contact_person||null,phone:w.phone||null,email:w.email||null,address:w.address||null};S.value?(await m(`/api/suppliers/${S.value.id}`,{method:`PUT`,body:JSON.stringify(e)}),p(`供应商更新成功`,`success`)):(await m(`/api/suppliers`,{method:`POST`,body:JSON.stringify(e)}),p(`供应商已创建`,`success`)),x.value=!1,b()}catch(e){l(e,`保存供应商`)}finally{C.value=!1}}}async function O(e){if(confirm(`确定要删除这个供应商吗?`))try{await m(`/api/suppliers/${e}`,{method:`DELETE`}),p(`供应商已删除`,`success`),b()}catch(e){l(e,`删除供应商`)}}return s(()=>{b()}),(e,r)=>{let i=d(`t-button`),s=d(`t-table-column`),l=d(`t-table`),p=d(`t-input`),m=d(`t-form-item`),_=d(`t-form`),b=d(`t-dialog`);return t(),g(`div`,v,[c(`div`,y,[o(i,{type:`primary`,onClick:T},{default:u(()=>[...r[7]||=[h(`+ 新增供应商`,-1)]]),_:1})]),o(l,{data:n(f).suppliers,style:{width:`100%`},loading:n(f).loading,"empty-text":`暂无供应商数据`},{default:u(()=>[o(s,{prop:`code`,label:`编码`}),o(s,{prop:`name`,label:`名称`}),o(s,{prop:`contact_person`,label:`联系人`},{default:u(({row:e})=>[h(a(e.contact_person||`-`),1)]),_:1}),o(s,{prop:`phone`,label:`电话`},{default:u(({row:e})=>[h(a(e.phone||`-`),1)]),_:1}),o(s,{prop:`email`,label:`邮箱`},{default:u(({row:e})=>[h(a(e.email||`-`),1)]),_:1}),o(s,{label:`操作`,width:`180`},{default:u(({row:e})=>[o(i,{size:`small`,onClick:t=>E(e)},{default:u(()=>[...r[8]||=[h(`编辑`,-1)]]),_:1},8,[`onClick`]),o(i,{size:`small`,type:`danger`,onClick:t=>O(e.id)},{default:u(()=>[...r[9]||=[h(`删除`,-1)]]),_:1},8,[`onClick`])]),_:1})]),_:1},8,[`data`,`loading`]),o(b,{modelValue:x.value,"onUpdate:modelValue":r[6]||=e=>x.value=e,title:S.value?`编辑供应商`:`新增供应商`,width:`520px`,"close-on-click-modal":!1},{footer:u(()=>[o(i,{onClick:r[5]||=e=>x.value=!1,disabled:C.value},{default:u(()=>[...r[10]||=[h(`取消`,-1)]]),_:1},8,[`disabled`]),o(i,{type:`primary`,loading:C.value,disabled:C.value,onClick:D},{default:u(()=>[...r[11]||=[h(`保存`,-1)]]),_:1},8,[`loading`,`disabled`])]),default:u(()=>[o(_,{model:w,"label-width":`80px`},{default:u(()=>[o(m,{label:`名称`,required:``},{default:u(()=>[o(p,{modelValue:w.name,"onUpdate:modelValue":r[0]||=e=>w.name=e,placeholder:`请输入供应商名称`},null,8,[`modelValue`])]),_:1}),o(m,{label:`联系人`},{default:u(()=>[o(p,{modelValue:w.contact_person,"onUpdate:modelValue":r[1]||=e=>w.contact_person=e,placeholder:`请输入联系人`},null,8,[`modelValue`])]),_:1}),o(m,{label:`电话`},{default:u(()=>[o(p,{modelValue:w.phone,"onUpdate:modelValue":r[2]||=e=>w.phone=e,placeholder:`请输入电话`},null,8,[`modelValue`])]),_:1}),o(m,{label:`邮箱`},{default:u(()=>[o(p,{modelValue:w.email,"onUpdate:modelValue":r[3]||=e=>w.email=e,type:`email`,placeholder:`请输入邮箱`},null,8,[`modelValue`])]),_:1}),o(m,{label:`地址`},{default:u(()=>[o(p,{modelValue:w.address,"onUpdate:modelValue":r[4]||=e=>w.address=e,placeholder:`请输入地址`},null,8,[`modelValue`])]),_:1})]),_:1},8,[`model`])]),_:1},8,[`modelValue`,`title`])])}}}),[[`__scopeId`,`data-v-e8c22e24`]]);export{b as default};
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
-1
View File
@@ -1 +0,0 @@
import{t as e}from"./inventory-BFlQBLDI.js";function t(){return e()}export{t};
-1
View File
@@ -1 +0,0 @@
function e(e){if(!e||e===0)return`0 B`;let t=1024,n=[`B`,`KB`,`MB`,`GB`],r=Math.floor(Math.log(e)/Math.log(t));return parseFloat((e/t**r).toFixed(2))+` `+n[r]}function t(e){return e==null?`N/A`:e>=1e6?(e/1e6).toFixed(2)+`M`:e>=1e3?(e/1e3).toFixed(2)+`K`:e.toFixed?e.toFixed(2):String(e)}function n(e){if(!e)return`N/A`;try{let t=new Date(e);return isNaN(t.getTime())?e:`${t.getFullYear()}/${String(t.getMonth()+1).padStart(2,`0`)}/${String(t.getDate()).padStart(2,`0`)} ${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}:${String(t.getSeconds()).padStart(2,`0`)}`}catch{return e}}function r(e){if(!e)return`N/A`;try{return new Date(e).toLocaleDateString(`zh-CN`)}catch{return e}}function i(e){return e==null?`¥0.00`:`¥`+Number(e).toFixed(2)}export{t as a,e as i,r as n,n as r,i as t};
-77
View File
@@ -1,77 +0,0 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Gemold - 模具制造管理系统</title>
<script>
(function () {
var params = new URLSearchParams(location.search);
var uiParam = params.get('ui');
var themeParam = params.get('theme');
var storedUi = null;
try { storedUi = localStorage.getItem('gemold_ui_version'); } catch (e) {}
var storedPercent = null;
try { storedPercent = localStorage.getItem('gemold_ui_rollout_percent'); } catch (e) {}
var percent = storedPercent ? Number(storedPercent) : 0;
if (!Number.isFinite(percent) || percent < 0) percent = 0;
if (percent > 100) percent = 100;
var uid = null;
try { uid = localStorage.getItem('gemold_uid'); } catch (e) {}
if (!uid) {
uid = 'u_' + Math.random().toString(36).slice(2, 10) + Date.now().toString(36);
try { localStorage.setItem('gemold_uid', uid); } catch (e) {}
}
function hash32(str) {
var h = 2166136261;
for (var i = 0; i < str.length; i++) {
h ^= str.charCodeAt(i);
h = Math.imul(h, 16777619);
}
return h >>> 0;
}
function chooseUiVersion() {
if (uiParam === 'v1' || uiParam === 'v2') return uiParam;
if (storedUi === 'v1' || storedUi === 'v2') return storedUi;
if (percent <= 0) return 'v1';
var bucket = hash32(uid) % 100;
return bucket < percent ? 'v2' : 'v1';
}
function chooseTheme() {
var storedTheme = null;
try { storedTheme = localStorage.getItem('gemold_theme'); } catch (e) {}
if (themeParam === 'light' || themeParam === 'dark') return themeParam;
if (storedTheme === 'light' || storedTheme === 'dark') return storedTheme;
return 'light';
}
var ui = chooseUiVersion();
var theme = chooseTheme();
document.documentElement.dataset.ui = ui;
document.documentElement.dataset.theme = theme;
try {
if (uiParam === 'v1' || uiParam === 'v2') localStorage.setItem('gemold_ui_version', uiParam);
if (themeParam === 'light' || themeParam === 'dark') localStorage.setItem('gemold_theme', themeParam);
} catch (e) {}
})();
</script>
<script type="module" crossorigin src="/static/assets/index-Dngmm__P.js"></script>
<link rel="stylesheet" crossorigin href="/static/assets/index-9snwVMjk.css">
</head>
<body>
<div id="app">
<div class="loading-overlay">
<div class="loading-content">
<div class="loading-spinner"></div>
<p style="margin-top: 16px; color: var(--text-secondary);">加载中...</p>
</div>
</div>
</div>
</body>
</html>