Pārlūkot izejas kodu

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

liujt 8 mēneši atpakaļ
vecāks
revīzija
178de5044f

+ 9 - 0
src/api/salesServiceManagement/index.js

@@ -485,3 +485,12 @@ export async function costDelete(data) {
   }
   return Promise.reject(new Error(res.data.message));
 }
+// 售后服务管理 派车管理
+
+export async function pageByDispatchRecord(params) {
+  const res = await request.get(`/eom/afterSalesReport/pageByDispatchRecord`, { params });
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 12 - 0
src/api/system/dictionary-data/index.js

@@ -86,3 +86,15 @@ export async function removeDictionaryDataBatch (data) {
   }
   return Promise.reject(new Error(res.data.message));
 }
+
+/**
+ * 查询机构列表
+ * @param params 查询条件
+ */
+export async function listOrganizations (params) {
+  const res = await request.get('/main/group/getGroupList', params);
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}

+ 41 - 32
src/views/salesServiceManagement/components/processSubmitDialog/processSubmitDialog.vue

@@ -11,9 +11,7 @@
     :maxable="true"
     :resizable="true"
   >
-    <!-- 核心流程布局:表单区 + 流程选择区 + 切换按钮 -->
     <div style="display: flex; height: 100%; justify-content: space-between">
-      <!-- 左侧表单区(保留原表单结构) -->
       <div class="form-box">
         <fm-generate-form
           :data="formSchema"
@@ -24,7 +22,6 @@
         ></fm-generate-form>
       </div>
 
-      <!-- 中间流程区切换按钮 -->
       <div
         style="
           align-self: center;
@@ -36,16 +33,12 @@
         @click="() => (isRight = !isRight)"
       >
         <span
-          style="
-            align-self: center;
-            transform: scale(1.5);
-          "
+          style="align-self: center; transform: scale(1.5)"
           :class="isRight ? 'el-icon-caret-left' : 'el-icon-caret-right'"
         ></span>
         <span style="writing-mode: vertical-rl">选择流程</span>
       </div>
 
-      <!-- 右侧流程选择核心区(流程分类、发起流程、执行人、流程图) -->
       <div style="flex: 1" v-if="isRight">
         <el-form
           ref="processForm"
@@ -53,7 +46,6 @@
           :model="form"
           label-width="80px"
         >
-          <!-- 流程分类 + 发起流程 -->
           <el-row>
             <el-col :span="12">
               <el-form-item label="流程分类">
@@ -91,7 +83,6 @@
             </el-col>
           </el-row>
 
-          <!-- 流程名称 + 流程标识 -->
           <el-row>
             <el-col :span="12">
               <el-form-item label="流程名称">
@@ -105,7 +96,6 @@
             </el-col>
           </el-row>
 
-          <!-- 流程执行人表格 + 流程图 -->
           <headerTitle
             title="流程执行人/流程图"
             style="margin-top: 30px"
@@ -148,7 +138,11 @@
                 </div>
                 <el-tag
                   size="medium"
-                  v-if="scope.row.type === 60 || scope.row.type === 70 || scope.row.type === 80"
+                  v-if="
+                    scope.row.type === 60 ||
+                    scope.row.type === 70 ||
+                    scope.row.type === 80
+                  "
                 >
                   {{ getAssignRuleOptionName(scope.row) }}
                 </el-tag>
@@ -194,7 +188,6 @@ import { topLevel1, topLevel2, topLevel3 } from '@/enum/dict';
 import { getToken } from '@/utils/token-util';
 import { mapGetters } from 'vuex';
 
-
 export default {
   name: 'processSubmitDialog',
   mixins: [dictMixins],
@@ -317,7 +310,7 @@ export default {
         processTypeId
       });
       // 过滤出有流程定义的流程(排除无效数据)
-      this.processList = list.filter(item => item.processDefinition);
+      this.processList = list.filter((item) => item.processDefinition);
     },
 
     /**
@@ -327,7 +320,8 @@ export default {
       if (!val) return;
 
       // 找到当前选中的流程信息
-      const selectedProcess = this.processList.find(item => item.id === val) || {};
+      const selectedProcess =
+        this.processList.find((item) => item.id === val) || {};
       const processDef = selectedProcess.processDefinition || {};
 
       // 更新流程基础信息
@@ -366,31 +360,39 @@ export default {
     getAssignRuleOptionName(row, option) {
       // 角色类型(10)
       if (row.type === 10) {
-        const role = this.roleOptions.find(item => item.id === option);
+        const role = this.roleOptions.find((item) => item.id === option);
         return role?.name || `未知角色(${option})`;
       }
       // 部门类型(20/21)
       else if (row.type === 20 || row.type === 21) {
-        const dept = this.deptOptions.find(item => item.id === option);
+        const dept = this.deptOptions.find((item) => item.id === option);
         return dept?.name || `未知部门(${option})`;
       }
       // 工种类型(22)
       else if (row.type === 22) {
-        return this.getDictV(this.dictEnum['工种类型'], option + '') || `未知工种(${option})`;
+        return (
+          this.getDictV(this.dictEnum['工种类型'], option + '') ||
+          `未知工种(${option})`
+        );
       }
       // 用户类型(30/31/32)
       else if (row.type === 30 || row.type === 31 || row.type === 32) {
-        const user = this.userOptions.find(item => item.id === option);
+        const user = this.userOptions.find((item) => item.id === option);
         return user?.nickname || user?.name || `未知用户(${option})`;
       }
       // 用户组类型(40)
       else if (row.type === 40) {
-        const group = this.userGroupOptions.find(item => item.id === option);
+        const group = this.userGroupOptions.find((item) => item.id === option);
         return group?.name || `未知用户组(${option})`;
       }
       // 自定义脚本类型(50)
       else if (row.type === 50) {
-        return this.getDictV(this.dictEnum['工作流任务分配自定义脚本'], option + '') || `未知脚本(${option})`;
+        return (
+          this.getDictV(
+            this.dictEnum['工作流任务分配自定义脚本'],
+            option + ''
+          ) || `未知脚本(${option})`
+        );
       }
       // 变量类型(60)
       else if (row.type === 60) {
@@ -400,10 +402,16 @@ export default {
       else if (row.type === 70) {
         const data = JSON.parse(row.variableName || '{}');
         const levelList = data.direction === 1 ? topLevel2 : topLevel1;
-        return levelList.find(item => item.value === data.topLevel)?.label || '未知层级';
+        return (
+          levelList.find((item) => item.value === data.topLevel)?.label ||
+          '未知层级'
+        );
       } else if (row.type === 80) {
         const data = JSON.parse(row.variableName || '{}');
-        return topLevel3.find(item => item.value === data.topLevel)?.label || '未知层级';
+        return (
+          topLevel3.find((item) => item.value === data.topLevel)?.label ||
+          '未知层级'
+        );
       }
       // 默认值
       return `未知类型(${option || '无'})`;
@@ -414,7 +422,9 @@ export default {
      */
     getDictV(dictCode, val) {
       if (!this.dictList[dictCode]) return '';
-      return this.dictList[dictCode].find(item => item.value === val)?.label || '';
+      return (
+        this.dictList[dictCode].find((item) => item.value === val)?.label || ''
+      );
     },
 
     /**
@@ -422,7 +432,7 @@ export default {
      */
     async getDictList(dictCode) {
       const { data: res } = await getByCode(dictCode);
-      this.dictList[dictCode] = res.map(item => {
+      this.dictList[dictCode] = res.map((item) => {
         const keys = Object.keys(item);
         return {
           value: keys[0],
@@ -432,24 +442,23 @@ export default {
     },
 
     generateFormValid(validate = true) {
-      return this.$refs.generateForm.getData(validate).then(data => data);
+      return this.$refs.generateForm.getData(validate).then((data) => data);
     },
 
-        async submit() {
+    async submit() {
       try {
         this.form.valueJson = await this.generateFormValid();
 
         const submitData = {
-          ...this.form, 
-          ...this.carByTemplate, 
-          processType: '1', 
-          variables: { ...this.form.valueJson } 
+          ...this.form,
+          ...this.carByTemplate,
+          processType: '1',
+          variables: { ...this.form.valueJson }
         };
 
         this.$emit('formSubmit', submitData);
 
         this.cancel();
-
       } catch (error) {
         console.error('表单验证失败:', error);
         this.$message.warning('表单验证失败,请检查填写内容');

+ 5 - 0
src/views/salesServiceManagement/demandList/components/addDialog.vue

@@ -213,10 +213,15 @@ export default {
     async handleParameter() {
       let data = this.$refs.infoRef.getValue();
       let sparePartsData = this.$refs.infoRef.getSpareInfoData();
+      console.log(sparePartsData.length);
       if (!data.contactInfoVOS?.length) {
         this.$message.warning('联系人信息至少有1条');
         return false;
       }
+      if (data.part === 1 && sparePartsData.length === 0) {
+        this.$message.warning('请添加配件信息');
+        return false;
+      }
       try {
         let valid = await this.$refs.infoRef.getValidate();
         let expectedTime = data.expectedTime

+ 105 - 35
src/views/salesServiceManagement/vehiclerecord/components/search.vue

@@ -1,49 +1,119 @@
-<!-- 搜索表单 -->
 <template>
-  <seekPage :seekList="seekList" :formLength="3" @search="search"></seekPage>
+  <el-form :model="form" label-width="100px" class="search-form">
+    <el-form-item label="关键字:">
+      <el-input v-model="form.keyWord" placeholder="请输入"></el-input>
+    </el-form-item>
+
+    <el-form-item label="所属部门:">
+      <ele-tree-select
+        v-model="form.deptId"
+        :data="deptTreeData"
+        label-key="name"
+        value-key="id"
+        clearable
+        default-expand-all
+        placeholder="请选择"
+        ref="deptTreeSelect"
+        @change="handleDeptChange"
+      />
+    </el-form-item>
+
+    <el-form-item label="派车类型:">
+      <el-select v-model="form.pieCarType" placeholder="请选择">
+        <el-option
+          v-for="item in pietypeList"
+          :key="item.value"
+          :label="item.label"
+          :value="item.value"
+        ></el-option>
+      </el-select>
+    </el-form-item>
+
+    <el-form-item>
+      <el-button type="primary" @click="search"> 搜索 </el-button>
+      <el-button @click="resetForm"> 重置 </el-button>
+    </el-form-item>
+  </el-form>
 </template>
+
 <script>
+import { listOrganizations } from '@/api/system/organization';
+import { getByCode } from '@/api/system/dictionary-data';
+
 export default {
   data() {
     return {
+      form: {
+        keyWord: '',
+        deptId: '',
+        pieCarType: ''
+      },
+      pietypeList: [],
+      deptTreeData: []
     };
   },
-  props: {},
-  computed: {
-    // 表格列配置
-    seekList() {
-      return [
-        {
-          label: '关键字:',
-          value: 'keyWord',
-          type: 'input',
-          placeholder: '请输入',
-          class:'123'
-        },
-        {
-          label: '所属部门:',
-          value: 'deptId',
-          type: 'select',
-          planList: this.serviceList,
-          placeholder: '请选择'
-        },
-        {
-          label: '派车类型:',
-          value: 'responseSpeed',
-          type: 'select',
-          planList: this.serviceList,
-          placeholder: '请选择'
-        },
-      ];
-    }
+
+  created() {
+    this.getpietypeCode('pie_car_type');
   },
+
   methods: {
-    /* 搜索 */
-    search(e) {
-      this.$emit('search', {
-        ...e
-      });
+    async getpietypeCode(code) {
+      try {
+        const res = await getByCode(code);
+        if (res.code == 0) {
+          let list = Object.values(res.data).map((el) => {
+            let k = Object.keys(el)[0];
+            let v = Object.values(el)[0];
+            return { label: v, value: k };
+          });
+          this.pietypeList = list;
+
+          const deptRes = await listOrganizations();
+          this.deptTreeData = this.$util.toTreeData({
+            data: deptRes || [],
+            idField: 'id',
+            parentIdField: 'parentId'
+          });
+
+          this.$emit('pass-pietype-list', list, deptRes);
+        }
+      } catch (err) {
+        this.$message.error(err.message);
+      }
+    },
+
+    search() {
+      this.$emit('search', { ...this.form });
+    },
+
+    resetForm() {
+      this.form = {
+        keyWord: '',
+        deptId: '',
+        pieCarType: ''
+      };
+      this.search()
+    },
+
+    handleDeptChange(val, node) {
+      console.log(val,node)
     }
   }
 };
 </script>
+
+<style scoped>
+/* 原有样式保留 */
+.search-form {
+  margin-bottom: 20px;
+  display: flex;
+  align-items: center;
+  gap: 20px;
+  flex-wrap: wrap;
+}
+
+.search-form /deep/ .el-form-item {
+  margin-bottom: 0;
+}
+</style>

+ 192 - 136
src/views/salesServiceManagement/vehiclerecord/index.vue

@@ -1,7 +1,11 @@
 <template>
   <div class="ele-body">
     <el-card shadow="never" v-loading="loading">
-      <search class="seep-search" @search="reload"></search>
+      <search
+        class="seep-search"
+        @search="reload"
+        @pass-pietype-list="handlePietypeList"
+      ></search>
       <!-- 数据表格 -->
       <ele-pro-table
         ref="table"
@@ -12,154 +16,206 @@
       >
         <!-- 表头工具栏 -->
         <template v-slot:toolbar></template>
-        <!-- <template v-slot:code="{ row }"
-          ><el-link
-            type="primary"
-            :underline="false"
-            @click="goDetail(row, 'view')"
-          >
-            {{ row.code }}
-          </el-link>
-        </template>-->
-        <!-- 操作列 -->
-        <!-- <template v-slot:action="{ row }"></template> -->
       </ele-pro-table>
     </el-card>
   </div>
 </template>
 
 <script>
-  import search from './components/search.vue';
-  import { evaluatePage } from '@/api/salesServiceManagement/index';
+import search from './components/search.vue';
+import { pageByDispatchRecord } from '@/api/salesServiceManagement/index';
+import dictMixins from '@/mixins/dictMixins';
 
-  import dictMixins from '@/mixins/dictMixins';
-  export default {
-    mixins: [dictMixins],
-    components: {
-      search
-    },
-    data() {
-      return {
-        evaluateStatus: {
-          1: '非常不满意',
-          2: '不满意',
-          3: '一般',
-          4: '满意',
-          5: '非常满意'
+export default {
+  mixins: [dictMixins],
+  components: {
+    search
+  },
+  data() {
+    return {
+      pietypeList: [],
+      deptResList: [], // 部门
+      deptIdToNameMap: {},
+      // 加载状态
+      loading: false
+    };
+  },
+  computed: {
+    columns() {
+      return [
+        {
+          columnKey: 'index',
+          label: '序号',
+          type: 'index',
+          width: 55,
+          align: 'center',
+          showOverflowTooltip: true,
+          fixed: 'left'
         },
-        // 表格列配置
-
-        // 加载状态
-        loading: 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: 'workCode',
-            label: '工单编码',
-            align: 'center',
-            showOverflowTooltip: true
-          },
-          {
-            prop: 'contactName',
-            label: '客户名称',
-            align: 'center',
-            showOverflowTooltip: true
-          },
-          {
-            prop: 'contactCode',
-            label: '客户编码',
-            align: 'center',
-            showOverflowTooltip: true
-          },
-          {
-            prop: 'attitudeRating',
-            label: '服务态度评分',
-            align: 'center',
-            showOverflowTooltip: true,
-            formatter: (row) => {
-              return this.evaluateStatus[row.attitudeRating];
-            }
-          },
-          {
-            prop: 'responseSpeed',
-            label: '响应速度评分',
-            align: 'center',
-            showOverflowTooltip: true,
-            formatter: (row) => {
-              return this.evaluateStatus[row.responseSpeed];
-            }
-          },
-          {
-            prop: 'serviceRating',
-            label: '整体满意度',
-            align: 'center',
-            showOverflowTooltip: true,
-            formatter: (row) => {
-              return this.evaluateStatus[row.serviceRating];
-            }
-          },
-          {
-            prop: 'evaluationContent',
-            label: '评价内容',
-            align: 'center',
-            showOverflowTooltip: true
-          },
-
-          {
-            prop: 'createUserName',
-            label: '创建人',
-            align: 'center',
-            showOverflowTooltip: true
-          },
-          {
-            prop: 'createTime',
-            label: '创建时间',
-            align: 'center',
-            showOverflowTooltip: true
+        {
+          slot: 'demandCode',
+          prop: 'demandCode',
+          label: '售后需求编码',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200
+        },
+        {
+          prop: 'pieCarType',
+          label: '派车类型',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+          formatter: (row) => this.getPieTypeLabel(row.pieCarType)
+        },
+        {
+          prop: 'createUserName',
+          label: '申请人',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+        },
+        {
+          prop: 'department',
+          label: '所属部门',
+          align: 'center',
+          minWidth: 300,
+          showOverflowTooltip: true,
+          formatter: (row) => {
+            const deptIds = row.valueJson?.department || [];
+            return this.getDeptNames(deptIds);
           }
-        ];
+        },
+        {
+          prop: 'subject_matter',
+          label: '出差事由',
+          align: 'center',
+          minWidth: 200,
+          showOverflowTooltip: true,
+          formatter: (row) => row.valueJson?.subject_matter || ''
+        },
+        {
+          prop: 'estimated_duration',
+          label: '预计出差时长',
+          align: 'center',
+          minWidth: 200,
+          showOverflowTooltip: true,
+          formatter: (row) => row.valueJson?.estimated_duration || ''
+        },
+        {
+          prop: 'travel_time',
+          label: '出差时间',
+          align: 'center',
+          minWidth: 200,
+          showOverflowTooltip: true,
+          formatter: (row) => row.valueJson?.travel_time || ''
+        },
+        {
+          prop: 'return_time',
+          label: '返回时间',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+          formatter: (row) => row.valueJson?.return_time || ''
+        },
+        {
+          prop: 'car_number',
+          label: '车牌号',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+          formatter: (row) => row.valueJson?.car_number || ''
+        },
+        {
+          prop: 'vehicle_user',
+          label: '用车人',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+          formatter: (row) => row.valueJson?.vehicle_user || ''
+        },
+        {
+          prop: 'vehicle_mileage',
+          label: '出差里程数',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+          formatter: (row) => row.valueJson?.vehicle_mileage || ''
+        },
+        {
+          prop: 'return_mileage_to_factory',
+          label: '返厂里程数',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+          formatter: (row) => row.valueJson?.return_mileage_to_factory || ''
+        },
+        {
+          prop: 'status',
+          label: '状态',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+        },
+        {
+          prop: 'createTime',
+          label: '创建时间',
+          align: 'center',
+          showOverflowTooltip: true,
+          minWidth: 200,
+        }
+      ];
+    }
+  },
+  methods: {
+    getDeptNames(deptIdArr) {
+      if (!deptIdArr || !Array.isArray(deptIdArr) || deptIdArr.length === 0) {
+        return "-";
       }
+      const deptNames = deptIdArr.map(deptId => 
+        this.deptIdToNameMap[deptId] || ''
+      );
+      return deptNames.join("、");
     },
-    created() {},
-    methods: {
-      /* 表格数据源 */
-      datasource({ page, limit, where, order }) {
-        return evaluatePage({ pageNum: page, size: limit, ...where });
-      },
-      /* 刷新表格 */
-      reload(where) {
-        this.$refs.table.reload({ page: 1, where });
-      }
+    getPieTypeLabel(value) {
+      if (!value) return '';
+      const target = this.pietypeList.find(item => item.value === String(value));
+      return target ? target.label : value;
+    },
+    handlePietypeList(list, deptRes) {
+      this.pietypeList = list;
+      this.deptResList = deptRes;
+      this.deptIdToNameMap = deptRes.reduce((map, dept) => {
+        map[dept.id] = dept.name;
+        return map;
+      }, {});
+    },
+    datasource({ page, limit, where }) {
+      const dataPromise = pageByDispatchRecord({
+        pageNum: page,
+        size: limit,
+        ...where
+      });
+      dataPromise
+        .then(response => console.log(response))
+        .catch(error => console.error('获取数据失败:', error));
+      return dataPromise;
+    },
+    /* 刷新表格 */
+    reload(where) {
+      this.$refs.table.reload({ page: 1, where });
     }
-  };
+  }
+};
 </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;
-    }
+::v-deep .el-input__inner::placeholder {
+  font-size: 13px;
+}
+::v-deep .seep-search {
+  .el-input__inner {
+    padding: 0 5px 0 10px;
   }
-</style>
+}
+</style>