Kaynağa Gözat

Merge branch 'dev' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend into dev

yusheng 1 ay önce
ebeveyn
işleme
5a3803ceb1

+ 82 - 0
src/api/rulesManagement/inventoryRules/index.js

@@ -0,0 +1,82 @@
+import request from '@/utils/request';
+
+// 获取盘点规则列表
+export function getTableList(data) {
+  return request({
+    url: '/api/inventoryRules/list',
+    method: 'post',
+    data
+  });
+}
+
+// 新增盘点规则
+export function addInventoryRules(data) {
+  return request({
+    url: '/api/inventoryRules',
+    method: 'post',
+    data
+  });
+}
+
+// 修改盘点规则
+export function updateInventoryRules(data) {
+  return request({
+    url: '/api/inventoryRules',
+    method: 'put',
+    data
+  });
+}
+
+// 删除盘点规则
+export function deleteInformation(data) {
+  return request({
+    url: '/api/inventoryRules',
+    method: 'delete',
+    data
+  });
+}
+
+// 获取仓库列表(库内盘点-选择范围)
+export function getWarehouseList(data) {
+  return request({
+    url: '/api/warehouse/list',
+    method: 'post',
+    data
+  });
+}
+
+// 获取库区列表
+export function getWarehouseAreaList(data) {
+  return request({
+    url: '/api/warehouseArea/list',
+    method: 'post',
+    data
+  });
+}
+
+// 获取货架列表
+export function getShelvesList(data) {
+  return request({
+    url: '/api/shelves/list',
+    method: 'post',
+    data
+  });
+}
+
+// 获取货位列表
+export function getLocationList(data) {
+  return request({
+    url: '/api/location/list',
+    method: 'post',
+    data
+  });
+}
+
+// 获取区域列表(库外盘点-选择范围)
+export function getRegionList(data) {
+  return request({
+    url: '/api/region/list',
+    method: 'post',
+    data
+  });
+}

+ 16 - 0
src/api/technology/production/index.js

@@ -45,6 +45,22 @@ export default {
       return res.data;
     }
   },
+  //发布
+  publish: async (data) => {
+    const res = await request.post('/main/producetask/publish', data);
+    if (res.data.code == 0) {
+      return res.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
+  //历史版本
+  history: async (taskId) => {
+    const res = await request.get(`/main/producetask/history/${taskId}`);
+    if (res.data.code == 0) {
+      return res.data.data;
+    }
+    return Promise.reject(new Error(res.data.message));
+  },
   //删除
   delete: async (data) => {
     const res = await request.delete('/main/producetask/delete', { data });

+ 17 - 59
src/views/factoryModel/station/components/edit.vue

@@ -61,12 +61,8 @@
             </el-form-item>
           </el-col>
 
-          <el-col :span="8">
-            <el-form-item
-              label="设备编码:"
-              prop="extInfo.assetCode"
-              v-if="form.extInfo.type == 1"
-            >
+          <el-col v-if="form.extInfo.type == 1" :span="8">
+            <el-form-item label="设备编码:" prop="extInfo.assetCode">
               <el-input
                 v-model="form.extInfo.assetCode"
                 readonly
@@ -75,12 +71,8 @@
             </el-form-item>
           </el-col>
 
-          <el-col :span="8">
-            <el-form-item
-              label="设备名称:"
-              prop="extInfo.assetName"
-              v-if="form.extInfo.type == 1"
-            >
+          <el-col v-if="form.extInfo.type == 1" :span="8">
+            <el-form-item label="设备名称:" prop="extInfo.assetName">
               <el-input disabled v-model="form.extInfo.assetName" />
             </el-form-item>
           </el-col>
@@ -180,42 +172,6 @@
               </el-select>
             </el-form-item>
           </el-col>
-          <el-col :span="8">
-            <el-form-item
-              label="设备编码:"
-              prop="extInfo.assetCode"
-              v-if="form.extInfo.type == 1"
-            >
-              <el-input
-                v-model="form.extInfo.assetCode"
-                readonly
-                @click.native="chooseAsset"
-              />
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="8">
-            <el-form-item
-              label="设备名称:"
-              prop="extInfo.assetName"
-              v-if="form.extInfo.type == 1"
-            >
-              <el-input disabled v-model="form.extInfo.assetName" />
-            </el-form-item>
-          </el-col>
-
-          <el-col :span="8">
-            <el-form-item label="所属区域:" prop="location_city">
-              <area-select
-                v-model="form.areaId"
-                @checkedKeys="getAreaInfo"
-                :data="areaTreeList"
-                ref="tree"
-                :disabled="form.extInfo.type"
-              />
-            </el-form-item>
-          </el-col>
-
           <el-col :span="8">
             <el-form-item label="班组:" prop="extInfo.teamId">
               <el-select
@@ -807,17 +763,20 @@
           if (!valid) {
             return false;
           }
-          if (this.clientEnvironmentId != 9) {
-            this.form.factoryWorkstationOperations =
-              this.$refs.stationMeter.getValue();
-            if (!this.form.factoryWorkstationOperations.length) {
-              return this.$message.error('请添加工序');
-            } else {
-              this.form.taskIds = this.form.factoryWorkstationOperations.map(
-                (n) => n.operationId
-              );
-            }
+
+          this.form.factoryWorkstationOperations =
+            this.$refs.stationMeter.getValue();
+          if (
+            !this.form.factoryWorkstationOperations.length &&
+            this.clientEnvironmentId != 9
+          ) {
+            return this.$message.warning('请添加工序');
+          } else {
+            this.form.taskIds = this.form.factoryWorkstationOperations.map(
+              (n) => n.operationId
+            );
           }
+
           this.loading = true;
 
           if (this.type != 'edit') {
@@ -1026,7 +985,6 @@
               factoryName: res.factoryName
             }
           };
-
           // this.form = this.deepCopy(Object.assign({}, this.form, res));
 
           // console.log(this.form, 'this.form1');

+ 2 - 0
src/views/material/BOMmanage/components/detailedList.vue

@@ -336,12 +336,14 @@
             prop: 'modelType',
             label: '型号',
             align: 'center',
+            width: 260,
             showOverflowTooltip: true
           },
           {
             prop: 'specification',
             label: '规格',
             align: 'center',
+            width: 260,
             showOverflowTooltip: true
           },
           {

+ 53 - 32
src/views/material/product/components/index-data.vue

@@ -917,53 +917,72 @@
         });
       },
       /* 表格数据源 */
