yangys
2025-09-04 2781142ab67deba83925da706ca26b7f8ea1a759
src/views/wel/shemi.vue
@@ -1,62 +1,135 @@
<template>
  <basic-container>
    <avue-crud
      :addBtn="false"
      :option="option"
      :table-loading="loading"
      :data="treeData"
      ref="crud"
      v-model:search="search"
      v-model:page="mypage"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
      @on-load="onLoad"
      @tree-load="treeLoad"
      @row-click="rowClick"
    >
      <template #search>
        <el-row :gutter="24">
          <el-col :span="6">
            <el-input v-model="search.name" placeholder="请输入节点名称" clearable/>
          </el-col>
          <el-col :span="6">
            <el-select v-model="search.nodeType" placeholder="请输入节点类型" clearable>
              <el-option v-for="item in nodeTypeList" :key="item.dictValue" :label="item.dictValue" :value="item.dictKey"/>formApprove.
            </el-select>
          </el-col>
          <el-col :span="6">
            <el-button type="primary" @click="searchTree"><el-icon class="el-icon--right" style="margin-right: 6px;"><Search /></el-icon>搜索</el-button>
            <el-button :icon="Delete" @click="setClearTree"><el-icon class="el-icon--right" style="margin-right: 6px;"><Delete /></el-icon>清空</el-button>
          </el-col>
        </el-row>
      </template>
      <!-- <template #menu-left>
    <div class="norightmenu" v-if="!isSearch">
      <avue-crud :addBtn="false" :option="option" :row-style="{height:'20px'}" :cell-style="{padding:'0px'}" :table-loading="loading" :data="treeData" ref="crud"
        v-model:search="search" v-model:page="mypage" @current-change="currentChange" @size-change="sizeChange"
        @refresh-change="refreshChange" @on-load="onLoad" @tree-load="treeLoad" @row-click="rowClick">
        <template #search>
          <el-row :gutter="24">
            <el-col :span="6" class="search-data-flex">
              <span class="search-data-title w68">程序状态:</span>
              <el-checkbox-group v-model="searchTreeData.programStatus" class="marginR12">
                <el-checkbox value="1" label="试切" />
                <el-checkbox value="2" label="固化" />
                <el-checkbox value="3" label="偏离" />
              </el-checkbox-group>
            </el-col>
            <el-col :span="6" class="search-data-flex">
              <span class="search-data-title">零组件号:</span>
              <el-select v-model="searchTreeData.drawingNo" filterable remote reserve-keyword placeholder="输入至少3个字符过滤数据"
                :remote-method="remoteMethod" :loading="searchLoading">
                <el-option v-for="item in drawingNoList" :key="item.value" :label="item.label"
                  :value="item.value" /></el-select>
            </el-col>
            <el-col :span="8" class="search-data-flex">
              <span class="search-data-title">时间范围:</span>
              <el-date-picker v-model="searchTreeData.createTime" type="daterange" start-placeholder="开始时间"
                end-placeholder="结束时间" :size="size" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
                @change="createTimeChange" /><!--:disabled-date="disabledDate" 不需要禁用日期-->
            </el-col>
            <el-col :span="4" class="search-data-flex">
              <el-button type="primary" @click="searchTree" :loading="treeSearchLoad"><el-icon class="el-icon--right"
                  style="margin-right: 6px;">
                  <Search />
                </el-icon>搜索</el-button>
              <el-button :icon="Delete" @click="setClearTree"><el-icon class="el-icon--right"
                  style="margin-right: 6px;">
                  <Delete />
                </el-icon>清空</el-button>
            </el-col>
          </el-row>
        </template>
        <!-- <template #menu-left>
        <el-button :size="size" type="primary" @click="showAdd()">新增根节点</el-button>
      </template> -->
      <template #name="{ row }">
        <span>{{row.name}}</span>
        <!-- <el-button :size="size" text v-if="row.nodeType != 70" icon="el-icon-setting" type="primary" placeholder="修改" @click="showEdit(row)" title="修改"></el-button>
        <template #name="{ row }">
          <span>{{ row.name }}</span>
          <!-- <el-button :size="size" text v-if="row.nodeType != 70" icon="el-icon-setting" type="primary" placeholder="修改" @click="showEdit(row)" title="修改"></el-button>
        <el-button :size="size" text v-if="row.nodeType != 10" icon="el-icon-delete" type="primary" @click="showDel(row)" placeholder="删除" title="删除"></el-button>
        <el-button :size="size" text v-if="row.nodeType != 60 && row.nodeType != 70" icon="el-icon-document-add" type="primary" @click="showAdd(row)" placeholder="新增子级" title="新增子级"></el-button>
        <el-button :size="size" text v-if="row.nodeType == 60 || row.nodeType == 50" icon="el-icon-upload" type="primary" @click="showUpload(row)" placeholder="文件上传" title="文件上传"></el-button> -->
        <!-- 涉密网才有 -->
        <!-- <el-button :size="size" text v-if="row.nodeType == 70" icon="el-icon-pie-chart" type="primary" @click="upgrade(row)" placeholder="升版" title="升版"></el-button> -->
        <!-- 工控网才有 -->
        <!-- <el-button :size="size" text v-if="row.nodeType == 70" icon="el-icon-position" type="primary" @click="downsend(row)" placeholder="下发" title="下发"></el-button> -->
        <!-- 替换 -->
        <el-button :size="size" text v-if="row.nodeType == 60 && row.parentIds.indexOf('0,1,')>-1" icon="el-icon-switch" type="primary" @click="replacement(row)" placeholder="替换" title="替换"></el-button>
        <el-button :size="size" text v-if="row.nodeType == 60 && row.parentIds.indexOf('0,2')>-1" icon="el-icon-lock" type="primary" @click="locked(row)" placeholder="锁定" title="锁定"></el-button>
        <!-- <el-button :size="size" text v-if="row.nodeType == 60 && row.parentIds.indexOf('0,2')>-1" icon="el-icon-unlock" type="primary" @click="locked(row)" placeholder="解锁" title="解锁"></el-button> -->
      </template>
    </avue-crud>
          <!-- 涉密网才有 -->
          <!-- <el-button :size="size" text v-if="row.nodeType == 70" icon="el-icon-pie-chart" type="primary" @click="upgrade(row)" placeholder="升版" title="升版"></el-button> -->
          <!-- 工控网才有 -->
          <!-- <el-button :size="size" text v-if="row.nodeType == 70" icon="el-icon-position" type="primary" @click="downsend(row)" placeholder="下发" title="下发"></el-button> -->
          <!-- 替换  v-if="permission.auto_dispatch"-->
          <el-button :size="size" text v-if="row.nodeType == 60 && row.parentIds.indexOf('0,1,') > -1"
            icon="el-icon-switch" type="primary" @click="replacement(row)" placeholder="替换" title="替换"></el-button>
          <el-button :size="size" text
            v-if="permission.lock_button && row.nodeType == 60 && row.parentIds.indexOf('0,2') > -1 && row.isLocked != 1"
            icon="el-icon-lock" type="primary" @click="showLockDlg(row)" placeholder="锁定" title="锁定"></el-button>
          <el-button :size="size" text
            v-if="permission.lock_button && row.nodeType == 60 && row.parentIds.indexOf('0,2') > -1 && row.isLocked == 1"
            icon="el-icon-unlock" type="primary" @click="startUnlock(row)" placeholder="解锁" title="解锁"></el-button>
        </template>
      </avue-crud>
    </div>
    <div class="norightmenu" v-else>
      <avue-crud :addBtn="false" :option="option" :row-style="{height:'20px'}" :cell-style="{padding:'0px'}" :table-loading="loading" :data="treeData" ref="crud"
        v-model:search="search" v-model:page="mypage" @current-change="currentChange" @size-change="sizeChange"
        @refresh-change="refreshChange" @on-load="onLoad" @tree-load="treeLoad" @row-click="rowClick">
        <template #search>
          <el-row :gutter="24">
            <el-col :span="6" class="search-data-flex">
              <span class="search-data-title w68">程序状态:</span>
              <el-checkbox-group v-model="searchTreeData.programStatus" class="marginR12">
                <el-checkbox value="1" label="试切" />
                <el-checkbox value="2" label="固化" />
                <el-checkbox value="3" label="偏离" />
              </el-checkbox-group>
            </el-col>
            <el-col :span="4" class="search-data-flex">
              <span class="search-data-title">零组件号:</span>
              <el-select v-model="searchTreeData.drawingNo" filterable remote reserve-keyword placeholder="输入至少3个字符过滤数据"
                :remote-method="remoteMethod" :loading="searchLoading">
                <el-option v-for="item in drawingNoList" :key="item.value" :label="item.label"
                  :value="item.value" /></el-select>
            </el-col>
            <el-col :span="8" class="search-data-flex">
              <span class="search-data-title">时间范围:</span>
              <el-date-picker v-model="searchTreeData.createTime" type="daterange" start-placeholder="开始时间"
                end-placeholder="结束时间" :size="size" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
                @change="createTimeChange" /><!--:disabled-date="disabledDate" 不需要禁用日期-->
            </el-col>
            <el-col :span="6" class="search-data-flex">
              <el-button type="primary" @click="searchTree" :loading="treeSearchLoad"><el-icon class="el-icon--right"
                  style="margin-right: 6px;">
                  <Search />
                </el-icon>搜索</el-button>
              <el-button :icon="Delete" @click="setClearTree"><el-icon class="el-icon--right"
                  style="margin-right: 6px;">
                  <Delete />
                </el-icon>清空</el-button>
            </el-col>
          </el-row>
        </template>
        <!-- <template #menu-left>
        <el-button :size="size" type="primary" @click="showAdd()">新增根节点</el-button>
      </template> -->
        <template #name="{ row }">
          <span>{{ row.name }}</span>
          <!-- 替换  v-if="permission.auto_dispatch"-->
          <el-button :size="size" text v-if="row.nodeType == 60 && row.parentIds.indexOf('0,1,') > -1"
            icon="el-icon-switch" type="primary" @click="replacement(row)" placeholder="替换" title="替换"></el-button>
          <el-button :size="size" text
            v-if="permission.lock_button && row.nodeType == 60 && row.parentIds.indexOf('0,2') > -1 && row.isLocked != 1"
            icon="el-icon-lock" type="primary" @click="showLockDlg(row)" placeholder="锁定" title="锁定"></el-button>
          <el-button :size="size" text
            v-if="permission.lock_button && row.nodeType == 60 && row.parentIds.indexOf('0,2') > -1 && row.isLocked == 1"
            icon="el-icon-unlock" type="primary" @click="startUnlock(row)" placeholder="解锁" title="解锁"></el-button>
        </template>
      </avue-crud>
    </div>
    <!-- 新增节点 -->
    <el-dialog :title="modalTitle" append-to-body v-model="modalBox">
      <avue-form :option="modalOption" v-model="modalForm" @submit="modalSubmit" @reset-change="modalCancel"/>
      <avue-form :option="modalOption" v-model="modalForm" @submit="modalSubmit" @reset-change="modalCancel" />
    </el-dialog>
    <el-dialog title="上传文件" append-to-body v-model="uploadmodalBox">
      <avue-form :option="uploadmodalOption" v-model="uploadmodalForm" @submit="uploadmodalSubmit" @reset-change="uploadmodalCancel" :upload-before="uploadBefore" :upload-after="uploadAfter">
        <template #fileList="{}" slot-scope="{ value }">
      <avue-form :option="uploadmodalOption" v-model="uploadmodalForm" @submit="uploadmodalSubmit"
        @reset-change="uploadmodalCancel" :upload-before="uploadBefore" :upload-after="uploadAfter">
        <template #fileList="{ }" slot-scope="{ value }">
          <div v-for="(file, index) in fileList" :key="index" v-if="fileList.length != 0">
            {{ file.name }}
          </div>
