Explorar o código

reactor:【SYSTEM 系统管理】邮箱日志,重构成 element-plus 标准界面

YunaiV hai 6 meses
pai
achega
cde1f209fb

+ 5 - 0
src/api/system/mail/log/index.ts

@@ -28,3 +28,8 @@ export const getMailLogPage = async (params: PageParam) => {
 export const getMailLog = async (id: number) => {
   return await request.get({ url: '/system/mail-log/get?id=' + id })
 }
+
+// 导出邮件日志
+export const exportMailLog = (params) => {
+  return request.download({ url: '/system/mail-log/export-excel', params })
+}

+ 54 - 10
src/views/system/mail/log/MailLogDetail.vue

@@ -1,33 +1,77 @@
 <template>
-  <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情">
-    <Descriptions :data="detailData" :schema="allSchemas.detailSchema">
-      <!-- 展示 HTML 内容 -->
-      <template #templateContent="{ row }">
-        <div v-dompurify-html="row.templateContent"></div>
-      </template>
-    </Descriptions>
+  <Dialog v-model="dialogVisible" :max-height="500" :scroll="true" title="详情" width="800">
+    <el-descriptions :column="1" border>
+      <el-descriptions-item label="日志主键" min-width="120">
+        {{ detailData.id }}
+      </el-descriptions-item>
+      <el-descriptions-item label="邮箱账号">
+        {{ accountList.find((account) => account.id === detailData.accountId)?.mail }}
+      </el-descriptions-item>
+      <el-descriptions-item label="邮件模板">
+        {{ detailData.templateId }} | {{ detailData.templateCode }}
+      </el-descriptions-item>
+      <el-descriptions-item label="模版发送人名称">
+        {{ detailData.templateNickname }}
+      </el-descriptions-item>
+      <el-descriptions-item label="用户信息">
+        {{ detailData.toMail }}
+        <span v-if="detailData.userType && detailData.userId">
+          <dict-tag :type="DICT_TYPE.USER_TYPE" :value="detailData.userType" />
+          ({{ detailData.userId }})
+        </span>
+      </el-descriptions-item>
+      <el-descriptions-item label="邮件标题">
+        {{ detailData.templateTitle }}
+      </el-descriptions-item>
+      <el-descriptions-item label="邮件内容">
+        <div v-dompurify-html="detailData.templateContent"></div>
+      </el-descriptions-item>
+      <el-descriptions-item label="邮件参数">
+        {{ detailData.templateParams }}
+      </el-descriptions-item>
+      <el-descriptions-item label="创建时间">
+        {{ formatDate(detailData.createTime) }}
+      </el-descriptions-item>
+      <el-descriptions-item label="发送状态">
+        <dict-tag :type="DICT_TYPE.SYSTEM_MAIL_SEND_STATUS" :value="detailData.sendStatus" />
+      </el-descriptions-item>
+      <el-descriptions-item label="发送时间">
+        {{ formatDate(detailData.sendTime) }}
+      </el-descriptions-item>
+      <el-descriptions-item label="发送返回的消息编号">
+        {{ detailData.sendMessageId }}
+      </el-descriptions-item>
+      <el-descriptions-item label="发送异常">
+        {{ detailData.sendException }}
+      </el-descriptions-item>
+    </el-descriptions>
   </Dialog>
 </template>
 <script lang="ts" setup>
+import { DICT_TYPE } from '@/utils/dict'
+import { formatDate } from '@/utils/formatTime'
 import * as MailLogApi from '@/api/system/mail/log'
-import { allSchemas } from './log.data'
+import * as MailAccountApi from '@/api/system/mail/account'
 
 defineOptions({ name: 'SystemMailLogDetail' })
 
 const dialogVisible = ref(false) // 弹窗的是否展示
 const detailLoading = ref(false) // 表单的加载中
 const detailData = ref() // 详情数据
+const accountList = ref([]) // 邮箱账号列表
 
 /** 打开弹窗 */
-const open = async (id: number) => {
+const open = async (data: MailLogApi.MailLogVO) => {
   dialogVisible.value = true
   // 设置数据
   detailLoading.value = true
   try {
-    detailData.value = await MailLogApi.getMailLog(id)
+    detailData.value = data
   } finally {
     detailLoading.value = false
   }
+  // 加载邮箱账号列表
+  accountList.value = await MailAccountApi.getSimpleMailAccountList()
 }
 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 </script>

+ 228 - 36
src/views/system/mail/log/index.vue

@@ -1,63 +1,255 @@
 <template>
   <doc-alert title="邮件配置" url="https://doc.iocoder.cn/mail" />
 
-  <!-- 搜索工作栏 -->
   <ContentWrap>
-    <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
-  </ContentWrap>
-
-  <!-- 列表 -->
-  <ContentWrap>
-    <Table
-      :columns="allSchemas.tableColumns"
-      :data="tableObject.tableList"
-      :loading="tableObject.loading"
-      :pagination="{
-        total: tableObject.total
-      }"
-      v-model:pageSize="tableObject.pageSize"
-      v-model:currentPage="tableObject.currentPage"
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="100px"
     >
-      <template #action="{ row }">
+      <el-form-item label="接收邮箱" prop="toMail">
+        <el-input
+          v-model="queryParams.toMail"
+          placeholder="请输入接收邮箱"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="邮箱账号" prop="accountId">
+        <el-select
+          v-model="queryParams.accountId"
+          placeholder="请选择邮箱账号"
+          clearable
+          class="!w-240px"
+        >
+          <el-option
+            v-for="account in accountList"
+            :key="account.id"
+            :value="account.id"
+            :label="account.mail"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="模板编号" prop="templateId">
+        <el-input
+          v-model="queryParams.templateId"
+          placeholder="请输入模板编号"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="发送状态" prop="sendStatus">
+        <el-select
+          v-model="queryParams.sendStatus"
+          placeholder="请选择发送状态"
+          clearable
+          class="!w-240px"
+        >
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.SYSTEM_MAIL_SEND_STATUS)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="用户编号" prop="userId">
+        <el-input
+          v-model="queryParams.userId"
+          placeholder="请输入用户编号"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item label="用户类型" prop="userType">
+        <el-select
+          v-model="queryParams.userType"
+          placeholder="请选择用户类型"
+          clearable
+          class="!w-240px"
+        >
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.USER_TYPE)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="发送时间" prop="sendTime">
+        <el-date-picker
+          v-model="queryParams.sendTime"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          type="daterange"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          class="!w-240px"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
         <el-button
