Explorar o código

feat:添加工装夹具相关逻辑

xieyong hai 2 días
pai
achega
9b01c9ab89

+ 605 - 0
src/views/ledgerAssets/fixture/components/fixture-list.vue

@@ -0,0 +1,605 @@
+<template>
+  <div>
+    <fixture-search
+      ref="searchRef"
+      @search="reload"
+      :networkCounts="networkCounts"
+    >
+    </fixture-search>
+    <!-- 数据表格 -->
+    <ele-pro-table
+      ref="table"
+      :pageSizes="tablePageSizes"
+      :columns="columns"
+      :page-size="defPageSize"
+      :datasource="datasource"
+      height="calc(100vh - 320px)"
+      full-height="calc(100vh - 115px)"
+      tool-class="ele-toolbar-form"
+      cache-key="fixtureTable"
+      @select="selectChange"
+      @select-all="changeSelectAll"
+    >
+      <!-- 表头工具栏 -->
+      <template v-slot:toolbar>
+        <el-button
+          size="small"
+          type="primary"
+          icon="el-icon-plus"
+          class="ele-btn-icon"
+          @click="add"
+        >
+          新建
+        </el-button>
+        <el-button
+          size="small"
+          icon="el-icon-download"
+          class="ele-btn-icon"
+          @click="btnExport"
+        >
+          导出
+        </el-button>
+        <el-button
+          :disabled="checkRadioData.length == 0"
+          size="small"
+          icon="el-icon-set-up"
+          class="ele-btn-icon"
+          @click="allPrinting()"
+        >
+          打印条码
+        </el-button>
+        <el-button
+          size="small"
+          :disabled="checkRadioData.length == 0"
+          icon="el-icon-thumb"
+          class="ele-btn-icon"
+          @click="moveTo(checkRadioData, 'person')"
+          v-if="$hasPermission('main:substance:update')"
+        >
+          设置片区负责人
+        </el-button>
+        <el-button
+          size="small"
+          :disabled="checkRadioData.length == 0"
+          icon="el-icon-s-tools"
+          class="ele-btn-icon"
+          @click="batchSettings(1)"
+          v-if="$hasPermission('main:substance:update')"
+        >
+          设置权属部门
+        </el-button>
+        <el-button
+          size="small"
+          :disabled="checkRadioData.length == 0"
+          icon="el-icon-setting"
+          class="ele-btn-icon"
+          @click="batchSettings(2)"
+          v-if="$hasPermission('main:substance:update')"
+        >
+          设置使用单位
+        </el-button>
+        <el-button
+          size="small"
+          :disabled="checkRadioData.length == 0"
+          icon="el-icon-s-tools"
+          class="ele-btn-icon"
+          type="danger"
+          @click="setStatus(1)"
+          v-if="$hasPermission('main:substance:stop')"
+        >
+          批量停机
+        </el-button>
+        <el-button
+          size="small"
+          :disabled="checkRadioData.length == 0"
+          icon="el-icon-setting"
+          class="ele-btn-icon"
+          @click="setStatus(2)"
+          v-if="$hasPermission('main:substance:run')"
+        >
+          批量运行
+        </el-button>
+        <el-button
+          size="small"
+          :disabled="checkRadioData.length == 0"
+          icon="el-icon-s-home"
+          class="ele-btn-icon"
+          @click="setFactory"
+          v-if="$hasPermission('main:substance:update')"
+        >
+          设置所属工厂
+        </el-button>
+      </template>
+
+      <!-- 编码列 -->
+      <template v-slot:code="{ row }">
+        <el-link type="primary" :underline="false" @click="details(row)">
+          {{ row.code }}
+        </el-link>
+      </template>
+      <!-- 牌号列 -->
+      <template v-slot:brandNum="{ row }">
+        <div>
+          {{ row.category.brandNum }}
+        </div>
+      </template>
+      <!-- 型号列 -->
+      <template v-slot:modelType="{ row }">
+        <div>
+          {{ row.category.modelType }}
+        </div>
+      </template>
+      <!-- 分类列 -->
+      <template v-slot:categoryLevelPath="{ row }">
+        <div>
+          {{ row.category.categoryLevelPath }}
+        </div>
+      </template>
+
+      <!-- 操作列 -->
+      <template v-slot:action="{ row }">
+        <el-link
+          type="primary"
+          :underline="false"
+          icon="el-icon-edit"
+          @click="goEdit(row)"
+        >
+          编辑
+        </el-link>
+        <el-link type="primary" @click="$refs.accountingLedgerListRef.open(row)"
+          >表计BOM</el-link
+        >
+        <el-link type="primary" @click="handelBOM(row)">BOM</el-link>
+      </template>
+    </ele-pro-table>
+    <print ref="printRef"></print>
+    <printSr ref="printSrRef"></printSr>
+    <printTg ref="printTgRef"></printTg>
+    <BomDetailsPop ref="bomDrawer"></BomDetailsPop>
+    <batchSetDialog ref="batchSetRef" @success="sucesstion" />
+    <batchSetFactory ref="batchSetFactoryRef" @success="sucesstion" />
+    <DialogMoveto ref="movetoRef" @success="sucesstion" />
+    <accountingLedgerList ref="accountingLedgerListRef"></accountingLedgerList>
+  </div>
+</template>
+
+<script>
+  import accountingLedgerList from '@/views/ledgerAssets/components/accountingLedgerList.vue';
+  import batchSetDialog from '@/views/ledgerAssets/equipment/components/batchSetDialog.vue';
+  import batchSetFactory from '@/views/ledgerAssets/equipment/components/batchSetFactory.vue';
+  import DialogMoveto from '@/views/ledgerAssets/equipment/components/DialogMoveTo.vue';
+  import print from '@/views/ledgerAssets/components/print.vue';
+  import printSr from '@/views/ledgerAssets/components/printSr.vue';
+  import printTg from '@/views/ledgerAssets/components/printTg.vue';
+  import { getByCode } from '@/api/system/dictionary-data';
+  import {
+    businessStatus,
+    networkStatus,
+    sourceStatus
+  } from '@/utils/dict/warehouse';
+  import FixtureSearch from './fixture-search.vue';
+
+  import {
+    getAssetList,
+    downloadAsset,
+    batchStop,
+    batchRun
+  } from '@/api/ledgerAssets';
+  import dictMixins from '@/mixins/dictMixins';
+  import axios from 'axios';
+  import {
+    API_BASE_URL,
+    TOKEN_HEADER_NAME,
+    LAYOUT_PATH
+  } from '@/config/setting';
+  import { download } from '@/utils/file';
+  import { getToken, setToken } from '@/utils/token-util';
+
+  import BomDetailsPop from '@/views/ledgerAssets/equipment/detailsPop.vue';
+
+  export default {
+    components: {
+      FixtureSearch,
+      print,
+      printSr,
+      printTg,
+      BomDetailsPop,
+      DialogMoveto,
+      batchSetDialog,
+      batchSetFactory,
+      accountingLedgerList
+    },
+    mixins: [dictMixins],
+    props: {
+      // 类别id
+      categoryId: [Number, String],
+      rootId: [Number, String],
+      current: {
+        typeof: Object,
+        default: {}
+      }
+    },
+    data() {
+      return {
+        QRvisible: false,
+        businessStatus,
+        networkStatus,
+        assetLevel: [],
+        networkCounts: {},
+        isConsumer: false,
+        // 表格列配置
+        columns: [
+          {
+            width: 45,
+            type: 'selection',
+            columnKey: 'selection',
+            align: 'center'
+          },
+          {
+            columnKey: 'index',
+            type: 'index',
+            label: '序号',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            columnKey: 'code',
+            prop: 'code',
+            slot: 'code',
+            label: '编码',
+            showOverflowTooltip: true,
+            minWidth: 180
+          },
+          {
+            prop: 'category.name',
+            label: '名称',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'fixCode',
+            label: '固资编码',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+
+          {
+            prop: 'codeNumber',
+            label: '编号',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'category.modelType',
+            label: '型号',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'category.specification',
+            label: '规格',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'extInfo.cyTimes',
+            label: '使用次数',
+            showOverflowTooltip: true,
+            minWidth: 130
+          },
+          {
+            prop: 'manufacturer',
+            label: '制造厂',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'manufactureTime',
+            label: '制造日期',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'createAccountsTime',
+            label: '建账日期',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'postName',
+            label: '使用单位',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'usePerson',
+            label: '使用人',
+            showOverflowTooltip: true,
+            minWidth: 80
+          },
+          {
+            prop: 'ownershipGroupName',
+            label: '权属部门',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'areaPersonInChargeUserName',
+            label: '片区负责人',
+            showOverflowTooltip: true,
+            minWidth: 150
+          },
+          {
+            prop: 'repairUserName',
+            label: '维修人',
+            showOverflowTooltip: true,
+            minWidth: 150
+          },
+          {
+            prop: 'endTime',
+            label: '有效期结束时间',
+            showOverflowTooltip: true,
+            minWidth: 150
+          },
+          {
+            prop: 'source',
+            label: '生命周期',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row) => {
+              return sourceStatus[_row.lifeCycle];
+            }
+          },
+          {
+            prop: 'level',
+            label: '级别',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row) => {
+              if (_row.level) {
+                return this.assetLevel.filter(
+                  (item) => item.id == _row.level
+                )[0].name;
+              } else {
+                return '';
+              }
+            }
+          },
+          {
+            prop: 'networkStatus',
+            label: '网络状态',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row) => {
+              if (_row.networkStatus) {
+                return this.networkStatus.filter(
+                  (item) => item.code == _row.networkStatus
+                )[0].label;
+              } else {
+                return '离线';
+              }
+            }
+          },
+          {
+            prop: 'status',
+            label: '状态',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row) => {
+              if (_row.status) {
+                return this.businessStatus.filter(
+                  (item) => item.code == _row.status
+                )[0].label;
+              } else {
+                return '空闲';
+              }
+            }
+          },
+          {
+            prop: 'runStatus',
+            label: '运行状态',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row) => {
+              return _row.runStatus == 5 ? '停机' : '运行';
+            }
+          },
+          {
+            prop: 'factoryName',
+            label: '所属工厂',
+            showOverflowTooltip: true,
+            minWidth: 110
+          },
+          {
+            prop: 'pathName',
+            label: '位置',
+            showOverflowTooltip: true,
+            minWidth: 110,
+            formatter: (_row) => {
+              const positionDetail =
+                _row.position &&
+                _row.position.length != 0 &&
+                _row.position[0].detailPosition
+                  ? _row.position[0].detailPosition
+                  : '-';
+              return _row.deviceLocationName
+                ? _row.deviceLocationName + '-' + positionDetail
+                : '';
+            }
+          },
+          {
+            columnKey: 'action',
+            slot: 'action',
+            label: '操作',
+            minWidth: 180,
+            fixed: 'right'
+          }
+        ],
+        checkRadioData: []
+      };
+    },
+    computed: {
+      clientEnvironmentId() {
+        return this.$store.state.user.info.clientEnvironmentId;
+      }
+    },
+    created() {
+      this.requestDict('生命周期');
+      this.getAssetLevelOptions();
+    },
+    methods: {
+      // 刷新回调
+      sucesstion(is) {
+        console.log(is);
+        if (is) {
+          this.reload();
+        }
+        this.checkRadioData = [];
+      },
+      // 移动到
+      moveTo(arr, type) {
+        this.$refs.movetoRef.open(arr, this.current, type);
+      },
+      batchSettings(type) {
+        let ids = this.checkRadioData.map((item) => {
+          return item.id;
+        });
+        this.$refs.batchSetRef.open(type, ids);
+        console.log(this.checkRadioData, 'checkRadioData 123');
+      },
+      allPrinting() {
+        if (this.clientEnvironmentId == 2) {
+          this.$refs.printSrRef.open(this.checkRadioData);
+        } else if (this.clientEnvironmentId == 3) {
+          this.$refs.printTgRef.open(this.checkRadioData);
+        } else {
+          this.$refs.printRef.open(this.checkRadioData);
+        }
+      },
+      // 全选
+      changeSelectAll(arr) {
+        console.log(arr);
+        if (arr.length != 0) {
+          this.checkRadioData = arr;
+        } else {
+          this.checkRadioData = [];
+        }
+      },
+      selectChange(selection, row) {
+        if (selection.length != 0) {
+          this.checkRadioData = selection;
+        } else {
+          this.checkRadioData = [];
+        }
+      },
+      setStatus(type) {
+        let api = type == 1 ? batchStop : batchRun;
+        api(this.checkRadioData.map((item) => item.id)).then((res) => {
+          this.$message.success('操作成功');
+          this.sucesstion(true);
+        });
+      },
+      setFactory() {
+        this.$refs.batchSetFactoryRef.open(this.checkRadioData);
+      },
+      // 获取资产级别下拉
+      async getAssetLevelOptions() {
+        let { data } = await getByCode('asset_level');
+        this.assetLevel =
+          data.length > 0
+            ? data.map((item) => {
+                return {
+                  name: Object.keys(item)[0],
+                  id: item[Object.keys(item)[0]]
+                };
+              })
+            : [];
+      },
+      // 跳转到详情页
+      add() {
+        this.$router.push({
+          path: '/ledgerAssets/fixture/edit'
+        });
+      },
+      // 跳转到编辑
+      goEdit({ id }) {
+        this.$router.push({
+          path: '/ledgerAssets/fixture/edit',
+          query: { id }
+        });
+      },
+      details({ id, code, name }) {
+        this.$router.push({
+          path: '/ledgerAssets/fixture/detail',
+          query: { id, code, name }
+        });
+      },
+      handelBOM(row) {
+        let rowData = {
+          categoryId: row.category.id,
+          categoryName: row.categoryName,
+          code: row.code,
+          versions: row.versions,
+          rootPathIdParent: row.category.categoryLevelPathIdParent,
+          isProduct: true,
+          bomType: '1',
+          isTemp: row.isTemp,
+          substanceId: row.id
+        };
+        this.$refs.bomDrawer.open(rowData);
+      },
+      btnExport() {
+        let params = {
+          ...this.$refs.searchRef.where,
+          exportType: 1,
+          categoryLevelId: this.categoryId,
+          rootCategoryLevelId: this.rootId
+        };
+        axios({
+          url: `${API_BASE_URL}/main/asset/page/export`,
+          method: 'post',
+          responseType: 'blob',
+          headers: {
+            Authorization: getToken()
+          },
+          data: params
+        }).then((res) => {
+          download(res.data, '工装夹具台账导出数据');
+        });
+      },
+      /* 刷新表格 */
+      reload(where) {
+        this.$refs.table.reload({ pageNum: 1, where });
+      },
+      /* 表格数据源 */
+      datasource({ page, limit, where, order }) {
+        return getAssetList({
+          ...order,
+          pageNum: page,
+          size: limit,
+          ...where,
+          categoryLevelId: this.categoryId,
+          rootCategoryLevelId: this.rootId
+        });
+      }
+    },
+    watch: {
+      categoryId() {
+        this.reload();
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  @media print {
+    #printSection {
+      font-size: 34px;
+      span {
+        font-size: 34px;
+      }
+    }
+  }
+</style>

+ 161 - 0
src/views/ledgerAssets/fixture/components/fixture-search.vue

@@ -0,0 +1,161 @@
+<template>
+  <seek-page
+    :seekList="seekList"
+    @search="handleSearch"
+    @reset="handleReset"
+    :formLength="3"
+  />
+</template>
+
+<script>
+  import { getByCode } from '@/api/system/dictionary-data';
+  import { getFactoryarea } from '@/api/factoryModel';
+  import { businessStatus, sourceStatus } from '@/utils/dict/warehouse';
+
+  export default {
+    props: ['networkCounts'],
+    data() {
+      return {
+        assetLevel: [],
+        factoryList: [],
+        businessStatus,
+        sourceStatus: Object.keys(sourceStatus).map((key) => {
+          return {
+            value: key,
+            label: sourceStatus[key]
+          };
+        }),
+        consumption: false
+      };
+    },
+    computed: {
+      seekList() {
+        return [
+          {
+            label: '编码',
+            value: 'code',
+            type: 'input',
+            placeholder: '请输入'
+          },
+          {
+            label: '名称',
+            value: 'name',
+            type: 'input',
+            placeholder: '请输入'
+          },
+          {
+            label: '使用单位',
+            value: 'postId',
+            type: 'DeptSelect',
+            placeholder: '请选择'
+          },
+          {
+            label: '固资编码',
+            value: 'fixCode',
+            type: 'input',
+            placeholder: '请输入'
+          },
+          {
+            label: '型号',
+            value: 'module',
+            type: 'input',
+            placeholder: '请输入'
+          },
+          {
+            label: '编号',
+            value: 'codeNumber',
+            type: 'input',
+            placeholder: '请输入'
+          },
+          {
+            label: '网络状态',
+            value: 'networkStatus',
+            type: 'DictSelection',
+            dictName: '网络状态',
+            placeholder: '请选择'
+          },
+          {
+            label: '生命周期',
+            value: 'lifeCycle',
+            type: 'select',
+            placeholder: '请选择',
+            selectList: this.sourceStatus
+          },
+          {
+            label: '有效期结束',
+            value: 'endTime',
+            type: 'date',
+            valueFormat: 'yyyy-MM',
+            dateType: 'month',
+            placeholder: '选择有效期结束时间'
+          },
+          {
+            label: '状态',
+            value: 'status',
+            type: 'select',
+            placeholder: '请选择',
+            selectList: this.businessStatus.map((item) => ({
+              value: item.code,
+              label: item.label
+            }))
+          },
+          {
+            label: '级别',
+            value: 'level',
+            type: 'select',
+            placeholder: '请选择',
+            selectList: this.assetLevel
+          },
+          {
+            label: '所属工厂',
+            value: 'factoryId',
+            type: 'select',
+            placeholder: '请选择',
+            selectList: this.factoryList
+          }
+        ];
+      }
+    },
+    created() {
+      this.getAssetLevelOptions();
+      this.getFactoryList();
+    },
+    methods: {
+      // 获取所属工厂下拉
+      getFactoryList() {
+        getFactoryarea({
+          size: 9999,
+          type: 1
+        }).then((res) => {
+          this.factoryList = (res.list || []).map((item) => ({
+            label: item.name,
+            value: item.id
+          }));
+        });
+      },
+      // 获取资产级别下拉
+      async getAssetLevelOptions() {
+        let { data } = await getByCode('asset_level');
+        this.assetLevel =
+          data.length > 0
+            ? data.map((item) => {
+                return {
+                  label: Object.keys(item)[0],
+                  value: item[Object.keys(item)[0]]
+                };
+              })
+            : [];
+      },
+
+      /* 搜索 */
+      handleSearch(where) {
+        this.$emit('search', where);
+      },
+
+      /* 重置 */
+      handleReset() {
+        this.$emit('reset');
+      }
+    }
+  };
+</script>

+ 121 - 0
src/views/ledgerAssets/fixture/components/fixtureInformation.vue

@@ -0,0 +1,121 @@
+<template>
+  <div>
+    <div class="basic-details-title border-none">
+      <span class="border-span">工装夹具信息</span>
+    </div>
+    <el-descriptions
+      :label-style="labelStyle"
+      :contentStyle="contentStyle"
+      title=""
+      :column="3"
+      size="medium"
+      border
+    >
+      <el-descriptions-item>
+        <template slot="label"> 收缩系数</template>
+        {{
+          categoryFixture.shrinkEffictive
+            ? categoryFixture.shrinkEffictive + '%'
+            : null
+        }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 芯杆数量 </template>
+        {{ categoryFixture.coreBarNum }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 模孔数量</template>
+        {{ categoryFixture.dieHoleNum }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 上冲头数量</template>
+        {{ categoryFixture.upperPunchNum }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 下冲头数量</template>
+        {{ categoryFixture.downPunchNum }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 最大冲压次数</template>
+        {{ categoryFixture.maxCyTimes }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 大模体型号 </template>
+        {{ categoryFixture.maxMoldType }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 芯棒直径 </template>
+        {{ categoryFixture.mandrelDiameter }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 长 </template>
+        {{ categoryFixture.length }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 宽 </template>
+        {{ categoryFixture.width }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 高 </template>
+        {{ categoryFixture.height }}
+      </el-descriptions-item>
+      <el-descriptions-item>
+        <template slot="label"> 直径 </template>
+        {{ categoryFixture.diameter }}
+      </el-descriptions-item>
+    </el-descriptions>
+  </div>
+</template>
+<script>
+  export default {
+    props: {
+      form: {
+        type: Object,
+        default: {
+          workstation: {}
+        }
+      }
+    },
+    watch: {
+      form: {
+        //监听的对象
+        deep: true, //深度监听设置为 true
+        handler: function (newValue) {
+          this.categoryFixture =
+            (newValue.category && newValue.category.categoryFixture) || {};
+        }
+      }
+    },
+    data() {
+      return {
+        labelStyle: {
+          width: '200px'
+        },
+        contentStyle: {
+          width: '400px'
+        },
+        categoryFixture: {}
+      };
+    },
+    methods: {
+      async getDetailInfoAugr(data) {
+        this.categoryFixture = { ...(data || {}) };
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .upload-container {
+    display: flex;
+    justify-content: flex-start;
+    .file-list {
+      margin-left: 50px;
+      flex: 1;
+    }
+  }
+  .basic-details-title {
+    font-size: 16px;
+    margin: 15px 0;
+  }
+</style>

+ 94 - 0
src/views/ledgerAssets/fixture/detail.vue

@@ -0,0 +1,94 @@
+<template>
+  <div class="ele-body">
+    <!-- tab切换 -->
+    <el-card :body-style="{ padding: 0 }">
+      <div class="switch">
+        <div class="switch_left">
+          <ul>
+            <li
+              v-for="item in tabOptions"
+              :key="item.key"
+              :class="{ active: activeComp == item.key }"
+              @click="activeComp = item.key"
+            >
+              {{ item.name }}
+            </li>
+          </ul>
+        </div>
+      </div>
+      <div class="page-title">
+        <el-page-header @back="$router.go(-1)">
+          <div slot="content" class="pageContent">
+            <span v-for="item in tabOptions" :key="item.key">
+              {{ item.key == activeComp ? item.name + '详情' : '' }}
+            </span>
+          </div>
+        </el-page-header>
+      </div>
+      <div class="content-wrapper">
+        <component
+          :is="activeComp"
+          :rowId="rowId"
+          :code="code"
+          :showTitle="false"
+        ></component>
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+  import baseInfo from './edit.vue';
+  import maintain from '../components/details/maintain.vue';
+  import repair from '../components/details/repair.vue';
+  import malfunction from '../components/details/malfunction.vue';
+  import inventory from '../components/details/inventory.vue';
+  import pointInspection from '../components/details/point-inspection.vue';
+  import internet from '../components/details/internet.vue';
+  import produceOrder from '../components/details/produceOrder/produce-order.vue';
+  export default {
+    name: 'fixtureDetail',
+    components: {
+      baseInfo,
+      pointInspection,
+      maintain,
+      repair,
+      inventory,
+      malfunction,
+      internet,
+      produceOrder
+    },
+    data() {
+      return {
+        activeComp: 'baseInfo',
+        tabOptions: [
+          { key: 'baseInfo', name: '工装夹具信息' },
+          { key: 'pointInspection', name: '巡点检记录' },
+          { key: 'maintain', name: '保养记录' },
+          { key: 'repair', name: '维修记录' },
+          { key: 'malfunction', name: '故障记录' },
+          { key: 'inventory', name: '盘点记录' },
+          { key: 'internet', name: '物联数据' },
+          { key: 'produceOrder', name: '生产记录' }
+        ],
+        rowId: null,
+        code: null
+      };
+    },
+    created() {
+      this.rowId = this.$route.query.id;
+      this.code = this.$route.query.code;
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .page-title {
+    background: #fff;
+    padding: 26px 10px 15px;
+    border-bottom: 1px solid #eaeafb;
+  }
+  .content-wrapper {
+    background-color: #fff;
+  }
+</style>

+ 561 - 0
src/views/ledgerAssets/fixture/edit.vue

@@ -0,0 +1,561 @@
+<template>
+  <div id="fixture_edit" class="ele-body baseinfo-container">
+    <el-card shadow="never">
+      <div class="page-title" v-if="showTitle">
+        <el-page-header @back="$router.go(-1)">
+          <div slot="content" class="pageContent">
+            <div>{{ title }}</div>
+          </div>
+        </el-page-header>
+        <div>
+          <el-button type="primary" @click="submit" :loading="btnLoading"
+            >确定</el-button
+          >
+        </div>
+      </div>
+      <div v-if="pageType == 'add'">
+        <el-button type="primary" plain @click="handlwpbm">选择物品</el-button>
+      </div>
+      <el-form
+        label-width="120px"
+        :model="{ ...form, ...positionInfo }"
+        ref="form"
+        :rules="rules"
+      >
+        <div class="content">
+          <basicInfoVue ref="basicInfoVueRef" />
+          <businessInformation ref="businessInformationRef" :form="form" />
+          <assetInformation ref="assetInformationRef" :form="form" />
+          <fixtureInformation ref="fixtureInformationRef" :form="form" />
+          <warehouseConfigVue ref="warehouseConfigRef" class="ims" />
+          <productInfoVue ref="productInfoRef" />
+          <planVue ref="planRef" />
+          <qualityConfig ref="qualityConfigRef" />
+          <footerVue ref="footerVueRef" />
+          <documentInformation ref="documentInformationRef" type="工装夹具" />
+          <div class="basic-details-title border-none">
+            <span class="border-span">物联参数</span>
+          </div>
+          <el-row>
+            <el-col>
+              <el-form-item label="是否启用物联">
+                <el-switch
+                  v-model="isIotEnable"
+                  active-text="开"
+                  inactive-text="关"
+                  :active-value="1"
+                  :inactive-value="0"
+                >
+                </el-switch>
+              </el-form-item>
+            </el-col>
+            <el-col>
+              <el-form-item label="物联ID">{{ iotId }}</el-form-item>
+            </el-col>
+          </el-row>
+          <el-row>
+            <el-col :span="6">
+              <el-form-item label="物联产品key">
+                <el-input class="input" v-model="form.iotProductKey"></el-input>
+              </el-form-item>
+            </el-col>
+            <el-col :span="6">
+              <el-form-item label="物联编号">
+                <el-input
+                  class="input"
+                  v-model="form.iotSubstanceCode"
+                ></el-input></el-form-item>
+            </el-col>
+          </el-row>
+          <div class="basic-details-title border-none">
+            <span class="border-span">扩展信息</span>
+          </div>
+          <div class="kzzd">
+            <el-row>
+              <el-col
+                :span="24"
+                v-for="(item, index) in form.extInfoSelf"
+                :key="index"
+                style="margin-bottom: 20px"
+              >
+                <el-form-item
+                  label-width="0"
+                  :prop="'extInfoSelf.' + index + '.key'"
+                  :rules="{
+                    required: true,
+                    message: '自定义参数名称不能为空',
+                    trigger: 'blur'
+                  }"
+                >
+                  <div class="add-col">
+                    <el-input
+                      class="col-input"
+                      v-model="item.key"
+                      placeholder="参数名称"
+                    ></el-input>
+                    <el-input
+                      class="col-input"
+                      v-model="item.value"
+                      placeholder="参数值"
+                    ></el-input>
+                    <el-button
+                      class="del"
+                      type="text"
+                      @click="delt(item, index)"
+                    >
+                      删除
+                    </el-button>
+                  </div>
+                </el-form-item>
+              </el-col>
+              <el-col :span="24" v-if="form.extInfoSelf.length < 10">
+                <el-form-item label-width="0">
+                  <el-button
+                    class="primarybutton"
+                    type="primary"
+                    @click="addItem"
+                    >增加自定义参数</el-button
+                  >
+                </el-form-item>
+              </el-col>
+            </el-row>
+          </div>
+        </div>
+      </el-form>
+      <DialogGoods
+        ref="DialogGoods"
+        @succeed="cbDialogGoods"
+        width="1200px"
+      ></DialogGoods>
+    </el-card>
+  </div>
+</template>
+
+<script>
+  import fixtureInformation from './components/fixtureInformation.vue';
+  import warehouseConfigVue from '@/views/ledgerAssets/components/warehouseConfig.vue';
+  import productInfoVue from '@/views/ledgerAssets/components/productInfo.vue';
+  import planVue from '@/views/ledgerAssets/components/plan.vue';
+  import qualityConfig from '@/views/ledgerAssets/components/qualityConfig.vue';
+  import footerVue from '@/views/ledgerAssets/components/footer.vue';
+  import documentInformation from '@/views/ledgerAssets/components/documentInformation.vue';
+  import basicInfoVue from '@/views/ledgerAssets/components/basicInfo.vue';
+  import DialogGoods from '@/views/ledgerAssets/components/DialogGoods';
+  import assetInformation from '@/views/ledgerAssets/components/assetInformation.vue';
+  import businessInformation from '@/views/ledgerAssets/components/businessInformation.vue';
+  import { getDetails } from '@/api/classifyManage/itemInformation';
+  import {
+    saveOrEdit,
+    getAssetInfo,
+    getCode,
+    getAssetNum
+  } from '@/api/ledgerAssets';
+  export default {
+    components: {
+      warehouseConfigVue,
+      productInfoVue,
+      planVue,
+      qualityConfig,
+      footerVue,
+      documentInformation,
+      DialogGoods,
+      assetInformation,
+      businessInformation,
+      basicInfoVue,
+      fixtureInformation
+    },
+    data() {
+      return {
+        labelStyle: {
+          width: '200px'
+        },
+        contentStyle: {
+          width: '400px'
+        },
+        isLink: true,
+        title: '新建工装夹具信息',
+        pageType: 'add',
+        btnLoading: false,
+        // 工装夹具主键id
+        id: '',
+        form: {
+          extInfoSelf: [],
+          // 基本信息
+          iotSubstanceCode: '',
+          iotProductKey: '',
+          code: '',
+          name: '',
+          productTime: '',
+          workstation: '',
+          fixCode: ''
+        },
+        rules: {
+          name: [
+            { required: true, message: '请输入工装夹具名称', trigger: 'blur' }
+          ],
+          code: [{ required: true, message: '请输入工装夹具编码', trigger: 'blur' }]
+        },
+        // 基本信息
+        basicInfo: {},
+        positionInfo: {
+          // 详细地址
+          deviceDetailAddress: '',
+          // 请选择产线
+          lineCode: '',
+          lineName: '',
+          // 请选择车间
+          workshopCode: '',
+          workshopName: '',
+          // 请选择工厂
+          factoryCode: '',
+          factoryName: ''
+        },
+        // 图片
+        imageUrl: null,
+        // 文档信息
+        attUrl: {
+          operatingManual: {
+            value: [],
+            sort: 1
+          },
+          productionLicence: {
+            value: [],
+            sort: 2
+          },
+          explosionProofCertificate: {
+            value: [],
+            sort: 3
+          },
+          surveyReport: {
+            value: [],
+            sort: 4
+          },
+          inspectionCycleManual: {
+            value: [],
+            sort: 5
+          },
+          informationDrawing: {
+            value: [],
+            sort: 6
+          },
+          productCertificate: {
+            value: [],
+            sort: 7
+          }
+        },
+        // 是否开始物联
+        isIotEnable: true,
+        // 物联ID
+        iotId: '',
+        // 回显过保时间
+        cbexpirationTime: '',
+        // 生命周期
+        sourceDICT: '',
+        // 网络状态
+        networkStatus: ''
+      };
+    },
+    props: {
+      showTitle: {
+        type: Boolean,
+        default: true
+      }
+    },
+    watch: {},
+    computed: {
+      // 过保时间
+      expirationTime() {
+        if (this.form.productTime && this.basicInfo.expirationDate) {
+          return this.setGbTime(
+            this.form.productTime,
+            this.basicInfo.expirationDate,
+            this.basicInfo.expirationDateUnit
+          );
+        } else {
+          return '';
+        }
+      }
+    },
+    async created() {
+      if (this.$route.query.id) {
+        this.pageType = 'edit';
+        this.id = this.$route.query.id;
+        await this.getInfo();
+        this.title = '编辑工装夹具信息';
+      } else {
+        this.pageType = 'add';
+        this.form.fixCode = await getCode('eam_fix_code');
+        this.title = '新增工装夹具信息';
+      }
+    },
+    methods: {
+      handlwpbm() {
+        this.$refs.DialogGoods.open("22");
+      },
+      async cbDialogGoods(data) {
+        let res = await getDetails(data.id);
+        if (!data.extInfoSelf) {
+          data.extInfoSelf = [];
+        }
+        if (!data.isPublic) {
+          data.isPublic = 0;
+        }
+        this.form = data;
+        this.form.category = res;
+        this.basicInfo = data;
+        this.form.rootCategoryLevelId =
+          this.basicInfo.categoryLevelPathIdParent;
+        this.form.categoryId = this.basicInfo.id;
+        this.form.name = this.basicInfo.name;
+        this.form.code = data.code;
+        this.form.iotProductKey = res.category.iotProductKey;
+        this.initOtherMsg();
+      },
+      // 计算过保时间
+      setGbTime(basic, value, type) {
+        basic = Date.parse(basic);
+        let time;
+        switch (type) {
+          case 'minute':
+            time = value * 1000 * 60;
+            break;
+          case 'hour':
+            time = value * 1000 * 60 * 60;
+            break;
+          case 'day':
+            time = value * 1000 * 60 * 60 * 24;
+            break;
+          case 'month':
+            time = value * 1000 * 60 * 60 * 24 * 30;
+            break;
+          case 'year':
+            time = value * 1000 * 60 * 60 * 24 * 365;
+            break;
+          default:
+            break;
+        }
+
+        let num = basic + time;
+        return parseTime(num);
+      },
+      // 添加自定义参数
+      addItem() {
+        if (this.form.extInfoSelf.length < 10) {
+          let item = { key: '', value: '' };
+          this.form.extInfoSelf.push(item);
+        } else {
+          this.$message.warning('自定义参数最多添加10条');
+        }
+      },
+      // 删除自定义参数
+      delt(item, index) {
+        this.form.extInfoSelf.splice(index, 1);
+      },
+      // 提交
+      submit() {
+        if (JSON.stringify(this.basicInfo) === '{}' && this.pageType == 'add') {
+          return this.$message.error('请选择物品');
+        }
+        this.$refs.form.validate(async (valid) => {
+          if (valid) {
+            if(!this.form.areaPersonInChargeGroupId){
+              this.$message.error('请选片区负责人部门');
+              return
+             }
+             if(!this.form.areaPersonInChargeUserId){
+              this.$message.error('请选片区负责人');
+              return
+             }
+            let par = {
+              ...this.form,
+              assetType: 1,
+              positionIds: '1,1,1,1',
+              position: {
+                detailPosition: this.positionInfo.deviceDetailAddress,
+                pathIds: `${
+                  this.positionInfo.factoryCode
+                    ? this.positionInfo.factoryCode + ','
+                    : ''
+                }${
+                  this.positionInfo.workshopCode
+                    ? this.positionInfo.workshopCode + ','
+                    : ''
+                }${this.positionInfo.lineCode}`,
+                pathName: `${
+                  this.positionInfo.factoryName
+                    ? this.positionInfo.factoryName + ','
+                    : ''
+                }${
+                  this.positionInfo.workshopName
+                    ? this.positionInfo.workshopName + ','
+                    : ''
+                }${this.positionInfo.lineName}`,
+                type: '1',
+                num: 1
+              },
+              attUrl: this.setWd() || [],
+              imageUrl: this.imageUrl || {},
+              isIotEnable: this.isIotEnable
+            };
+            par.deviceLocationName = par.location
+              ? par.location.toString()
+              : '';
+            // 工装夹具扩展字段:与后端约定 categoryFixture(待与后端确认)
+            par.extInfo = { ...(this.form.category.categoryFixture || {}) };
+            let obj = {};
+            (par.extInfoSelf || []).forEach((item) => {
+              obj[item.key] = item.value;
+            });
+            par.extInfoSelf = obj;
+            if (this.pageType == 'edit') {
+              par.id = this.id;
+            } else {
+              // const batchNo = await getCode('lot_number_code');
+              // const res = await getAssetNum({
+              //   assetCode: par.code,
+              //   batchNum: batchNo,
+              //   num: 1
+              // });
+              // par.code = res.data.shift().onlyCode;
+              par.id = '';
+            }
+            this.btnLoading = true;
+            saveOrEdit(par)
+              .then((res) => {
+                this.$message.success('操作成功');
+                this.$router.go(-1);
+              })
+              .finally(() => {
+                this.btnLoading = false;
+              });
+          } else {
+            return false;
+          }
+        });
+      },
+      // 处理文档信息
+      setWd() {
+        return Object.values(this.attUrl).map((item) => ({
+          ...(item.value[0] || {}),
+          sort: item.sort
+        }));
+      },
+      // 获取工装夹具详情
+      async getInfo() {
+        const data = await getAssetInfo(this.id);
+        data.extInfoSelf = data.extInfoSelf || [];
+        if (!data.isPublic) {
+          data.isPublic = 0;
+        }
+        this.form = data;
+        this.form.location = data.deviceLocationName.split(',');
+        this.basicInfo = data;
+        this.cbexpirationTime = data.expirationTime;
+        this.sourceDICT = data.sourceDICT;
+        this.networkStatus = data.networkStatus;
+        this.positionInfo.deviceDetailAddress = data.deviceDetailAddress;
+        this.initOtherMsg();
+        this.imageUrl = data.imageUrl;
+        this.isIotEnable = data.isIotEnable;
+        this.iotId = data.iotId;
+        this.form.iotProductKey =
+          this.form.iotProductKey || data.category.category.iotProductKey;
+      },
+      async initOtherMsg() {
+        this.$refs.basicInfoVueRef.getDetailInfoAugr(
+          this.form.category.category
+        );
+        this.$refs.warehouseConfigRef.getDetailInfoAugr(
+          this.form.category.categoryWms
+        );
+        this.$refs.productInfoRef.getDetailInfoAugr(
+          this.form.category.categoryMes
+        );
+        this.$refs.planRef.getDetailInfoAugr(this.form.category.categoryAps);
+        this.$refs.qualityConfigRef.getDetailInfoAugr(
+          this.form.category.categoryQms
+        );
+        // 工装夹具信息
+        this.$refs.fixtureInformationRef.getDetailInfoAugr(
+          this.form.category.categoryFixture
+        );
+        this.$refs.footerVueRef.getDetailInfoAugr(this.form.category.category);
+        if (this.form.attUrl && this.form.attUrl.length > 0) {
+          Object.keys(this.attUrl).forEach((n, index) => {
+            this.attUrl[n].value =
+              (this.form.attUrl[index]?.storePath && [
+                this.form.attUrl[index]
+              ]) ||
+              [];
+          });
+          this.$refs.documentInformationRef.getDetailInfoAugr(this.attUrl);
+        }
+      },
+      setbzcn(val) {
+        if (!val) {
+          return '';
+        }
+        let item = JSON.parse(val);
+        return item.standardCapacity || '';
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  ::v-deep .descriptions {
+    margin-bottom: 10px;
+  }
+  .baseinfo-container .basic-details-title {
+    font-size: 16px;
+    margin: 15px 0;
+  }
+  .upload-container {
+    display: flex;
+    justify-content: flex-start;
+    .file-list {
+      margin-left: 50px;
+      flex: 1;
+    }
+  }
+  .equipment-container {
+    .label-none {
+      .el-form-item__content {
+        margin-left: 0 !important;
+      }
+    }
+  }
+  .sbwz {
+    .item {
+      width: 120px !important;
+    }
+    .item + .item {
+      margin-left: 10px;
+    }
+    .item-input {
+      width: 350px !important;
+    }
+  }
+  .input {
+    width: 100%;
+  }
+  .kzzd {
+    width: 500px;
+    .add-col {
+      display: flex;
+      .col-input {
+        & + .col-input {
+          margin-left: 10px;
+        }
+      }
+      .del {
+        margin-left: 10px;
+      }
+    }
+  }
+  ::v-deep .el-descriptions {
+    .el-form-item {
+      margin-bottom: 0px;
+    }
+  }
+</style>

+ 130 - 0
src/views/ledgerAssets/fixture/index.vue

@@ -0,0 +1,130 @@
+<template>
+  <div
+    class="ele-body"
+    :style="
+      $route.query.isDrawer
+        ? {
+            position: 'fixed',
+            height: '100vh',
+            top: '0',
+            bottom: '0',
+            left: '0',
+            right: '0',
+            zIndex: 1000,
+            background: '#fff'
+          }
+        : {}
+    "
+  >
+    <el-card shadow="never" v-loading="loading">
+      <ele-split-layout
+        width="266px"
+        allow-collapse
+        :right-style="{ overflow: 'hidden' }"
+      >
+        <div>
+          <div class="ele-border-lighter sys-organization-list">
+            <AssetTree
+              @handleNodeClick="handleNodeClick"
+              @setRootId="setRootId"
+              id="22"
+              ref="treeList"
+            />
+          </div>
+        </div>
+        <template v-slot:content>
+          <fixture-list
+            v-if="current"
+            :category-id="current.id"
+            :root-id="rootId"
+            :current="current"
+            ref="listRef"
+          />
+        </template>
+      </ele-split-layout>
+    </el-card>
+  </div>
+</template>
+
+<script>
+  import AssetTree from '@/components/AssetTree';
+  import FixtureList from './components/fixture-list.vue';
+  export default {
+    name: 'fixtureIndex',
+    components: {
+      AssetTree,
+      FixtureList
+    },
+    data() {
+      return {
+        // 加载状态
+        loading: false,
+        // 表格选中数据
+        selection: [],
+        // 工装夹具固定根分类 ID(默认 22)
+        rootId: '22',
+        // 默认选中工装夹具分类节点
+        current: { id: '22', parentId: '22', name: '工装夹具' }
+      };
+    },
+    computed: {},
+    created() {
+      console.log(this.$route.query);
+    },
+    mounted() {
+      // 先用 22/22 触发首次数据加载,再加载资产分类树(避免 AssetTree 自动选中覆盖初始值)
+      this.$nextTick(() => {
+        if (this.$refs.listRef) {
+          this.$refs.listRef.sucesstion(true);
+        }
+        if (this.$refs.treeList && typeof this.$refs.treeList.getTreeData === 'function') {
+          this.$refs.treeList.getTreeData();
+        }
+      });
+    },
+
+    methods: {
+      handleNodeClick(info) {
+        console.log(info);
+        // 工装夹具台账:categoryLevelId 与 rootCategoryLevelId 始终固定为 22
+        // 左侧树的点击仅用于视觉/浏览,不影响接口参数(避免误以为切换了分类)
+        this.current = { id: '22', parentId: '22', name: '工装夹具' };
+        this.rootId = '22';
+        this.$nextTick(() => {
+          this.$refs.listRef.sucesstion(false);
+        });
+      },
+      // 获取根节点 id(固定为 22,忽略 AssetTree 传上来的根 id)
+      setRootId(id) {
+        this.rootId = '22';
+      }
+    },
+    activated() {
+      this.$nextTick(() => {
+        if (this.current.id) {
+          this.$refs.listRef.sucesstion(true);
+        }
+      });
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .sys-organization-list {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    box-sizing: border-box;
+    border-width: 1px;
+    border-style: solid;
+    overflow: auto;
+  }
+  .sys-organization-list :deep(.el-tree-node__content) {
+    height: 40px;
+    & > .el-tree-node__expand-icon {
+      margin-left: 10px;
+    }
+  }
+</style>