Selaa lähdekoodia

1.1.0开发中

刘洋 1 vuosi sitten
vanhempi
commit
7f2a73395a

+ 66 - 0
src/components/common/device-manage-new/index.vue

@@ -0,0 +1,66 @@
+<template>
+  <my-drawer
+    class="sop-dialog"
+    :visible="visible"
+    header="设备管理"
+    size="85%"
+    attach="body"
+    :destroyOnClose="true"
+    :closeOnOverlayClick="false"
+    :close-btn="true"
+    @close="emit('update:visible', false)"
+  >
+    <t-collapse class="sop-step-mid" defaultExpandAll>
+      <t-collapse-panel disabled>
+        <template #expandIcon></template>
+        <template #header>
+          项目派单信息(SOP流水单号:{{ sop.sopNo }})
+        </template>
+        <t-form colon label-width="72px">
+          <t-row :gutter="[0, 4]">
+            <t-col :span="4">
+              <t-form-item label="项目单号">{{ sop.crmNo }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="项目名称">{{ sop.crmName }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="科目名称">{{}}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="客户类型">{{
+                sop.customManagerTypeStr
+              }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="客户名称">{{ sop.customName }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="实施产品">{{ sop.productName }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="服务单元">{{ sop.serviceName }}</t-form-item>
+            </t-col>
+          </t-row>
+        </t-form>
+      </t-collapse-panel>
+    </t-collapse>
+
+    <div class="mt-10px"> </div>
+  </my-drawer>
+</template>
+
+<script lang="ts" name="DeviceManageNew" setup>
+import { computed, ref } from 'vue';
+const props = defineProps({
+  visible: Boolean,
+  type: String,
+  sop: {
+    type: Object,
+    default() {
+      return {};
+    },
+  },
+});
+const emit = defineEmits(['update:visible', 'confirm']);
+</script>

+ 10 - 10
src/components/global/my-dialog/index.vue

@@ -1,8 +1,8 @@
 <template>
-  <t-dialog v-bind="attrs">
-    <template #body v-if="isFirstOpen">
-      <slot></slot>
-    </template>
+  <t-dialog v-bind="attrs" destroyOnClose>
+    <!-- <template #body v-if="isFirstOpen"> -->
+    <slot></slot>
+    <!-- </template> -->
     <template #footer v-if="slots.foot">
       <slot name="foot"></slot>
     </template>
@@ -12,16 +12,16 @@
 import { useAttrs, useSlots, ref, watch } from 'vue';
 const attrs = useAttrs();
 const slots = useSlots();
-let isFirstOpen = ref(false);
+// let isFirstOpen = ref(false);
 watch(
   () => attrs.visible,
   () => {
-    if (!isFirstOpen.value) {
-      isFirstOpen.value = true;
-      if (attrs.callBacks) {
-        attrs.callBacks.forEach((item) => item());
-      }
+    // if (!isFirstOpen.value) {
+    //   isFirstOpen.value = true;
+    if (attrs.callBacks) {
+      attrs.callBacks.forEach((item) => item());
     }
+    // }
   }
 );
 </script>

+ 3 - 0
src/components/global/search-form/components/search-form-item.vue

@@ -80,6 +80,9 @@
       v-model="params[item.prop]"
       :mode="item.mode || 'date'"
       value-type="time-stamp"
+      enable-time-picker
+      format="YYYY/MM/DD HH:mm"
+      :time-picker-props="{ format: 'HH:mm' }"
       v-bind="attrs"
     />
   </template>

+ 10 - 2
src/components/global/search-form/index.vue

@@ -5,13 +5,14 @@
   <div
     v-if="fields?.length"
     class="table-search"
-    :class="{ 'in-padding': inPadding }"
+    :class="{ 'in-padding': inPadding, 'no-border': noBorder }"
   >
-    <t-form ref="formRef" :model="params" :inline="true">
+    <t-form ref="formRef" :data="params" :inline="true" :rules="rules">
       <div class="first-row flex">
         <t-form-item
           v-for="item in firstLineItemsFilter"
           :key="item.prop"
+          :name="item.prop"
           :label="item.label || ''"
           :labelWidth="item.labelWidth || 0"
           :style="{ width: colToWidth(item.colSpan || 0) }"
@@ -28,6 +29,7 @@
         <t-form-item
           v-for="item in firstLineItemsIsRight"
           :key="item.prop"
+          :name="item.prop"
           :label="item.label || ''"
           :labelWidth="item.labelWidth || 0"
           :style="{ width: colToWidth(item.colSpan || 0) }"
@@ -58,6 +60,7 @@
         <t-form-item
           v-for="item in otherLineItems"
           :key="item.prop"
+          :name="item.prop"
           :label="item.label || ''"
           :labelWidth="item.labelWidth || 0"
           :style="{ width: colToWidth(item.colSpan || 0) }"
@@ -117,6 +120,8 @@ const props = defineProps({
   showAll: { type: Boolean, default: true }, //是否要求直接展开,无需折叠换行按钮
   inPadding: Boolean,
   search: { type: Function, default: () => {} },
+  noBorder: { type: Boolean, default: false },
+  rules: { type: Object, default: () => {} },
 });
 //fields示例:(目前支持控件:input、select、dropdown按钮、treeSelect、date选择框、time选择框、timerange时间范围选择框、daterange日期范围选择框...后期可以按需求扩展)
 /*
@@ -254,4 +259,7 @@ const colToWidth = (colSpan) => {
   let canUseWidth = comWidth.value - (props.showAll ? 40 : 60);
   return Math.floor((canUseWidth * colSpan) / 24) + 'px';
 };
+
+const formRef = ref();
+defineExpose({ formRef });
 </script>

+ 5 - 0
src/config/constants.js

@@ -243,3 +243,8 @@ export const DEVICE_SEND_STATUS = {
   // CANCEL: '作废',
   RETURN: '已返还',
 };
+
+export const SERVICE_RANGE = {
+  1: '仅扫描',
+  2: '扫描+阅卷',
+};

+ 17 - 10
src/style/global.less

@@ -45,7 +45,12 @@ body {
   padding: 16px 16px 1px;
   background-color: #fff;
   border-bottom: 1px solid #e5e5e5;
-
+  &.no-border {
+    border: none;
+    .other-rows {
+      overflow: visible;
+    }
+  }
   .other-rows {
     height: 0;
     overflow: hidden;
@@ -58,15 +63,17 @@ body {
     margin: -10px;
   }
 
-  .t-form__item {
-    margin-bottom: 16px;
-    .t-form__label {
-      padding-right: 8px;
-    }
-    .t-form__controls-content {
-      & > .t-date-picker,
-      & > .t-time-picker {
-        width: 100%;
+  &:not(.no-border) {
+    .t-form__item {
+      margin-bottom: 16px;
+      .t-form__label {
+        padding-right: 8px;
+      }
+      .t-form__controls-content {
+        & > .t-date-picker,
+        & > .t-time-picker {
+          width: 100%;
+        }
       }
     }
   }

+ 135 - 0
src/views/service-unit/dispatch/dispatch-manage/allocation-dialog.vue

@@ -0,0 +1,135 @@
+<template>
+  <my-dialog
+    :visible="visible"
+    header="调配"
+    :width="800"
+    attach="body"
+    :closeOnOverlayClick="false"
+    @close="emit('update:visible', false)"
+    @opened="dialogOpened"
+  >
+    <t-form ref="formRef" :labelWidth="66" colon>
+      <t-row :gutter="[20, 0]">
+        <t-col :span="6">
+          <t-form-item label="服务单元"
+            >{{ dispatchInfo.service }}
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="项目单号">{{ dispatchInfo.crmNo }} </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="客户类型"
+            >{{ customerTypeFilter(dispatchInfo.customType) }}
+          </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="客户名称">{{ dispatchInfo.custom }} </t-form-item>
+        </t-col>
+        <t-col :span="6">
+          <t-form-item label="服务档位"></t-form-item>
+        </t-col>
+        <t-col :span="12">
+          <t-form-item label="客户地址">
+            <!-- <t-space>
+              <span>{{ formData.province }}</span>
+              <span>{{ formData.city }}</span>
+              <span>{{ formData.area }}</span>
+              <span>{{ formData.address }}</span>
+            </t-space> -->
+          </t-form-item>
+        </t-col>
+        <t-col :span="12">
+          <t-form-item label="人员调配" labelAlign="top">
+            <div>
+              <t-table
+                size="small"
+                row-key="roleId"
+                :columns="roleColumns"
+                :data="tableData"
+                bordered
+              >
+                <template #users="{ row }">
+                  <select-free-engineer
+                    v-model="row.userIdList"
+                    :type="row.roleType"
+                    :unit-id="dispatchInfo.serviceId"
+                    :crm-no="dispatchInfo.crmNo"
+                    multiple
+                    :min-collapsed-num="10"
+                    :max="row.roleType === 'REGION_COORDINATOR' ? 1 : 0"
+                  ></select-free-engineer>
+                </template>
+              </t-table>
+            </div>
+          </t-form-item>
+        </t-col>
+      </t-row>
+    </t-form>
+    <template #foot>
+      <t-button theme="default" @click="emit('update:visible', false)"
+        >取消</t-button
+      >
+      <t-button theme="primary" @click="save">保存</t-button>
+    </template>
+  </my-dialog>
+</template>
+<script setup name="PersonDeployDialog">
+import { computed, onMounted, ref, watch } from 'vue';
+import { MessagePlugin } from 'tdesign-vue-next';
+import { MinusCircleFilledIcon } from 'tdesign-icons-vue-next';
+import useAuthenRole from '@/hooks/useAuthenRole';
+import {
+  personAllocateDeployApi,
+  personAllocateRoleDetailApi,
+} from '@/api/resource-guard';
+import { customerTypeFilter } from '@/utils/filter';
+import { cloneDeep } from 'lodash';
+
+const emit = defineEmits(['update:visible', 'success']);
+const props = defineProps({
+  visible: Boolean,
+  curRow: Object,
+  dispatchInfo: { type: Object, default: () => {} },
+});
+
+const formRef = ref(null);
+
+const { roleList, getRoleList } = useAuthenRole();
+
+const tableData = ref([
+  {
+    roleName: '区域协调人',
+    users: [],
+    history: '',
+    roleType: 'REGION_COORDINATOR',
+  },
+  {
+    roleName: '项目经理',
+    users: [],
+    history: '',
+    roleType: 'REGION_MANAGER',
+  },
+  {
+    roleName: '工程师',
+    users: [],
+    history: '',
+    roleType: 'EFFECT_ENGINEER,ASSISTANT_ENGINEER',
+  },
+]);
+const roleColumns = [
+  { colKey: 'roleName', title: '角色', width: 120 },
+  { colKey: 'users', title: '人员', cell: 'users' },
+  { colKey: 'history', title: '', width: 60 },
+];
+
+const save = async () => {
+  MessagePlugin.success('保存成功');
+  emit('update:visible', false);
+  emit('success');
+};
+
+onMounted(() => {
+  getRoleList();
+});
+</script>

+ 164 - 0
src/views/service-unit/dispatch/dispatch-manage/create-sop-item.vue

@@ -0,0 +1,164 @@
+<template>
+  <my-dialog
+    :visible="visible"
+    :header="`${isEdit ? '编辑' : '新增'}sop`"
+    :width="600"
+    :closeOnOverlayClick="false"
+    attach="body"
+    @close="emit('update:visible', false)"
+    @confirm="createHandler"
+  >
+    <SearchForm
+      :fields="fields"
+      :params="formData"
+      noBorder
+      :rules="rules"
+      ref="searchForm"
+    ></SearchForm>
+  </my-dialog>
+</template>
+<script name="CreateSopItem" setup>
+import { ref, computed, onMounted, reactive } from 'vue';
+import { SERVICE_RANGE } from '@/config/constants';
+import { dictToOptionList } from '@/utils/tool';
+import useClearDialog from '@/hooks/useClearDialog';
+const searchForm = ref();
+const props = defineProps({
+  visible: Boolean,
+  curRow: { type: Object, default: null },
+});
+const emit = defineEmits(['update:visible', 'confirm']);
+
+const rules = {
+  aaa: [{ required: true, message: '请填写科目名称' }],
+  bbb: [{ required: true, message: '请填写考生人数' }],
+  eee: [{ required: true, message: '请选择服务范围' }],
+  fff: [{ required: true, message: '请选择扫描开始时间' }],
+  ggg: [{ required: true, message: '请选择扫描结束时间' }],
+  hhh: [{ required: true, message: '请选择评卷开始时间' }],
+  iii: [{ required: true, message: '请选择评卷结束时间' }],
+};
+
+const { formData, isEdit } = useClearDialog(
+  {
+    aaa: '',
+    bbb: '',
+    ccc: '',
+    ddd: '',
+    eee: '',
+    fff: '',
+    ggg: '',
+    hhh: '',
+    iii: '',
+  },
+  props,
+  null,
+  () => {
+    for (let key in formData) {
+      formData[key] = props.curRow[key];
+    }
+  }
+);
+
+const fields = ref([
+  {
+    prop: 'aaa',
+    label: '科目名称',
+    labelWidth: 100,
+    colSpan: 24,
+    attrs: {
+      clearable: true,
+    },
+  },
+  {
+    prop: 'bbb',
+    label: '考生人数',
+    labelWidth: 100,
+    colSpan: 24,
+    attrs: {
+      clearable: true,
+    },
+  },
+  {
+    prop: 'ccc',
+    label: '联系人',
+    labelWidth: 100,
+    colSpan: 24,
+    attrs: {
+      clearable: true,
+    },
+  },
+  {
+    prop: 'ddd',
+    label: '电话',
+    labelWidth: 100,
+    colSpan: 24,
+    attrs: {
+      clearable: true,
+    },
+  },
+  {
+    prop: 'eee',
+    label: '服务范围',
+    type: 'select',
+    labelWidth: 100,
+    colSpan: 24,
+    options: dictToOptionList(SERVICE_RANGE),
+    attrs: {
+      clearable: true,
+    },
+  },
+  {
+    prop: 'fff',
+    label: '扫描开始时间',
+    type: 'date',
+    labelWidth: 100,
+    colSpan: 24,
+    attrs: {
+      clearable: true,
+      valueType: 'time-stamp',
+    },
+  },
+  {
+    prop: 'ggg',
+    label: '扫描结束时间',
+    type: 'date',
+    labelWidth: 100,
+    colSpan: 24,
+    attrs: {
+      clearable: true,
+      valueType: 'time-stamp',
+    },
+  },
+  {
+    prop: 'hhh',
+    label: '评卷开始时间',
+    type: 'date',
+    labelWidth: 100,
+    colSpan: 24,
+    attrs: {
+      clearable: true,
+      valueType: 'time-stamp',
+    },
+  },
+  {
+    prop: 'iii',
+    label: '评卷结束时间',
+    type: 'date',
+    labelWidth: 100,
+    colSpan: 24,
+    attrs: {
+      clearable: true,
+      valueType: 'time-stamp',
+    },
+  },
+]);
+const createHandler = async () => {
+  const formRef = searchForm.value.formRef;
+  const valid = await formRef?.validate();
+  if (valid !== true) return;
+  emit('update:visible', false);
+  emit('confirm', { ...formData });
+};
+</script>
+<style lang="less" scoped></style>

+ 164 - 0
src/views/service-unit/dispatch/dispatch-manage/create-sop.vue

@@ -0,0 +1,164 @@
+<template>
+  <my-drawer
+    class="sop-dialog"
+    :visible="visible"
+    :header="title"
+    size="85%"
+    attach="body"
+    :destroyOnClose="true"
+    :closeOnOverlayClick="false"
+    :close-btn="true"
+    @close="visible = false"
+  >
+    <t-collapse class="sop-step-mid" defaultExpandAll>
+      <t-collapse-panel disabled>
+        <template #expandIcon></template>
+        <template #header>
+          项目派单信息(派单号:{{ dispatchInfo.crmNo }})
+        </template>
+        <t-form colon label-width="72px">
+          <t-row :gutter="[0, 4]">
+            <t-col :span="4">
+              <t-form-item label="客户经理">{{
+                dispatchInfo.crmUserName
+              }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="项目名称">{{
+                dispatchInfo.name
+              }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="客户类型">教务处</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="客户名称">{{
+                dispatchInfo.custom
+              }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="实施产品">{{
+                dispatchInfo.product
+              }}</t-form-item>
+            </t-col>
+            <t-col :span="4">
+              <t-form-item label="服务单元">{{
+                dispatchInfo.service
+              }}</t-form-item>
+            </t-col>
+          </t-row>
+        </t-form>
+      </t-collapse-panel>
+    </t-collapse>
+    <div class="btn-box mt-10px">
+      <t-button @click="toCreateSop">创建sop</t-button>
+    </div>
+    <div class="mt-10px">
+      <t-table
+        size="small"
+        row-key="index"
+        :columns="columns"
+        :data="sopList"
+        bordered
+      >
+        <template #operate="{ row }">
+          <div class="table-operations" @click.stop>
+            <t-link theme="primary" hover="color" @click="allocation(row)">
+              人员配置
+            </t-link>
+            <t-link theme="primary" hover="color" @click="editSopItem(row)">
+              编辑
+            </t-link>
+            <t-link theme="primary" hover="color"> 发布 </t-link>
+            <t-link theme="primary" hover="color"> 删除 </t-link>
+          </div>
+        </template>
+      </t-table>
+    </div>
+    <CreateSopItem
+      v-model:visible="showCreateDialog"
+      :curRow="curRow"
+      @confirm="addSopItem"
+    ></CreateSopItem>
+
+    <AllocationDialog
+      v-model:visible="showAllocationDialog"
+      :curRow="curRow"
+      :dispatchInfo="dispatchInfo"
+    ></AllocationDialog>
+  </my-drawer>
+</template>
+
+<script lang="ts" name="CreateSop" setup>
+import { computed, ref } from 'vue';
+import { useVModel } from '@vueuse/core';
+import CreateSopItem from './create-sop-item.vue';
+import AllocationDialog from './allocation-dialog.vue';
+const showAllocationDialog = ref(false);
+const props = defineProps({
+  modelValue: Boolean,
+  type: String,
+  dispatchInfo: {
+    type: Object,
+    default() {
+      return {};
+    },
+  },
+});
+const emit = defineEmits(['update:modelValue', 'confirm']);
+const sopList = ref([
+  {
+    aaa: 'aaa',
+    bbb: 'bbb',
+    ccc: 'ccc',
+    ddd: 'ddd',
+    eee: 'eee',
+    fff: 1714492800000,
+    ggg: 1714586400000,
+    hhh: 1716231780000,
+    iii: 1717167600000,
+  },
+]);
+const visible = useVModel(props, 'modelValue', emit);
+const title = computed(() => {
+  if (props.type === 'new') return '新增SOP';
+  if (props.type === 'edit') return '编辑SOP';
+});
+const columns = [
+  { colKey: 'aaa', title: '科目名称' },
+  { colKey: 'bbb', title: '考生人数' },
+  { colKey: 'ccc', title: '联系人' },
+  { colKey: 'ddd', title: '电话' },
+  { colKey: 'eee', title: '服务范围' },
+  { colKey: 'fff', title: '扫描开始时间' },
+  { colKey: 'ggg', title: '扫描结束时间' },
+  { colKey: 'hhh', title: '评卷开始时间' },
+  { colKey: 'iii', title: '评卷结束时间' },
+  {
+    colKey: 'operate',
+    title: '管理',
+    fixed: 'right',
+    width: 250,
+    cell: 'operate',
+  },
+];
+const showCreateDialog = ref(false);
+const curRow = ref(null);
+const toCreateSop = () => {
+  showCreateDialog.value = true;
+};
+const addSopItem = (item) => {
+  sopList.value.push(item);
+};
+const editSopItem = (row) => {
+  curRow.value = row;
+  showCreateDialog.value = true;
+};
+const allocation = (row) => {
+  curRow.value = row;
+  showAllocationDialog.value = true;
+};
+const stepConfirm = () => {
+  emit('confirm');
+};
+</script>

+ 18 - 1
src/views/service-unit/dispatch/dispatch-manage/index.vue

@@ -112,6 +112,9 @@
                 修改
               </t-link>
             </template>
+            <t-link theme="primary" hover="color" @click="createSop(row)">
+              创建sop
+            </t-link>
           </div>
         </template>
       </t-table>
@@ -187,6 +190,12 @@
         </t-form>
       </div>
     </mult-delineation-dialog>
+    <CreateSop
+      :dispatchInfo="curRow"
+      :type="sopDialogType"
+      v-model="showCreateSop"
+    >
+    </CreateSop>
   </div>
 </template>
 
@@ -195,6 +204,7 @@ import { reactive, ref, computed, onMounted } from 'vue';
 import { omit } from 'lodash';
 import { DialogPlugin, MessagePlugin } from 'tdesign-vue-next';
 import { ErrorCircleFilledIcon, FactCheckIcon } from 'tdesign-icons-vue-next';
+import CreateSop from './create-sop.vue';
 import usePermission from '@/hooks/usePermission';
 const { perm } = usePermission();
 
@@ -363,7 +373,7 @@ const columns = [
     title: '管理',
     colKey: 'operate',
     fixed: 'right',
-    width: 140,
+    width: 200,
     cell: 'operate',
   },
 ];
@@ -443,6 +453,13 @@ const handleEdit = (row) => {
   curRow.value = row;
   showAddDispatchDialog.value = true;
 };
+const sopDialogType = ref('new');
+const showCreateSop = ref(false);
+const createSop = (row) => {
+  sopDialogType.value = 'new';
+  curRow.value = row;
+  showCreateSop.value = true;
+};
 const handleBatchDisable = () => {
   if (!selectedRowKeys.value.length) {
     MessagePlugin.error('请选择要作废的记录');

+ 22 - 2
src/views/service-unit/dispatch/dispatch-manage/mult-delineation-dialog.vue

@@ -14,7 +14,6 @@
         <t-col :span="12">
           <t-form-item label="服务单元" name="serviceUnitId">
             <select-service-unit
-              v-if="visible"
               v-model="formData.serviceUnitId"
               :filterParams="{
                 statusList: ['PUBLISH'],
@@ -24,6 +23,22 @@
             </select-service-unit>
           </t-form-item>
         </t-col>
+        <t-col :span="12">
+          <t-form-item label="大区经理" name="aaa">
+            <t-select v-model="formData.aaa">
+              <t-option value="1" label="按地域系统自动指定大区经理"></t-option>
+              <t-option value="2" label="直接指定大区经理"></t-option>
+            </t-select>
+          </t-form-item>
+        </t-col>
+        <t-col :span="12" v-if="formData.aaa == '2'">
+          <t-form-item label="大区经理" name="bbb">
+            <select-type-user
+              v-model="formData.bbb"
+              type="REGION_MANAGER"
+            ></select-type-user>
+          </t-form-item>
+        </t-col>
       </t-row>
     </t-form>
     <template #foot>
@@ -50,7 +65,12 @@ const props = defineProps({
   dialogTitle: { type: String, default: '划定服务单元' },
 });
 
-const formData = reactive({ serviceUnitId: null, crmIdList: [] });
+const formData = reactive({
+  serviceUnitId: null,
+  crmIdList: [],
+  aaa: '1',
+  bbb: '',
+});
 const rules = {
   serviceUnitId: [
     {

+ 14 - 0
src/views/sop/sop-manage/student-sop/index.vue

@@ -183,6 +183,9 @@
                 编辑
               </t-link>
             </template>
+            <t-link theme="primary" hover="color" @click="toDeviceManage(row)"
+              >设备管理</t-link
+            >
           </div>
         </template>
       </my-table>
@@ -218,6 +221,10 @@
       v-model:visible="showAddViolationDialog"
       :sop="curSopData"
     ></add-violation-dialog>
+    <DeviceManageNew
+      v-model:visible="showDeviceManage"
+      :sop="curSopData"
+    ></DeviceManageNew>
   </div>
 </template>
 
@@ -239,6 +246,7 @@ import SopSortPanel from '../../components/sop-sort-panel/index.vue';
 import { cloneDeep } from 'lodash';
 import { CUSTOMER_TYPE, FLOW_STATUS } from '@/config/constants';
 import { dictToOptionList } from '@/utils/tool';
+import DeviceManageNew from '@/components/common/device-manage-new';
 const { perm } = usePermission();
 
 const appStore = useAppStore();
@@ -508,4 +516,10 @@ const createQualityIssueHandle = (row) => {
   };
   showQualityIssueDialog.value = true;
 };
+
+const showDeviceManage = ref(false);
+const toDeviceManage = (row) => {
+  curSopData.value = row;
+  showDeviceManage.value = true;
+};
 </script>