+      hasCurrentCategory() {
+        return (
+          this.currentId !== undefined &&
+          this.currentId !== null &&
+          this.currentId !== ''
+        );
+      },
+      getCategoryParams(params = {}) {
+        return {
+          ...params,
+          categoryLevelId: this.currentId
+        };
+      },
       async datasource({ page, limit, where, order }) {
         this.currentPage = page;
-        let labs = getMaterialList({
+        if (!this.hasCurrentCategory()) {
+          return {
+            pageNum: page,
+            current: page,
+            size: limit,
+            count: 0,
+            list: []
+          };
+        }
+        const params = this.getCategoryParams({
           pageNum: page,
           size: limit,
           ...this.sort,
-          ...where,
-          categoryLevelId: this.currentId
+          ...where
         });
-        this.whereData = {
-          pageNum: page,
-          size: limit,
-          ...this.sort,
-          ...where,
-          categoryLevelId: this.currentId
-        };
-        let a = await labs;
-
-        return labs;
+        this.whereData = params;
+        return getMaterialList(params);
       },
       /* 刷新表格 */
       reload(where) {
-        let labs = {
-          page: 1,
-          where: where,
-          categoryLevelId: this.currentId
-        };
-        this.whereData = labs;
-        this.$refs.table.reload({
+        if (!this.hasCurrentCategory()) {
+          return;
+        }
+        let labs = this.getCategoryParams({
           page: 1,
-          where: where,
-          categoryLevelId: this.currentId
+          where: where
         });
+        this.whereData = labs;
+        this.$refs.table.reload(
+          this.getCategoryParams({
+            page: 1,
+            where: where
+          })
+        );
       },
       /* 刷新表格 */
       reloadNew(where) {
-        let labs = {
+        if (!this.hasCurrentCategory()) {
+          return;
+        }
+        let labs = this.getCategoryParams({
           page: 1,
-          where: where,
-          categoryLevelId: this.currentId
-        };
-        this.whereData = labs;
-        this.$refs.table.reload({
-          page: this.currentPage,
-          where: where,
-          categoryLevelId: this.currentId
+          where: where
         });
+        this.whereData = labs;
+        this.$refs.table.reload(
+          this.getCategoryParams({
+            page: this.currentPage,
+            where: where
+          })
+        );
       },
       getFieldModel() {
         fieldModel({ relevance: 't_main_category' }).then((res) => {
@@ -1186,7 +1205,9 @@
     watch: {
       // 监听物料组id变化
       currentId() {
-        this.reload();
+        if (this.hasCurrentCategory()) {
+          this.reload();
+        }
       },
 
       $route: {

+ 3 - 1
src/views/material/product/index.vue

@@ -166,7 +166,9 @@
     activated() {
       // this.getTreeData();
       this.$nextTick(() => {
-        this.$refs.listData.reloadNew(this.where);
+        if (this.current && this.current.id && this.$refs.listData) {
+          this.$refs.listData.reloadNew(this.where);
+        }
       });
     },
     computed: {

+ 3 - 1
src/views/material/product/oneProduct.vue

@@ -170,7 +170,9 @@
       this.$nextTick(() => {
         if (this.$refs.listData) {
           this.$refs.listData.getCategoryNeedApprove();
-          this.$refs.listData.reloadNew(this.where);
+          if (this.current && this.current.id) {
+            this.$refs.listData.reloadNew(this.where);
+          }
         }
       });
     },

+ 529 - 0
src/views/rulesManagement/inventoryRules/components/addDialog.vue

@@ -0,0 +1,529 @@
+<!-- 新增/编辑弹窗 -->
+<template>
+  <ele-modal
+    width="1000px"
+    :visible="visible"
+    :append-to-body="true"
+    :close-on-click-modal="false"
+    custom-class="ele-dialog-form inventory-rules-dialog"
+    :title="dialogTitle"
+    @update:visible="updateVisible"
+  >
+    <el-form
+      ref="form"
+      :model="form"
+      :rules="rules"
+      label-width="120px"
+      label-position="right"
+    >
+      <!-- 基本信息 -->
+      <div class="basic-details-title">
+        <span class="border-span">基本信息</span>
+      </div>
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <el-form-item label="盘点规则编码:" prop="code">
+            <el-input
+              v-model="form.code"
+              placeholder="系统自动生成,PDGZ+年月日+3位数字"
+              :disabled="true"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="盘点规则名称:" prop="name">
+            <el-input
+              clearable
+              v-model="form.name"
+              placeholder="请输入盘点规则名称"
+              :disabled="isDetail"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="盘点类型:" prop="type">
+            <el-select
+              v-model="form.type"
+              placeholder="请选择"
+              style="width: 100%"
+              :disabled="isDetail"
+              @change="handleTypeChange"
+            >
+              <el-option label="库内盘点" :value="1" />
+              <el-option label="库外盘点" :value="2" />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="盘点分类:" prop="category">
+            <el-select
+              v-model="form.category"
+              placeholder="请选择"
+              style="width: 100%"
+              :disabled="isDetail"
+            >
+              <el-option label="产品" :value="1" />
+              <el-option label="物料" :value="2" />
+              <el-option label="生产设备" :value="3" />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="盘点模式:" prop="mode">
+            <el-select
+              v-model="form.mode"
+              placeholder="请选择"
+              style="width: 100%"
+              :disabled="isDetail"
+            >
+              <el-option label="明盘" :value="1" />
+              <el-option label="盲盘" :value="2" />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="频率类型:" prop="frequencyType">
+            <el-select
+              v-model="form.frequencyType"
+              placeholder="请选择"
+              style="width: 100%"
+              :disabled="isDetail"
+            >
+              <el-option label="一次性" :value="1" />
+              <el-option label="周期性" :value="2" />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8" v-if="form.frequencyType !== 1">
+          <el-form-item label="周期:" prop="periodValue">
+            <el-input
+              v-model="form.periodValue"
+              placeholder="请输入"
+              :disabled="isDetail"
+              style="width: calc(100% - 98px); margin-right: 8px;"
+            />
+            <el-select
+              v-model="form.periodUnit"
+              placeholder="请选择"
+              style="width: 90px;"
+              :disabled="isDetail"
+            >
+              <el-option
+                v-for="item in periodUnitOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="8">
+          <el-form-item label="状态:" prop="status">
+            <el-switch
+              v-model="form.status"
+              active-color="#1890ff"
+              inactive-color="#ccc"
+              :active-value="1"
+              :inactive-value="0"
+              :disabled="isDetail"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
+      <!-- 盘点策略 -->
+      <div class="basic-details-title">
+        <span class="border-span">盘点策略</span>
+      </div>
+      <el-row :gutter="20">
+        <el-col :span="8">
+          <el-form-item label="盘点精度:" prop="accuracy">
+            <el-select
+              v-model="form.accuracy"
+              placeholder="请选择"
+              style="width: 100%"
+              :disabled="isDetail"
+            >
+              <el-option
+                v-for="item in accuracyOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="16">
+          <el-form-item label="盘点范围:" prop="range">
+            <el-select
+              v-model="form.range"
+              placeholder="请选择"
+              style="width: 180px; margin-right: 8px;"
+              :disabled="isDetail"
+              @change="handleRangeChange"
+            >
+              <el-option
+                v-for="item in rangeOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+            <el-input
+              v-model="form.rangeDesc"
+              :placeholder="rangePlaceholder"
+              :disabled="isDetail"
+              style="width: calc(100% - 188px);"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="8" v-if="form.type !== 2">
+          <el-form-item label="冻结策略:" prop="freezeStrategy">
+            <el-select
+              v-model="form.freezeStrategy"
+              placeholder="请选择"
+              style="width: 100%"
+              :disabled="isDetail"
+            >
+              <el-option
+                v-for="item in freezeStrategyOptions"
+                :key="item.value"
+                :label="item.label"
+                :value="item.value"
+              />
+            </el-select>
+          </el-form-item>
+        </el-col>
+        <el-col :span="16" v-if="form.type !== 2">
+          <el-form-item label="是否允许新增'无账货':" prop="allowAddNoAccount">
+            <el-radio-group v-model="form.allowAddNoAccount" :disabled="isDetail">
+              <el-radio :label="0">否</el-radio>
+              <el-radio :label="1">是</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+
+    <template v-slot:footer>
+      <template v-if="isDetail">
+        <el-button @click="updateVisible(false)">关闭</el-button>
+      </template>
+      <template v-else>
+        <el-button type="primary" :loading="loading" @click="save">
+          确定
+        </el-button>
+        <el-button @click="updateVisible(false)">取消</el-button>
+      </template>
+    </template>
+  </ele-modal>
+</template>
+
+<script>
+  import {
+    addInventoryRules,
+    updateInventoryRules
+  } from '@/api/rulesManagement/inventoryRules';
+
+  export default {
+    data() {
+      return {
+        visible: false,
+        loading: false,
+        isUpdate: false,
+        isDetail: false,
+        // 盘点类型:1-库内盘点 2-库外盘点
+        // 库内盘点范围
+        rangeOptionsIn: [
+          { value: 1, label: '按仓库' },
+          { value: 2, label: '按库区' },
+          { value: 3, label: '按货架' },
+          { value: 4, label: '按货位' }
+        ],
+        // 库外盘点范围
+        rangeOptionsOut: [
+          { value: 5, label: '按区域' },
+          { value: 6, label: '按工厂' },
+          { value: 7, label: '按厂房' },
+          { value: 8, label: '按车间' },
+          { value: 9, label: '按产线' },
+          { value: 10, label: '按部门' }
+        ],
+        // 所有冻结策略
+        allFreezeStrategy: [
+          { value: 1, label: '库存快照(不锁库)' },
+          { value: 2, label: '仓库锁' },
+          { value: 3, label: '库区锁' },
+          { value: 4, label: '货架锁' },
+          { value: 5, label: '货位锁' }
+        ],
+        // 周期单位
+        periodUnitOptions: [
+          { value: '分/次', label: '分/次' },
+          { value: '时/次', label: '时/次' },
+          { value: '天/次', label: '天/次' },
+          { value: '周/次', label: '周/次' },
+          { value: '月/次', label: '月/次' },
+          { value: '年/次', label: '年/次' },
+          { value: '次/天', label: '次/天' },
+          { value: '次/周', label: '次/周' },
+          { value: '次/月', label: '次/月' },
+          { value: '次/年', label: '次/年' }
+        ],
+        // 盘点精度
+        accuracyOptions: [
+          { value: 1, label: '物品维度' },
+          { value: 2, label: '批次维度' },
+          { value: 3, label: '包装维度' }
+        ],
+        form: {
+          id: null,
+          code: '',
+          name: '',
+          type: null,           // 1-库内 2-库外
+          category: null,       // 1-产品 2-物料 3-生产设备
+          mode: null,           // 1-明盘 2-盲盘
+          frequencyType: null,  // 1-一次性 2-周期性
+          periodValue: '',
+          periodUnit: '分/次',
+          status: 1,
+          accuracy: null,       // 1-物品 2-批次 3-包装
+          range: null,          // 盘点范围
+          rangeDesc: '',        // 范围描述
+          freezeStrategy: null, // 冻结策略
+          allowAddNoAccount: 1  // 是否允许新增无账货:默认是
+        },
+        rules: {
+          name: [{ required: true, message: '请输入盘点规则名称', trigger: 'blur' }],
+          type: [{ required: true, message: '请选择盘点类型', trigger: 'change' }],
+          category: [{ required: true, message: '请选择盘点分类', trigger: 'change' }],
+          mode: [{ required: true, message: '请选择盘点模式', trigger: 'change' }],
+          frequencyType: [{ required: true, message: '请选择频率类型', trigger: 'change' }],
+          periodValue: [
+            {
+              validator: (value, callback) => {
+                if (this.form.frequencyType === 1) {
+                  callback();
+                } else if (!value) {
+                  callback(new Error('请输入周期'));
+                } else {
+                  callback();
+                }
+              },
+              trigger: 'blur'
+            }
+          ],
+          accuracy: [{ required: true, message: '请选择盘点精度', trigger: 'change' }],
+          range: [{ required: true, message: '请选择盘点范围', trigger: 'change' }],
+          rangeDesc: [{ required: true, message: '请选择范围', trigger: 'change' }],
+          freezeStrategy: [
+            {
+              validator: (value, callback) => {
+                if (this.form.type === 2) {
+                  callback();
+                } else if (value === null || value === undefined || value === '') {
+                  callback(new Error('请选择冻结策略'));
+                } else {
+                  callback();
+                }
+              },
+              trigger: 'change'
+            }
+          ]
+        }
+      };
+    },
+    computed: {
+      // 弹窗标题(根据盘点类型动态切换)
+      dialogTitle() {
+        if (this.isDetail) {
+          return '盘点规则详情';
+        }
+        if (this.isUpdate) {
+          return '修改盘点规则';
+        }
+        if (this.form.type === 1) {
+          return '新增库内盘点规则';
+        }
+        if (this.form.type === 2) {
+          return '新增库外盘点规则';
+        }
+        return '新增盘点规则';
+      },
+      // 当前盘点类型下可选的盘点范围
+      rangeOptions() {
+        if (this.form.type === 1) {
+          return this.rangeOptionsIn;
+        }
+        if (this.form.type === 2) {
+          return this.rangeOptionsOut;
+        }
+        return [];
+      },
+      // 范围描述占位符
+      rangePlaceholder() {
+        if (this.form.type === 1) {
+          return '选择仓库';
+        }
+        if (this.form.type === 2) {
+          return '选择区域';
+        }
+        return '请先选择盘点类型';
+      },
+      // 根据盘点范围和盘点类型限制冻结策略
+      freezeStrategyOptions() {
+        // 库外盘点:只允许库存快照(不锁库)
+        if (this.form.type === 2) {
+          return this.allFreezeStrategy.filter(item => item.value === 1);
+        }
+        // 库内盘点:根据范围限制
+        if (this.form.type === 1) {
+          switch (this.form.range) {
+            case 1: // 按仓库:库存快照、仓库锁
+              return this.allFreezeStrategy.filter(item => item.value === 1 || item.value === 2);
+            case 2: // 按库区:库存快照、仓库锁、库区锁
+              return this.allFreezeStrategy.filter(item => [1, 2, 3].includes(item.value));
+            case 3: // 按货架:库存快照、仓库锁、库区锁、货架锁
+              return this.allFreezeStrategy.filter(item => [1, 2, 3, 4].includes(item.value));
+            case 4: // 按货位:所有
+              return this.allFreezeStrategy;
+            default:
+              return this.allFreezeStrategy;
+          }
+        }
+        return this.allFreezeStrategy;
+      }
+    },
+    watch: {
+      'form.type'() {
+        // 切换盘点类型时,清空已选择的范围、范围描述、冻结策略
+        if (this.form.range !== null) {
+          this.form.range = null;
+          this.form.rangeDesc = '';
+        }
+        if (this.form.freezeStrategy !== null) {
+          this.form.freezeStrategy = null;
+        }
+      },
+      'form.frequencyType'() {
+        // 切换频率类型时,清空已填周期值
+        this.form.periodValue = '';
+        this.form.periodUnit = '分';
+      }
+    },
+    methods: {
+      // 生成编码 PDGZ+年月日+3位数字
+      generateCode() {
+        const now = new Date();
+        const year = now.getFullYear();
+        const month = String(now.getMonth() + 1).padStart(2, '0');
+        const day = String(now.getDate()).padStart(2, '0');
+        const random = String(Math.floor(Math.random() * 900) + 100);
+        this.form.code = `PDGZ${year}${month}${day}${random}`;
+      },
+
+      // 盘点类型变化
+      handleTypeChange() {
+        // watch中已处理清空,这里不需要额外操作
+      },
+
+      // 盘点范围变化
+      handleRangeChange() {
+        // 切换范围时清空范围描述和冻结策略
+        this.form.rangeDesc = '';
+        this.form.freezeStrategy = null;
+      },
+
+      open(type, row) {
+        this.visible = true;
+        this.isUpdate = type === 'edit';
+        this.isDetail = type === 'detail';
+        if ((this.isUpdate || this.isDetail) && row) {
+          this.form = {
+            ...this.form,
+            ...row
+          };
+        } else {
+          this.resetForm();
+          // this.generateCode();
+        }
+        this.$nextTick(() => {
+          this.$refs.form && this.$refs.form.clearValidate();
+        });
+      },
+
+      resetForm() {
+        this.form = {
+          id: null,
+          code: '',
+          name: '',
+          type: null,
+          category: null,
+          mode: null,
+          frequencyType: null,
+          periodValue: '',
+          periodUnit: '分/次',
+          status: 1,
+          accuracy: null,
+          range: null,
+          rangeDesc: '',
+          freezeStrategy: null,
+          allowAddNoAccount: 1
+        };
+      },
+
+      save() {
+        this.$refs.form.validate((valid) => {
+          if (!valid) return;
+          this.loading = true;
+          const saveOrUpdate = this.isUpdate ? updateInventoryRules : addInventoryRules;
+          saveOrUpdate(this.form)
+            .then(() => {
+              this.loading = false;
+              this.$message.success(this.isUpdate ? '修改成功' : '新增成功');
+              this.updateVisible(false);
+              this.$emit('done');
+            })
+            .catch(() => {
+              this.loading = false;
+            });
+        });
+      },
+
+      updateVisible(value) {
+        this.visible = value;
+        if (!value) {
+          this.resetForm();
+        }
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .inventory-rules-dialog {
+    :deep(.el-dialog__body) {
+      padding: 16px 24px;
+    }
+  }
+  .basic-details-title {
+    margin-bottom: 16px;
+    margin-top: 8px;
+    border-bottom: 1px solid #1890ff;
+    padding-bottom: 8px;
+    display: flex;
+    justify-content: space-between;
+    &:first-of-type {
+      margin-top: 0;
+    }
+  }
+  .basic-details-title .border-span {
+    height: 18px;
+    line-height: 18px;
+    font-size: 16px;
+    font-weight: 600;
+    color: #303133;
+    border-left: 4px solid #1890ff;
+    padding-left: 8px;
+  }
+</style>

+ 59 - 0
src/views/rulesManagement/inventoryRules/components/searchForm.vue

@@ -0,0 +1,59 @@
+<!-- 搜索表单 -->
+<template>
+  <seekPage :seekList="seekList" :formLength="3" @search="search"></seekPage>
+</template>
+
+<script>
+  export default {
+    data() {
+      return {};
+    },
+    computed: {
+      seekList() {
+        return [
+          {
+            label: '关键词:',
+            value: 'searchName',
+            type: 'input',
+            placeholder: '编码、名称'
+          },
+          {
+            label: '适用类型:',
+            value: 'searchType',
+            type: 'select',
+            placeholder: '请选择',
+            planList: [
+              { value: 1, label: '库内盘点' },
+              { value: 2, label: '库外盘点' },
+            ]
+          },
+          {
+            label: '盘点精度:',
+            value: 'searchName2',
+            type: 'select',
+            placeholder: '请选择',
+            planList: [
+              { value: 1, label: '物品维度' },
+              { value: 2, label: '批次维度' },
+              { value: 3, label: '包装维度' }
+            ]
+          },
+          {
+            label: '创建时间:',
+            value: 'createTime',
+            type: 'date',
+            dateType: 'daterange',
+            placeholder: '',
+            width: 380,
+            valueAr: ['createTimeStart', 'createTimeEnd']
+          }
+        ];
+      }
+    },
+    methods: {
+      search(e) {
+        this.$emit('search', { ...e });
+      }
+    }
+  };
+</script>

+ 276 - 0
src/views/rulesManagement/inventoryRules/index.vue

@@ -0,0 +1,276 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never" v-loading="loading">
+      <div class="ele-border-lighter form-content" v-loading="loading">
+        <search-form @search="reload"> </search-form>
+
+        <!-- 数据表格 -->
+        <ele-pro-table
+          ref="table"
+          :columns="columns"
+          :datasource="datasource"
+          height="calc(100vh - 375px)"
+          full-height="calc(100vh - 116px)"
+          tool-class="ele-toolbar-form"
+          :selection.sync="selection"
+          :page-size="20"
+          @columns-change="handleColumnChange"
+          :cache-key="cacheKeyUrl"
+        >
+          <!-- 表头工具栏 -->
+          <template v-slot:toolbar>
+            <el-button
+              size="small"
+              type="primary"
+              icon="el-icon-plus"
+              class="ele-btn-icon"
+              @click="openEdit('add', {})"
+            >
+              新增
+            </el-button>
+          </template>
+
+          <!-- 操作列 -->
+          <template v-slot:action="{ row }">
+            <el-link
+              type="primary"
+              :underline="false"
+              icon="el-icon-view"
+              @click="openDetail(row)"
+            >
+              详情
+            </el-link>
+            <el-link
+              type="primary"
+              :underline="false"
+              icon="el-icon-edit"
+              @click="openEdit('edit', row)"
+            >
+              修改
+            </el-link>
+            <el-popconfirm
+              class="ele-action"
+              title="确定要删除此信息吗?"
+              @confirm="remove([row.id])"
+            >
+              <template v-slot:reference>
+                <el-link type="danger" :underline="false" icon="el-icon-delete">
+                  删除
+                </el-link>
+              </template>
+            </el-popconfirm>
+          </template>
+        </ele-pro-table>
+      </div>
+    </el-card>
+
+    <add-dialog ref="addDialogRef" @done="reload"></add-dialog>
+  </div>
+</template>
+
+<script>
+  import searchForm from './components/searchForm.vue';
+  import addDialog from './components/addDialog.vue';
+  import tabMixins from '@/mixins/tableColumnsMixin';
+  import {
+    getTableList,
+    deleteInformation
+  } from '@/api/rulesManagement/receiveTerms';
+
+  export default {
+    mixins: [tabMixins],
+    components: {
+      searchForm,
+      addDialog
+    },
+    data() {
+      return {
+        selection: [],
+        loading: false,
+        columns: [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center'
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            prop: 'code',
+            label: '盘点规则编码',
+            align: 'center',
+            sortable: true,
+            showOverflowTooltip: true,
+            minWidth: 160
+          },
+          {
+            prop: 'name',
+            label: '盘点规则名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 160
+          },
+          {
+            prop: 'calcDateType',
+            label: '适用类型',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 160,
+            formatter: (row) => {
+              const map = {
+                1: '订单日期',
+                2: '出库日期',
+                3: '应收单日期',
+                4: '开票日期',
+                5: '对账单日期'
+              };
+              return map[row.calcDateType] || '';
+            }
+          },
+          {
+            prop: 'paymentMethod',
+            label: '盘点模式',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 140
+          },
+          {
+            prop: 'confirmType',
+            label: '盘点类型',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 140,
+            formatter: (row) => {
+              const map = {
+                1: '交易日',
+                2: 'X天后'
+              };
+              return map[row.confirmType] || '';
+            }
+          },
+          {
+            prop: 'confirmDesc',
+            label: '频率类型',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 180
+          },
+          {
+            prop: 'createUserName',
+            label: '周期',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120
+          },
+          {
+            prop: 'createUserName',
+            label: '盘点精度',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120
+          },
+          {
+            prop: 'createUserName',
+            label: '盘点范围',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120
+          },
+          {
+            prop: 'createUserName',
+            label: '盘点范围描述',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120
+          },
+          {
+            prop: 'createUserName',
+            label: '冻结策略',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120
+          },
+          {
+            prop: 'createUserName',
+            label: '创建人',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120
+          },
+          {
+            prop: 'createUserName',
+            label: '创建时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120
+          },
+          {
+            prop: 'createUserName',
+            label: '状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 120
+          },
+          {
+            columnKey: 'action',
+            label: '操作',
+            width: 170,
+            align: 'center',
+            resizable: false,
+            slot: 'action',
+            showOverflowTooltip: true,
+            fixed: 'right'
+          }
+        ],
+        cacheKeyUrl: 'eos-receiveTerms-list'
+      };
+    },
+    methods: {
+      /* 表格数据源 */
+      datasource({ page, limit, where, order }) {
+        return getTableList({
+          pageNum: page,
+          size: limit,
+          ...where
+        });
+      },
+
+      /* 刷新表格 */
+      reload(where) {
+        this.$refs.table.reload({ page: 1, where });
+      },
+
+      // 新增编辑
+      openEdit(type, row) {
+        this.$refs.addDialogRef.open(type, row);
+      },
+
+      // 查看详情
+      openDetail(row) {
+        this.$refs.addDialogRef.open('detail', row);
+      },
+
+      // 删除
+      remove(delData) {
+        deleteInformation(delData).then(() => {
+          this.$message.success('删除成功!');
+          this.reload();
+        });
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  :deep(.el-link--inner) {
+    margin-left: 0px !important;
+  }
+</style>

+ 23 - 5
src/views/system/menu/index.vue

@@ -59,7 +59,7 @@
             <span v-if="row.icon" class="menu-icon-wrap">
               <i :class="row.icon"></i>
             </span>
-            <span class="menu-name-text">{{ row.name }}</span>
+            <span class="menu-name-text" :title="row.name">{{ row.name }}</span>
           </span>
         </template>
         <!-- 标题列 -->
@@ -165,7 +165,7 @@
           {
             columnKey: 'index',
             type: 'index',
-            width: 45,
+            width: 68,
             align: 'center',
             showOverflowTooltip: false,
             fixed: 'left'
@@ -174,7 +174,8 @@
             prop: 'name',
             label: '菜单名称',
             showOverflowTooltip: true,
-            minWidth: 180,
+            minWidth: 240,
+            className: 'menu-name-column',
             slot: 'name'
           },
           {
@@ -426,6 +427,19 @@
       border-color: #edf2f7;
     }
 
+    ::v-deep .el-table__fixed .el-table__cell:first-child .cell,
+    ::v-deep .el-table__body .el-table__cell:first-child .cell {
+      white-space: nowrap;
+      word-break: keep-all;
+    }
+
+    ::v-deep .menu-name-column .cell {
+      display: flex;
+      align-items: center;
+      min-width: 0;
+      white-space: nowrap;
+    }
+
     ::v-deep .el-table__row {
       transition: none;
     }
@@ -484,6 +498,8 @@
   .menu-name-cell {
     display: inline-flex;
     align-items: center;
+    flex: 1 1 auto;
+    min-width: 0;
     max-width: 100%;
     gap: 8px;
     color: #26384d;
@@ -521,7 +537,7 @@
     }
 
     .menu-name-text {
-      padding: 3px 9px 3px 0;
+      padding: 3px 4px 3px 0;
       border-radius: 0 6px 6px 0;
       color: #354a62;
       background: #f7fbff;
@@ -542,7 +558,9 @@
   }
 
   .menu-name-text {
-    min-width: 0;
+    display: block;
+    flex: 1 1 auto;
+    min-width: 24px;
     overflow: hidden;
     text-overflow: ellipsis;
     white-space: nowrap;

+ 205 - 0
src/views/technology/production/components/history-modal.vue

@@ -0,0 +1,205 @@
+<template>
+  <ele-modal
+    title="历史版本"
+    :visible.sync="visible"
+    :close-on-click-modal="false"
+    width="900px"
+    :maxable="true"
+    @close="handleClose"
+  >
+    <ele-pro-table
+      ref="table"
+      :columns="columns"
+      :datasource="historyList"
+      :need-page="false"
+      row-key="id"
+      max-height="520"
+    >
+      <template v-slot:isPublished="{ row }">
+        <el-tag v-if="row.isPublished == 1" type="success">已发布</el-tag>
+        <el-tag v-else type="info">未发布</el-tag>
+      </template>
+
+      <template v-slot:action="{ row }">
+        <el-link type="primary" :underline="false" @click="openDetail(row)">
+          详情
+        </el-link>
+      </template>
+    </ele-pro-table>
+
+    <user-edit
+      :visible.sync="showDetail"
+      :data="current"
+      :controlList="controlList"
+      :typeList="typeList"
+      :detail="true"
+      ref="userEdit"
+    />
+
+    <template v-slot:footer>
+      <el-button @click="handleClose">关闭</el-button>
+    </template>
+  </ele-modal>
+</template>
+
+<script>
+  import producetask from '@/api/technology/production';
+  import control from '@/api/technology/control';
+  import UserEdit from './user-edit.vue';
+
+  export default {
+    components: {
+      UserEdit
+    },
+    data() {
+      return {
+        visible: false,
+        showDetail: false,
+        current: null,
+        currentTask: null,
+        historyList: [],
+        controlList: [],
+        typeList: [
+          {
+            value: 99,
+            label: '关键工序'
+          },
+          {
+            value: 1,
+            label: '普通工序'
+          },
+          {
+            value: 3,
+            label: '抽样质检'
+          },
+          {
+            value: 4,
+            label: '包装工序'
+          },
+          {
+            value: 6,
+            label: '质检工序'
+          }
+        ],
+        columns: [
+          {
+            columnKey: 'index',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            label: '序号'
+          },
+          {
+            prop: 'versionNumber',
+            label: '版本号',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 90,
+            formatter: (row) => this.formatVersion(row.versionNumber)
+          },
+          {
+            prop: 'isPublished',
+            slot: 'isPublished',
+            label: '发布状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 100
+          },
+          {
+            prop: 'publishedName',
+            label: '发布人',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'publishedTime',
+            label: '发布时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 160,
+            formatter: (row) => this.formatDate(row.publishedTime)
+          },
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            align: 'center',
+            showOverflowTooltip: true,
+            minWidth: 160,
+            formatter: (row) => this.formatDate(row.createTime)
+          },
+          {
+            prop: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center',
+            width: 90
+          }
+        ]
+      };
+    },
+    methods: {
+      async open(row) {
+        this.visible = true;
+        this.currentTask = row || null;
+        await this.getControlList();
+        await this.getHistoryList();
+      },
+
+      handleClose() {
+        this.visible = false;
+        this.showDetail = false;
+        this.current = null;
+        this.currentTask = null;
+        this.historyList = [];
+      },
+
+      async getHistoryList() {
+        if (!this.currentTask || !this.currentTask.id) {
+          this.historyList = [];
+          return;
+        }
+        this.historyList =
+          (await producetask.history(this.currentTask.id)) || [];
+      },
+
+      async getControlList() {
+        const res = await control.list({
+          pageNum: 1,
+          size: -1
+        });
+        this.controlList = (res && res.list) || [];
+      },
+
+      openDetail(row) {
+        this.current = {
+          ...row,
+          id: row.taskId || row.id
+        };
+        this.showDetail = true;
+      },
+
+      formatVersion(versionNumber) {
+        if (
+          versionNumber === undefined ||
+          versionNumber === null ||
+          versionNumber === ''
+        ) {
+          return '';
+        }
+        const version = String(versionNumber).trim();
+        if (!version) {
+          return '';
+        }
+        if (/^v\s*/i.test(version)) {
+          return version;
+        }
+        return `V ${version.includes('.') ? version : version + '.0'}`;
+      },
+
+      formatDate(value) {
+        return value ? this.$util.toDateString(value) : '';
+      }
+    }
+  };
+</script>

+ 15 - 5
src/views/technology/production/components/user-edit.vue

@@ -742,11 +742,12 @@
     },
     computed: {
       totalTime() {
+        const workBeat = this.form.workBeat || {};
         let to =
-          (-this.form.workBeat.restTimes +
-            -this.form.workBeat.preTimes +
-            -this.form.workBeat.proTimes +
-            -this.form.workBeat.otherTimes) *
+          (-workBeat.restTimes +
+            -workBeat.preTimes +
+            -workBeat.proTimes +
+            -workBeat.otherTimes) *
           -1;
         return to;
       },
@@ -825,9 +826,18 @@
           console.log(this.form, 'this.form');
           if (this.data) {
             const res = await producetask.getById(this.data.id);
+            const defaultData = this.defaultForm();
 
             this.$util.assignObject(this.form, {
-              ...res
+              ...res,
+              intervalTime: {
+                ...defaultData.intervalTime,
+                ...((res && res.intervalTime) || {})
+              },
+              workBeat: {
+                ...defaultData.workBeat,
+                ...((res && res.workBeat) || {})
+              }
             });
 
             this.isUpdate = true;

+ 21 - 7
src/views/technology/production/index.vue

@@ -108,6 +108,10 @@
           {{ typeLabel(row.type) }}
         </template>
 
+        <template v-slot:version="{ row }">
+          <span v-if="row.version">{{ 'V ' + row.version + '.0' }}</span>
+        </template>
+
         <template v-slot:processLabel="{ row }">
           <el-tag v-if="row.processLabel == 1">自制</el-tag>
           <el-tag v-if="row.processLabel == 2" type="success">委外</el-tag>
@@ -177,6 +181,10 @@
               <el-link type="primary" :underline="false"> 发布 </el-link>
             </template>
           </el-popconfirm>
+
+          <el-link type="primary" :underline="false" @click="openHistory(row)">
+            历史版本
+          </el-link>
         </template>
       </ele-pro-table>
     </el-card>
@@ -225,6 +233,8 @@
     <userSettingMatterProcessDrawer
       ref="userSettingMatterProcessDrawerRef"
     ></userSettingMatterProcessDrawer>
+
+    <history-modal ref="historyModalRef" />
   </div>
 </template>
 
@@ -244,6 +254,7 @@
   import dictMixins from '@/mixins/dictMixins';
   import productionCheck from './components/productionCheck.vue';
   import { getFactoryarea } from '@/api/factoryModel';
+  import HistoryModal from './components/history-modal.vue';
 
   export default {
     name: 'technologyProduction',
@@ -257,7 +268,8 @@
       WorkCenter,
       userSettingMatter,
       userSettingMatterProcessDrawer,
-      productionCheck
+      productionCheck,
+      HistoryModal
     },
     data() {
       return {
@@ -357,7 +369,7 @@
           {
             columnKey: 'action',
             label: '操作',
-            width: 230,
+            width: 300,
             align: 'center',
             resizable: false,
             slot: 'action',
@@ -566,15 +578,17 @@
         this.openEdit(row, true);
       },
 
+      openHistory(row) {
+        this.$refs.historyModalRef.open(row);
+      },
+
       async release(row) {
         const loading = this.$loading({ lock: true });
         try {
-          const detail = await producetask.getById(row.id);
-          await producetask.save({
-            ...detail,
-            isRelease: 1
+          const res = await producetask.publish({
+            taskId: row.id
           });
-          this.$message.success('发布成功');
+          this.$message.success((res && res.message) || '发布成功');
           this.reload();
         } finally {
           loading.close();