瀏覽代碼

工单新增优化

unknown 1 月之前
父節點
當前提交
e45db212f9

+ 1 - 0
fastadmin/application/admin/lang/zh-cn/ps/workorder.php

@@ -6,6 +6,7 @@ return [
     'Creator_user_id' => '创建人',
     'No'              => '工单号',
     'Product_id'      => '产品',
+    'Product_name'    => '名称',
     'Qty'             => '数量',
     'Batch_no'        => '批次',
     'Plan_date'       => '计划日期',

+ 8 - 2
fastadmin/application/admin/view/ps/workorder/add.html

@@ -21,13 +21,19 @@
     <div class="form-group">
         <label class="control-label col-xs-12 col-sm-2">{:__('Product_id')}:</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-product_id" data-rule="required" min="0" data-source="ps/product/index" data-field="name" class="form-control selectpage" name="row[product_id]" type="text" value="">
+            <input id="c-product_id" min="0" data-source="ps/product/index" data-field="name" class="form-control selectpage" name="row[product_id]" type="text" value="">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Product_name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-product_name" data-rule="required" class="form-control" name="row[product_name]" type="text" value="">
         </div>
     </div>
     <div class="form-group">
         <label class="control-label col-xs-12 col-sm-2">{:__('Qty')}:</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-qty" data-rule="required" class="form-control" step="0.01" name="row[qty]" type="number" value="0.00">
+            <input id="c-qty" class="form-control" step="0.01" name="row[qty]" type="number" value="0.00">
         </div>
     </div>
     <div class="form-group">

+ 8 - 2
fastadmin/application/admin/view/ps/workorder/edit.html

@@ -21,13 +21,19 @@
     <div class="form-group">
         <label class="control-label col-xs-12 col-sm-2">{:__('Product_id')}:</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-product_id" data-rule="required" min="0" data-source="ps/product/index" data-field="name" class="form-control selectpage" name="row[product_id]" type="text" value="{$row.product_id|htmlentities}">
+            <input id="c-product_id" min="0" data-source="ps/product/index" data-field="name" class="form-control selectpage" name="row[product_id]" type="text" value="{$row.product_id|htmlentities}">
+        </div>
+    </div>
+    <div class="form-group">
+        <label class="control-label col-xs-12 col-sm-2">{:__('Product_name')}:</label>
+        <div class="col-xs-12 col-sm-8">
+            <input id="c-product_name" data-rule="required" class="form-control" name="row[product_name]" type="text" value="{$row.product_name|htmlentities}">
         </div>
     </div>
     <div class="form-group">
         <label class="control-label col-xs-12 col-sm-2">{:__('Qty')}:</label>
         <div class="col-xs-12 col-sm-8">
-            <input id="c-qty" data-rule="required" class="form-control" step="0.01" name="row[qty]" type="number" value="{$row.qty|htmlentities}">
+            <input id="c-qty" class="form-control" step="0.01" name="row[qty]" type="number" value="{$row.qty|htmlentities}">
         </div>
     </div>
     <div class="form-group">

+ 2 - 6
fastadmin/application/api/controller/ps/Open.php

@@ -120,8 +120,6 @@ class Open extends Api
                     'name'      => '产品名称',
                     'spec'      => '规格',
                     'unit'      => '单位,默认件',
-                    'qty'       => '总数量',
-                    'sheet_qty' => '每版数量,一版一张流程单',
                     'remark'    => '备注',
                     'processes' => [
                         ['code' => '工艺编号', 'seq' => 1, 'name' => '工序名', 'workstation' => '工位', 'standard_time' => '工时', 'qc_points' => '质检要点'],
@@ -132,10 +130,8 @@ class Open extends Api
                 'method' => 'POST /api/ps/open/workorder',
                 'fields' => [
                     'no'            => '工单号,必填,本厂内唯一,存在则更新',
-                    'product_code'  => '产品编号,可自动建档',
-                    'product_name'  => '产品名称(新建产品时用)',
-                    'qty'           => '总数量',
-                    'sheet_qty'     => '每版数量,一版一张流程单',
+                    'product_code'  => '产品编号,可选;填写则关联已有产品或自动建档',
+                    'product_name'  => '产品名称。不选产品时必填;选了产品可带出',
                     'batch_no'      => '批次',
                     'customer'      => '客户',
                     'plan_date'     => '计划日期 YYYY-MM-DD',

+ 2 - 2
fastadmin/application/api/controller/ps/Product.php

@@ -66,7 +66,7 @@ class Product extends Api
             $this->error(__('Parameter %s can not be empty', ''));
         }
         $params['creator_user_id'] = $this->auth->id;
-        unset($params['id'], $params['factory_id']);
+        unset($params['id'], $params['factory_id'], $params['qty'], $params['sheet_qty']);
         $processes = isset($params['processes']) ? $params['processes'] : [];
         unset($params['processes']);
         $this->model->allowField(true)->save($params);
@@ -85,7 +85,7 @@ class Product extends Api
             $this->error(__('No Results were found'));
         }
         $params = $this->request->post();
-        unset($params['id'], $params['factory_id']);
+        unset($params['id'], $params['factory_id'], $params['qty'], $params['sheet_qty']);
         $processes = isset($params['processes']) ? $params['processes'] : null;
         unset($params['processes']);
         $row->allowField(true)->save($params);

+ 28 - 3
fastadmin/application/api/controller/ps/Workorder.php

@@ -38,7 +38,7 @@ class Workorder extends Api
         $keyword = $this->request->request('keyword', '', 'trim');
         $query = $this->model->order('id desc');
         if ($keyword !== '') {
-            $query->where('no|batch_no|customer', 'like', '%' . $keyword . '%');
+            $query->where('no|batch_no|customer|product_name', 'like', '%' . $keyword . '%');
         }
         $list = $query->paginate($limit);
         $this->success('', ['total' => $list->total(), 'rows' => $list->items()]);
@@ -67,7 +67,8 @@ class Workorder extends Api
             $this->error(__('Parameter %s can not be empty', ''));
         }
         $params['creator_user_id'] = $this->auth->id;
-        unset($params['id'], $params['factory_id']);
+        unset($params['id'], $params['factory_id'], $params['qty'], $params['sheet_qty'], $params['product']);
+        $params = $this->normalizeProduct($params);
         $processes = isset($params['processes']) ? $params['processes'] : [];
         unset($params['processes']);
         $this->model->allowField(true)->save($params);
@@ -90,7 +91,8 @@ class Workorder extends Api
             $this->error(__('No Results were found'));
         }
         $params = $this->request->post();
-        unset($params['id'], $params['factory_id']);
+        unset($params['id'], $params['factory_id'], $params['qty'], $params['sheet_qty'], $params['product']);
+        $params = $this->normalizeProduct($params);
         $processes = isset($params['processes']) ? $params['processes'] : null;
         unset($params['processes']);
         $row->allowField(true)->save($params);
@@ -116,4 +118,27 @@ class Workorder extends Api
         }
         $this->success();
     }
+
+    /**
+     * 产品可选:选了带出名称,不选则必填名称。
+     *
+     * @param array $params
+     * @return array
+     */
+    protected function normalizeProduct(array $params)
+    {
+        $productId = (int)($params['product_id'] ?? 0);
+        $name = trim((string)($params['product_name'] ?? ''));
+        unset($params['name']);
+        if ($productId > 0 && $name === '') {
+            $product = ProductModel::get($productId);
+            $name = $product ? (string)$product['name'] : '';
+        }
+        if ($name === '') {
+            $this->error('请选择产品或填写名称');
+        }
+        $params['product_id'] = $productId;
+        $params['product_name'] = mb_substr($name, 0, 100);
+        return $params;
+    }
 }

+ 9 - 5
fastadmin/application/common/library/ps/BizIngest.php

@@ -38,8 +38,6 @@ class BizIngest
             'name'            => $name,
             'spec'            => self::str($payload, ['spec'], 100),
             'unit'            => self::str($payload, ['unit'], 20) ?: '件',
