diff --git a/src/pages/message/my/index.tsx b/src/pages/message/my/index.tsx index 503eeeb..63971f4 100644 --- a/src/pages/message/my/index.tsx +++ b/src/pages/message/my/index.tsx @@ -1,5 +1,5 @@ import {useTranslation} from '@/i18n.ts' -import {Badge, Button, Divider, Form, Input, Space, Tooltip} from 'antd' +import {Badge, Button, Divider, Form, Input, Select, Space, Tooltip} from 'antd' import {useAtom, useAtomValue} from 'jotai' import React, {useEffect, useMemo, useState} from 'react' import {BetaSchemaForm, ProColumns, ProFormColumnsType,} from '@ant-design/pro-components' @@ -10,6 +10,7 @@ import {getValueCount, unSetColumnRules} from '@/utils' import {Table as ProTable} from '@/components/table' import {msgListAtom, msgSearchAtom, saveMsgAtom} from "@/store/message/my.ts"; import {templateAllListAtom} from "@/store/message/template.ts"; +import {IMsgTemplate} from "@/types/message/template.ts"; const i18nPrefix = 'msgMy.list' @@ -26,8 +27,77 @@ const MdwMessage = () => { const [open, setOpen] = useState(false) const [openFilter, setFilterOpen] = useState(false) + const [currentTemplate, setCurrentTemplate] = useState() const [searchKey, setSearchKey] = useState(search?.title) + const [templateType, setTemplateType] = useState('') + const typeHandlerChange = (value: string) => { + if (value !== 'EMAIL') { + setTemplateTitle('') + form.setFieldsValue({'title': undefined}) + } + setTemplateType(value) + } + + const templateChange = (index: number) => { + if (templateList && index !== undefined) { + // key转换 + const result = templateList[index].fields.split(',').map(item => { + return { + field_key: item, + field_value: '' + }; + }); + setCurrentTemplate(templateList[index]) + form.setFieldsValue({...templateList[index], 'fieldList': result}) + setTemplateType(templateList[index].type) + setTemplateTitle(templateList[index].title) + setTemplateContent(templateList[index].content) + } else { + form.resetFields() + setTemplateType('') + setCurrentTemplate(undefined) + } + } + + const [templateTitle, setTemplateTitle] = useState(''); + const [templateContent, setTemplateContent] = useState(''); + + useEffect(() => { + handleChange() + }, [templateTitle, templateContent]); + + const handleContentChange = (e) => { + const value = e.target.value; + setTemplateContent(value) + }; + + const titheHandleContentChange = (e) => { + const value = e.target.value; + setTemplateTitle(value) + }; + + const handleChange = () => { + // 使用正则表达式匹配 ${var} 格式的变量 + const regex = /\${\.([a-zA-Z0-9_]+)}/g; + const matches = [...(templateTitle + templateContent).matchAll(regex)]; + + // 提取变量名 + const variables = Array.from(new Set(matches.map(match => match[1]))); + const result = variables.map(item => { + return { + field_key: item, + field_value: '' + }; + }); + form.setFieldsValue({'fieldList': result}) + }; + + const handleInputChange = (index, e) => { + form.getFieldValue("fieldList")[index].field_value = e.target.value + } + + const drawerColumns = useMemo(() => { return [ { @@ -38,7 +108,25 @@ const MdwMessage = () => { formItemProps: {hidden: true} }, { - title: t(`${i18nPrefix}.columns.type`, '选择模板'), + title: t(`${i18nPrefix}.columns.template`, '选择模板'), + valueType: 'select', + fieldProps: { + allowClear: true, + }, + renderFormItem: () => { + return + } + }, + { + title: t(`${i18nPrefix}.columns.type`, '消息类型'), dataIndex: 'type', valueType: 'select', fieldProps: { @@ -48,6 +136,7 @@ const MdwMessage = () => { {label: 'Telegram', value: 'TG'} ], allowClear: false, + onChange: typeHandlerChange }, formItemProps: { rules: [ @@ -64,46 +153,60 @@ const MdwMessage = () => { fieldProps: { maxLength: 100, showCount: true, + onChange: titheHandleContentChange, + }, + formItemProps: { + tooltip: '支持邮件类型', + hidden: templateType != 'EMAIL', + rules: [ + { + required: templateType == 'EMAIL', + message: t('message.required', '模板内容必填') + } + ] }, }, { - title: t(`${i18nPrefix}.columns.content`, '模板内容'), + title: t(`${i18nPrefix}.columns.content`, '正文'), dataIndex: 'content', valueType: 'textarea', fieldProps: { - defaultValue: "你好,我叫${.name}", maxLength: 1000, showCount: true, rows: 15, + onChange: handleContentChange, }, formItemProps: { rules: [ { required: true, - message: t('message.required', '模板内容必填') + message: t('message.required', '内容必填') } ] } }, { - title: t(`${i18nPrefix}.columns.field`, '识别到的变量'), - dataIndex: 'field', - renderFormItem: () => { + title: t(`${i18nPrefix}.columns.fieldList`, '填充变量'), + dataIndex: 'fieldList', + formItemProps: { + hidden: currentTemplate === undefined, + }, + renderFormItem: (_, config) => { return ( <> { - templateList?.map((variable, index) => ( + config.value?.map((variable, index) => (
handleInputChange(index, e)} />
- ))} + )) + } ); - } + }, }, { title: t(`${i18nPrefix}.columns.dest`, '收件人(多个收件人用英文逗号隔开,如果类型是TG,则填token)'), @@ -112,12 +215,20 @@ const MdwMessage = () => { fieldProps: { maxLength: 1000, showCount: true, - rows: 15, + rows: 5, placeholder: 'aaa@qq.com,bbb@gmail.com', }, + formItemProps: { + rules: [ + { + required: true, + message: t('message.required', '内容必填') + } + ] + } }, ] as ProColumns[] - }, [search]) + }, [search, templateType, templateList]) const columns = useMemo(() => { return [ @@ -129,17 +240,37 @@ const MdwMessage = () => { formItemProps: {hidden: true} }, { - title: t(`${i18nPrefix}.columns.name`, '模板名称'), - dataIndex: 'name', + title: t(`${i18nPrefix}.columns.type`, '类型'), + dataIndex: 'type', + render: (_, record) => { + return
{record.type}
+ } }, { - title: t(`${i18nPrefix}.columns.title`, '模板标题'), + title: t(`${i18nPrefix}.columns.title`, '标题'), dataIndex: 'title', }, { - title: t(`${i18nPrefix}.columns.content`, '模板内容'), + title: t(`${i18nPrefix}.columns.content`, '正文'), dataIndex: 'content', }, + { + title: t(`${i18nPrefix}.columns.dest`, '收件人'), + dataIndex: 'dest', + }, + { + title: t(`${i18nPrefix}.columns.status`, '状态'), + dataIndex: 'status', + render: (_text, record) => { + return + } + }, + { + title: t(`${i18nPrefix}.columns.send_at`, '发送时间'), + dataIndex: 'send_at', + }, // { // title: t(`${i18nPrefix}.columns.option`, '操作'), // key: 'option', @@ -160,7 +291,7 @@ const MdwMessage = () => { // ] // } ] as ProColumns[] - }, [search]) + }, [search, currentTemplate]) useEffect(() => { @@ -179,7 +310,7 @@ const MdwMessage = () => { { }) setOpen(true) }} - type={'primary'}>{t(`${i18nPrefix}.add`, '添加模板')} + type={'primary'}>{t(`${i18nPrefix}.add`, '发送消息')} ] }} scroll={{ @@ -261,7 +392,7 @@ const MdwMessage = () => { form={form} layout={'vertical'} scrollToFirstError={true} - title={t(`${i18nPrefix}.title_${form.getFieldValue('id') !== 0 ? 'edit' : 'add'}`, form.getFieldValue('id') !== 0 ? '模板编辑' : '模板添加')} + title={t(`${i18nPrefix}.title_add}`, '发送消息')} layoutType={'DrawerForm'} open={open} drawerProps={{ @@ -275,7 +406,7 @@ const MdwMessage = () => { }} onFinish={async (values) => { - saveOrUpdate(values) + saveOrUpdate({...values, "template_id": currentTemplate?.id}) }} columns={drawerColumns as ProFormColumnsType[]}/> { } }, [open]); - const handleChange = (title: string, content: string) => { + const handleChange = () => { // 使用正则表达式匹配 ${var} 格式的变量 const regex = /\${\.([a-zA-Z0-9_]+)}/g; - const matches = [...(title + content).matchAll(regex)]; + const matches = [...(templateTitle + templateContent).matchAll(regex)]; // 提取变量名 const variables = Array.from(new Set(matches.map(match => match[1]))); setTemplateField(variables); }; + useEffect(() => { + handleChange() + }, [templateTitle, templateContent]); + const handleContentChange = (e) => { const value = e.target.value; setTemplateContent(value) - handleChange(templateTitle, value) }; const titheHandleContentChange = (e) => { const value = e.target.value; setTemplateTitle(value) - handleChange(value, templateContent) }; const typeHandlerChange = (value) => { diff --git a/src/store/message/my.ts b/src/store/message/my.ts index 80e6073..4a62ded 100644 --- a/src/store/message/my.ts +++ b/src/store/message/my.ts @@ -1,10 +1,10 @@ import { atom } from 'jotai/index' import { IApiResult, IPage } from '@/global' import { atomWithMutation, atomWithQuery, queryClientAtom } from 'jotai-tanstack-query' -import messageTemplate from '@/service/message/template.ts' import { message } from 'antd' import { t } from 'i18next' import { IMsgMy } from '@/types/message/my.ts' +import messageMy from '@/service/message/my.ts' type SearchParams = IPage & { key?: string @@ -29,7 +29,7 @@ export const msgListAtom = atomWithQuery((get) => { return { queryKey: [ 'msgList', get(msgSearchAtom) ], queryFn: async ({ queryKey: [ , params ] }) => { - const list = await messageTemplate.list(params as SearchParams) + const list = await messageMy.list(params as SearchParams) return list.data } } @@ -39,12 +39,12 @@ export const deleteMsgAtom = atomWithMutation((get) => { return { mutationKey: [ 'deleteMsg' ], mutationFn: async (ids: number) => { - return await messageTemplate.delete(ids ?? get(msgIdsAtom) as number) + return await messageMy.delete(ids ?? get(msgIdsAtom) as number) }, onSuccess: (res) => { message.success('message.deleteSuccess') //更新列表 - get(queryClientAtom).invalidateQueries({ queryKey: [ 'templateList', get(msgSearchAtom) ] }) + get(queryClientAtom).invalidateQueries({ queryKey: [ 'msgList', get(msgSearchAtom) ] }) return res } } @@ -55,15 +55,12 @@ export const saveMsgAtom = atomWithMutation((get) => { return { mutationKey: [ 'saveMsg' ], mutationFn: async (data) => { - if (data.id === 0) { - return await messageTemplate.add(data) - } - return await messageTemplate.update(data) + return await messageMy.add(data) }, onSuccess: (res) => { message.success(t('message.saveSuccess', '保存成功')) - get(queryClientAtom).invalidateQueries({ queryKey: [ 'templateList', get(msgSearchAtom) ] }) + get(queryClientAtom).invalidateQueries({ queryKey: [ 'msgList', get(msgSearchAtom) ] }) return res }