-          link
-          type="primary"
-          @click="openDetail(row.id)"
-          v-hasPermi="['system:mail-log:query']"
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['system:mail-log:export']"
         >
-          详情
+          <Icon icon="ep:download" class="mr-5px" /> 导出
         </el-button>
-      </template>
-    </Table>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="编号" align="center" prop="id" />
+      <el-table-column
+        label="发送时间"
+        align="center"
+        prop="sendTime"
+        width="180"
+        :formatter="dateFormatter"
+      />
+      <el-table-column label="接收邮箱" align="center" prop="toMail" width="200">
+        <template #default="scope">
+          <div>{{ scope.row.toMail }}</div>
+          <div v-if="scope.row.userType && scope.row.userId">
+            <dict-tag :type="DICT_TYPE.USER_TYPE" :value="scope.row.userType" />
+            {{ '(' + scope.row.userId + ')' }}
+          </div>
+        </template>
+      </el-table-column>
+      <el-table-column label="邮件标题" align="center" prop="templateTitle" width="200" />
+      <el-table-column label="发送状态" align="center" width="120">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.SYSTEM_MAIL_SEND_STATUS" :value="scope.row.sendStatus" />
+        </template>
+      </el-table-column>
+      <el-table-column label="邮箱账号" align="center" width="200">
+        <template #default="scope">
+          {{ getAccountMail(scope.row.accountId) }}
+        </template>
+      </el-table-column>
+      <el-table-column label="模板编号" align="center" prop="templateId" />
+      <el-table-column label="操作" align="center" fixed="right" class-name="fixed-width">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openDetail(scope.row)"
+            v-hasPermi="['system:mail-log:query']"
+          >
+            详情
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
   </ContentWrap>
 
   <!-- 表单弹窗:详情 -->
-  <mail-log-detail ref="detailRef" />
+  <MailLogDetail ref="detailRef" />
 </template>
 <script lang="ts" setup>
-import { allSchemas } from './log.data'
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { dateFormatter, formatDate } from '@/utils/formatTime'
+import download from '@/utils/download'
+import * as MailAccountApi from '@/api/system/mail/account'
 import * as MailLogApi from '@/api/system/mail/log'
 import MailLogDetail from './MailLogDetail.vue'
 
 defineOptions({ name: 'SystemMailLog' })
 
-// tableObject:表格的属性对象,可获得分页大小、条数等属性
-// tableMethods:表格的操作对象,可进行获得分页、删除记录等操作
-// 详细可见:https://doc.iocoder.cn/vue3/crud-schema/
-const { tableObject, tableMethods } = useTable({
-  getListApi: MailLogApi.getMailLogPage // 分页接口
+const message = useMessage() // 消息弹窗
+
+const loading = ref(false) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryFormRef = ref() // 搜索的表单
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  toMail: '',
+  accountId: null,
+  templateId: null,
+  sendStatus: null,
+  userId: null,
+  userType: null,
+  sendTime: []
 })
