Browse Source

✨ feat<任务列表>: 增加消息通知

xinyan 10 months ago
parent
commit
4aeab49009

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

@@ -74,4 +74,13 @@ export function exportTaskData(query) {
     params: query,
     responseType: 'blob'
   });
+}
+
+export function postSendMessage(query, body) {
+  return request({
+    url: `/api/report_manage/summary-tasks/sendinform/`,
+    method: 'POST',
+    data: body,
+    params: query,
+  });
 }

+ 162 - 79
src/views/reportManage/TaskManage/index.vue

@@ -1,19 +1,25 @@
 <script lang="ts" setup>
 import Selector from '/src/views/reportManage/dataCenter/normalDisplay/components/Selector/index.vue';
-import { ref, reactive, onMounted, nextTick, watch } from 'vue';
-import { VXETable, VxeGridInstance, VxeGridProps, VxeGridListeners } from 'vxe-table';
+import { onMounted, reactive, ref } from 'vue';
+import { VxeGridInstance, VxeGridListeners, VxeGridProps, VXETable } from 'vxe-table';
 import {
+  exportTaskData,
+  getCurrencyCodeSelect,
+  getOperationSelect,
   getTasks,
   postCreateTask,
-  getOperationSelect,
+  postDeleteTask, postSendMessage,
   postUpdateTask,
-  postDeleteTask,
-  getCurrencyCodeSelect, exportTaskData, postUpdateTaskStatus
+  postUpdateTaskStatus
 } from '/src/views/reportManage/TaskManage/api.ts';
 import { ComponentSize, ElMessage, FormInstance, FormRules } from 'element-plus';
-import { Plus, Delete } from '@element-plus/icons-vue';
+import { Delete, Plus } from '@element-plus/icons-vue';
+import { message } from '/@/utils/message';
+import { labelInner } from 'echarts/types/src/label/labelStyle';
+import { dateType } from '/@/views/reportManage/TaskManage/utils/enum';
 
 const selectorRef = ref(null);
+const message = ref('day');
 
 //表单
 interface taskRuleForm {
@@ -47,17 +53,17 @@ const resetForm = (formEl: FormInstance | undefined) => {
   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'}],
-  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'}],
+  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' }],
+  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' }],
 });
 const currencyList = ref([]);
 
@@ -124,47 +130,82 @@ const gridOptions = reactive<VxeGridProps<RowVO>>({
     range: true,
   },
   columns: [
-    {type: 'checkbox', width: 50},
+    { type: 'checkbox', width: 50 },
     {
       field: 'platformNumber',
       title: '平台编号',
-      editRender: {autofocus: '.vxe-input--inner'},
-      slots: {edit: 'number_edit'},
-      minWidth:97
+      editRender: { autofocus: '.vxe-input--inner' },
+      slots: { edit: 'number_edit' },
+      minWidth: 97
     },
     {
       field: 'platformName',
       title: '平台名称',
-      editRender: {autofocus: '.vxe-input--inner'},
-      slots: {edit: 'name_edit'},
+      editRender: { autofocus: '.vxe-input--inner' },
+      slots: { edit: 'name_edit' },
       align: 'center',
       minWidth: 150
     },
     {
       field: 'country',
       title: '国家',
-      editRender: {autofocus: '.vxe-input--inner'},
-      slots: {edit: 'country_edit'},
+      editRender: { autofocus: '.vxe-input--inner' },
+      slots: { edit: 'country_edit' },
       minWidth: 89,
       align: 'center'
     },
-    {field: 'brandName', title: '品牌', editRender: {}, slots: {edit: 'brand_edit'}, align: 'center',minWidth: 89,},
-    {field: 'user_name', title: '运营', editRender: {}, slots: {edit: 'operation_edit'}, align: 'center',minWidth: 89},
-    {field: 'currencyCode', title: '回款币种', editRender: {}, slots: {edit: 'currency_edit'}, align: 'center',minWidth: 89},
+    {
+      field: 'brandName',
+      title: '品牌',
+      editRender: {},
+      slots: { edit: 'brand_edit' },
+      align: 'center',
+      minWidth: 89,
+    },
+    {
+      field: 'user_name',
+      title: '运营',
+      editRender: {},
+      slots: { edit: 'operation_edit' },
+      align: 'center',
+      minWidth: 89
+    },
+    {
+      field: 'currencyCode',
+      title: '回款币种',
+      editRender: {},
+      slots: { edit: 'currency_edit' },
+      align: 'center',
+      minWidth: 89
+    },
     {
       field: 'currencyCodePlatform',
       title: '回款/余额币种',
       editRender: {},
-      slots: {edit: 'currencyCodePlatform_edit'},
+      slots: { edit: 'currencyCodePlatform_edit' },
       minWidth: 130,
       align: 'center'
     },
-    {field: 'line', title: '线路', editRender: {}, slots: {edit: 'line_edit'}, align: 'center',minWidth: 89},
-    {field: 'ipaddress', title: 'IP地址', editRender: {}, slots: {edit: 'ipaddress_edit'}, minWidth: 138},
-    {field: 'company', title: '注册公司', editRender: {}, slots: {edit: 'company_edit'}, align: 'center',minWidth: 89},
-    {field: 'platform', title: '平台', editRender: {}, slots: {edit: 'platform_edit'}, align: 'center',minWidth: 89},
-    {field: 'status', title: '状态',  slots: {default: 'status_default'}, align: 'center',minWidth: 89},
-    {title: '操作', width: 120, slots: {default: 'operate'}},
+    { field: 'line', title: '线路', editRender: {}, slots: { edit: 'line_edit' }, align: 'center', minWidth: 89 },
+    { field: 'ipaddress', title: 'IP地址', editRender: {}, slots: { edit: 'ipaddress_edit' }, minWidth: 138 },
+    {
+      field: 'company',
+      title: '注册公司',
+      editRender: {},
+      slots: { edit: 'company_edit' },
+      align: 'center',
+      minWidth: 89
+    },
+    {
+      field: 'platform',
+      title: '平台',
+      editRender: {},
+      slots: { edit: 'platform_edit' },
+      align: 'center',
+      minWidth: 89
+    },
+    { field: 'status', title: '状态', slots: { default: 'status_default' }, align: 'center', minWidth: 89 },
+    { title: '操作', width: 120, slots: { default: 'operate' } },
   ],
   data: [],
 });
@@ -172,7 +213,7 @@ const gridOptions = reactive<VxeGridProps<RowVO>>({
 const operationList = ref([]);
 
 const gridEvents: VxeGridListeners<RowVO> = {
-  pageChange({currentPage, pageSize}) {
+  pageChange({ currentPage, pageSize }) {
     if (gridOptions.pagerConfig) {
       gridOptions.pagerConfig.currentPage = currentPage;
       gridOptions.pagerConfig.pageSize = pageSize;
@@ -181,19 +222,6 @@ const gridEvents: VxeGridListeners<RowVO> = {
   },
 };
 
-//async function fetchAllTasks(page = 1, limit = 100) {
-//  try {
-//    const response = await getTasks({page, limit});
-//    allTasks = allTasks.concat(response.data);
-//
-//    if (response.data.length === limit) {
-//      await fetchAllTasks(page + 1, limit);
-//    }
-//  } catch (error) {
-//    console.error('Error fetching all tasks:', error);
-//  }
-//}
-
 async function getTaskList(filters = {}) {
   try {
     gridOptions.loading = true;
@@ -204,9 +232,6 @@ async function getTaskList(filters = {}) {
     });
     gridOptions.data = response.data;
     gridOptions.pagerConfig.total = response.total;
-
-    //allTasks = []; // 重置 allTasks
-    //await fetchAllTasks(); // 获取所有任务数据
   } catch (error) {
     console.error('Error fetching task data:', error);
   } finally {
@@ -236,7 +261,7 @@ const editRowEvent = (row: RowVO) => {
   const $grid = xGrid.value;
   if ($grid) {
     // 在进入编辑状态前保存原始数据
-    originalDataMap.set(row.id, {...row});
+    originalDataMap.set(row.id, { ...row });
     // 初始化 row.user 确保其与 row.user_name 同步
     if (!row.user || row.user.length === 0) {
       row.user = operationList.value
@@ -266,7 +291,7 @@ async function deleteTask() {
     const selectRecords = $grid.getCheckboxRecords();
     const selectedIds = selectRecords.map(record => record.id);
     // console.log(selectedIds);
-    const obj = {keys: selectedIds};
+    const obj = { keys: selectedIds };
     try {
       const resp = await postDeleteTask(obj);
       if (resp.code === 2000) {
@@ -301,29 +326,29 @@ const removeEvent = async () => {
         await $grid.removeCheckboxRow();
       }
     } else {
-      await VXETable.modal.message({content: '请选择要删除的数据', status: 'error'});
+      await VXETable.modal.message({ content: '请选择要删除的数据', status: 'error' });
     }
   }
 };
 
 const requiredFields = [
-  {field: 'platformNumber', title: '平台编号'},
-  {field: 'platformName', title: '平台名称'},
-  {field: 'country', title: '国家'},
-  {field: 'brandName', title: '品牌'},
-  {field: 'user', title: '运营'},
-  {field: 'currencyCode', title: '回款币种'},
-  {field: 'currencyCodePlatform', title: '回款/余额币种'},
-  {field: 'line', title: '线路'},
-  {field: 'ipaddress', title: 'IP地址'},
-  {field: 'company', title: '注册公司'},
-  {field: 'platform', title: '平台'},
+  { field: 'platformNumber', title: '平台编号' },
+  { field: 'platformName', title: '平台名称' },
+  { field: 'country', title: '国家' },
+  { field: 'brandName', title: '品牌' },
+  { field: 'user', title: '运营' },
+  { field: 'currencyCode', title: '回款币种' },
+  { field: 'currencyCodePlatform', title: '回款/余额币种' },
+  { field: 'line', title: '线路' },
+  { field: 'ipaddress', title: 'IP地址' },
+  { field: 'company', title: '注册公司' },
+  { field: 'platform', title: '平台' },
 ];
 
 const validateRow = (row) => {
-  for (const {field, title} of requiredFields) {
+  for (const { field, title } of requiredFields) {
     if (!row[field] || (Array.isArray(row[field]) && row[field].length === 0)) {
-      ElMessage.error(`${title}不能为空`);
+      ElMessage.error(`${ title }不能为空`);
       return;
     }
   }
@@ -361,7 +386,7 @@ async function updateRow(row) {
       if (response.code === 2000) {
         ElMessage.success('更新成功');
       } else if (response.code == 400) {
-        ElMessage.warning(`${response.data.description}`);
+        ElMessage.warning(`${ response.data.description }`);
       } else {
         ElMessage.error('更新失败');
       }
@@ -378,18 +403,18 @@ async function handleStatusChange(row) {
       id: row.id,
       status: row.status,
     };
-    const query ={partial:1,}
+    const query = { partial: 1, };
     console.log('updatedData', updatedData);
     try {
-      const response = await postUpdateTaskStatus(query,updatedData);
+      const response = await postUpdateTaskStatus(query, updatedData);
       if (response.code === 2000) {
         ElMessage.success('状态更新成功');
       } else if (response.code == 400) {
-        ElMessage.warning(`${response.data.description}`);
+        ElMessage.warning(`${ response.data.description }`);
       } else {
         ElMessage.error('状态更新失败');
       }
-    }catch (error){
+    } catch (error) {
       console.log('error:', error);
     }
   }
@@ -431,10 +456,10 @@ async function createTask() {
       dialogFormVisible.value = false;
       gridOptions.data.push(body);
       await getTaskList(); // 重新获取任务列表
-      ElMessage({message: '创建成功', type: 'success',});
+      ElMessage({ message: '创建成功', type: 'success', });
     }
   } catch (error) {
-    ElMessage({message: '创建失败', type: 'error',});
+    ElMessage({ message: '创建失败', type: 'error', });
   }
 }
 
@@ -444,17 +469,17 @@ const submitForm = async (formEl) => {
     if (valid) {
       const isDuplicate = allTasks.some(task => String(task.platformNumber) === String(taskRuleForm.number));
       if (isDuplicate) {
-        await ElMessage({message: '平台编号已存在,请重新输入', type: 'warning'});
+        await ElMessage({ message: '平台编号已存在,请重新输入', type: 'warning' });
         return;
       }
 
       if (!currencyList.value.includes(taskRuleForm.currency)) {
-        await ElMessage({message: '回款币种无效,请重新选择', type: 'warning'});
+        await ElMessage({ message: '回款币种无效,请重新选择', type: 'warning' });
         return;
       }
 
       if (!currencyList.value.includes(taskRuleForm.currencyCodePlatform)) {
-        await ElMessage({message: '回款/余额币种无效,请重新选择', type: 'warning'});
+        await ElMessage({ message: '回款/余额币种无效,请重新选择', type: 'warning' });
         return;
       }
 
@@ -486,7 +511,7 @@ async function fetchOperationSelect() {
   try {
     const resp = await getOperationSelect();
     operationList.value = resp.data.map((item: any) => {
-      return {value: item.id, label: item.name};
+      return { value: item.id, label: item.name };
     });
   } catch (e) {
     console.error('Failed to fetch operation select:', e);
@@ -538,6 +563,24 @@ const headerCellStyle = () => {
   };
 };
 
+//发送通知
+async function sendMessage() {
+  const body = {
+    date_type: message.value,
+  };
+  try {
+    //console.log('body', body);
+    const response = await postSendMessage(body);
+    if (response.code === 2000) {
+      ElMessage.success('发送成功');
+    } else if (response.code == 400) {
+      ElMessage.warning(`${ response.data.description }`);
+    } else {
+      ElMessage.error('发送失败');
+    }
+  }catch (error) {
+  }
+}
 
 onMounted(() => {
   getTaskList();
@@ -558,6 +601,26 @@ onMounted(() => {
           <el-button :icon="Plus" plain type="primary" @click="dialogFormVisible = true"> 添加任务</el-button>
           <el-button :disabled="isDeleteDisabled" :icon="Delete" plain type="danger" @click="removeEvent">删除
           </el-button>
+          <!--<el-select-->
+          <!--    v-model="message"-->
+          <!--    placeholder="Select"-->
+          <!--    style="width: 100px;padding-left: 10px"-->
+          <!--&gt;-->
+          <!--  <el-option-->
+          <!--      v-for="item in options"-->
+          <!--      :key="item.value"-->
+          <!--      :label="item.label"-->
+          <!--      :value="item.value"-->
+          <!--  />-->
+          <!--</el-select>-->
+          <el-popover :width="75">
+            <template #reference>
+              <el-button :icon="Send" plain @click="sendMessage">发送通知</el-button>
+            </template>
+            <div class="popver-content">
+              <span class="popver-content-item" v-for="info of dateType" @click="sendMessage(info.value)">{{ info.label }}</span>
+            </div>
+          </el-popover>
         </template>
         <template #toolbar_tools>
           <div class="mx-3.5">
@@ -746,4 +809,24 @@ onMounted(() => {
   transition: all 0.2s ease-in-out;
 }
 
+.popver-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  .popver-content-item {
+    padding: 5px 0;
+    /* text-align: center; */
+    &:hover {
+      background-color: #f4f7fd;
+      color: blue;
+      cursor: pointer;
+    }
+  }
+}
+
+::v-deep(.el-popover) {
+  max-width: 75px !important;
+  min-width: 75px !important;
+  width: 75px !important;
+}
 </style>

+ 5 - 0
src/views/reportManage/TaskManage/utils/enum.ts

@@ -0,0 +1,5 @@
+export const dateType = [
+  { value: 'day', label: '日', },
+  { value: 'week', label: '周', },
+  { value: 'month', label: '月', },
+]