@@ -64,45 +137,57 @@
        </template>
      </avue-form>
    </el-dialog>
    <!-- 锁定对话框 -->
    <el-dialog title="程序锁定" append-to-body v-model="lockBox">
      <avue-form :option="lockOption" v-model="lockForm" @submit="lockSubmit" @reset-change="lockCancel" />
    </el-dialog>
    <avue-tabs :option="tabsOption" @change="tabsHandleChange" style="margin-top: 30px;" v-if="isShowTabs"></avue-tabs>
    <avue-form v-if="tabsType == 'tab1'" :option="tabsFormOption" v-model="tabsForm"></avue-form>
    <!--<span v-else-if="tabsType == 'tab2'">版本信息</span>-->
    <template v-else-if="tabsType == 'tab3'">
        <div v-html="convertToHtml(fileContent)" class="convertToHtml"></div>
      <div v-html="convertToHtml(fileContent)" class="convertToHtml"></div>
    </template>
    <template v-else-if="tabsType == 'tab4'">
        <avue-crud :addBtn="false" :option="tabsFormOption4" :data="tabsForm4" ref="crud4" @selection-change="selectionChange">
          <template #menu-left>
            <el-button :size="size" type="primary" @click="comparison" :disabled="selectionList.length != 2">对比</el-button>
          </template>
        </avue-crud>
      <avue-crud :addBtn="false" :option="tabsFormOption4" :data="tabsForm4" ref="crud4"
        @selection-change="selectionChange">
        <template #menu-left>
          <el-button :size="size" type="primary" @click="comparison"
            :disabled="selectionList.length != 2">对比</el-button>
        </template>
      </avue-crud>
    </template>
    <el-dialog title="升版" append-to-body v-model="upgradeModal" width="500">
      <avue-form :option="upgradeModalOption" v-model="upgradeModalForm" @submit="upgradeSubmit" @reset-change="upgradeCancel"></avue-form>
      <avue-form :option="upgradeModalOption" v-model="upgradeModalForm" @submit="upgradeSubmit"
        @reset-change="upgradeCancel"></avue-form>
    </el-dialog>
  </basic-container>
  <!-- 文件对比 -->
  <el-drawer title="文件对比" append-to-body v-model="diffBox" size="100%" class="code-box">
      <div>
          <code-diff :old-string="this.content1" :new-string="this.content2" output-format="side-by-side" :hideStat="true" :filename="codeDiffFileName1" :newFilename="codeDiffFileName2"/>
      </div>
    <div>
      <code-diff :old-string="this.content1" :new-string="this.content2" output-format="side-by-side" :hideStat="true"
        :filename="codeDiffFileName1" :newFilename="codeDiffFileName2" />
    </div>
  </el-drawer>
  <!-- 替换 -->
  <el-drawer title="替换" append-to-body v-model="todolistModel" size="100%" class="code-box">
    <div class="approve-box">
        <div class="left">
            <TodolistLeft :row="row" :replaceDataId="replaceDataId" :drawingNo="drawingNo" :processNo="processNo" :processEdition="processEdition" @selection-change="todoSelectionChange" />
        </div>
        <div class="right">
            <TodolistRightTop :row="row" :name="name" />
            <avue-form ref="form" :option="optionApprove" v-model="formApprove" @submit="handleSubmit" />
        </div>
      <div class="left">
        <TodolistLeft :row="row" :replaceDataId="replaceDataId" :drawingNo="drawingNo" :processNo="processNo"
          :processEdition="processEdition" @selection-change="todoSelectionChange" />
      </div>
      <div class="right">
        <TodolistRightTop :row="row" :name="name" />
        <avue-form ref="form" :option="optionApprove" v-model="formApprove" @submit="handleSubmit" />
      </div>
    </div>
  </el-drawer>
