Ver Fonte

✨ feat<任务列表>: 添加批量更新功能

xinyan há 9 meses atrás
pai
commit
5f15e11d82

+ 9 - 1
src/views/reportManage/TaskManage/api.ts

@@ -1,7 +1,7 @@
 import { request } from '/@/utils/service';
 import { UserPageQuery } from '@fast-crud/fast-crud';
 
-// 任务列表
+// 任务列表接口
 export function postCreateTask(body) {
   return request({
     url: '/api/report_manage/summary-tasks/',
@@ -42,6 +42,14 @@ export function postUpdateTask(body) {
   });
 }
 
+export function postUpdateManyTask(body) {
+  return request({
+    url: `/api/report_manage/summary-tasks/update/many/`,
+    method: 'POST',
+    data: body,
+  });
+}
+
 export function postUpdateTaskStatus(query, body) {
   return request({
     url: `/api/report_manage/summary-tasks/${body.id}/`,

+ 178 - 0
src/views/reportManage/TaskManage/components/createTaskDialog.vue

@@ -0,0 +1,178 @@
+<script lang="ts" setup>/**
+ * @Name: createTaskDialog.vue
+ * @Description: 创建任务弹窗
+ * @Author: xinyan
+ */
+import { reactive, ref } from 'vue';
+import { ComponentSize, ElMessage, FormInstance, FormRules } from 'element-plus';
+
+//表单
+interface taskRuleForm {
+  number: string;
+  name: string;
+  country: string;
+  brand: string;
+  operation: string[];
+  operater: string[];
+  currency: string;
+  currencyCodePlatform: string;
+  line: string;
+  ipaddress: string;
+  company: string;
+  platform: string;
+}
+
+const formSize = ref<ComponentSize>('default');
+const dialogFormVisible = ref(false);
+const taskRuleFormRef = ref<FormInstance>();
+const taskRuleForm = reactive({
+  number: '',
+  name: '',
+  country: '',
+  brand: '',
+  operation: [],
+  operater: [],
+  currency: '',
+  currencyCodePlatform: '',
+});
+const resetForm = (formEl: FormInstance | undefined) => {
+  if (!formEl) return;
+  formEl.resetFields();
+};
+const rules = reactive<FormRules>({
+  number: [{ required: true, message: '请输入平台编号', trigger: 'blur' },],
+  name: [{ required: true, message: '请输入平台名称', trigger: 'blur' }],
+  country: [{ required: true, message: '请输入国家', trigger: 'blur' }],
+  brand: [{ required: true, message: '请输入品牌', trigger: 'blur' }],
+  operation: [{ required: true, message: '请选择填写人', trigger: 'change' }],
+  operater: [{ required: true, message: '请输入运营', trigger: 'change' }],
+  currency: [{ required: true, message: '请输入回款/余额币种', trigger: 'blur' }],
+  currencyCodePlatform: [{ required: true, message: '请输入平台货币', trigger: 'blur' }],
+  line: [{ required: true, message: '请输入线路', trigger: 'blur' }],
+  ipaddress: [{ required: true, message: '请输入IP地址', trigger: 'blur' }],
+  company: [{ required: true, message: '请输入注册公司', trigger: 'blur' }],
+  platform: [{ required: true, message: '请输入平台', trigger: 'blur' }],
+});
+
+function handleClose(done: Function) {
+  if (taskRuleFormRef.value) taskRuleFormRef.value.resetFields();
+  done();
+}
+
+const submitForm = async (formEl) => {
+  if (!formEl) return;
+  await formEl.validate(async (valid, fields) => {
+    if (valid) {
+      const isDuplicate = allTasks.some(task => String(task.platformNumber) === String(taskRuleForm.number));
+      if (isDuplicate) {
+        await ElMessage({ message: '平台编号已存在,请重新输入', type: 'warning' });
+        return;
+      }
+
+      if (!currencyList.value.includes(taskRuleForm.currency)) {
+        await ElMessage({ message: '回款币种无效,请重新选择', type: 'warning' });
+        return;
+      }
+
+      if (!currencyList.value.includes(taskRuleForm.currencyCodePlatform)) {
+        await ElMessage({ message: '回款/余额币种无效,请重新选择', type: 'warning' });
+        return;
+      }
+
+      await createTask();
+      taskRuleFormRef.value.resetFields();
+    }
+  });
+};
+
+</script>
+
+<template>
+  <el-dialog v-model="dialogFormVisible" :before-close="handleClose" style="border-radius: 10px;" title="新建任务"
+             width="500">
+    <el-form
+        ref="taskRuleFormRef"
+        :model="taskRuleForm"
+        :rules="rules"
+        :size="formSize"
+        class="demo-taskRuleForm"
+        label-width="auto"
+        status-icon
+        style="max-width: 600px">
+      <el-form-item label="平台编号" prop="number">
+        <el-input v-model="taskRuleForm.number" placeholder="请输入平台编号" />
+      </el-form-item>
+      <el-form-item label="平台名称" prop="name">
+        <el-input v-model="taskRuleForm.name" placeholder="请输入平台名称" />
+      </el-form-item>
+      <el-form-item label="国家" prop="country">
+        <el-input v-model="taskRuleForm.country" placeholder="请输入国家" />
+      </el-form-item>
+      <el-form-item label="品牌" prop="brand">
+        <el-input v-model="taskRuleForm.brand" placeholder="请输入品牌" />
+      </el-form-item>
+      <el-form-item label="录入人员" prop="operation">
+        <el-select v-model="taskRuleForm.operation" collapse-tags collapse-tags-tooltip multiple
+                   placeholder="请选择录入人员">
+          <el-option v-for="item in operationList" :key="item.value" :label="item.label"
+                     :value="item.value"></el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="运营" prop="operater">
+        <el-input v-model="taskRuleForm.operater" placeholder="请输入运营" />
+      </el-form-item>
+      <el-form-item label="平台币种" prop="currency">
+        <el-autocomplete
+            v-model="taskRuleForm.currency"
+            :debounce="100"
+            :fetch-suggestions="querySearch"
+            :trigger-on-focus="false"
+            clearable
+            placeholder="请输入回款币种"
+            @select="handleSelect"
+        >
+          <template v-slot="{ item }">
+            <div>{{ item }}</div> <!-- 确保正确显示每个选项 -->
+          </template>
+        </el-autocomplete>
+      </el-form-item>
+      <el-form-item label="回款/余额币种" prop="currencyCodePlatform">
+        <el-autocomplete
+            v-model="taskRuleForm.currencyCodePlatform"
+            :debounce="100"
+            :fetch-suggestions="querySearch"
+            :trigger-on-focus="false"
+            clearable
+            placeholder="请输入回款/余额币种"
+            @select="handleCurrencyCodePlatformSelect"
+        >
+          <template v-slot="{ item }">
+            <div>{{ item }}</div> <!-- 确保正确显示每个选项 -->
+          </template>
+        </el-autocomplete>
+      </el-form-item>
+      <el-form-item label="线路" prop="line">
+        <el-input v-model="taskRuleForm.line" placeholder="请输入线路" />
+      </el-form-item>
+      <el-form-item label="IP地址" prop="ipaddress">
+        <el-input v-model="taskRuleForm.ipaddress" placeholder="请输入IP地址" />
+      </el-form-item>
+      <el-form-item label="注册公司" prop="company">
+        <el-input v-model="taskRuleForm.company" placeholder="请输入注册公司" />
+      </el-form-item>
+      <el-form-item label="平台" prop="platform">
+        <el-input v-model="taskRuleForm.platform" placeholder="请输入平台" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="dialogFormVisible = false ;resetForm(taskRuleFormRef)">取消</el-button>
+        <el-button type="primary" @click="submitForm(taskRuleFormRef)"> 确认</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<style scoped>
+
+</style>

+ 85 - 21
src/views/reportManage/TaskManage/index.vue

@@ -9,7 +9,7 @@ import {
   getTasks,
   postCreateTask,
   postDeleteTask,
-  postSendMessage,
+  postSendMessage, postUpdateManyTask,
   postUpdateTask,
   postUpdateTaskStatus
 } from '/src/views/reportManage/TaskManage/api.ts';
@@ -124,10 +124,10 @@ const gridOptions = reactive<VxeGridProps<RowVO>>({
     pageSizes: [10, 20, 30],
   },
   editConfig: {
-    trigger: 'manual',
+    trigger: 'click',
     mode: 'row',
     showStatus: true,
-    autoClear: false,
+    //autoClear: false,
   },
   checkboxConfig: {
     reserve: true,
@@ -149,7 +149,7 @@ const gridOptions = reactive<VxeGridProps<RowVO>>({
       editRender: { autofocus: '.vxe-input--inner' },
       slots: { edit: 'name_edit' },
       align: 'center',
-      minWidth: 150
+      minWidth: 150, isEditing: false
     },
     {
       field: 'country',
@@ -171,7 +171,9 @@ const gridOptions = reactive<VxeGridProps<RowVO>>({
       field: 'user_name',
       title: '填写人',
       editRender: {},
-      slots: { edit: 'operation_edit' },
+      slots: { edit: 'operation_edit' ,
+        //default: 'operation_default'
+      },
       align: 'center',
       minWidth: 104
     },
@@ -274,30 +276,60 @@ const editRowEvent = (row: RowVO) => {
   const $grid = xGrid.value;
   if ($grid) {
     // 在进入编辑状态前保存原始数据
-    originalDataMap.set(row.id, { ...row });
-    // 初始化 row.user 确保其与 row.user_name 同步
+    //originalDataMap.set(row.id, { ...row });
+    //// 初始化 row.user 确保其与 row.user_name 同步
     if (!row.user || row.user.length === 0) {
-      row.user = operationList.value
-          .filter(op => row.user_name.includes(op.label))
-          .map(op => op.value);
+      row.user = userNameToUser(row.user_name); // 转换 user_name 到 user
     }
+    console.log('row.user',row.user);
     $grid.setEditRow(row);
   }
 };
 
-const clearRowEvent = (row: RowVO) => {
+// 清除编辑状态并保存已编辑的数据
+const clearRowEvent = (row) => {
   const $grid = xGrid.value;
   if ($grid) {
-    const originalData = originalDataMap.get(row.id);
-    if (originalData) {
-      // 恢复原始数据
-      Object.assign(row, originalData);
-      originalDataMap.delete(row.id);
+    // 手动保存当前行的数据
+    const editRecord = $grid.getEditRecord();
+    console.log("1editRecord", editRecord);
+    if (editRecord) {
+      const { row: editedRow } = editRecord;
+      // 更新原始 row 数据,确保编辑的值被保存
+      row.user = editedRow.user;
+      row.user_name = userToUserName(editedRow.user);
     }
+    // 清除编辑状态
     $grid.clearEdit();
   }
 };
 
+async function saveEvent (row) {
+  const $grid = xGrid.value;
+  if ($grid) {
+    try {
+      const { updateRecords } = $grid.getRecordset();
+      updateRecords.forEach(record => {
+        if (!record.user || record.user.length === 0) {
+          record.user = userNameToUser(record.user_name); // 转换 user_name 到 user
+        }
+      });
+
+      await postUpdateManyTask(updateRecords);
+      console.log("=>(index.vue:325) updateRecords", updateRecords);
+      await getTaskList();
+      await VXETable.modal.message({
+        content: `更新 ${updateRecords.length} 条`,
+        status: 'success',
+      });
+
+    } catch (e) {
+      console.log('error',e);
+    }
+
+  }
+}
+
 // 删除任务
 async function deleteTask() {
   const $grid = xGrid.value;
@@ -381,7 +413,6 @@ async function updateRow(row) {
       company: row.company,
       platform: row.platform,
     };
-    //console.log('updatedRowData', updatedRowData);
     try {
       const response = await postUpdateTask(updatedRowData);
       if (response.code === 2000) {
@@ -583,7 +614,34 @@ async function sendMessage(selectedValue: string) {
   } catch (error) {
   }
 }
-
+// 将 user 数组转换为 user_name 字符串
+function userToUserName(user: string[]): string {
+  return operationList.value
+      .filter(op => user.includes(op.value))
+      .map(op => op.label)
+      .join(', ');
+}
+// 将 user_name 字符串转换为 user 数组
+function userNameToUser(user_name: string): string[] {
+  return operationList.value
+      .filter(op => user_name.includes(op.label))
+      .map(op => op.value);
+}
+const handleEditActived = ({ row, column }) => {
+  if (column.property === 'user_name') {
+    if (!row.user || row.user.length === 0) {
+      row.user = userNameToUser(row.user_name); // 转换 user_name 到 user
+    }
+  }
+};
+const handleEditClosed = ({ row, column }) => {
+  if (column.property === 'user_name') {
+    // 将 user 转换为 user_name 并更新 row
+    row.user_name = userToUserName(row.user);
+    // 强制刷新视图
+    $grid.refreshRow(row);
+  }
+};
 onMounted(() => {
   //getTaskList();
   fetchOperationSelect();
@@ -599,7 +657,7 @@ onMounted(() => {
     <el-card class="my-3" shadow="hover">
       <div style="position: relative">
         <vxe-grid ref="xGrid" :cell-style="cellStyle" :header-cell-style="headerCellStyle" stripe v-bind="gridOptions"
-                  v-on="gridEvents">
+                  v-on="gridEvents" @edit-actived="handleEditActived" @edit-closed="handleEditClosed">
           <template #toolbar_buttons>
             <el-button :icon="Plus" plain type="success" @click="dialogFormVisible = true"> 添加任务</el-button>
             <el-dropdown style="padding: 0 10px;" trigger="click">
@@ -618,8 +676,8 @@ onMounted(() => {
                 </el-dropdown-menu>
               </template>
             </el-dropdown>
-            <el-button :disabled="isDeleteDisabled" :icon="Delete" plain type="danger" @click="removeEvent">删除
-            </el-button>
+            <el-button :disabled="isDeleteDisabled" :icon="Delete" plain type="danger" @click="removeEvent">删除</el-button>
+            <el-button :icon="Save" @click="saveEvent">保存</el-button>
           </template>
           <template #toolbar_tools>
             <div class="mx-3.5">
@@ -707,6 +765,12 @@ onMounted(() => {
               </template>
             </el-autocomplete>
           </template>
+          <!--<template #operation_default="{ row }">-->
+          <!--  <vxe-select v-model="row.user_name" multiple>-->
+          <!--    <vxe-option v-for="item in operationList" :key="item.value" :label="item.label"-->
+          <!--                :value="item.value"></vxe-option>-->
+          <!--  </vxe-select>-->
+          <!--</template>-->
         </vxe-grid>
       </div>
     </el-card>