-// 获得表格的各种操作
-const { getList, setSearchParams } = tableMethods
+const exportLoading = ref(false) // 导出的加载中
+const accountList = ref([]) // 邮箱账号列表
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await MailLogApi.getMailLogPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await MailLogApi.exportMailLog(queryParams)
+    download.excel(data, '邮件日志.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
 
 /** 详情操作 */
 const detailRef = ref()
-const openDetail = (id: number) => {
-  detailRef.value.open(id)
+const openDetail = (data: MailLogApi.MailLogVO) => {
+  detailRef.value.open(data)
+}
+
+/** 获取邮箱账号名称 */
+const getAccountMail = (accountId: number) => {
+  const account = accountList.value.find((account) => account.id === accountId)
+  return account?.mail || ''
 }
 
 /** 初始化 **/
-onMounted(() => {
-  getList()
+onMounted(async () => {
+  await getList()
+  // 加载邮箱账号列表
+  accountList.value = await MailAccountApi.getSimpleMailAccountList()
 })
 </script>

+ 0 - 167
src/views/system/mail/log/log.data.ts

@@ -1,167 +0,0 @@
-import type { CrudSchema } from '@/hooks/web/useCrudSchemas'
-import { dateFormatter } from '@/utils/formatTime'
-import * as MailAccountApi from '@/api/system/mail/account'
-
-// 邮箱账号的列表
-const accountList = await MailAccountApi.getSimpleMailAccountList()
-
-// CrudSchema:https://doc.iocoder.cn/vue3/crud-schema/
-const crudSchemas = reactive<CrudSchema[]>([
-  {
-    label: '编号',
-    field: 'id'
-  },
-  {
-    label: '发送时间',
-    field: 'sendTime',
-    formatter: dateFormatter,
-    search: {
-      show: true,
-      component: 'DatePicker',
-      componentProps: {
-        valueFormat: 'YYYY-MM-DD HH:mm:ss',
-        type: 'daterange',
-        defaultTime: [new Date('1 00:00:00'), new Date('1 23:59:59')],
-        style: {
-          width: '240px'
-        }
-      }
-    },
-    detail: {
-      dateFormat: 'YYYY-MM-DD HH:mm:ss'
-    }
-  },
-  {
-    label: '接收邮箱',
-    field: 'toMail'
-  },
-  {
-    label: '用户编号',
-    field: 'userId',
-    isSearch: true,
-    isTable: false,
-    search: {
-      componentProps: {
-        style: {
-          width: '240px'
-        }
-      }
-    }
-  },
-  {
-    label: '用户类型',
-    field: 'userType',
-    dictType: DICT_TYPE.USER_TYPE,
-    dictClass: 'number',
-    isSearch: true,
-    isTable: false,
-    search: {
-      componentProps: {
-        style: {
-          width: '240px'
-        }
-      }
-    }
-  },
-  {
-    label: '邮件标题',
-    field: 'templateTitle'
-  },
-  {
-    label: '邮件内容',
-    field: 'templateContent',
-    isTable: false
-  },
-  {
-    label: '邮箱参数',
-    field: 'templateParams',
-    isTable: false
-  },
-  {
-    label: '发送状态',
-    field: 'sendStatus',
-    dictType: DICT_TYPE.SYSTEM_MAIL_SEND_STATUS,
-    dictClass: 'string',
-    isSearch: true,
-    search: {
-      componentProps: {
-        style: {
-          width: '240px'
-        }
-      }
-    }
-  },
-  {
-    label: '邮箱账号',
-    field: 'accountId',
-    isTable: false,
-    search: {
-      show: true,
-      component: 'Select',
-      api: () => accountList,
-      componentProps: {
-        optionsAlias: {
-          labelField: 'mail',
-          valueField: 'id'
-        },
-        style: {
-          width: '240px'
-        }
-      }
-    }
-  },
-  {
-    label: '发送邮箱地址',
-    field: 'fromMail',
-    table: {
-      label: '邮箱账号'
-    }
-  },
-  {
-    label: '模板编号',
-    field: 'templateId',
-    isSearch: true,
-    search: {
-      componentProps: {
-        style: {
-          width: '240px'
-        }
-      }
-    }
-  },
-  {
-    label: '模板编码',
-    field: 'templateCode',
-    isTable: false
-  },
-  {
-    label: '模版发送人名称',
-    field: 'templateNickname',
-    isTable: false
-  },
-  {
-    label: '发送返回的消息编号',
-    field: 'sendMessageId',
-    isTable: false
-  },
-  {
-    label: '发送异常',
-    field: 'sendException',
-    isTable: false
-  },
-  {
-    label: '创建时间',
-    field: 'createTime',
-    isTable: false,
-    formatter: dateFormatter,
-    detail: {
-      dateFormat: 'YYYY-MM-DD HH:mm:ss'
-    }
-  },
-  {
-    label: '操作',
-    field: 'action',
-    isDetail: false
-  }
-])
-export const { allSchemas } = useCrudSchemas(crudSchemas)