-            'qty'             => self::num($payload, ['qty', 'quantity', 'total_qty']),
-            'sheet_qty'       => self::num($payload, ['sheet_qty', 'per_sheet', 'tldx']),
             'remark'          => self::str($payload, ['remark'], 255),
             'status'          => 'normal',
             'creator_user_id' => $userId,
@@ -88,13 +86,19 @@ class BizIngest
             $product = Product::with('processes')->find($productId);
             $processes = $product ? $product['processes'] : [];
         }
-        $qty = self::num($payload, ['qty', 'quantity', 'total_qty']);
+        $productName = self::str($payload, ['product_name', 'name'], 100);
+        if ($productName === '' && $productId > 0) {
+            $linked = isset($product) ? $product : Product::get($productId);
+            $productName = $linked ? (string)$linked['name'] : '';
+        }
+        if ($productName === '') {
+            throw new Exception('请选择产品或填写名称');
+        }
         $row = (new Workorder())->where('factory_id', $factoryId)->where('no', $no)->find();
         $data = [
             'no'              => $no,
             'product_id'      => $productId,
-            'qty'             => $qty,
-            'sheet_qty'       => self::num($payload, ['sheet_qty', 'per_sheet', 'tldx']),
+            'product_name'    => $productName,
             'batch_no'        => self::str($payload, ['batch_no', 'batch'], 64),
             'customer'        => self::str($payload, ['customer'], 100),
             'plan_date'       => self::date($payload, ['plan_date', 'date']),

+ 6 - 2
fastadmin/application/common/library/ps/PrintPlanner.php

@@ -61,10 +61,14 @@ class PrintPlanner
                 'customer'     => (string)$workorder['customer'],
                 'remark'       => (string)$workorder['remark'],
             ];
