Jelajahi Sumber

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

liujt 8 bulan lalu
induk
melakukan
6925ff7b98

+ 14 - 8
src/BIZComponents/outdetails.vue

@@ -38,11 +38,11 @@
                   <span>{{ extInfo?.documentSource }}</span>
                 </el-form-item>
               </el-col>
-              <el-col :span="8" >
+              <el-col :span="8">
                 <el-form-item label="客户名称:">
                   <span>{{ infoData.clientName }}</span>
-                </el-form-item> </el-col
-              >
+                </el-form-item>
+              </el-col>
               <!-- <el-col :span="8" v-if="infoData.bizType == 3">
                 <el-form-item label="客户联系人:">
                   <span>{{ infoData.clientUser }}</span>
@@ -67,7 +67,7 @@
               </el-col>
               <el-col :span="8">
                 <el-form-item label="出库时间">
-                  <span>{{ infoData.storageTime||infoData.createTime }}</span>
+                  <span>{{ infoData.storageTime || infoData.createTime }}</span>
                 </el-form-item>
               </el-col>
               <el-col :span="8">
@@ -631,9 +631,12 @@
       },
       async _getInfo(sourceBizNo, type, list = [], returnSourceType) {
         const params = {
-          isCreateReturnOrder: 1,
-        }
-        const dataArray = await getInfoBySourceBizNoAll(sourceBizNo, returnSourceType === 3 ? params : {});
+          isCreateReturnOrder: 1
+        };
+        const dataArray = await getInfoBySourceBizNoAll(
+          sourceBizNo,
+          returnSourceType === 3 ? params : {}
+        );
         let res = {};
 
         if (dataArray && dataArray.length > 0) {
@@ -693,7 +696,7 @@
               ...this.productList[key].outInDetailRecordRequestList[k],
               modelType: this.productList[key].categoryModel,
               specification: this.productList[key].specification,
-              productBrand: this.productList[key].brandNum,
+              productBrand: this.productList[key].brandNum
             });
           }
         }
@@ -778,6 +781,9 @@
       getValue() {
         return [...this.setMultipleSelection(), ...this.setProductSelection()];
       },
+      getDefValue() {
+        return [...this.multipleSelection, ...this.productSelection];
+      },
       download(row) {
         if (row.storePath) {
           getFile({ objectName: row.storePath }, row.name);

+ 59 - 0
src/api/salesServiceManagement/return.js

@@ -0,0 +1,59 @@
+import request from '@/utils/request';
+import { download } from '@/utils/file';
+
+//列表---------------------------------------------------------------
+export async function getPage(data) {
+  const res = await request.get('/eom/aftersalessparepartsreturnapply/page', {
+    params: data
+  });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
+//新增
+export async function save(data) {
+  const res = await request.post(
+    '/eom/aftersalessparepartsreturnapply/save',
+    data
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//根据id查询详情
+export async function getById(id) {
+  const res = await request.get(
+    `/eom/aftersalessparepartsreturnapply/getById/${id}`
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//修改
+export async function update(data) {
+  const res = await request.put(
+    '/eom/aftersalessparepartsreturnapply/update',
+    data
+  );
+  if (res.data.code === '0') {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+//删除
+export async function deleteList(data) {
+  const res = await request.delete(
+    '/eom/aftersalessparepartsreturnapply/delete',
+    {
+      data
+    }
+  );
+  if (res.data.code == 0) {
+    return res.data.message;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 1 - 0
src/views/salesServiceManagement/accessory/components/accessoryDialog.vue

@@ -245,6 +245,7 @@
     },
     methods: {
       init(row, type) {
+        this.activeComp = 'main';
         let currentUser = getCurrentUser();
         this.form.receivingDeptId = currentUser.currentGroupId; // 部门id
         this.roleVOListData();

+ 246 - 0
src/views/salesServiceManagement/accessory/components/accessoryList.vue

@@ -0,0 +1,246 @@
+<template>
+  <ele-modal
+    custom-class="ele-dialog-form long-dialog-form"
+    :centered="true"
+    :visible.sync="addRepairNotesDialog"
+    title="选择配件申请单"
+    :close-on-click-modal="false"
+    width="85%"
+    :maxable="true"
+    append-to-body
+    @close="handleClose"
+  >
+    <div class="ele-body">
+      <el-card shadow="never" v-loading="loading">
+        <search class="seep-search" @search="reload"></search>
+        <!-- 数据表格 -->
+        <ele-pro-table
+          ref="table"
+          :columns="columns"
+          :datasource="datasource"
+          cache-key="systemRoleTable"
+          :pageSize="20"
+          @cell-click="cellClick"
+          row-key="id"
+        >
+          <!-- 表头工具栏 -->
+          <template v-slot:action="{ row }">
+            <el-radio class="radio" v-model="radio" :label="row.id">
+              <i></i>
+            </el-radio>
+          </template>
+        </ele-pro-table>
+      </el-card>
+    </div>
+
+    <div slot="footer">
+      <el-button type="primary" size="small" @click="selected">选择</el-button>
+      <el-button size="small" @click="handleClose">关闭</el-button>
+    </div>
+  </ele-modal>
+</template>
+
+<script>
+  import search from './search.vue';
+
+  import { accessoryPage } from '@/api/salesServiceManagement/index';
+  export default {
+    components: {
+      search
+    },
+    data() {
+      return {
+        // 加载状态
+        loading: false,
+        addRepairNotesDialog: false,
+        radio: '',
+        current: {}
+      };
+    },
+    computed: {
+      columns() {
+        return [
+          {
+            action: 'action',
+            slot: 'action',
+            align: 'center',
+            label: '选择'
+          },
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            slot: 'code',
+            prop: 'code',
+            label: '编码',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'orderCode',
+            label: '工单编码',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'approvalStatus',
+            label: '审核状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (_row, _column, cellValue) => {
+              return cellValue == 0
+                ? '未提交'
+                : cellValue == 1
+                ? '审核中'
+                : cellValue == 2
+                ? '审核通过'
+                : cellValue == 3
+                ? '审核不通过'
+                : '';
+            }
+          },
+          {
+            prop: 'categoryLevelName',
+            label: '物品分类',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (row) => {
+              if (!row.details) return '';
+              let str = '';
+              row.details.map((el, idx) => {
+                if (idx + 1 == row.details.length) {
+                  str += el.categoryLevelName;
+                } else {
+                  str = el.categoryLevelName
+                    ? str + '' + el.categoryLevelName + ','
+                    : str + '';
+                }
+              });
+              return str;
+            }
+          },
+          // + +关键字
+          {
+            prop: 'categoryName',
+            label: '物品名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (row) => {
+              if (!row.details) return '';
+              let str = '';
+              row.details.map((el, idx) => {
+                if (idx + 1 == row.details.length) {
+                  str += el.categoryName;
+                } else {
+                  str = str + '' + el.categoryName + ',';
+                }
+              });
+              return str;
+            }
+          },
+          {
+            prop: 'receivingDeptName',
+            label: '领用部门',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          // + + 时间选择
+          {
+            prop: 'recipientName',
+            label: '领用人',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'contactName',
+            label: '客户名称',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            label: '设备名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (row) => {
+              if (!row.deviceDetails) return '';
+              let str = '';
+              row.deviceDetails.map((el, idx) => {
+                if (idx + 1 == row.deviceDetails.length) {
+                  str += el.categoryName;
+                } else {
+                  str = str + '' + el.categoryName + ',';
+                }
+              });
+              return str;
+            }
+          },
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'usageTime',
+            label: '使用时间',
+            align: 'center',
+            showOverflowTooltip: true
+          }
+        ];
+      }
+    },
+    created() {},
+    methods: {
+      /* 表格数据源 */
+      datasource({ page, limit, where, order }) {
+        return accessoryPage({
+          pageNum: page,
+          size: limit,
+          ...where,
+          approvalStatus: 2
+        });
+      },
+      /* 刷新表格 */
+      reload(where) {
+        this.$refs.table.reload({ page: 1, where });
+      },
+      open() {
+        this.addRepairNotesDialog = true;
+      },
+      selected() {
+        if (!this.current) {
+          return this.$message.warning('请一条数据!');
+        }
+        this.$emit('changeSelect', this.current);
+        this.handleClose();
+      },
+      // 单击获取id
+      cellClick(row) {
+        this.current = row;
+        this.radio = row.id;
+      },
+      handleClose() {
+        this.addRepairNotesDialog = false;
+        this.current = null;
+        this.radio = '';
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  ::v-deep .el-input__inner::placeholder {
+    font-size: 13px;
+  }
+  ::v-deep .seep-search {
+    .el-input__inner {
+      padding: 0 5px 0 10px;
+    }
+  }
+</style>

+ 16 - 2
src/views/salesServiceManagement/accessory/index.vue

@@ -40,6 +40,13 @@
             @click="openEdit(row, 'edit')"
             >修改</el-link
           >
+          <el-link
+            type="primary"
+            v-if="row.approvalStatus == 2"
+            :underline="false"
+            @click="returnAdd(row)"
+            >归还入库</el-link
+          >
           <!-- <el-link
             type="primary"
             v-if="row.source == 0"
@@ -73,13 +80,14 @@
     ></process-submit-dialog> -->
     <!-- 新建或编辑弹窗 -->
     <accessoryDialog ref="accessoryDialog" @refresh="reload" />
+    <returnAddDiaLog ref="returnAddDiaLogRef" @refresh="reload"></returnAddDiaLog>
   </div>
 </template>
 
 <script>
   import search from './components/search.vue';
   import accessoryDialog from './components/accessoryDialog.vue';
-  // import processSubmitDialog from '@/BIZComponents/processSubmitDialog/processSubmitDialog.vue';
+  import returnAddDiaLog from '@/views/salesServiceManagement/return/component/recycleDialog.vue';
 
   import {
     accessoryPage,
@@ -92,13 +100,15 @@
     components: {
       search,
       accessoryDialog,
+      returnAddDiaLog
       // processSubmitDialog
     },
     data() {
       return {
         // 加载状态
         loading: false,
-        processSubmitDialogFlag: false // 加载状态 弹窗
+        processSubmitDialogFlag: false, // 加载状态 弹窗
+        outboundDetailsDialogFlag: false //
       };
     },
     computed: {
@@ -264,6 +274,10 @@
           }
         });
       },
+      returnAdd(row) {
+        this.$refs.returnAddDiaLogRef.init(row,'add','accessory');
+      },
+
       openProcess(data) {
         this.processSubmitDialogFlag = true;
         this.$nextTick(() => {

+ 8 - 1
src/views/salesServiceManagement/index.vue

@@ -49,6 +49,10 @@
           <div v-if="activeComp == 'recycle'">
             <recycle ref="recycleRef" />
           </div>
+          <div v-if="activeComp == 'return'">
+            <returnView ref="returnViewRef" />
+          </div>
+
           <div v-if="activeComp == 'knowledge'">
             <knowledge ref="knowledgeRef" />
           </div>
@@ -75,6 +79,7 @@
   import knowledge from './knowledge';
   import vehiclerecord from './vehiclerecord';
   import recycle from './recycle';
+  import returnView from './return/index.vue';
   import Cost from './cost';
   import statisReport from './statisReport';
   import { getToDoReminder } from '@/api/common/index';
@@ -90,7 +95,8 @@
       recycle,
       Cost,
       statisReport,
-      vehiclerecord
+      vehiclerecord,
+      returnView
     },
     data() {
       return {
@@ -110,6 +116,7 @@
           { key: 'cost', name: '费用清单', reminder: 'expenseListNum' },
           { key: 'evaluate', name: '客户评价' },
           { key: 'accessory', name: '配件申请记录' },
+          { key: 'return', name: '配件归还记录' },
           { key: 'recycle', name: '配件回收记录' },
           { key: 'knowledge', name: '故障知识库' },
           { key: 'statisReport', name: '统计报表' },

+ 292 - 0
src/views/salesServiceManagement/return/component/outboundDetailsDialog.vue

@@ -0,0 +1,292 @@
+<template>
+  <ele-modal
+    custom-class="ele-dialog-form long-dialog-form"
+    :centered="true"
+    :visible.sync="outboundDetailsDialogFlag"
+    :title="title"
+    append-to-body
+    :close-on-click-modal="false"
+    width="70%"
+    :maxable="true"
+    :resizable="true"
+    :before-close="cancel"
+  >
+    <outboundDetailsDialog
+      ref="outboundDetailsDialogRef"
+      @handleSave="handleSave"
+    ></outboundDetailsDialog>
+    <div slot="footer">
+      <el-button type="primary" @click="handleSave">保存</el-button>
+      <el-button type="info" @click="cancel">关闭</el-button>
+    </div>
+  </ele-modal>
+</template>
+
+<script>
+  import outboundDetailsDialog from '@/BIZComponents/outdetails.vue';
+
+  export default {
+    props: {
+      outboundDetailsDialogFlag: {
+        type: Boolean,
+        default: false
+      }
+    },
+    components: {
+      outboundDetailsDialog
+    },
+    data() {
+      return {
+        title: '信息'
+      };
+    },
+    watch: {},
+    computed: {},
+
+    created() {},
+    methods: {
+      async init(row = {}, list = []) {
+        this.$nextTick(() => {
+          this.$refs.outboundDetailsDialogRef._getInfo(
+            row.code,
+            row.type,
+            list,
+            3
+          );
+        });
+      },
+
+      handleSave() {
+        const list = this.$refs.outboundDetailsDialogRef.getValue() || [];
+        if (list.length == 0) return this.$message.warning('请选择归还明细');
+
+        this.$emit('saveDate', list);
+        this.cancel();
+      },
+      cancel() {
+        this.$emit('update:outboundDetailsDialogFlag', false);
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .stepsStatus {
+    width: 40%;
+    margin: 0 auto;
+  }
+
+  .p20 {
+    padding: 20px;
+  }
+
+  .flex {
+    display: flex;
+  }
+
+  .title {
+    justify-content: space-between;
+    border-bottom: 1px solid #ccc;
+    padding-bottom: 5px;
+
+    span {
+      font-size: 16px;
+    }
+
+    .col {
+      padding-left: 40px;
+      font-size: 14px;
+      color: #aaaaaa;
+    }
+  }
+
+  .degree {
+    margin-right: 10px;
+    padding: 0px 15px;
+    color: #fff;
+    font-size: 13px;
+    line-height: 23px;
+    border-radius: 23px;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+
+    span {
+      width: 5px;
+      height: 5px;
+      border-radius: 100%;
+      margin-right: 6px;
+      background-color: #fff;
+    }
+  }
+
+  .red {
+    background-color: rgb(163, 0, 20);
+  }
+
+  .blue {
+    background-color: #1989fa;
+  }
+
+  .createdInfo {
+    justify-content: space-around;
+    margin-top: 10px;
+    font-size: 14px;
+
+    .col {
+      color: #6e6e6e;
+      padding-right: 10px;
+    }
+  }
+
+  .mt40 {
+    margin-top: 40px;
+  }
+
+  .custSteps {
+    margin-top: 20px;
+    margin-left: 70px;
+
+    .box {
+      width: 158px;
+      border: 1px solid #ccc;
+      padding: 10px;
+      flex-direction: row;
+      flex-wrap: wrap;
+      // justify-content: space-between;
+      font-size: 12px;
+      color: #9e9e9e;
+
+      .x {
+        width: 20px;
+        height: 15px;
+        margin-right: 5px;
+      }
+
+      .q {
+        background-color: #d0e4d5;
+      }
+
+      .b {
+        background-color: #1989fa;
+      }
+
+      .g {
+        background-color: #157a2c;
+      }
+
+      .r {
+        background-color: #a30014;
+      }
+
+      .a {
+        align-items: center;
+        margin-bottom: 10px;
+      }
+
+      .mr10 {
+        margin-right: 10px;
+      }
+
+      .mb0 {
+        margin-bottom: 0;
+      }
+    }
+
+    .stepsInfo {
+      // flex: 1;
+      width: 483px;
+    }
+  }
+
+  .mt20 {
+    margin-top: 20px;
+  }
+
+  .content-detail {
+    overflow: hidden;
+  }
+
+  .executor {
+    font-size: 14px;
+
+    .col {
+      color: #6e6e6e;
+      padding-right: 10px;
+    }
+  }
+
+  .result {
+    justify-content: space-around;
+  }
+
+  .mr20 {
+    margin-right: 20px;
+  }
+
+  .details {
+    font-size: 14px;
+    margin-bottom: 10px;
+  }
+
+  .customSteps {
+    margin-top: 40px;
+    font-size: 14px;
+    margin-left: 80px;
+
+    .time {
+      font-size: 12px;
+      color: #6e6e6e;
+      margin-right: 20px;
+      position: relative;
+
+      &::after {
+        content: '';
+        width: 1px;
+        height: 100%;
+        background-color: #157a2c;
+        position: absolute;
+        right: -26px;
+      }
+    }
+
+    .flex:last-child {
+      .time {
+        &::after {
+          display: none;
+        }
+      }
+    }
+
+    .round {
+      margin-right: 20px;
+      width: 10px;
+      height: 10px;
+      border-radius: 100%;
+      background-color: #157a2c;
+      position: relative;
+
+      span {
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        width: 4px;
+        height: 4px;
+        background-color: #fff;
+        border-radius: 100%;
+        transform: translate(-2px, -2px);
+      }
+    }
+
+    .text {
+      .info {
+        margin-top: 10px;
+        width: 955px;
+        background-color: #f0f3f3;
+        overflow: hidden;
+        padding: 10px;
+        margin-bottom: 10px;
+      }
+    }
+  }
+</style>

+ 408 - 0
src/views/salesServiceManagement/return/component/recycleDialog.vue

@@ -0,0 +1,408 @@
+<template>
+  <ele-modal
+    custom-class="ele-dialog-form long-dialog-form"
+    :centered="true"
+    :visible.sync="editRepairNotesDialog"
+    :title="title"
+    :close-on-click-modal="false"
+    width="85%"
+    :maxable="true"
+    append-to-body
+    @close="handleClose"
+  >
+    <div class="switch" v-if="type == 'view'">
+      <div class="switch_left">
+        <ul>
+          <li
+            v-for="item in tabOptions"
+            :key="item.key"
+            :class="{ active: activeComp == item.key }"
+            @click="handleTag(item.key)"
+          >
+            {{ item.name }}
+          </li>
+        </ul>
+      </div>
+    </div>
+    <el-form
+      ref="recyleFormRef"
+      :model="form"
+      label-width="100px"
+      v-show="activeComp === 'main'"
+    >
+      <headerTitle title="基本信息" style="margin-top: 15px"></headerTitle>
+      <el-row>
+        <el-col :span="12">
+          <el-form-item label="编码:" prop="code">
+            <el-input v-model="form.code" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item
+            label="名称:"
+            prop="name"
+            :rules="{
+              required: true,
+              message: '请输入名称',
+              trigger: 'change'
+            }"
+          >
+            <el-input v-model="form.name" :disabled="type == 'view'" />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item
+            label="配件申请单:"
+            prop="sparePartsApplyCode"
+            :rules="{
+              required: true,
+              message: '请选择配件申请单',
+              trigger: 'change'
+            }"
+          >
+            <el-input
+              v-model="form.sparePartsApplyCode"
+              :disabled="type == 'view'"
+              @click.native="$refs.accessoryListRef.open"
+              placeholder="请选择"
+            />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="备注:" prop="remark">
+            <el-input
+              v-model="form.remark"
+              :disabled="type == 'view'"
+              type="textarea"
+              placeholder="请输入"
+            />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <headerTitle title="归还配件明细" style="margin-top: 15px"> </headerTitle>
+      <ele-pro-table
+        ref="table"
+        :needPage="false"
+        :columns="columns"
+        :datasource="form.detailList"
+        class="time-form"
+        :maxHeight="400"
+        full-height="calc(100vh - 116px)"
+      >
+        <!-- 表头工具栏 -->
+        <template v-slot:toolbar v-if="type != 'view'">
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-plus"
+            class="ele-btn-icon"
+            @click="openOutbound({ code: form.sparePartsApplyCode })"
+            >新增</el-button
+          >
+        </template>
+        <template v-slot:measureQuantity="scope">
+          <el-form-item
+            label-width="0"
+            :prop="'detailList.' + scope.$index + '.measureQuantity'"
+            :rules="[{ required: true, message: '请输入', trigger: 'blur' }]"
+            style="margin-bottom: 0"
+          >
+            <el-input
+              v-model="scope.row.measureQuantity"
+              :disabled="type == 'view'"
+              type="number"
+            ></el-input>
+          </el-form-item>
+        </template>
+        <template v-slot:action="{ row, $index }" v-if="type != 'view'">
+          <el-popconfirm
+            class="ele-action"
+            title="确定要删除此条数据吗?"
+            @confirm="del($index)"
+          >
+            <template v-slot:reference>
+              <el-link type="danger" icon="el-icon-delete" :underline="false"
+                >删除</el-link
+              >
+            </template>
+          </el-popconfirm>
+        </template>
+      </ele-pro-table>
+    </el-form>
+    <template v-slot:footer>
+      <el-button @click="handleClose">取消</el-button>
+      <el-button
+        type="primary"
+        v-if="type != 'view'"
+        @click="save"
+        :loading="loading"
+        >确认</el-button
+      >
+    </template>
+    <bpmDetail
+      v-if="activeComp === 'bpm' && form.processInstanceId"
+      :id="form.processInstanceId"
+    ></bpmDetail>
+
+    <!--入库详情-->
+    <innerBoundDetails
+      v-if="activeComp === 'store' && form.approvalStatus == 2"
+      ref="innerBoundDetailsRef"
+    ></innerBoundDetails>
+    <accessoryList
+      ref="accessoryListRef"
+      @changeSelect="changeSelect"
+    ></accessoryList>
+    <outboundDetailsDialog
+      ref="outboundDetailsDialogRef"
+      :outboundDetailsDialogFlag.sync="outboundDetailsDialogFlag"
+      @saveDate="saveDate"
+    ></outboundDetailsDialog>
+  </ele-modal>
+</template>
+
+<script>
+  import { save, update, getById } from '@/api/salesServiceManagement/return';
+  import bpmDetail from '@/views/bpm/processInstance/detail.vue';
+
+  import accessoryList from '@/views/salesServiceManagement/accessory/components/accessoryList.vue';
+  import outboundDetailsDialog from './outboundDetailsDialog.vue';
+  import innerBoundDetails from '@/BIZComponents/innerdetails.vue';
+
+  const defForm = {
+    code: '',
+    name: '',
+    sparePartsApplyId: '',
+    sparePartsApplyCode: '',
+    workOrderId: '',
+    remark: '',
+    detailList: []
+  };
+
+  export default {
+    props: {},
+    components: {
+      accessoryList,
+      outboundDetailsDialog,
+      bpmDetail,
+      innerBoundDetails
+    },
+
+    data() {
+      return {
+        loading: false,
+        title: '新增',
+        editRepairNotesDialog: false,
+        outboundDetailsDialogFlag: false,
+        activeComp: 'main',
+        tabOptions: [
+          { key: 'main', name: '发货单详情' },
+          { key: 'bpm', name: '流程详情' },
+          { key: 'store', name: '入库单详情' }
+        ],
+        type: 'add',
+        form: {
+          ...defForm
+        },
+        columns: [
+          {
+            width: 45,
+            type: 'index',
+            columnKey: 'index',
+            align: 'center',
+            fixed: 'left'
+          },
+
+          {
+            minWidth: 160,
+            prop: 'categoryCode',
+            label: '编码',
+            showOverflowTooltip: true,
+            align: 'center'
+          },
+          {
+            minWidth: 120,
+            prop: 'categoryName',
+            label: '名称',
+            showOverflowTooltip: true,
+            align: 'center'
+          },
+
+          {
+            minWidth: 160,
+            prop: 'batchNo',
+            label: '批次号',
+            showOverflowTooltip: true,
+            slot: 'batchNo',
+            align: 'center'
+          },
+          {
+            minWidth: 150,
+            prop: 'measureQuantity',
+            slot: 'measureQuantity',
+            label: '归还数量',
+            showOverflowTooltip: true,
+            align: 'center'
+          },
+          {
+            minWidth: 150,
+            prop: 'measureUnit',
+            label: '计量单位',
+            showOverflowTooltip: true,
+            align: 'center'
+          },
+          {
+            minWidth: 160,
+            prop: 'sendCode',
+            label: '发货条码',
+            showOverflowTooltip: true,
+            slot: 'barcodes',
+            align: 'center'
+          },
+
+          {
+            minWidth: 160,
+            prop: 'packageNo',
+            align: 'center',
+            label: '包装编码',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 160,
+            prop: 'categoryModel',
+            align: 'center',
+            label: '型号',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 160,
+            prop: 'specification',
+            align: 'center',
+            label: '规格',
+            showOverflowTooltip: true
+          },
+          {
+            minWidth: 160,
+            prop: 'brandNum',
+            align: 'center',
+            label: '牌号',
+            showOverflowTooltip: true
+          },
+          {
+            columnKey: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center',
+            width: 130,
+            resizable: false,
+            showOverflowTooltip: true
+          }
+          // {
+          //   minWidth: 120,
+          //   prop: 'packingUnit',
+          //   align: 'center',
+          //   label: '包装单位',
+          //   showOverflowTooltip: true
+          // },
+        ]
+      };
+    },
+
+    methods: {
+      async init(row, type, isPage) {
+        this.editRepairNotesDialog = true;
+        this.activeComp = 'main';
+
+        this.type = type;
+        this.title = type == 'add' ? '新增' : type == 'edit' ? '编辑' : '详情';
+        if (isPage) {
+          this.$nextTick(() => {
+            this.changeSelect(row);
+          });
+          return;
+        }
+        if (row?.id) {
+          this.getDetail(row);
+        }
+      },
+      async getDetail(row) {
+        this.form = await getById(row.id);
+      },
+      handleTag(val) {
+        this.activeComp = val;
+        if (val == 'store') {
+          this.$nextTick(() => {
+            this.$refs.innerBoundDetailsRef._getInfo(this.form.code);
+          });
+        }
+      },
+      changeSelect(row) {
+        this.form.sparePartsApplyCode = row.code;
+        this.form.sparePartsApplyId = row.id;
+        this.form.workOrderId = row.repairId;
+
+        this.openOutbound(row);
+      },
+      del(index) {
+        this.form.detailList.splice(index, 1);
+      },
+      openOutbound(row) {
+        this.outboundDetailsDialogFlag = true;
+        if (!row.code) {
+          this.$message.warning('请选择配件申请单');
+
+          return;
+        }
+        this.$nextTick(() => {
+          this.$refs.outboundDetailsDialogRef.init(row);
+        });
+      },
+      saveDate(list) {
+        this.form.detailList = list.map((item) => {
+          item.id = '';
+          return item;
+        });
+        console.log(list);
+      },
+
+      handleClose() {
+        this.editRepairNotesDialog = false;
+        this.form = {
+          ...defForm
+        };
+      },
+      async save() {
+        if (this.form.detailList.length == 0) {
+          this.$message.warning('请至少添加一条归还配件明细');
+          return;
+        }
+        this.$refs.recyleFormRef.validate(async (valid) => {
+          if (valid) {
+            const requestName = this.type == 'add' ? save : update;
+            const res = await requestName(this.form);
+            if (res) {
+              this.$message.success('操作成功');
+              this.handleClose();
+              this.$emit('refresh');
+            }
+          }
+        });
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  .device_name {
+    .el-select-dropdown__wrap {
+      .el-select-dropdown__item {
+        padding: 0 !important;
+      }
+    }
+
+    .option_ {
+      width: 100%;
+      padding: 0 20px;
+    }
+  }
+</style>

+ 60 - 0
src/views/salesServiceManagement/return/component/search.vue

@@ -0,0 +1,60 @@
+<!-- 搜索表单 -->
+<template>
+  <seekPage :seekList="seekList" :formLength="3" @search="search"></seekPage>
+</template>
+<script>
+  export default {
+    data() {
+      return {};
+    },
+    props: {
+      user: {
+        type: 'String',
+        default: ''
+      }
+    },
+    computed: {
+      // 表格列配置
+      seekList() {
+        return [
+          {
+            label: '编码:',
+            value: 'code',
+            type: 'input',
+            placeholder: ''
+          },
+          {
+            label: '名称:',
+            value: 'name',
+            type: 'input',
+            placeholder: ''
+          },
+          {
+            label: '配件申请单编码:',
+            value: 'sparePartsApplyCode',
+            type: 'input',
+            placeholder: ''
+          },
+
+          {
+            label: '创建时间:',
+            value: 'createTime',
+            type: 'date',
+            dateType: 'datetimerange',
+            placeholder: '',
+            width: 380,
+            valueAr: ['endTime', 'endTime']
+          }
+        ];
+      }
+    },
+    methods: {
+      /* 搜索 */
+      search(e) {
+        this.$emit('search', {
+          ...e
+        });
+      }
+    }
+  };
+</script>

+ 247 - 0
src/views/salesServiceManagement/return/index.vue

@@ -0,0 +1,247 @@
+<template>
+  <div class="ele-body">
+    <el-card shadow="never" v-loading="loading">
+      <search class="seep-search" user="recycleName" @search="reload"></search>
+      <!-- 数据表格 -->
+      <ele-pro-table
+        ref="table"
+        :columns="columns"
+        :datasource="datasource"
+        cache-key="systemRoleTable"
+        :pageSize="20"
+      >
+        <!-- 表头工具栏 -->
+        <template v-slot:toolbar>
+          <el-button
+            size="small"
+            type="primary"
+            icon="el-icon-plus"
+            class="ele-btn-icon"
+            @click="openEdit('', 'add')"
+            v-if="$hasPermission('eom:aftersalesaccessoryapply:save')"
+            >新建</el-button
+          >
+        </template>
+        <template v-slot:code="{ row }">
+          <el-link
+            type="primary"
+            :underline="false"
+            @click="openEdit(row, 'view')"
+            >{{ row.code }}</el-link
+          >
+        </template>
+        <template v-slot:action="{ row }">
+          <el-link
+            v-if="row.approvalStatus != 2 && row.approvalStatus != 1"
+            type="primary"
+            :underline="false"
+            @click="submit(row)"
+            >提交</el-link
+          >
+          <el-link
+            v-if="row.approvalStatus != 2 && row.approvalStatus != 1"
+            type="primary"
+            :underline="false"
+            @click="openEdit(row, 'edit')"
+            >修改</el-link
+          >
+          <el-popconfirm
+            class="ele-action"
+            title="确定要删除此条数据吗?"
+            @confirm="handleRemove(row)"
+          >
+            <template v-slot:reference>
+              <el-link
+                v-if="row.approvalStatus != 2 && row.approvalStatus != 1"
+                type="danger"
+                icon="el-icon-delete"
+                :underline="false"
+                >删除</el-link
+              >
+            </template>
+          </el-popconfirm>
+        </template>
+      </ele-pro-table>
+    </el-card>
+    <recycleDialog ref="recycleRef" @refresh="reload" />
+    <process-submit-dialog
+      :isNotNeedProcess="false"
+      :processSubmitDialogFlag.sync="processSubmitDialogFlag"
+      v-if="processSubmitDialogFlag"
+      ref="processSubmitDialogRef"
+      @reload="reload"
+    ></process-submit-dialog>
+  </div>
+</template>
+
+<script>
+  import recycleDialog from './component/recycleDialog.vue';
+  import search from './component/search.vue';
+  import {
+    getPage,
+    deleteList,
+    getById
+  } from '@/api/salesServiceManagement/return';
+  import processSubmitDialog from '@/BIZComponents/processSubmitDialog/processSubmitDialog.vue';
+  import { getWarehouseListByIds } from '@/api/purchasingManage/returnGoods';
+
+  export default {
+    components: {
+      search,
+      recycleDialog,
+      processSubmitDialog
+    },
+    data() {
+      return {
+        // 加载状态
+        loading: false,
+        processSubmitDialogFlag: false
+      };
+    },
+    computed: {
+      columns() {
+        return [
+          {
+            columnKey: 'index',
+            label: '序号',
+            type: 'index',
+            width: 55,
+            align: 'center',
+            showOverflowTooltip: true,
+            fixed: 'left'
+          },
+          {
+            slot: 'code',
+            prop: 'code',
+            label: '编码',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'name',
+            label: '名称',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'sparePartsApplyCode',
+            label: '配件申请单',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'categoryName',
+            label: '物品名称',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (row) => {
+              if (!row.details) return '';
+              let str = '';
+              row.details.map((el, idx) => {
+                if (idx + 1 == row.details.length) {
+                  str += el.categoryName;
+                } else {
+                  str = str + '' + el.categoryName + ',';
+                }
+              });
+              return str;
+            }
+          },
+          {
+            prop: 'approvalStatus',
+            label: '审核状态',
+            align: 'center',
+            showOverflowTooltip: true,
+            formatter: (_row, _column, cellValue) => {
+              return cellValue == 1
+                ? '审核中'
+                : cellValue == 2
+                ? '审核通过'
+                : cellValue == 3
+                ? '审核不通过'
+                : '未提交';
+            }
+          },
+          {
+            prop: 'createTime',
+            label: '创建时间',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            prop: 'remark',
+            label: '备注',
+            align: 'center',
+            showOverflowTooltip: true
+          },
+          {
+            columnKey: 'action',
+            slot: 'action',
+            label: '操作',
+            align: 'center',
+            width: 180,
+            resizable: false,
+            showOverflowTooltip: true
+          }
+        ];
+      }
+    },
+    created() {},
+    methods: {
+      /* 表格数据源 */
+      async datasource({ page, limit, where, order }) {
+        return getPage({ pageNum: page, size: limit, ...where });
+      },
+      /* 刷新表格 */
+      reload(where) {
+        this.$refs.table.reload({ page: 1, where });
+      },
+      handleRemove(row) {
+        deleteList([row.id]).then((res) => {
+          if (res) {
+            this.$message.success('操作成功!');
+            this.reload();
+          }
+        });
+      },
+      openEdit(row, type) {
+        this.$refs.recycleRef.init(row, type);
+      },
+      async submit(res) {
+        const data = await getById(res.id);
+        let storemanIds = '';
+        let ids = data.detailList.map((item) => item.warehouseId);
+        let warehouseList = await getWarehouseListByIds(ids || []);
+        storemanIds = warehouseList.map((item) => item.ownerId);
+        this.processSubmitDialogFlag = true;
+
+        this.$nextTick(() => {
+          let params = {
+            businessId: res.id,
+            businessKey: 'after_sale_return_accessories',
+            formCreateUserId: res.createUserId,
+            variables: {
+              businessCode: res.code,
+              businessName: res.name,
+              businessType: '售后配件归还入库',
+              storemanIds: storemanIds.toString()
+            }
+          };
+
+          this.$refs.processSubmitDialogRef.init(params);
+        });
+      }
+    }
+  };
+</script>
+
+<style lang="scss" scoped>
+  ::v-deep .el-input__inner::placeholder {
+    font-size: 13px;
+  }
+  ::v-deep .seep-search {
+    .el-input__inner {
+      padding: 0 5px 0 10px;
+    }
+  }
+</style>