</template>
<script>
import debounce from 'lodash/debounce';
import { ElMessage } from 'element-plus';
import TodolistLeft from './components/TodolistLeft.vue';
import TodolistRightTop from './components/TodolistRightTop.vue';
@@ -114,9 +199,20 @@
  data() {
    let rejectText = '驳回';//+this.row.categoryName;
    return {
      isSearch: null,
      treeSearchLoad: false,
      drawingNoList: [],
      searchLoading: false,
      searchTreeData: {
        programStatus: [],
        drawingNo: "",
        createTime: [],
        createTimeBegin: "",
        createTimeEnd: ""
      },
      drawingNo: '',
      processNo: '',
     processEdition: '',
      processEdition: '',
      replaceDataId: "",
      formApprove: {
        title: '',
@@ -148,32 +244,32 @@
            rules: [{ required: true, message: '请选择', trigger: 'change' }],
          },
          {
              label: '工序版次',
              prop: 'processEdition',
              type: 'input',
              span: 24,
              // disabled: true,
              display: false,// 隐藏显示
              // rules: [{ required: true, message: '请选择下一审批用户', trigger: 'blur' }],
            label: '工序版次',
            prop: 'processEdition',
            type: 'input',
            span: 24,
            // disabled: true,
            display: false,// 隐藏显示
            // rules: [{ required: true, message: '请选择下一审批用户', trigger: 'blur' }],
          },
          {
              label: '备注',
              span: 24,
              prop: 'comment',
              type: 'textarea',
              // rules: [{ required: true, message: '请输入审批意见', trigger: 'blur' }],
              rules: [
                  {
                  validator: (rule, value, callback) => {
                      if (value === '' && this.formApprove.approve !== 'Y') {
                          callback(new Error('请输入备注'));
                      } else {
                          callback();
                      }
                  },
                  trigger: 'blur'
            label: '备注',
            span: 24,
            prop: 'comment',
            type: 'textarea',
            // rules: [{ required: true, message: '请输入审批意见', trigger: 'blur' }],
            rules: [
              {
                validator: (rule, value, callback) => {
                  if (value === '' && this.formApprove.approve !== 'Y') {
                    callback(new Error('请输入备注'));
                  } else {
                    callback();
                  }
              ]
                },
                trigger: 'blur'
              }
            ]
          },
        ],
      },
@@ -342,12 +438,34 @@
      },
      modalBox: false,
      modalTitle: "",
      id: "",
      parentId:1,
      search: {
        name: "",
        nodeType: ""
      lockOption: {
        submitText: "锁定",
        emptyText: "取消",
        menuPosition: "right",
        column: [
          {
            label: '程序包名',
            prop: 'name',
            disabled:true,
            labelWidth: "120",
          },
          {
            label: '锁定原因',
            prop: 'remark',
            type: "textarea",
            labelWidth: "120",
            span: 24,
            rules: [{ required: true, message: '必填', trigger: 'blur' }],
          }
        ]
      },
      lockForm: {},
      lockBox: false,
      id: "",
      parentId: 1,
      loading: true,
      mypage: {
        size: 10,
@@ -364,19 +482,22 @@
        emptyBtn: false,
        menu: false,
        column: [
          {label: '版本号',prop: 'versionNumber'},
          {label: '创建时间',prop: 'createTime'},
          {label: '创建人',prop: 'createUserName'},
          { label: '版本号', prop: 'versionNumber' },
          { label: '创建时间', prop: 'createTime' },
          { label: '创建人', prop: 'createUserName' },
        ]
      },
      tabsForm4: {},
      defaultExpandedKeys: [],
      option: {
        highlightCurrentRow: true,
        rowKey: "id",
        treeProps: {
          children: "children",
          hasChildren: 'hasChildren',
          value: 'id',
          label: 'name'
        },
        defaultExpandedKeys: [],
        defaultExpandAll: false,
        lazy: true,
        rowKey: 'id',
@@ -403,32 +524,17 @@
            label: '版本',
            prop: 'versionNumber',
            formatter: (val, value, label) => {
                if(val.nodeType == '60'){
                    if(value==-1){
                        return '';
                    }else{
                        return value;
                    }
                }else{
                    return '';
              if (val.nodeType == '60') {
                if (value == -1) {
                  return '';
                } else {
                  return value;
                }
            }
          },/*
          {
            label: '版次',
            prop: 'processEdition',
            formatter: (val, value, label) => {
                if(val.nodeType == '60'){
                    return value;
                }else{
                    return '';
                }
              } else {
                return '';
              }
            }
          },
          {
            label: '描述',
            prop: 'abc'
          },*/
          {
            label: '类型',
            prop: 'nodeTypeName'
@@ -442,46 +548,42 @@
            label: '锁定状态',
            prop: 'isLocked',
            formatter: (val, value, label) => {
                if(val.nodeType == '60' || val.nodeType == '70'){
                    if(value==1){
                        return '已锁定';
                    }else{
                        return '未锁定';
                    }
              if (val.nodeType == '60') {
                if (value == 1) {
                  return '已锁定';
                } else {
                  return '未锁定';
                }
              }
            }
          },
          {
            label: '流程状态',
            prop: 'flowStatus',
                  formatter: (val, value, label) => {
                    if(val.nodeType != '60'){
                        //非程序节点
                        return '';
                    }else{
                        if(value==0||value==-1){
                            return '未启动';
                        }else if(value == 1){
                            return '审批中';
                        }else if(value == 2){
                            return '已通过';
                        }else{
                            return '';
                        }
                      }
                  },
          },/*
          {
            label: '测试程序',
            prop: 'abc'
          },*/
            formatter: (val, value, label) => {
              if (val.nodeType != '60') {
                //非程序节点
                return '';
              } else {
                if (value == 0 || value == -1) {
                  return '未启动';
                } else if (value == 1) {
                  return '审批中';
                } else if (value == 2) {
                  return '已通过';
                } else {
                  return '';
                }
              }
            },
          },
          {
            label: '创建人',
            prop: 'createUserName',
            width: '180'
          },
        {
          {
            label: '创建时间',
            prop: 'createTime',
            width: '180'
@@ -493,6 +595,7 @@
    };
  },
  computed: {
    ...mapGetters(['userInfo', 'permission']),
    uploadmodalOption() {
      return {
        submitText: "保存",
@@ -591,7 +694,7 @@
            prop: 'uploadFile',
            labelWidth: "120",
            type: 'upload',
            data: {nodeId: this.id},
            data: { nodeId: this.id },
            action: "",
            showFileList: false,
            span: 24,
@@ -627,11 +730,69 @@
    }
  },
  watch: {
  },
  methods: {
    locked(row) {
      this.$confirm('是否锁定吗?', {
    disabledDate(time) {
      //不需要禁用日期
      // 获取当前日期
      const today = new Date();
      today.setHours(0, 0, 0, 0); // 设置为当天开始时间
      // 获取三个月前的日期
      const threeMonthsAgo = new Date();
      threeMonthsAgo.setMonth(threeMonthsAgo.getMonth() - 3);
      threeMonthsAgo.setHours(0, 0, 0, 0);
      // 禁用今天之后的日期 即可
      return time.getTime() > today.getTime() || time.getTime() < threeMonthsAgo.getTime();//
    },
    createTimeChange(value) {
      console.log('createTimeChange', value)
      this.searchTreeData.createTimeBegin = value[0];
      this.searchTreeData.createTimeEnd = value[1];
    },
    remoteMethod(query) {
      if (query && query.length>2) {
        this.searchLoading = true;
        this.getRemote(query);
      } else {
        this.drawingNoList = [];
      }
    },
    getRemote: debounce(function(query){
            //防抖,这里设置600毫秒请求一次后台
            this.getList(query)
    },600),
    async getList(query){
      this.searchLoading = false;
      axios({
          url: '/blade-mdm/program/node/drawing-no-pick',
          method: 'get',
          params: { drawingNo: query }
        }).then(resp => {
          this.searchLoading = false;
          var drawingNoList = [];
          resp.data.data.forEach(item => {
            drawingNoList.push({ label: item, value: item })
          })
          this.drawingNoList = drawingNoList;
        });
    },
    showLockDlg(row){
      this.lockForm = row;
     //this.lockForm.name = row.name;
     // this.lockForm.id = row.id;
      this.lockForm.remark = '';
      this.lockBox = true;
    },
    lockCancel() {
      this.lockBox = false;
      this.lockForm = {};
    },
    lockSubmit() {
      //锁定提交
      this.$confirm('是否锁定', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
@@ -639,14 +800,41 @@
        axios({
          url: '/blade-mdm/program/node/lock',
          method: 'post',
          params: {id: row.id}
          params: this.lockForm
        }).then(res => {
          if(res.data.code == 200) {
            this.$message({type: 'success',message: '操作成功!'});
          }else {
            this.$message({type: 'success',message: res.data.msg});
          if (res.data.code == 200) {
            this.$message({ type: 'success', message: '操作成功!' });
            this.addLocalTreeNode(this.lockForm.parentId);
            this.lockBox = false;
          } else {
            this.$message({ type: 'success', message: res.data.msg });
          }
        });
      }).catch(action => {
        console.log('cancel')
      });
    },
    startUnlock(row) {
      //启动解锁流程
      this.$confirm(`是否解锁`, {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        axios({
          url: '/blade-mdm/flow/lock/start-unlock',
          method: 'post',
          params: {nodeId: row.id }
        }).then(res => {
          if (res.data.code == 200) {
            this.$message({ type: 'success', message: '解锁流程已启动!' });
            this.addLocalTreeNode(row.parentId);
          } else {
            this.$message({ type: 'success', message: res.data.msg });
          }
        });
      }).catch(action => {
        console.log('cancel')
      });
    },
    handleSubmit(form, done) {
@@ -655,21 +843,23 @@
        title: this.formApprove.title,
        nodeId: this.id,
        tempInstanceId: this.replaceDataId,
          comment: this.formApprove.comment,
        comment: this.formApprove.comment,
        assignee: this.formApprove.assignee
      }
      axios({
        url: '/blade-mdm/flow/replace/start',
        method: 'post',
        data: obj
      }).then(
      resp => {
      }).then(resp => {
        this.$message({
          type: 'success',
          message: '操作成功!',
        });
        done();
        this.todolistModel = false;
      }).catch(error => {
        window.console.log('haha', error);
        done();
      });
      // if(this.row.taskDefinitionKey === 'programmingTask') {
      //     // if(this.applist.length !== 1) {
@@ -700,24 +890,35 @@
    todoSelectionChange(applist) {
      this.applist = applist;
    },
    showReplaceDlg(row) {  //替换对话框
      if (row.nodeType == 60) { //程序包
        return;
      }
      //111
      this.modalTitle = "新增子节点";
      this.selectedColumn.parentId = row.id;
      this.modalForm = this.selectedColumn;
      this.modalBox = true;
    },
    replacement(row) {  //替换
      this.id = row.id;
      this.formApprove = {
          comment: '',
          approve: 'Y', // 默认同
        comment: '',
        approve: 'Y', // 默认同
      }
      //准备程序替换流程 
      axios({
        url: '/blade-mdm/flow/replace/pre',
        method: 'post',
        params: {nodeId: row.id}
      }).then(
      resp => {
        params: { nodeId: row.id }
      }).then(resp => {
        this.row = row;
        this.replaceDataId = resp.data.data.processInstanceId;
        this.processNo = resp.data.data.processNo;
        this.processEdition = resp.data.data.processEdition;
          this.drawingNo = resp.data.data.drawingNo;
        this.drawingNo = resp.data.data.drawingNo;
        this.formApprove.title = resp.data.data.name + "替换";
        this.getHandler(); //获取处理人
        this.todolistModel = true;
@@ -727,30 +928,20 @@
      axios({
        url: '/blade-mdm/flow/replace/default-assignees',
        method: 'get',
        params: {drawingNo: this.drawingNo}
        params: { drawingNo: this.drawingNo }
      }).then(
      resp => {
        if(resp.data.code == 200) {
          this.formApprove.assignee = resp.data.data.checkerId;
        }else {
          this.$message.success(resp.msg);
        }
      });
        resp => {
          if (resp.data.code == 200) {
            this.formApprove.assignee = resp.data.data.checkerId;
          } else {
            this.$message.success(resp.msg);
          }
        });
    },
    convertToHtml(text) {
        return text.replace(/\n/g, '<br>');
      return text.replace(/\n/g, '<br>');
    },
    removeHasChildren(treeData) {  //查询时候使用,删掉hasChildren
      return treeData.map(node => {
        if (node.children && node.children.length > 0) {
          node.children = this.removeHasChildren(node.children);
        }
        // 删除当前节点的 hasChildren 属性
        const { hasChildren, ...rest } = node;
        return rest;
      });
    },
     // 递归查找目标行(name="机床1")
    // 递归查找目标行(name="机床1")
    findTargetRow(data, targetName) {
      for (const item of data) {
        if (item.name === targetName) {
@@ -764,52 +955,101 @@
      return null; // 未找到
    },
    highlightTargetRow() {  // 高亮目标行
      const targetName = this.search.name;
      const targetName = this.searchTreeData.drawingNo;
      this.targetRow = this.findTargetRow(this.treeData, targetName);
      if (this.targetRow && this.$refs.crud) {
        this.$refs.crud.setCurrentRow(this.targetRow); // 高亮目标行
      }
    },
    searchTree() {
      axios({
        url: '/blade-mdm/program/node/search-list',
        method: 'get',
        params: this.search,
      }).then(res => {
        this.option.defaultExpandAll = true;
        this.treeData = this.removeHasChildren(res.data.data);
        this.$nextTick(() => {
          this.highlightTargetRow();  // 设置当前行高亮
          this.tabsForm = this.targetRow;  //tabs节点信息
          this.nodeTypeList.forEach(item=> {
            if(item.dictKey == this.tabsForm.nodeType) {
              this.tabsForm.nodeTypeName = item.dictValue;
            }
          })
        })
        if(this.treeData.length == 0) {
          return;
    removeHasChildren(treeData) {  //查询时候使用,删掉hasChildren
      return treeData.map(node => {
        if (node.children && node.children.length > 0) {
          this.defaultExpandedKeys.push(node.id);
          console.log('>>>>>>>>', this.defaultExpandedKeys)
          node.children = this.removeHasChildren(node.children);
        }
        if (node.children.length > 0) {
          const { hasChildren, ...rest } = node;
          return Object.assign(rest, {});
        } else {
          return node;
        }
        // 删除当前节点的 hasChildren 属性
      });
    },
    searchTree() {
      if (this.searchTreeData.programStatus.length == 0 || this.searchTreeData.drawingNo == ""){
        this.$message.warning('请输入程序状态和零组件号进行搜索');
        return;
      }
      this.treeSearchLoad = true;
      this.isSearch = !this.isSearch
      this.searchTreeData.status = this.searchTreeData.programStatus.join();
      this.treeData = []
      this.defaultExpandedKeys = []
      axios({
        url: '/blade-mdm/program/node/search-list2',
        method: 'get',
        params: this.searchTreeData
      }).then(res => {
        if (res.data.data.length == 0) {
          this.treeData = [];
          this.treeSearchLoad = false;
          return
        };
        // this.option.defaultExpandAll = true;
        let treeData = this.removeHasChildren(res.data.data);
        console.log('treeData', treeData)
        this.option = Object.assign({},this.option,{defaultExpandedKeys: this.defaultExpandedKeys,lazy: true,defaultExpandAll: true});
        setTimeout(() => {
          this.treeSearchLoad = false;
          this.treeData = treeData;
          this.$nextTick(() => {
            this.highlightTargetRow();  // 设置当前行高亮
            this.tabsForm = this.targetRow;  //tabs节点信息
            if (this.tabsForm == null) return;
            this.nodeTypeList.forEach(item => {
              if (item.dictKey == this.tabsForm.nodeType) {
                this.tabsForm.nodeTypeName = item.dictValue;
              }
            })
          })
          if (this.treeData.length == 0) {
            return;
          }
        }, 100);
      });
    },
    setClearTree() {
      this.option.defaultExpandAll = false;
      this.searchTreeData = {
        programStatus: [],
        status: '',
        drawingNo: "",
        createTime: [],
        createTimeBegin: "",
        createTimeEnd: ""
      };
      this.treeData = [];
      this.$nextTick(()=> {
      this.$nextTick(() => {
        this.onLoad();
      })
    },
    upgradeSubmit(row,done) {  //升版
    upgradeSubmit(row, done) {  //升版
      axios({
        url: '/blade-mdm/program/ncfile/upgrade-process-edition',
        method: 'post',
        params: {bindNcNodeId:row.id,newProcessEdition: row.processEdition},
        params: { bindNcNodeId: row.id, newProcessEdition: row.processEdition },
      }).then(
        res => {
            done();
            this.upgradeModal = false;
            this.$message.success('操作成功');
            this.addLocalTreeNode(row.parentId);
          done();
          this.upgradeModal = false;
          this.$message.success('操作成功');
          this.addLocalTreeNode(row.parentId);
        }
      );
    },
@@ -821,21 +1061,21 @@
      axios({
        url: '/blade-mdm/program/ncfile/send-to-machine-by-nodeid',
        method: 'post',
        params: {nodeId:row.id},
        params: { nodeId: row.id },
      }).then(
        res => {
            this.loading = false;
            this.$message.success('操作成功');
          this.loading = false;
          this.$message.success('操作成功');
        }
      );
    },
    upgrade(row) {  //升版
      this.upgradeModalForm = {...row};
      this.upgradeModalForm = { ...row };
      this.upgradeModal = true;
    },
    delFile(item) {
      this.loading = true;
      var obj = {id: item.id}
      var obj = { id: item.id }
      axios({
        url: '/blade-mdm/program/ncfile/remove',
        method: 'post',
@@ -847,7 +1087,7 @@
        }
      );
    },
    uploadBefore(file,done,loading,column) {
    uploadBefore(file, done, loading, column) {
      this.file = file;
      this.fileList.push(file);
      //done();  放开就上传了
@@ -855,16 +1095,16 @@
    },
    uploadAfter() {
    },
    uploadmodalSubmit(row,done) {  //上传提交接口
      if(this.file == null) {
    uploadmodalSubmit(row, done) {  //上传提交接口
      if (this.file == null) {
        this.$message.error('请上传文件');
        return;
      }
      var formData = new FormData();
      formData.append('file', this.file);
      formData.append('nodeId', this.id);
      if(this.isRepeatUpload) {
        formData.append('cofirm','1');
      if (this.isRepeatUpload) {
        formData.append('cofirm', '1');
      }
      Object.keys(this.uploadmodalForm).forEach(key => {
        formData.append(key, this.uploadmodalForm[key]);
@@ -875,48 +1115,48 @@
        method: 'post',
        data: formData,
      }).then(res => {
          this.loading = false;
          if(res.data.code == 2) {
            this.$confirm('文件名已存在,确定上传吗?', '提示', {
              distinguishCancelAndClose: true,
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              this.isRepeatUpload = true;
              this.uploadmodalSubmit(row,done);
            }).catch(action => {
              this.isRepeatUpload = false;
              this.$message({
                type: 'info',
                message:'取消上传'
              })
            });
          }else if(res.data.success) {
        this.loading = false;
        if (res.data.code == 2) {
          this.$confirm('文件名已存在,确定上传吗?', '提示', {
            distinguishCancelAndClose: true,
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
          }).then(() => {
            this.isRepeatUpload = true;
            this.uploadmodalSubmit(row, done);
          }).catch(action => {
            this.isRepeatUpload = false;
            this.uploadmodalBox = false;
            this.$message({type: 'success',message: '操作成功!'});
            this.addLocalTreeNode(row.id);  //重新加载下一级
          }else {
            this.isRepeatUpload = false;
            alert(1)
          }
          done();
            this.$message({
              type: 'info',
              message: '取消上传'
            })
          });
        } else if (res.data.success) {
          this.isRepeatUpload = false;
          this.uploadmodalBox = false;
          this.$message({ type: 'success', message: '操作成功!' });
          this.addLocalTreeNode(row.id);  //重新加载下一级
        } else {
          this.isRepeatUpload = false;
          alert(1)
        }
        done();
      }
      );
    },
    rowClick(row) {
      this.tabsForm = row;
      this.id = row.id;
      this.isShowTabs = false;
      this.nodeTypeList.forEach(item=> {
        if(item.dictKey == row.nodeType) {
      this.nodeTypeList.forEach(item => {
        if (item.dictKey == row.nodeType) {
          this.tabsForm.nodeTypeName = item.dictValue;
        }
      })
      if(this.tabsForm.nodeType != 70) {
      if (this.tabsForm.nodeType != 70) {
        this.tabsOption = this.tabsOption1;
      }else {
      } else {
        this.tabsOption = this.tabsOption2;
        //获取文件list
        this.getFile(row.id);
@@ -926,7 +1166,7 @@
        this.content1 = "";
        this.content2 = "";
      }
      this.$nextTick(()=> {
      this.$nextTick(() => {
        this.tabsType = 'tab1';
        this.isShowTabs = true;
      })
@@ -938,7 +1178,7 @@
      this.fileList = [];
      this.uploadmodalForm = row;
      this.loading = true;
      var obj = {parentId: row.id}
      var obj = { parentId: row.id }
      axios({
        url: '/blade-mdm/program/node/lazy-list',
        method: 'get',
@@ -955,7 +1195,7 @@
      axios({
        url: '/blade-mdm/program/ncfile/content-by-nodeid',
        method: 'get',
        params: {nodeId:id},
        params: { nodeId: id },
      }).then(
        res => {
          this.loading = false;
@@ -968,7 +1208,7 @@
      axios({
        url: '/blade-mdm/program/node/history-by-nodeid',
        method: 'get',
        params: {id},
        params: { id },
      }).then(
        res => {
          this.loading = false;
@@ -981,7 +1221,7 @@
      axios({
        url: '/blade-mdm/program/node/compare-content',
        method: 'get',
        params: {id1:this.selectionList[0].id,id2:this.selectionList[1].id},
        params: { id1: this.selectionList[0].id, id2: this.selectionList[1].id },
      }).then(
        res => {
          this.loading = false;
@@ -996,7 +1236,7 @@
    selectionChange(list) {
      this.selectionList = list;
    },
    showEdit(row,done) {
    showEdit(row, done) {
      this.modalTitle = "修改";
      this.modalBox = true;
      this.modalForm = row;
@@ -1012,7 +1252,7 @@
        axios({
          url: '/blade-mdm/program/node/remove',
          method: 'post',
          params: {id: row.id},
          params: { id: row.id },
        }).then(
          res => {
            this.loading = false;
@@ -1021,19 +1261,19 @@
        );
      })
    },
    showAdd (row) {  //新增子节点
      if(!row) {
    showAdd(row) {  //新增子节点
      if (!row) {
        this.modalTitle = "新增根节点";
        this.modalForm.nodeType = this.nodeTypeList[0].dictKey;
        this.modalForm.parentId = 0;
      }else {
        if(row.nodeType == 60) { //程序包
      } else {
        if (row.nodeType == 60) { //程序包
          return;
        }
        var defalutNodeType = "";  //下一级节点类型
        for(var i=0;i<this.nodeTypeList.length;i++) {
          if(row.nodeType == this.nodeTypeList[i].dictKey) {
            defalutNodeType = this.nodeTypeList[i+1].dictKey;
        for (var i = 0; i < this.nodeTypeList.length; i++) {
          if (row.nodeType == this.nodeTypeList[i].dictKey) {
            defalutNodeType = this.nodeTypeList[i + 1].dictKey;
          }
        }
        this.modalTitle = "新增子节点";
@@ -1045,10 +1285,10 @@
      }
      this.modalBox = true;
    },
    modalSubmit(row,done) {  //新增子节点保存/修改
      if(this.modalTitle == "修改") {
    modalSubmit(row, done) {  //新增子节点保存/修改
      if (this.modalTitle == "修改") {
        var url = "/blade-mdm/program/node/update";
      }else {
      } else {
        var url = "/blade-mdm/program/node/save";
      }
      //调用接口
@@ -1064,7 +1304,7 @@
          // 修改,更新本地数据
          if (this.modalTitle === "修改") {
            this.addLocalTreeNode(row.parentId);
          }else {
          } else {
            // 如果是新增操作,可能需要重新加载数据
            //this.$refs.crud.refreshTable();
            //this.onLoad();
@@ -1077,12 +1317,12 @@
      );
    },
    addLocalTreeNode(parentId) {
      if(this.modalTitle == "新增根节点") {
      if (this.modalTitle == "新增根节点") {
        this.onLoad();
        return;
      }
      this.loading = true;
      var obj = {parentId: parentId}
      var obj = { parentId: parentId }
      axios({
        url: '/blade-mdm/program/node/lazy-list',
        method: 'get',
@@ -1090,9 +1330,9 @@
      }).then(
        res => {
          var children = res.data.data || [];
          if(parentId == 0) {
          if (parentId == 0) {
            this.treeData = [...children];
          }else {
          } else {
            this.$refs.crud.$refs.table.store.states.lazyTreeNodeMap.value[parentId] = [...children];
          }
          this.loading = false;
@@ -1105,9 +1345,11 @@
    uploadmodalCancel() {
      this.uploadmodalBox = false;
    },
    treeLoad (tree, treeNode, resolve) {
    treeLoad(tree, treeNode, resolve) {
      console.log('tree', tree, treeNode, this.option)
      this.loading = true;
      var obj = {parentId: tree.id}
      var obj = { parentId: tree.id }
      axios({
        url: '/blade-mdm/program/node/lazy-list',
        method: 'get',
@@ -1126,11 +1368,15 @@
      this.mypage.size = size;
    },
    refreshChange() {
    },
    onLoad() {  //查询treeTable
      if(this.isSearch !== null){
        return
      }
      this.loading = true;
      var obj = {parentId: ""}
      var obj = { parentId: "" }
      axios({
        url: '/blade-mdm/program/node/lazy-list',
        method: 'get',
@@ -1139,12 +1385,12 @@
        res => {
          this.loading = false;
          this.treeData = res.data.data;
          if(this.treeData.length == 0) {
          if (this.treeData.length == 0) {
            return;
          }
          this.tabsForm = res.data.data[0];  //节点信息
          this.nodeTypeList.forEach(item=> {
            if(item.dictKey == this.treeData[0].nodeType) {
          this.nodeTypeList.forEach(item => {
            if (item.dictKey == this.treeData[0].nodeType) {
              this.tabsForm.nodeTypeName = item.dictValue;
            }
          })
@@ -1153,64 +1399,116 @@
    },
    getPre() {
      alert(1)
    }
    },
    subtractMonths(date, months) {
      const newDate = new Date(date);
      const currentMonth = newDate.getMonth();
      newDate.setMonth(currentMonth - months);
      return newDate;
    },
    getBeginDate() {
      var beginDate = this.subtractMonths(new Date(), 3);
      return `${beginDate.getFullYear()}-${(beginDate.getMonth() + 1).toString().padStart(2, '0')}-${beginDate.getDate().toString().padStart(2, '0')}`;
    },
    getToday() {
      let today = new Date();
      return `${today.getFullYear()}-${(today.getMonth() + 1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`;
    },
  },
  mounted() {
    let b = this.getBeginDate()
    //this.defaultTimeRange = [b,this.getToday()];
    let defTimeRange = [b, this.getToday()];
    this.searchTreeData.createTime = defTimeRange
    this.createTimeChange(defTimeRange)
    this.tabsOption = this.tabsOption1;
    //获取nodetype
    axios({url: '/blade-system/dict-biz/dictionary?code=nc_node_type',method: 'get'}).then(res => {
        this.nodeTypeList = res.data.data;
      }
    axios({ url: '/blade-system/dict-biz/dictionary?code=nc_node_type', method: 'get' }).then(res => {
      this.nodeTypeList = res.data.data;
    }
    );
  }
};
</script>
<style lang="scss">
.norightmenu .avue-crud .avue-crud__header {
  display: none !important;
}
.delFile {
  color: red;
  margin-left: 12px;
  cursor: pointer;
}
.fileListStyle {
  margin-left: 10px;
  margin-top: 12px;
}
.highlight-row {
  background-color: #f0f7ff !important; /* 浅蓝色背景 */
  font-weight: bold; /* 加粗文字 */
  background-color: #f0f7ff !important;
  /* 浅蓝色背景 */
  font-weight: bold;
  /* 加粗文字 */
}
/* 如果需要悬停效果 */
.highlight-row:hover {
  background-color: #e6f0ff !important;
}
.approve-box {
  display: flex;
  &>div {
      border: 1px solid #ccc;
    border: 1px solid #ccc;
  }
  .left {
      width: 400px;
    width: 400px;
  }
  .right {
      flex: 1;
    flex: 1;
  }
}
.convertToHtml {
  background-color: #fffee1;
  padding: 6px 12px;
}
</style>
<style>
  .highlight-row {
    background-color: #f0f7ff;
    font-weight: bold;
  }
  .code-box .el-drawer__header {
    margin-bottom: 0;
  }
.highlight-row {
  background-color: #f0f7ff;
  font-weight: bold;
}
.code-box .el-drawer__header {
  margin-bottom: 0;
}
.search-data-title {
  font-size: 14px;
  margin-right: 8px;
  display: inline-block;
  width: 95px;
}
.search-data-flex {
  display: flex !important;
  align-items: center;
}
.w68 {
  width: 68px;
}
.marginR12 label {
  margin-right: 12px;
}
</style>