-            $nameOverride = self::pickText($options, 'name', '');
+            $storedName = trim((string)($workorder['product_name'] ?? ''));
+            $nameOverride = self::pickText($options, 'name', $storedName);
+            if ($nameOverride === '' && $product) {
+                $nameOverride = (string)$product['name'];
+            }
             if ($nameOverride !== '' && $product) {
                 $product['name'] = $nameOverride;
-            } elseif ($nameOverride !== '' && !$product) {
+            } elseif ($nameOverride !== '') {
                 $product = ['id' => 0, 'code' => '', 'name' => $nameOverride, 'spec' => '', 'unit' => ''];
             }
         } elseif ($bizId > 0) {

+ 1 - 0
fastadmin/application/sql/ps_schema.sql

@@ -174,6 +174,7 @@ CREATE TABLE IF NOT EXISTS `fa_ps_workorder` (
   `creator_user_id` int(10) unsigned NOT NULL DEFAULT '0',
   `no` varchar(64) NOT NULL DEFAULT '' COMMENT '工单号',
   `product_id` int(10) unsigned NOT NULL DEFAULT '0',
+  `product_name` varchar(100) NOT NULL DEFAULT '' COMMENT '产品名称,可不关联产品档案',
   `qty` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '总数量',
   `sheet_qty` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '每版数量,一版一张流程单',
   `batch_no` varchar(64) NOT NULL DEFAULT '' COMMENT '批次',

+ 1 - 0
fastadmin/public/assets/js/backend/ps/workorder.js

@@ -31,6 +31,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                         {field: 'factory.name', title: __('Factory_id'), operate: 'LIKE'},
                         {field: 'no', title: __('No'), operate: 'LIKE'},
                         {field: 'product_id', title: __('Product_id')},
+                        {field: 'product_name', title: __('Product_name'), operate: 'LIKE'},
                         {field: 'qty', title: __('Qty'), operate:'BETWEEN'},
                         {field: 'batch_no', title: __('Batch_no'), operate: 'LIKE'},
                         {field: 'plan_date', title: __('Plan_date'), operate:'RANGE', addclass:'datetimerange', autocomplete:false},

+ 1 - 13
vue/src/components/ImportDialog.vue

@@ -8,7 +8,7 @@
     @close="onClose"
   >
     <p class="hint">
-      支持 Excel / CSV / 文本 / PDF / 图片。系统会用 AI 提取编号、名称、数量、工艺编号等信息,确认后再写入本厂数据库。
+      支持 Excel / CSV / 文本 / PDF / 图片。系统会提取编号、名称、工艺等信息,确认后再写入本厂数据库。工单可不关联产品档案,但需要名称。总数量和每版数量在套打时填写。
     </p>
     <el-upload
       drag
@@ -33,12 +33,6 @@
         <el-table-column label="单位" width="80">
           <template #default="{ row }"><el-input v-model="row.unit" size="small" /></template>
         </el-table-column>
-        <el-table-column label="总数量" width="90">
-          <template #default="{ row }"><el-input v-model="row.qty" size="small" /></template>
-        </el-table-column>
-        <el-table-column label="每版数量" width="90">
-          <template #default="{ row }"><el-input v-model="row.sheet_qty" size="small" /></template>
-        </el-table-column>
       </template>
       <template v-else>
         <el-table-column label="工单号" min-width="130">
@@ -50,12 +44,6 @@
         <el-table-column label="产品名称" min-width="120">
           <template #default="{ row }"><el-input v-model="row.product_name" size="small" /></template>
         </el-table-column>
-        <el-table-column label="总数量" width="90">
-          <template #default="{ row }"><el-input v-model="row.qty" size="small" /></template>
-        </el-table-column>
-        <el-table-column label="每版数量" width="90">
-          <template #default="{ row }"><el-input v-model="row.sheet_qty" size="small" /></template>
-        </el-table-column>
       </template>
       <el-table-column label="工序数" width="80">
         <template #default="{ row }">{{ (row.processes && row.processes.length) || row.process_count || 0 }}</template>

+ 5 - 8
vue/src/components/PrintDialog.vue

@@ -56,10 +56,10 @@
           </el-form-item>
 
           <el-form-item label="总数量">
-            <el-input v-model="form.qty" placeholder="计划总件数" />
+            <el-input v-model="form.qty" placeholder="本次套打的计划总件数" />
           </el-form-item>
           <el-form-item label="每版数量">
-            <el-input v-model="form.sheet_qty" placeholder="一版 = 一张流程单" />
+            <el-input v-model="form.sheet_qty" placeholder="一版 = 一张流程单,仅本次套打使用" />
           </el-form-item>
           <el-form-item label="预计版数">
             <span class="plate-num">{{ plateTotal || '—' }}</span>
@@ -222,7 +222,8 @@ function optionValue(item) {
 
 function optionLabel(item) {
   if (form.biz_type === 'workorder') {
-    return item.no + ' / 总量 ' + (item.qty || 0)
+    const name = item.product_name || (item.product && item.product.name) || ''
+    return name ? (item.no + ' / ' + name) : (item.no || '')
   }
   return (item.code || '无编号') + ' / ' + (item.name || '')
 }
@@ -353,9 +354,7 @@ async function loadBizDetail(id) {
     const row = await workorderInfo(id)
     form.biz_id = row.id
     form.no = row.no || ''
-    form.name = (row.product && row.product.name) || form.name || ''
-    form.qty = row.qty || ''
-    form.sheet_qty = row.sheet_qty || ''
+    form.name = row.product_name || (row.product && row.product.name) || form.name || ''
     const procs = row.processes && row.processes.length
       ? row.processes
       : ((row.product && row.product.processes) || [])
@@ -365,8 +364,6 @@ async function loadBizDetail(id) {
     form.biz_id = row.id
     form.no = row.code || ''
     form.name = row.name || ''
-    form.qty = row.qty || ''
-    form.sheet_qty = row.sheet_qty || ''
     applySavedProcesses(row.processes || [])
   }
   syncPlateRange()

+ 1 - 6
vue/src/views/factory/index.vue

@@ -41,19 +41,14 @@
   "name": "外壳",
   "spec": "",
   "unit": "件",
-  "qty": 1000,
-  "sheet_qty": 300,
   "processes": [
     { "code": "OP10", "seq": 1, "name": "冲压", "workstation": "", "standard_time": "", "qc_points": "" }
   ]
 }</pre>
-          <p>工单:<code>POST {{ apiBase }}/workorder</code></p>
+          <p>工单:<code>POST {{ apiBase }}/workorder</code>(产品编号可选)</p>
 <pre>{
   "no": "WO20260821",
-  "product_code": "P001",
   "product_name": "外壳",
-  "qty": 1000,
-  "sheet_qty": 300,
   "batch_no": "",
   "customer": "",
   "plan_date": "2026-08-22",

+ 12 - 4
vue/src/views/print/Index.vue

@@ -14,7 +14,7 @@
       </el-form-item>
       <el-form-item v-if="form.biz_type === 'workorder'" label="工单">
         <el-select v-model="form.biz_id" filterable placeholder="选择工单" style="width:100%">
-          <el-option v-for="item in workorders" :key="item.id" :label="item.no + ' / 数量 ' + item.qty" :value="item.id" />
+          <el-option v-for="item in workorders" :key="item.id" :label="item.no + (item.product_name ? ' / ' + item.product_name : '')" :value="item.id" />
         </el-select>
       </el-form-item>
       <el-form-item v-else label="产品">
@@ -23,10 +23,10 @@
         </el-select>
       </el-form-item>
       <el-form-item label="每张数量">
-        <el-input v-model="form.sheet_qty" placeholder="对应旧系统投料大箱;留空则只打一张" />
+        <el-input v-model="form.sheet_qty" placeholder="一版一张流程单" />
       </el-form-item>
-      <el-form-item label="覆盖总量">
-        <el-input v-model="form.qty" placeholder="可留空,默认用工单数量" />
+      <el-form-item label="总数量">
+        <el-input v-model="form.qty" placeholder="本次套打计划总件数" />
       </el-form-item>
       <el-form-item label="整套份数">
         <el-input-number v-model="form.copies" :min="1" />
@@ -105,6 +105,10 @@ async function onPrepare() {
     ElMessage.warning('请选择模板和工单/产品')
     return
   }
+  if (!(Number(form.qty) > 0) || !(Number(form.sheet_qty) > 0)) {
+    ElMessage.warning('请填写总数量和每版数量')
+    return
+  }
   preparing.value = true
   try {
     preview.value = await printPrepare(payload())
@@ -118,6 +122,10 @@ async function onConfirm() {
     ElMessage.warning('请选择模板和工单/产品')
     return
   }
+  if (!(Number(form.qty) > 0) || !(Number(form.sheet_qty) > 0)) {
+    ElMessage.warning('请填写总数量和每版数量')
+    return
+  }
   saving.value = true
   try {
     const data = await printConfirm(payload())

+ 7 - 19
vue/src/views/product/Edit.vue

@@ -5,11 +5,6 @@
       <el-form-item label="产品名称"><el-input v-model="form.name" /></el-form-item>
       <el-form-item label="规格"><el-input v-model="form.spec" /></el-form-item>
       <el-form-item label="单位"><el-input v-model="form.unit" /></el-form-item>
-      <el-form-item label="总数量"><el-input v-model="form.qty" /></el-form-item>
-      <el-form-item label="每版数量">
-        <el-input v-model="form.sheet_qty" placeholder="一版 = 一张流程单" />
-        <p v-if="sheetHint" class="qty-hint">{{ sheetHint }}</p>
-      </el-form-item>
       <el-form-item label="备注"><el-input v-model="form.remark" type="textarea" /></el-form-item>
       <el-form-item label="工序">
         <ProcessEditor v-model="form.processes" />
@@ -25,13 +20,12 @@
 </template>
 
 <script setup>
-import { computed, onMounted, reactive, ref } from 'vue'
+import { onMounted, reactive, ref } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import ProcessEditor from '@/components/ProcessEditor.vue'
 import { productDel, productInfo, productSave } from '@/api/ps'
 import { openPrint } from '@/utils/print'
-import { sheetCountText } from '@/utils/sheet'
 
 const route = useRoute()
 const router = useRouter()
@@ -43,13 +37,10 @@ const form = reactive({
   name: '',
   spec: '',
   unit: '',
-  qty: '',
-  sheet_qty: '',
   remark: '',
   status: 'normal',
   processes: [],
 })
-const sheetHint = computed(() => sheetCountText(form.qty, form.sheet_qty))
 
 onMounted(async () => {
   if (!route.params.id) {
@@ -73,17 +64,18 @@ async function onDel() {
 }
 
 async function onSave() {
-  if (!form.name) {
-    ElMessage.warning('请填写产品名称')
+  if (!String(form.code || '').trim()) {
+    ElMessage.warning('请填写产品编码')
     return
   }
-  if (!(Number(form.qty) > 0) || !(Number(form.sheet_qty) > 0)) {
-    ElMessage.warning('请填写总数量和每版数量')
+  if (!String(form.name || '').trim()) {
+    ElMessage.warning('请填写产品名称')
     return
   }
   saving.value = true
   try {
-    await productSave(form)
+    const { qty, sheet_qty, ...payload } = form
+    await productSave(payload)
     ElMessage.success('已保存')
     router.push('/products')
   } finally {
@@ -91,7 +83,3 @@ async function onSave() {
   }
 }
 </script>
-
-<style scoped>
-.qty-hint { margin: 6px 0 0; color: #7a8794; font-size: 12px; }
-</style>

+ 0 - 2
vue/src/views/product/List.vue

@@ -12,8 +12,6 @@
       <el-table-column prop="name" label="名称" />
       <el-table-column prop="spec" label="规格" />
       <el-table-column prop="unit" label="单位" width="80" />
-      <el-table-column prop="qty" label="总数量" width="90" />
-      <el-table-column prop="sheet_qty" label="每版数量" width="90" />
       <el-table-column label="操作" width="260">
         <template #default="{ row }">
           <el-button text type="success" @click="openPrint({ bizType: 'product', bizId: row.id })">套打</el-button>

+ 24 - 24
vue/src/views/workorder/Edit.vue

@@ -3,14 +3,19 @@
     <el-form :model="form" label-width="90px" style="max-width:880px">
       <el-form-item label="工单号"><el-input v-model="form.no" /></el-form-item>
       <el-form-item label="产品">
-        <el-select v-model="form.product_id" filterable placeholder="选择产品" style="width:100%" @change="onProduct">
+        <el-select
+          v-model="form.product_id"
+          filterable
+          clearable
+          placeholder="可不选,选择后带出名称和工序"
+          style="width:100%"
+          @change="onProduct"
+        >
           <el-option v-for="item in products" :key="item.id" :label="item.name + ' / ' + item.code" :value="item.id" />
         </el-select>
       </el-form-item>
-      <el-form-item label="总数量"><el-input v-model="form.qty" /></el-form-item>
-      <el-form-item label="每版数量">
-        <el-input v-model="form.sheet_qty" placeholder="一版 = 一张流程单" />
-        <p v-if="sheetHint" class="qty-hint">{{ sheetHint }}</p>
+      <el-form-item label="名称">
+        <el-input v-model="form.product_name" placeholder="选择产品后自动带出,不选产品则手动填写" />
       </el-form-item>
       <el-form-item label="批次"><el-input v-model="form.batch_no" /></el-form-item>
       <el-form-item label="客户"><el-input v-model="form.customer" /></el-form-item>
@@ -30,13 +35,12 @@
 </template>
 
 <script setup>
-import { computed, onMounted, reactive, ref } from 'vue'
+import { onMounted, reactive, ref } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import ProcessEditor from '@/components/ProcessEditor.vue'
 import { productInfo, productList, workorderDel, workorderInfo, workorderSave } from '@/api/ps'
 import { openPrint } from '@/utils/print'
-import { sheetCountText } from '@/utils/sheet'
 
 const route = useRoute()
 const router = useRouter()
@@ -47,8 +51,7 @@ const form = reactive({
   id: 0,
   no: '',
   product_id: '',
-  qty: '',
-  sheet_qty: '',
+  product_name: '',
   batch_no: '',
   customer: '',
   plan_date: '',
@@ -56,7 +59,6 @@ const form = reactive({
   status: 'draft',
   processes: [],
 })
-const sheetHint = computed(() => sheetCountText(form.qty, form.sheet_qty))
 
 onMounted(async () => {
   const list = await productList({ limit: 200 })
@@ -68,6 +70,8 @@ onMounted(async () => {
   try {
     const row = await workorderInfo(route.params.id)
     Object.assign(form, row)
+    form.product_id = row.product_id || ''
+    form.product_name = row.product_name || (row.product && row.product.name) || ''
     form.processes = row.processes || []
   } finally {
     loading.value = false
@@ -79,12 +83,7 @@ async function onProduct(id) {
     return
   }
   const row = await productInfo(id)
-  if (row.qty) {
-    form.qty = row.qty
-  }
-  if (row.sheet_qty) {
-    form.sheet_qty = row.sheet_qty
-  }
+  form.product_name = row.name || ''
   if (form.processes && form.processes.length) {
     return
   }
@@ -107,17 +106,22 @@ async function onDel() {
 }
 
 async function onSave() {
-  if (!form.no) {
+  if (!String(form.no || '').trim()) {
     ElMessage.warning('请填写工单号')
     return
   }
-  if (!(Number(form.qty) > 0) || !(Number(form.sheet_qty) > 0)) {
-    ElMessage.warning('请填写总数量和每版数量')
+  if (!form.product_id && !String(form.product_name || '').trim()) {
+    ElMessage.warning('请选择产品或填写名称')
     return
   }
   saving.value = true
   try {
-    await workorderSave(form)
+    const { qty, sheet_qty, product, ...rest } = form
+    await workorderSave({
+      ...rest,
+      product_id: Number(form.product_id) || 0,
+      product_name: String(form.product_name || '').trim(),
+    })
     ElMessage.success('已保存')
     router.push('/workorders')
   } finally {
@@ -125,7 +129,3 @@ async function onSave() {
   }
 }
 </script>
-
-<style scoped>
-.qty-hint { margin: 6px 0 0; color: #7a8794; font-size: 12px; }
-</style>

+ 2 - 3
vue/src/views/workorder/List.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="page-card">
     <div class="toolbar">
-      <el-input v-model="keyword" placeholder="搜索工单号 / 批次 / 客户" style="width:260px" clearable @keyup.enter="load" />
+      <el-input v-model="keyword" placeholder="搜索工单号 / 名称 / 批次 / 客户" style="width:280px" clearable @keyup.enter="load" />
       <div>
         <InstallLodopButton />
         <el-button @click="historyVisible = true">打印记录</el-button>
@@ -11,8 +11,7 @@
     </div>
     <el-table :data="rows" v-loading="loading">
       <el-table-column prop="no" label="工单号" width="160" />
-      <el-table-column prop="qty" label="总数量" width="90" />
-      <el-table-column prop="sheet_qty" label="每版数量" width="90" />
+      <el-table-column prop="product_name" label="名称" />
       <el-table-column prop="batch_no" label="批次" />
       <el-table-column prop="customer" label="客户" />
       <el-table-column prop="plan_date" label="计划日期" width="120" />

+ 3 - 0
vue/vite.config.ts

@@ -48,6 +48,9 @@ export default ({ mode }: ConfigEnv): UserConfigExport => {
       // 预热文件以提前转换和缓存结果,降低启动期间的初始页面加载时长并防止转换瀑布
       warmup: {
         clientFiles: ["./index.html", "./src/{views,components}/*"]
+      },
+      watch: {
+        ignored: ["**/dist.zip"]
       }
     },
     plugins: getPluginsList(VITE_CDN, VITE_COMPRESSION),