mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-30 09:48:43 +08:00 
			
		
		
		
	邮箱模块:vue3 邮件模版的管理
This commit is contained in:
		| @@ -39,3 +39,8 @@ export const updateMailAccountApi = async (data: MailAccountVO) => { | |||||||
| export const deleteMailAccountApi = async (id: number) => { | export const deleteMailAccountApi = async (id: number) => { | ||||||
|   return await request.delete({ url: '/system/mail-account/delete?id=' + id }) |   return await request.delete({ url: '/system/mail-account/delete?id=' + id }) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 获得邮箱账号精简列表 | ||||||
|  | export const getSimpleMailAccounts = async () => { | ||||||
|  |   return request.get({ url: '/system/mail-account/list-all-simple' }) | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										58
									
								
								yudao-ui-admin-vue3/src/api/system/mail/template/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								yudao-ui-admin-vue3/src/api/system/mail/template/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | |||||||
|  | import request from '@/config/axios' | ||||||
|  |  | ||||||
|  | export interface MailTemplateVO { | ||||||
|  |   id: number | ||||||
|  |   name: string | ||||||
|  |   code: string | ||||||
|  |   accountId: number | ||||||
|  |   nickname: string | ||||||
|  |   title: string | ||||||
|  |   content: string | ||||||
|  |   params: string | ||||||
|  |   status: number | ||||||
|  |   remark: string | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface MailTemplatePageReqVO extends PageParam { | ||||||
|  |   name?: string | ||||||
|  |   code?: string | ||||||
|  |   accountId?: number | ||||||
|  |   status?: number | ||||||
|  |   createTime?: Date[] | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface MailSmsReqVO { | ||||||
|  |   mail: string | ||||||
|  |   templateCode: string | ||||||
|  |   templateParams: Map<String, Object> | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 查询邮件模版列表 | ||||||
|  | export const getMailTemplatePageApi = async (params: MailTemplatePageReqVO) => { | ||||||
|  |   return await request.get({ url: '/system/mail-template/page', params }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 查询邮件模版详情 | ||||||
|  | export const getMailTemplateApi = async (id: number) => { | ||||||
|  |   return await request.get({ url: '/system/mail-template/get?id=' + id }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 新增邮件模版 | ||||||
|  | export const createMailTemplateApi = async (data: MailTemplateVO) => { | ||||||
|  |   return await request.post({ url: '/system/mail-template/create', data }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 修改邮件模版 | ||||||
|  | export const updateMailTemplateApi = async (data: MailTemplateVO) => { | ||||||
|  |   return await request.put({ url: '/system/mail-template/update', data }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 删除邮件模版 | ||||||
|  | export const deleteMailTemplateApi = async (id: number) => { | ||||||
|  |   return await request.delete({ url: '/system/mail-template/delete?id=' + id }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 发送邮件 | ||||||
|  | export const sendMailApi = (data: MailSmsReqVO) => { | ||||||
|  |   return request.post({ url: '/system/mail-template/send-mail', data }) | ||||||
|  | } | ||||||
| @@ -69,7 +69,7 @@ | |||||||
| <script setup lang="ts" name="MailAccount"> | <script setup lang="ts" name="MailAccount"> | ||||||
| import { FormExpose } from '@/components/Form' | import { FormExpose } from '@/components/Form' | ||||||
| // 业务相关的 import | // 业务相关的 import | ||||||
| import { rules, allSchemas } from './account.template.data' | import { rules, allSchemas } from './account.data' | ||||||
| import * as MailAccountApi from '@/api/system/mail/account' | import * as MailAccountApi from '@/api/system/mail/account' | ||||||
|  |  | ||||||
| const { t } = useI18n() // 国际化 | const { t } = useI18n() // 国际化 | ||||||
|   | |||||||
							
								
								
									
										258
									
								
								yudao-ui-admin-vue3/src/views/system/mail/template/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								yudao-ui-admin-vue3/src/views/system/mail/template/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,258 @@ | |||||||
|  | <template> | ||||||
|  |   <ContentWrap> | ||||||
|  |     <!-- 列表 --> | ||||||
|  |     <XTable @register="registerTable"> | ||||||
|  |       <template #toolbar_buttons> | ||||||
|  |         <!-- 操作:新增 --> | ||||||
|  |         <XButton | ||||||
|  |           type="primary" | ||||||
|  |           preIcon="ep:zoom-in" | ||||||
|  |           :title="t('action.add')" | ||||||
|  |           v-hasPermi="['system:mail-template:create']" | ||||||
|  |           @click="handleCreate()" | ||||||
|  |         /> | ||||||
|  |       </template> | ||||||
|  |       <template #accountId_default="{ row }"> | ||||||
|  |         <span>{{ accountOptions.find((account) => account.id === row.accountId)?.mail }}</span> | ||||||
|  |       </template> | ||||||
|  |       <template #actionbtns_default="{ row }"> | ||||||
|  |         <!-- 操作:测试短信 --> | ||||||
|  |         <XTextButton | ||||||
|  |           preIcon="ep:cpu" | ||||||
|  |           :title="t('action.test')" | ||||||
|  |           v-hasPermi="['system:mail-template:send-mail']" | ||||||
|  |           @click="handleSendMail(row)" | ||||||
|  |         /> | ||||||
|  |         <!-- 操作:修改 --> | ||||||
|  |         <XTextButton | ||||||
|  |           preIcon="ep:edit" | ||||||
|  |           :title="t('action.edit')" | ||||||
|  |           v-hasPermi="['system:mail-template:update']" | ||||||
|  |           @click="handleUpdate(row.id)" | ||||||
|  |         /> | ||||||
|  |         <!-- 操作:详情 --> | ||||||
|  |         <XTextButton | ||||||
|  |           preIcon="ep:view" | ||||||
|  |           :title="t('action.detail')" | ||||||
|  |           v-hasPermi="['system:mail-template:query']" | ||||||
|  |           @click="handleDetail(row.id)" | ||||||
|  |         /> | ||||||
|  |         <!-- 操作:删除 --> | ||||||
|  |         <XTextButton | ||||||
|  |           preIcon="ep:delete" | ||||||
|  |           :title="t('action.del')" | ||||||
|  |           v-hasPermi="['system:mail-template:delete']" | ||||||
|  |           @click="deleteData(row.id)" | ||||||
|  |         /> | ||||||
|  |       </template> | ||||||
|  |     </XTable> | ||||||
|  |   </ContentWrap> | ||||||
|  |  | ||||||
|  |   <!-- 添加/修改/详情的弹窗 --> | ||||||
|  |   <XModal id="mailTemplateModel" :loading="modelLoading" v-model="modelVisible" :title="modelTitle"> | ||||||
|  |     <!-- 表单:添加/修改 --> | ||||||
|  |     <Form | ||||||
|  |       ref="formRef" | ||||||
|  |       v-if="['create', 'update'].includes(actionType)" | ||||||
|  |       :schema="allSchemas.formSchema" | ||||||
|  |       :rules="rules" | ||||||
|  |     > | ||||||
|  |       <template #accountId="form"> | ||||||
|  |         <el-select v-model="form.accountId"> | ||||||
|  |           <el-option | ||||||
|  |             v-for="item in accountOptions" | ||||||
|  |             :key="item.id" | ||||||
|  |             :label="item.mail" | ||||||
|  |             :value="item.id" | ||||||
|  |           /> | ||||||
|  |         </el-select> | ||||||
|  |       </template> | ||||||
|  |     </Form> | ||||||
|  |     <!-- 表单:详情 --> | ||||||
|  |     <Descriptions | ||||||
|  |       v-if="actionType === 'detail'" | ||||||
|  |       :schema="allSchemas.detailSchema" | ||||||
|  |       :data="detailData" | ||||||
|  |     /> | ||||||
|  |     <template #footer> | ||||||
|  |       <!-- 按钮:保存 --> | ||||||
|  |       <XButton | ||||||
|  |         v-if="['create', 'update'].includes(actionType)" | ||||||
|  |         type="primary" | ||||||
|  |         :title="t('action.save')" | ||||||
|  |         :loading="actionLoading" | ||||||
|  |         @click="submitForm()" | ||||||
|  |       /> | ||||||
|  |       <!-- 按钮:关闭 --> | ||||||
|  |       <XButton :loading="actionLoading" :title="t('dialog.close')" @click="modelVisible = false" /> | ||||||
|  |     </template> | ||||||
|  |   </XModal> | ||||||
|  |  | ||||||
|  |   <!-- 测试邮件的弹窗 --> | ||||||
|  |   <XModal id="sendTest" v-model="sendVisible" title="测试"> | ||||||
|  |     <el-form :model="sendForm" :rules="sendRules" label-width="200px" label-position="top"> | ||||||
|  |       <el-form-item label="模板内容" prop="content"> | ||||||
|  |         <Editor :model-value="sendForm.content" readonly height="150px" /> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item label="收件邮箱" prop="mail"> | ||||||
|  |         <el-input v-model="sendForm.mail" placeholder="请输入收件邮箱" /> | ||||||
|  |       </el-form-item> | ||||||
|  |       <el-form-item | ||||||
|  |         v-for="param in sendForm.params" | ||||||
|  |         :key="param" | ||||||
|  |         :label="'参数 {' + param + '}'" | ||||||
|  |         :prop="'templateParams.' + param" | ||||||
|  |       > | ||||||
|  |         <el-input | ||||||
|  |           v-model="sendForm.templateParams[param]" | ||||||
|  |           :placeholder="'请输入 ' + param + ' 参数'" | ||||||
|  |         /> | ||||||
|  |       </el-form-item> | ||||||
|  |     </el-form> | ||||||
|  |     <!-- 操作按钮 --> | ||||||
|  |     <template #footer> | ||||||
|  |       <XButton | ||||||
|  |         type="primary" | ||||||
|  |         :title="t('action.test')" | ||||||
|  |         :loading="actionLoading" | ||||||
|  |         @click="sendTest()" | ||||||
|  |       /> | ||||||
|  |       <XButton :title="t('dialog.close')" @click="sendVisible = false" /> | ||||||
|  |     </template> | ||||||
|  |   </XModal> | ||||||
|  | </template> | ||||||
|  | <script setup lang="ts" name="MailTemplate"> | ||||||
|  | import { FormExpose } from '@/components/Form' | ||||||
|  | // 业务相关的 import | ||||||
|  | import { rules, allSchemas } from './template.data' | ||||||
|  | import * as MailTemplateApi from '@/api/system/mail/template' | ||||||
|  | import * as MailAccountApi from '@/api/system/mail/account' | ||||||
|  |  | ||||||
|  | const { t } = useI18n() // 国际化 | ||||||
|  | const message = useMessage() // 消息弹窗 | ||||||
|  |  | ||||||
|  | // 列表相关的变量 | ||||||
|  | const [registerTable, { reload, deleteData }] = useXTable({ | ||||||
|  |   allSchemas: allSchemas, | ||||||
|  |   getListApi: MailTemplateApi.getMailTemplatePageApi, | ||||||
|  |   deleteApi: MailTemplateApi.deleteMailTemplateApi | ||||||
|  | }) | ||||||
|  | const accountOptions = ref([]) // 账号下拉选项 | ||||||
|  |  | ||||||
|  | // 弹窗相关的变量 | ||||||
|  | const modelVisible = ref(false) // 是否显示弹出层 | ||||||
|  | const modelTitle = ref('edit') // 弹出层标题 | ||||||
|  | const modelLoading = ref(false) // 弹出层loading | ||||||
|  | const actionType = ref('') // 操作按钮的类型 | ||||||
|  | const actionLoading = ref(false) // 按钮 Loading | ||||||
|  | const formRef = ref<FormExpose>() // 表单 Ref | ||||||
|  | const detailData = ref() // 详情 Ref | ||||||
|  |  | ||||||
|  | // 设置标题 | ||||||
|  | const setDialogTile = (type: string) => { | ||||||
|  |   modelLoading.value = true | ||||||
|  |   modelTitle.value = t('action.' + type) | ||||||
|  |   actionType.value = type | ||||||
|  |   modelVisible.value = true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 新增操作 | ||||||
|  | const handleCreate = () => { | ||||||
|  |   setDialogTile('create') | ||||||
|  |   modelLoading.value = false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 修改操作 | ||||||
|  | const handleUpdate = async (rowId: number) => { | ||||||
|  |   setDialogTile('update') | ||||||
|  |   // 设置数据 | ||||||
|  |   const res = await MailTemplateApi.getMailTemplateApi(rowId) | ||||||
|  |   unref(formRef)?.setValues(res) | ||||||
|  |   modelLoading.value = false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 详情操作 | ||||||
|  | const handleDetail = async (rowId: number) => { | ||||||
|  |   setDialogTile('detail') | ||||||
|  |   const res = await MailTemplateApi.getMailTemplateApi(rowId) | ||||||
|  |   detailData.value = res | ||||||
|  |   modelLoading.value = false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 提交按钮 | ||||||
|  | const submitForm = async () => { | ||||||
|  |   const elForm = unref(formRef)?.getElFormRef() | ||||||
|  |   if (!elForm) return | ||||||
|  |   elForm.validate(async (valid) => { | ||||||
|  |     if (valid) { | ||||||
|  |       actionLoading.value = true | ||||||
|  |       // 提交请求 | ||||||
|  |       try { | ||||||
|  |         const data = unref(formRef)?.formModel as MailTemplateApi.MailTemplateVO | ||||||
|  |         if (actionType.value === 'create') { | ||||||
|  |           await MailTemplateApi.createMailTemplateApi(data) | ||||||
|  |           message.success(t('common.createSuccess')) | ||||||
|  |         } else { | ||||||
|  |           await MailTemplateApi.updateMailTemplateApi(data) | ||||||
|  |           message.success(t('common.updateSuccess')) | ||||||
|  |         } | ||||||
|  |         modelVisible.value = false | ||||||
|  |       } finally { | ||||||
|  |         actionLoading.value = false | ||||||
|  |         // 刷新列表 | ||||||
|  |         await reload() | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ========== 测试相关 ========== | ||||||
|  | const sendForm = ref({ | ||||||
|  |   content: '', | ||||||
|  |   params: {}, | ||||||
|  |   mail: '', | ||||||
|  |   templateCode: '', | ||||||
|  |   templateParams: {} | ||||||
|  | }) | ||||||
|  | const sendRules = ref({ | ||||||
|  |   mail: [{ required: true, message: '邮箱不能为空', trigger: 'blur' }], | ||||||
|  |   templateCode: [{ required: true, message: '模版编号不能为空', trigger: 'blur' }], | ||||||
|  |   templateParams: {} | ||||||
|  | }) | ||||||
|  | const sendVisible = ref(false) | ||||||
|  |  | ||||||
|  | const handleSendMail = (row: any) => { | ||||||
|  |   sendForm.value.content = row.content | ||||||
|  |   sendForm.value.params = row.params | ||||||
|  |   sendForm.value.templateCode = row.code | ||||||
|  |   sendForm.value.templateParams = row.params.reduce(function (obj, item) { | ||||||
|  |     obj[item] = undefined | ||||||
|  |     return obj | ||||||
|  |   }, {}) | ||||||
|  |   sendRules.value.templateParams = row.params.reduce(function (obj, item) { | ||||||
|  |     obj[item] = { required: true, message: '参数 ' + item + ' 不能为空', trigger: 'change' } | ||||||
|  |     return obj | ||||||
|  |   }, {}) | ||||||
|  |   sendVisible.value = true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const sendTest = async () => { | ||||||
|  |   const data: MailTemplateApi.MailSmsReqVO = { | ||||||
|  |     mail: sendForm.value.mail, | ||||||
|  |     templateCode: sendForm.value.templateCode, | ||||||
|  |     templateParams: sendForm.value.templateParams as unknown as Map<string, Object> | ||||||
|  |   } | ||||||
|  |   const res = await MailTemplateApi.sendMailApi(data) | ||||||
|  |   if (res) { | ||||||
|  |     message.success('提交发送成功!发送结果,见发送日志编号:' + res) | ||||||
|  |   } | ||||||
|  |   sendVisible.value = false | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ========== 初始化 ========== | ||||||
|  | onMounted(() => { | ||||||
|  |   MailAccountApi.getSimpleMailAccounts().then((data) => { | ||||||
|  |     accountOptions.value = data | ||||||
|  |   }) | ||||||
|  | }) | ||||||
|  | </script> | ||||||
| @@ -0,0 +1,93 @@ | |||||||
|  | import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas' | ||||||
|  |  | ||||||
|  | // 表单校验 | ||||||
|  | export const rules = reactive({ | ||||||
|  |   name: [required], | ||||||
|  |   code: [required], | ||||||
|  |   accountId: [required], | ||||||
|  |   title: [required], | ||||||
|  |   content: [required], | ||||||
|  |   params: [required], | ||||||
|  |   status: [required] | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | // CrudSchema | ||||||
|  | const crudSchemas = reactive<VxeCrudSchema>({ | ||||||
|  |   primaryKey: 'id', // 默认的主键ID | ||||||
|  |   primaryTitle: '编号', // 默认显示的值 | ||||||
|  |   primaryType: null, | ||||||
|  |   action: true, | ||||||
|  |   actionWidth: '260', | ||||||
|  |   columns: [ | ||||||
|  |     { | ||||||
|  |       title: '模板编码', | ||||||
|  |       field: 'code', | ||||||
|  |       isSearch: true | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '模板名称', | ||||||
|  |       field: 'name', | ||||||
|  |       isSearch: true | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '模板标题', | ||||||
|  |       field: 'title' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '模板内容', | ||||||
|  |       field: 'content', | ||||||
|  |       form: { | ||||||
|  |         component: 'Editor', | ||||||
|  |         colProps: { | ||||||
|  |           span: 24 | ||||||
|  |         }, | ||||||
|  |         componentProps: { | ||||||
|  |           valueHtml: '' | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '邮箱账号', | ||||||
|  |       field: 'accountId', | ||||||
|  |       isSearch: true, | ||||||
|  |       table: { | ||||||
|  |         width: 200, | ||||||
|  |         slots: { | ||||||
|  |           default: 'accountId_default' | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '发送人名称', | ||||||
|  |       field: 'nickname' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '开启状态', | ||||||
|  |       field: 'status', | ||||||
|  |       isSearch: true, | ||||||
|  |       dictType: DICT_TYPE.COMMON_STATUS, | ||||||
|  |       dictClass: 'number' | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '备注', | ||||||
|  |       field: 'remark', | ||||||
|  |       isTable: false | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       title: '创建时间', | ||||||
|  |       field: 'createTime', | ||||||
|  |       isForm: false, | ||||||
|  |       formatter: 'formatDate', | ||||||
|  |       table: { | ||||||
|  |         width: 180 | ||||||
|  |       }, | ||||||
|  |       search: { | ||||||
|  |         show: true, | ||||||
|  |         itemRender: { | ||||||
|  |           name: 'XDataTimePicker' | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   ] | ||||||
|  | }) | ||||||
|  | export const { allSchemas } = useVxeCrudSchemas(crudSchemas) | ||||||
| @@ -197,7 +197,7 @@ const sendSmsForm = ref({ | |||||||
| }) | }) | ||||||
| const sendSmsRules = ref({ | const sendSmsRules = ref({ | ||||||
|   mobile: [{ required: true, message: '手机不能为空', trigger: 'blur' }], |   mobile: [{ required: true, message: '手机不能为空', trigger: 'blur' }], | ||||||
|   templateCode: [{ required: true, message: '手机不能为空', trigger: 'blur' }], |   templateCode: [{ required: true, message: '模版编号不能为空', trigger: 'blur' }], | ||||||
|   templateParams: {} |   templateParams: {} | ||||||
| }) | }) | ||||||
| const sendVisible = ref(false) | const sendVisible = ref(false) | ||||||
| @@ -225,7 +225,7 @@ const sendSmsTest = async () => { | |||||||
|   } |   } | ||||||
|   const res = await SmsTemplateApi.sendSmsApi(data) |   const res = await SmsTemplateApi.sendSmsApi(data) | ||||||
|   if (res) { |   if (res) { | ||||||
|     message.success('发送成功') |     message.success('提交发送成功!发送结果,见发送日志编号:' + res) | ||||||
|   } |   } | ||||||
|   sendVisible.value = false |   sendVisible.value = false | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV