Ver código fonte

feat:【mp】完善“模版消息”的功能

YunaiV 2 meses atrás
pai
commit
3ce4ea3146

+ 49 - 0
src/api/mp/messageTemplate/index.ts

@@ -0,0 +1,49 @@
+import request from '@/config/axios'
+
+// 消息模板 VO
+export interface MsgTemplateVO {
+  id: number // 模版主键
+  accountId: number // 公众号账号的编号
+  appId: string // appId
+  templateId: string // 公众号模板 ID
+  title: string // 标题
+  content: string // 模板内容
+  example: string // 模板示例
+  primaryIndustry: string // 模板所属行业的一级行业
+  deputyIndustry: string // 模板所属行业的二级行业
+  createTime: Date // 创建时间
+}
+
+// 发送消息模板请求 VO
+export interface MsgTemplateSendVO {
+  id: number // 模板编号
+  userId: number // 用户编号
+  data?: string // 模板数据(JSON 格式字符串)
+  url?: string // 跳转链接
+  miniProgramAppId?: string // 小程序 appId
+  miniProgramPagePath?: string // 小程序页面路径
+  miniprogram?: string // 小程序信息(JSON 格式字符串)
+}
+
+// 公众号消息模板 API
+export const MessageTemplateApi = {
+  // 查询消息模板分页
+  getMessageTemplateList: async (params: any) => {
+    return await request.get({ url: `/mp/message-template/list`, params })
+  },
+
+  // 删除消息模板
+  deleteMessageTemplate: async (id: number) => {
+    return await request.delete({ url: `/mp/message-template/delete?id=` + id })
+  },
+
+  // 同步公众号模板
+  syncMessageTemplate: async (accountId: number) => {
+    return await request.post({ url: `/mp/message-template/sync?accountId=` + accountId })
+  },
+
+  // 发送消息模板
+  sendMessageTemplate: async (data: MsgTemplateSendVO) => {
+    return await request.post({ url: `/mp/message-template/send`, data })
+  }
+}

+ 0 - 115
src/api/mp/template/index.ts

@@ -1,115 +0,0 @@
-import request from '@/config/axios'
-
-// 消息模板 VO
-export interface MsgTemplateVO {
-    id: number // 主键
-    appId: string // appid
-    templateId: string // 公众号模板ID
-    name: string // 模版名称
-    title: string // 标题
-    content: string // 模板内容
-    data: string // 消息内容
-    url: string // 链接
-    //miniprogram: string // 小程序信息
-    miniProgramAppId: string
-    miniProgramPagePath: string
-    isRemoved: number
-    configId: number
-    templateType: number
-    status: number // 是否有效
-}
-
-// 消息模板 API
-export const MsgTemplateApi = {
-    // 查询消息模板分页
-    getMsgTemplatePage: async (params: any) => {
-        return await request.get({ url: `/mp/template/page`, params })
-    },
-
-    // 查询消息模板详情
-    getMsgTemplate: async (id: number) => {
-        return await request.get({ url: `/mp/template/get?id=` + id })
-    },
-
-    // 新增消息模板
-    createMsgTemplate: async (data: MsgTemplateVO) => {
-        return await request.post({ url: `/mp/template/create`, data })
-    },
-
-    // 修改消息模板
-    updateMsgTemplate: async (data: MsgTemplateVO) => {
-        return await request.put({ url: `/mp/template/update`, data })
-    },
-
-    // 删除消息模板
-    deleteMsgTemplate: async (id: number) => {
-        return await request.delete({ url: `/mp/template/delete?id=` + id })
-    },
-
-    // 导出消息模板 Excel
-    exportMsgTemplate: async (params) => {
-        return await request.download({ url: `/mp/template/export-excel`, params })
-    },
-
-    // 同步公众号模板
-    syncMsgTemplate: async (params: any) => {
-        return await request.get({ url: `/mp/template/syncMsgTemplate`,params})
-    },
-
-    // 同步公众号模板
-    sendMsgBatch: async (data: any) => {
-        return await request.post({ url: `/mp/template/sendMsgBatch`,data})
-    },
-
-    deleteList: async (data: any) => {
-        return await request.delete({ url: `/mp/template/delete-list`,data})
-    },
-}
-
-// 微信模版消息发送记录 VO
-export interface MsgTemplateLogVO {
-    id: number // 主键
-    appId: string // appId
-    toUser: string // 用户openid
-    templateId: string // 公众号模板ID
-    data: string // 消息内容
-    url: string // 链接
-    miniProgramAppId: string // 小程序appid
-    miniProgramPagePath: string // 小程序页面路径
-    sendTime: Date // 发送时间
-    sendStatus: string // 发送状态 0成功,1失败
-    sendResult: string // 发送结果
-}
-
-// 微信模版消息发送记录 API
-export const MsgTemplateLogApi = {
-    // 查询微信模版消息发送记录分页
-    getMsgTemplateLogPage: async (params: any) => {
-        return await request.get({ url: `/mp/template/log/page`, params })
-    },
-
-    // 查询微信模版消息发送记录详情
-    getMsgTemplateLog: async (id: number) => {
-        return await request.get({ url: `/mp/template/log/get?id=` + id })
-    },
-
-    // 新增微信模版消息发送记录
-    createMsgTemplateLog: async (data: MsgTemplateLogVO) => {
-        return await request.post({ url: `/mp/template/log/create`, data })
-    },
-
-    // 修改微信模版消息发送记录
-    updateMsgTemplateLog: async (data: MsgTemplateLogVO) => {
-        return await request.put({ url: `/mp/template/log/update`, data })
-    },
-
-    // 删除微信模版消息发送记录
-    deleteMsgTemplateLog: async (id: number) => {
-        return await request.delete({ url: `/mp/template/log/delete?id=` + id })
-    },
-
-    // 导出微信模版消息发送记录 Excel
-    exportMsgTemplateLog: async (params) => {
-        return await request.download({ url: `/mp/template/log/export-excel`, params })
-    },
-}

+ 163 - 0
src/views/mp/messageTemplate/MessageTemplateSendForm.vue

@@ -0,0 +1,163 @@
+<template>
+  <Dialog title="发送消息模板" v-model="dialogVisible" width="600px">
+    <el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px">
+      <el-form-item label="模板编号">
+        <el-input v-model="formData.id" disabled />
+      </el-form-item>
+      <el-form-item label="模板标题">
+        <el-input v-model="templateTitle" disabled />
+      </el-form-item>
+      <el-form-item label="用户" prop="userId">
+        <el-select
+          v-model="formData.userId"
+          filterable
+          remote
+          reserve-keyword
+          placeholder="请输入用户昵称搜索"
+          :remote-method="searchUser"
+          :loading="userLoading"
+          class="!w-full"
+        >
+          <el-option
+            v-for="user in userList"
+            :key="user.id"
+            :label="user.nickname || user.openid"
+            :value="user.id"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="模板数据" prop="data">
+        <el-input
+          v-model="formData.data"
+          type="textarea"
+          :rows="4"
+          placeholder='请输入模板数据(JSON 格式),例如:{"keyword1": {"value": "测试内容"}}'
+        />
+      </el-form-item>
+      <el-form-item label="跳转链接" prop="url">
+        <el-input v-model="formData.url" placeholder="请输入跳转链接" />
+      </el-form-item>
+      <el-form-item label="小程序 appId" prop="miniProgramAppId">
+        <el-input v-model="formData.miniProgramAppId" placeholder="请输入小程序 appId" />
+      </el-form-item>
+      <el-form-item label="小程序页面路径" prop="miniProgramPagePath">
+        <el-input v-model="formData.miniProgramPagePath" placeholder="请输入小程序页面路径" />
+      </el-form-item>
+    </el-form>
+    <template #footer>
+      <el-button type="primary" @click="submitForm" :loading="loading">发 送</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+
+<script setup lang="ts">
+import { MessageTemplateApi, MsgTemplateVO, MsgTemplateSendVO } from '@/api/mp/messageTemplate'
+import * as MpUserApi from '@/api/mp/user'
+
+const message = useMessage() // 消息弹窗
+
+const dialogVisible = ref(false) // 弹窗是否展示
+const loading = ref(false) // 提交加载中
+const templateTitle = ref('') // 模板标题
+const accountId = ref<number>() // 公众号账号编号
+
+const formRef = ref() // 表单 Ref
+const formData = ref<MsgTemplateSendVO>({
+  id: undefined!,
+  userId: undefined!,
+  data: '',
+  url: '',
+  miniProgramAppId: '',
+  miniProgramPagePath: ''
+})
+const formRules = reactive({
+  userId: [{ required: true, message: '请选择用户', trigger: 'change' }]
+})
+
+// 用户搜索相关
+const userLoading = ref(false)
+const userList = ref<any[]>([])
+
+/** 搜索用户 */
+const searchUser = async (query: string) => {
+  if (!accountId.value) {
+    return
+  }
+  userLoading.value = true
+  try {
+    const data = await MpUserApi.getUserPage({
+      pageNo: 1,
+      pageSize: 20,
+      accountId: accountId.value,
+      nickname: query || undefined
+    })
+    userList.value = data.list || []
+  } finally {
+    userLoading.value = false
+  }
+}
+
+/** 打开弹窗 */
+const open = async (row: MsgTemplateVO) => {
+  resetForm()
+  dialogVisible.value = true
+  // 设置表单数据
+  formData.value.id = row.id
+  accountId.value = row.accountId
+  templateTitle.value = row.title
+  // 加载用户列表
+  await searchUser('')
+}
+defineExpose({ open }) // 暴露 open 方法
+
+/** 提交表单 */
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef.value) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  loading.value = true
+  try {
+    const sendData: MsgTemplateSendVO = {
+      ...formData.value
+    }
+    // 如果填写了小程序信息,需要拼接成 miniprogram 字段
+    if (sendData.miniProgramAppId && sendData.miniProgramPagePath) {
+      sendData.miniprogram = JSON.stringify({
+        appid: sendData.miniProgramAppId,
+        pagepath: sendData.miniProgramPagePath
+      })
+    }
+    // 如果填写了 data 字段
+    if (sendData.data) {
+      try {
+        sendData.data = JSON.parse(sendData.data)
+      } catch (e) {
+        message.error('模板数据格式不正确,请输入有效的 JSON 格式')
+        return
+      }
+    }
+    await MessageTemplateApi.sendMessageTemplate(sendData)
+    message.success('发送成功')
+    dialogVisible.value = false
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    id: undefined!,
+    userId: undefined!,
+    data: '',
+    url: '',
+    miniProgramAppId: '',
+    miniProgramPagePath: ''
+  }
+  userList.value = []
+  formRef.value?.resetFields()
+}
+</script>

+ 142 - 0
src/views/mp/messageTemplate/index.vue

@@ -0,0 +1,142 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="公众号" prop="accountId">
+        <WxAccountSelect @change="onAccountChanged" />
+      </el-form-item>
+      <el-form-item>
+        <el-button
+          type="success"
+          plain
+          @click="handleSync"
+          :loading="syncLoading"
+          v-hasPermi="['mp:message-template:sync']"
+          :disabled="queryParams.accountId === -1"
+        >
+          <Icon icon="ep:refresh" class="mr-5px" /> 同步
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column label="公众号模板 ID" align="center" prop="templateId" width="200px" />
+      <el-table-column label="标题" align="center" prop="title" width="150px" />
+      <el-table-column label="模板内容" align="center" prop="content" />
+      <el-table-column label="模板示例" align="center" prop="example" width="200px" />
+      <el-table-column label="一级行业" align="center" prop="primaryIndustry" width="120px" />
+      <el-table-column label="二级行业" align="center" prop="deputyIndustry" width="120px" />
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <el-table-column label="操作" align="center" width="160">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="handleSend(scope.row)"
+            v-hasPermi="['mp:message-template:send']"
+          >
+            发送
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['mp:message-template:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </ContentWrap>
+
+  <!-- 表单弹窗:发送消息 -->
+  <MessageTemplateSendForm ref="sendFormRef" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import { MessageTemplateApi, MsgTemplateVO } from '@/api/mp/messageTemplate'
+import MessageTemplateSendForm from './MessageTemplateSendForm.vue'
+import WxAccountSelect from '@/views/mp/components/wx-account-select'
+
+/** 公众号消息模板列表 */
+defineOptions({ name: 'MpMessageTemplate' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<MsgTemplateVO[]>([]) // 列表的数据
+const queryParams = reactive({
+  accountId: -1
+})
+const queryFormRef = ref() // 搜索的表单
+const syncLoading = ref(false) // 同步模板的加载中
+
+/** 公众号选择变化 */
+const onAccountChanged = (accountId: number) => {
+  queryParams.accountId = accountId
+  getList()
+}
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await MessageTemplateApi.getMessageTemplateList(queryParams)
+    if (data) {
+      list.value = data
+    }
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 同步操作 */
+const handleSync = async () => {
+  try {
+    await message.confirm('是否确认同步消息模板?')
+    syncLoading.value = true
+    await MessageTemplateApi.syncMessageTemplate(queryParams.accountId)
+    message.success('同步消息模板成功')
+    await getList()
+  } finally {
+    syncLoading.value = false
+  }
+}
+
+/** 发送消息操作 */
+const sendFormRef = ref()
+const handleSend = (row: MsgTemplateVO) => {
+  sendFormRef.value.open(row)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await MessageTemplateApi.deleteMessageTemplate(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+</script>

+ 0 - 333
src/views/mp/template/MsgTemplate.vue

@@ -1,333 +0,0 @@
-<template>
-  <ContentWrap>
-    <!-- 搜索工作栏 -->
-    <el-form
-        class="-mb-15px"
-        :model="queryParams"
-        ref="queryFormRef"
-        :inline="true"
-        label-width="68px"
-    >
-      <el-form-item label="公众号" prop="accountId">
-        <WxAccountSelect @change="onAccountChanged"/>
-      </el-form-item>
-      <!--      <el-form-item label="appId" prop="appId">
-              <el-input v-model="queryParams.appId" placeholder="请输入appId" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="公众号模板ID" prop="templateId">
-              <el-input v-model="queryParams.templateId" placeholder="请输入公众号模板ID" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="模版名称" prop="name">
-              <el-input v-model="queryParams.name" placeholder="请输入模版名称" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <el-form-item label="标题" prop="title">
-        <el-input
-            v-model="queryParams.title"
-            placeholder="请输入标题"
-            clearable
-            @keyup.enter="handleQuery"
-            class="!w-240px"
-        />
-      </el-form-item>
-      <!--      <el-form-item label="消息内容" prop="data">
-              <el-input v-model="queryParams.data" placeholder="请输入消息内容" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="链接" prop="url">
-              <el-input v-model="queryParams.url" placeholder="请输入链接" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="小程序appId" prop="miniProgramAppId">
-              <el-input v-model="queryParams.miniProgramAppId" placeholder="请输入小程序appId" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="小程序页面路径" prop="miniProgramPagePath">
-              <el-input v-model="queryParams.miniProgramPagePath" placeholder="请输入小程序页面路径" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="是否有效" prop="status">
-              <el-select v-model="queryParams.status" placeholder="请选择是否有效" clearable class="!w-240px">
-                <el-option label="请选择字典生成" value="" />
-              </el-select>
-            </el-form-item>-->
-      <!--      <el-form-item label="公众号是否已移除" prop="isRemoved">
-              <el-input v-model="queryParams.isRemoved" placeholder="请输入公众号是否已移除" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="创建时间" prop="createTime">
-              <el-date-picker
-                v-model="queryParams.createTime"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="daterange"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-                class="!w-220px"
-              />
-            </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 type="primary" plain @click="openForm('create')" v-hasPermi="['mp:template:create']">
-                  <Icon icon="ep:plus" class="mr-5px" /> 新增
-                </el-button>-->
-        <el-button type="warning" plain @click="handleSync" :loading="syncLoading" v-hasPermi="['mp:template:sync']">
-          <Icon icon="ep:refresh" class="mr-5px"/>
-          同步模板
-        </el-button>
-        <el-button type="success" plain @click="handleExport" :loading="exportLoading"
-                   v-hasPermi="['mp:template:export']">
-          <Icon icon="ep:download" class="mr-5px"/>
-          导出
-        </el-button>
-        <el-button :disabled="multipleSelection.length !== 1" type="success" plain @click="sendMessage()"
-                   v-hasPermi="['mp:template:send']">
-          <el-icon>
-            <Promotion/>
-          </el-icon>
-          推送消息
-        </el-button>
-        <el-button :disabled="multipleSelection.length === 0" type="danger" plain @click="batchDelete()"
-                   v-hasPermi="['mp:template:delete']">
-          <el-icon>
-            <DeleteFilled/>
-          </el-icon>
-          批量删除
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </ContentWrap>
-
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-table
-        v-loading="loading"
-        :data="list"
-        :stripe="true"
-        :show-overflow-tooltip="true"
-        @selection-change="handleSelectionChange"
-    >
-      <!--      <el-table-column label="主键" align="center" prop="id" />-->
-      <el-table-column type="selection" width="55"/>
-      <el-table-column label="appId" align="center" prop="appId"/>
-      <el-table-column label="公众号模板ID" align="center" prop="templateId"/>
-      <el-table-column label="模版名称" align="center" prop="name"/>
-      <el-table-column label="标题" align="center" prop="title"/>
-      <el-table-column label="模板内容" align="center" prop="content"/>
-      <el-table-column label="消息内容" align="center" prop="data"/>
-      <el-table-column label="链接" align="center" prop="url"/>
-      <el-table-column label="小程序appId" align="center" prop="miniProgramAppId"/>
-      <el-table-column label="小程序页面路径" align="center" prop="miniProgramPagePath"/>
-      <el-table-column label="是否有效" align="center" prop="status">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.IS_VALID" :value="scope.row.status"/>
-        </template>
-      </el-table-column>
-      <el-table-column label="公众号是否已移除" align="center" prop="isRemoved">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.IS_DELETE" :value="scope.row.isRemoved"/>
-        </template>
-      </el-table-column>
-      <el-table-column
-          label="创建时间"
-          align="center"
-          prop="createTime"
-          :formatter="dateFormatter"
-          width="180px"
-      />
-      <el-table-column label="操作" align="center" min-width="120px">
-        <template #default="scope">
-          <el-button
-              link
-              type="primary"
-              @click="openForm('update', scope.row.id)"
-              v-hasPermi="['mp:template:update']"
-          >
-            配置
-          </el-button>
-          <el-button
-              link
-              type="danger"
-              @click="handleDelete(scope.row.id)"
-              v-hasPermi="['mp:template:delete']"
-          >
-            删除
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination
-        :total="total"
-        v-model:page="queryParams.pageNo"
-        v-model:limit="queryParams.pageSize"
-        @pagination="getList"
-    />
-  </ContentWrap>
-
-  <!-- 表单弹窗:添加/修改 -->
-  <MsgTemplateForm ref="formRef" @success="getList"/>
-  <MsgTemplateSend ref="sendRef" @success="getList"/>
-</template>
-
-<script setup lang="ts">
-import {DICT_TYPE} from '@/utils/dict'
-import {dateFormatter} from '@/utils/formatTime'
-import download from '@/utils/download'
-import {MsgTemplateApi, MsgTemplateVO} from '@/api/mp/template'
-import MsgTemplateForm from './MsgTemplateForm.vue'
-import MsgTemplateSend from './MsgTemplateSend.vue'
-import WxAccountSelect from '@/views/mp/components/wx-account-select'
-import {DeleteFilled, Promotion} from '@element-plus/icons-vue'
-
-/** 消息模板 列表 */
-defineOptions({name: 'MsgTemplate'})
-
-const message = useMessage() // 消息弹窗
-const {t} = useI18n() // 国际化
-
-const loading = ref(true) // 列表的加载中
-const list = ref<MsgTemplateVO[]>([]) // 列表的数据
-const total = ref(0) // 列表的总页数
-const multipleSelection = ref<MsgTemplateVO[]>([])
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  accountId: -1,
-  appId: undefined,
-  templateId: undefined,
-  name: undefined,
-  title: undefined,
-  content: undefined,
-  data: undefined,
-  url: undefined,
-  miniProgramAppId: undefined,
-  miniProgramPagePath: undefined,
-  status: undefined,
-  isRemoved: undefined,
-  createTime: []
-})
-const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
-const syncLoading = ref(false) // 同步模板的加载中
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    const data = await MsgTemplateApi.getMsgTemplatePage(queryParams)
-    if (data) {
-      list.value = data.list
-      total.value = data.total
-    }
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 搜索按钮操作 */
-const handleQuery = () => {
-  queryParams.pageNo = 1
-  getList()
-}
-
-const handleSelectionChange = (val: MsgTemplateVO[]) => {
-  multipleSelection.value = val
-}
-
-/** 重置按钮操作 */
-const resetQuery = async () => {
-  // 暂存 accountId,并在 reset 后恢复
-  const accountId = queryParams.accountId
-  queryFormRef.value?.resetFields()
-  queryParams.accountId = accountId
-  handleQuery()
-}
-
-/** 添加/修改操作 */
-const formRef = ref()
-const openForm = (type: string, id?: number) => {
-  formRef.value.open(type, id)
-}
-/** 添加/修改操作 */
-const sendRef = ref()
-const sendMessage = () => {
-  let templateId = multipleSelection.value[0].templateId;
-  let data = multipleSelection.value[0].data;
-  if (!templateId) {
-    message.warning('消息模板无效')
-    return
-  }
-  if (!data || data.length === 0) {
-    message.warning('消息模板数据无效')
-    return
-  }
-  sendRef.value.open(queryParams.accountId, multipleSelection.value[0].appId, templateId)
-}
-
-/** 删除按钮操作 */
-const handleDelete = async (id: number) => {
-  try {
-    // 删除的二次确认
-    await message.delConfirm()
-    // 发起删除
-    await MsgTemplateApi.deleteMsgTemplate(id)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    await getList()
-  } catch {
-  }
-}
-
-/** 导出按钮操作 */
-const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await MsgTemplateApi.exportMsgTemplate(queryParams)
-    download.excel(data, '消息模板.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-}
-
-/** 同步公众号模板 */
-const handleSync = async () => {
-  try {
-    // 同步的二次确认
-    await message.confirm('确认要同步公众号模板吗?', '提示')
-    // 发起同步
-    syncLoading.value = true
-    await MsgTemplateApi.syncMsgTemplate(queryParams)
-    message.success('同步成功')
-    // 刷新列表
-    await getList()
-  } catch {
-  } finally {
-    syncLoading.value = false
-  }
-}
-
-/** 公众号选择变化 */
-const onAccountChanged = (accountId: number) => {
-  queryParams.accountId = accountId
-  queryParams.pageNo = 1
-  handleQuery()
-}
-
-const batchDelete = async () => {
-  let ids = multipleSelection.value.map((item) => item.id);
-  await message.confirm('确认要删除所选的公众号模板吗?', '提示')
-  await MsgTemplateApi.deleteList(ids)
-  message.success('删除成功')
-}
-
-/** 初始化 **/
-onMounted(() => {
-  // getList()
-})
-</script>

+ 0 - 335
src/views/mp/template/MsgTemplateForm.vue

@@ -1,335 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form ref="formRef" :model="formData" :rules="formRules" label-width="140px" v-loading="formLoading">
-      <!-- 其他表单项保持不变 -->
-      <el-form-item label="appId" prop="appId">
-        <el-input v-model="formData.appId" placeholder="请输入appId"/>
-      </el-form-item>
-      <el-form-item label="公众号模板ID" prop="templateId">
-        <el-input v-model="formData.templateId" placeholder="请输入公众号模板ID"/>
-      </el-form-item>
-      <el-form-item label="模版名称" prop="name">
-        <el-input v-model="formData.name" placeholder="请输入模版名称"/>
-      </el-form-item>
-      <el-form-item label="标题" prop="title">
-        <el-input v-model="formData.title" placeholder="请输入标题"/>
-      </el-form-item>
-      <el-form-item label="链接" prop="url">
-        <el-input v-model="formData.url" placeholder="请输入链接"/>
-      </el-form-item>
-      <el-form-item label="小程序appId" prop="miniProgramAppId">
-        <el-input v-model="formData.miniProgramAppId" placeholder="请输入小程序appId"/>
-      </el-form-item>
-      <el-form-item label="小程序页面路径" prop="miniProgramPagePath">
-        <el-input v-model="formData.miniProgramPagePath" placeholder="请输入小程序页面路径"/>
-      </el-form-item>
-      <el-row :gutter="10">
-        <el-col :span="12">
-          <el-form-item label="是否有效" prop="status">
-            <el-radio-group v-model="formData.status">
-              <el-radio
-                  v-for="dict in getIntDictOptions(DICT_TYPE.IS_VALID)"
-                  :key="dict.value"
-                  :label="dict.value"
-              >
-                {{ dict.label }}
-              </el-radio>
-            </el-radio-group>
-          </el-form-item>
-        </el-col>
-        <!--        <el-col :span="12">
-                  <el-form-item label="公众号是否已移除" prop="isRemoved">
-                    <el-radio-group v-model="formData.isRemoved">
-                      <el-radio
-                          v-for="dict in getIntDictOptions(DICT_TYPE.IS_DELETE)"
-                          :key="dict.value"
-                          :label="dict.value"
-                      >
-                        {{ dict.label }}
-                      </el-radio>
-                    </el-radio-group>
-                  </el-form-item>
-                </el-col>-->
-      </el-row>
-      <el-form-item label="模板内容" prop="content">
-        <el-input
-            readonly
-            type="textarea"
-            v-model="formData.content"
-            :rows="3"
-            autosize
-            placeholder="请输入模板内容,使用{{变量名.DATA}}格式定义变量"
-        />
-      </el-form-item>
-
-      <!-- 修改点:消息变量部分 -->
-      <el-form-item label="消息变量" v-if="templateVariables.length > 0">
-        <div class="variable-editor">
-          <div v-for="(item, index) in templateVariables" :key="item.name" class="variable-item">
-            <el-row :gutter="10">
-              <el-col :span="6">
-                <div class="variable-name">{{ item.name }}</div>
-              </el-col>
-              <el-col :span="14">  <!-- 修改点:增加输入框宽度 -->
-                <el-form-item
-                    :prop="`templateVariables.${index}.value`"
-                >
-                  <el-input v-model="item.value" placeholder="填充内容" clearable/>
-                </el-form-item>
-              </el-col>
-              <el-col :span="4">
-                <el-form-item>
-                  <el-color-picker v-model="item.color" :predefine="predefineColors" size="small"/>
-                </el-form-item>
-              </el-col>
-            </el-row>
-          </div>
-        </div>
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-
-<script setup lang="ts">
-import {ref, reactive, watch, nextTick} from 'vue'
-import {MsgTemplateApi, type MsgTemplateVO} from '@/api/mp/template'
-import {getIntDictOptions, DICT_TYPE} from '@/utils/dict'
-import type {FormInstance, FormRules} from 'element-plus'
-
-interface TemplateVariable {
-  name: string;
-  value: string;
-  color: string;
-}
-
-// 消息模板表单组件
-defineOptions({name: 'MsgTemplateForm'})
-
-const {t} = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-const dialogVisible = ref(false) // 弹窗是否展示
-const dialogTitle = ref('') // 弹窗标题
-const formLoading = ref(false) // 表单加载状态
-const formType = ref('') // 表单类型:create/update
-const list = ref<any[]>([])
-
-// 表单数据保持不变
-const formData = reactive<MsgTemplateVO>({
-  id: undefined,
-  appId: '',
-  templateId: '',
-  name: '',
-  title: '',
-  content: '',
-  data: '',
-  url: '',
-  miniProgramAppId: '',
-  miniProgramPagePath: '',
-  status: 0,
-  isRemoved: 0
-})
-
-// 表单验证规则保持不变
-const formRules = reactive<FormRules<MsgTemplateVO>>({
-  appId: [{required: true, message: 'appId不能为空', trigger: 'blur'}],
-  templateId: [{required: true, message: '公众号模板ID不能为空', trigger: 'blur'}],
-  name: [{required: true, message: '模板名称不能为空', trigger: 'blur'}],
-  title: [{required: true, message: '标题不能为空', trigger: 'blur'}],
-  status: [{required: true, message: '请选择是否有效', trigger: 'change'}]
-})
-
-const templateVariables = ref<TemplateVariable[]>([]) // 模板变量
-const predefineColors = ref([
-  '#000000', // 黑色
-  '#173177', // 深蓝色
-  '#ff0000', // 红色
-  '#00b050', // 绿色
-  '#ff9900', // 橙色
-  '#800080', // 紫色
-]) // 预定义颜色
-
-const formRef = ref<FormInstance>() // 表单引用
-
-// 以下是新增的模板变量相关代码
-
-// 提取模板中的变量名
-const extractTemplateVariables = (content: string): string[] => {
-  if (!content) return []
-  const regex = /\{\{(\w+)\.DATA\}\}/g
-  const matches = content.match(regex) || []
-  const uniqueNames = [...new Set(matches.map(match =>
-      match.replace('{{', '').replace('.DATA}}', '')
-  ))]
-  return uniqueNames
-}
-
-// 当模板内容变化时更新变量列表
-watch(() => formData.content, (newContent) => {
-  const variableNames = extractTemplateVariables(newContent)
-
-  // 保留现有变量值
-  const currentVariables = [...templateVariables.value]
-
-  // 创建新的变量列表
-  const newVariables = variableNames.map(name => {
-    const existing = currentVariables.find(v => v.name === name)
-    return existing || {name, value: '', color: '#000000'}
-  })
-
-  templateVariables.value = newVariables
-})
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-
-  if (id) {
-    formLoading.value = true
-    try {
-      const res = await MsgTemplateApi.getMsgTemplate(id)
-      Object.assign(formData, res)
-
-      // 解析模板变量
-      if (res.data) {
-        try {
-          const parsedData = JSON.parse(res.data)
-          if (Array.isArray(parsedData)) {
-            templateVariables.value = parsedData
-          }
-        } catch (e) {
-          // 如果解析失败,从内容中提取变量
-          const variableNames = extractTemplateVariables(res.content || '')
-          templateVariables.value = variableNames.map(name => ({
-            name,
-            value: '',
-            color: '#000000'
-          }))
-        }
-      } else {
-        // 没有数据字段,从内容中提取变量
-        const variableNames = extractTemplateVariables(res.content || '')
-        templateVariables.value = variableNames.map(name => ({
-          name,
-          value: '',
-          color: '#000000'
-        }))
-      }
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-
-defineExpose({open}) // 暴露open方法
-
-/** 提交表单 */
-const emit = defineEmits(['success'])
-const submitForm = async () => {
-  if (!formRef.value) return
-
-  // 使用 Element Plus 表单验证统一处理所有校验
-  try {
-    await formRef.value.validate()
-
-    // 验证模板变量是否都填写了
-    const isAllFilled = templateVariables.value.every(item => item.value.trim() !== '')
-    if (!isAllFilled) {
-      message.error('请填写所有消息变量的内容')
-      return
-    }
-
-    // 准备数据 - 修改点:将模板变量转为JSON字符串
-    const submitData = {
-      ...formData,
-      data: JSON.stringify(templateVariables.value)
-    }
-
-    formLoading.value = true
-    try {
-      if (formType.value === 'create') {
-        await MsgTemplateApi.createMsgTemplate(submitData)
-        message.success(t('common.createSuccess'))
-      } else {
-        await MsgTemplateApi.updateMsgTemplate(submitData)
-        message.success(t('common.updateSuccess'))
-      }
-      dialogVisible.value = false
-      emit('success')
-    } catch (error) {
-      message.error('操作失败,请重试')
-    } finally {
-      formLoading.value = false
-    }
-  } catch (error) {
-    // 表单验证失败
-    message.error('请完善表单信息')
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formRef.value?.resetFields()
-  Object.assign(formData, {
-    id: undefined,
-    appId: '',
-    templateId: '',
-    name: '',
-    title: '',
-    content: '',
-    data: '',
-    url: '',
-    miniProgramAppId: '',
-    miniProgramPagePath: '',
-    status: 0,
-    isRemoved: 0
-  })
-  // 新增:重置模板变量
-  templateVariables.value = []
-}
-</script>
-
-<style scoped>
-/* 新增的样式 */
-.variable-editor {
-  width: 100%;
-  border: 1px solid #EBEEF5;
-  border-radius: 4px;
-  padding: 12px;
-  background-color: var(--el-bg-color);
-}
-
-.variable-item {
-  padding: 8px 0;
-}
-
-.variable-item + .variable-item {
-  border-top: 1px dashed #EBEEF5;
-  padding-top: 12px;
-}
-
-.variable-name {
-  line-height: 32px;
-  font-weight: bold;
-  color: var(--el-text-color);
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}
-
-:deep(.el-color-picker) {
-  vertical-align: middle;
-  margin-left: 8px;
-}
-
-/* 增加输入框宽度 */
-.variable-editor :deep(.el-input) {
-  width: 100%;
-}
-</style>

+ 0 - 214
src/views/mp/template/MsgTemplateLog.vue

@@ -1,214 +0,0 @@
-<template>
-  <ContentWrap>
-    <!-- 搜索工作栏 -->
-    <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="100px">
-      <!--      <el-form-item label="appId" prop="appId">
-              <el-input v-model="queryParams.appId" placeholder="请输入appId" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <el-form-item label="用户openid" prop="toUser">
-        <el-input v-model="queryParams.toUser" placeholder="请输入用户openid" clearable @keyup.enter="handleQuery"
-                  class="!w-240px"/>
-      </el-form-item>
-      <!--      <el-form-item label="公众号模板ID" prop="templateId">
-              <el-input v-model="queryParams.templateId" placeholder="请输入公众号模板ID" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="消息内容" prop="data">
-              <el-input v-model="queryParams.data" placeholder="请输入消息内容" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="链接" prop="url">
-              <el-input v-model="queryParams.url" placeholder="请输入链接" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="小程序appid" prop="miniProgramAppId">
-              <el-input v-model="queryParams.miniProgramAppId" placeholder="请输入小程序appid" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="小程序页面路径" prop="miniProgramPagePath">
-              <el-input v-model="queryParams.miniProgramPagePath" placeholder="请输入小程序页面路径" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </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="结束日期"
-                :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-                class="!w-220px"
-              />
-            </el-form-item>-->
-      <!--      <el-form-item label="发送状态 0成功,1失败" prop="sendStatus">
-              <el-select v-model="queryParams.sendStatus" placeholder="请选择发送状态 0成功,1失败" clearable class="!w-240px">
-                <el-option label="请选择字典生成" value="" />
-              </el-select>
-            </el-form-item>-->
-      <!--      <el-form-item label="发送结果" prop="sendResult">
-              <el-input v-model="queryParams.sendResult" placeholder="请输入发送结果" clearable @keyup.enter="handleQuery" class="!w-240px"/>
-            </el-form-item>-->
-      <!--      <el-form-item label="创建时间" prop="createTime">
-              <el-date-picker
-                v-model="queryParams.createTime"
-                value-format="YYYY-MM-DD HH:mm:ss"
-                type="daterange"
-                start-placeholder="开始日期"
-                end-placeholder="结束日期"
-                :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-                class="!w-220px"
-              />
-            </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 type="primary" plain @click="openForm('create')" v-hasPermi="['mp:template-log:create']">
-                  <Icon icon="ep:plus" class="mr-5px" /> 新增
-                </el-button>-->
-        <el-button type="success" plain @click="handleExport" :loading="exportLoading"
-                   v-hasPermi="['mp:template-log:export']">
-          <Icon icon="ep:download" class="mr-5px"/>
-          导出
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </ContentWrap>
-
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <!--      <el-table-column label="主键" align="center" prop="id" />-->
-      <el-table-column label="appId" align="center" prop="appId"/>
-      <el-table-column label="用户openid" align="center" prop="toUser"/>
-      <el-table-column label="公众号模板ID" align="center" prop="templateId"/>
-      <el-table-column label="消息内容" align="center" prop="data"/>
-      <el-table-column label="链接" align="center" prop="url"/>
-      <el-table-column label="小程序appid" align="center" prop="miniProgramAppId"/>
-      <el-table-column label="小程序页面路径" align="center" prop="miniProgramPagePath"/>
-      <el-table-column label="发送时间" align="center" prop="sendTime" :formatter="dateFormatter" width="180px"/>
-      <el-table-column label="发送状态" align="center" prop="sendStatus">
-        <template #default="scope">
-          <dict-tag :type="DICT_TYPE.SEND_STATUS" :value="scope.row.sendStatus"/>
-        </template>
-      </el-table-column>
-      <el-table-column label="发送结果" align="center" prop="sendResult"/>
-      <el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px"/>
-      <el-table-column label="操作" align="center" min-width="120px">
-        <template #default="scope">
-          <!--          <el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['mp:template-log:update']">
-                      编辑
-                    </el-button>-->
-          <el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['mp:template-log:delete']">
-            删除
-          </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
-                @pagination="getList"/>
-  </ContentWrap>
-
-  <!-- 表单弹窗:添加/修改 -->
-  <MsgTemplateLogForm ref="formRef" @success="getList"/>
-</template>
-
-<script setup lang="ts">
-import {DICT_TYPE} from '@/utils/dict'
-import {dateFormatter} from '@/utils/formatTime'
-import download from '@/utils/download'
-import {MsgTemplateLogApi, MsgTemplateLogVO} from '@/api/mp/template'
-import MsgTemplateLogForm from './MsgTemplateLogForm.vue'
-
-/** 微信模版消息发送记录 列表 */
-defineOptions({name: 'MsgTemplateLog'})
-
-const message = useMessage() // 消息弹窗
-const {t} = useI18n() // 国际化
-
-const loading = ref(true) // 列表的加载中
-const list = ref<MsgTemplateLogVO[]>([]) // 列表的数据
-const total = ref(0) // 列表的总页数
-const queryParams = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  appId: undefined,
-  toUser: undefined,
-  templateId: undefined,
-  data: undefined,
-  url: undefined,
-  miniProgramAppId: undefined,
-  miniProgramPagePath: undefined,
-  sendTime: [],
-  sendStatus: undefined,
-  sendResult: undefined,
-  createTime: [],
-})
-const queryFormRef = ref() // 搜索的表单
-const exportLoading = ref(false) // 导出的加载中
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    const data = await MsgTemplateLogApi.getMsgTemplateLogPage(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 formRef = ref()
-const openForm = (type: string, id?: number) => {
-  formRef.value.open(type, id)
-}
-
-/** 删除按钮操作 */
-const handleDelete = async (id: number) => {
-  try {
-    // 删除的二次确认
-    await message.delConfirm()
-    // 发起删除
-    await MsgTemplateLogApi.deleteMsgTemplateLog(id)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    await getList()
-  } catch {
-  }
-}
-
-/** 导出按钮操作 */
-const handleExport = async () => {
-  try {
-    // 导出的二次确认
-    await message.exportConfirm()
-    // 发起导出
-    exportLoading.value = true
-    const data = await MsgTemplateLogApi.exportMsgTemplateLog(queryParams)
-    download.excel(data, '微信模版消息发送记录.xls')
-  } catch {
-  } finally {
-    exportLoading.value = false
-  }
-}
-
-/** 初始化 **/
-onMounted(() => {
-  getList()
-})
-</script>

+ 0 - 144
src/views/mp/template/MsgTemplateLogForm.vue

@@ -1,144 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form
-        ref="formRef"
-        :model="formData"
-        :rules="formRules"
-        label-width="100px"
-        v-loading="formLoading"
-    >
-      <el-form-item label="appId" prop="appId">
-        <el-input v-model="formData.appId" placeholder="请输入appId"/>
-      </el-form-item>
-      <el-form-item label="用户openid" prop="toUser">
-        <el-input v-model="formData.toUser" placeholder="请输入用户openid"/>
-      </el-form-item>
-      <el-form-item label="公众号模板ID" prop="templateId">
-        <el-input v-model="formData.templateId" placeholder="请输入公众号模板ID"/>
-      </el-form-item>
-      <el-form-item label="消息内容" prop="data">
-        <el-input v-model="formData.data" placeholder="请输入消息内容"/>
-      </el-form-item>
-      <el-form-item label="链接" prop="url">
-        <el-input v-model="formData.url" placeholder="请输入链接"/>
-      </el-form-item>
-      <el-form-item label="小程序appid" prop="miniProgramAppId">
-        <el-input v-model="formData.miniProgramAppId" placeholder="请输入小程序appid"/>
-      </el-form-item>
-      <el-form-item label="小程序页面路径" prop="miniProgramPagePath">
-        <el-input v-model="formData.miniProgramPagePath" placeholder="请输入小程序页面路径"/>
-      </el-form-item>
-      <el-form-item label="发送时间" prop="sendTime">
-        <el-date-picker
-            v-model="formData.sendTime"
-            type="date"
-            value-format="x"
-            placeholder="选择发送时间"
-        />
-      </el-form-item>
-      <el-form-item label="发送状态 0成功,1失败" prop="sendStatus">
-        <el-radio-group v-model="formData.sendStatus">
-          <el-radio value="1">请选择字典生成</el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="发送结果" prop="sendResult">
-        <el-input v-model="formData.sendResult" placeholder="请输入发送结果"/>
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts">
-import {MsgTemplateLogApi, MsgTemplateLogVO} from '@/api/mp/template'
-
-/** 微信模版消息发送记录 表单 */
-defineOptions({name: 'MsgTemplateLogForm'})
-
-const {t} = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref({
-  id: undefined,
-  appId: undefined,
-  toUser: undefined,
-  templateId: undefined,
-  data: undefined,
-  url: undefined,
-  miniProgramAppId: undefined,
-  miniProgramPagePath: undefined,
-  sendTime: undefined,
-  sendStatus: undefined,
-  sendResult: undefined,
-})
-const formRules = reactive({
-  appId: [{required: true, message: 'appId不能为空', trigger: 'blur'}],
-})
-const formRef = ref() // 表单 Ref
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  // 修改时,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await MsgTemplateLogApi.getMsgTemplateLog(id)
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({open}) // 提供 open 方法,用于打开弹窗
-
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-  // 校验表单
-  await formRef.value.validate()
-  // 提交请求
-  formLoading.value = true
-  try {
-    const data = formData.value as unknown as MsgTemplateLogVO
-    if (formType.value === 'create') {
-      await MsgTemplateLogApi.createMsgTemplateLog(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await MsgTemplateLogApi.updateMsgTemplateLog(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
-    // 发送操作成功的事件
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-    id: undefined,
-    appId: undefined,
-    toUser: undefined,
-    templateId: undefined,
-    data: undefined,
-    url: undefined,
-    miniProgramAppId: undefined,
-    miniProgramPagePath: undefined,
-    sendTime: undefined,
-    sendStatus: undefined,
-    sendResult: undefined,
-  }
-  formRef.value?.resetFields()
-}
-</script>

+ 0 - 82
src/views/mp/template/MsgTemplateSend.vue

@@ -1,82 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <div style="font-size: 16px;margin: 10px 0;">已选择{{
-        multipleSelection.length > 0 ? multipleSelection
-            .length : total
-      }}个用户
-    </div>
-    <mpUser ref="mpUserRef" @change="mpUserChange"/>
-    <template #footer>
-      <el-button type="primary" @click="submit" :disabled="multipleSelection.length==0&&total==0" :loading="loading">推 送</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-
-<script setup lang="ts">
-import {ref, nextTick} from "vue";
-import mpUser from '@/views/mp/user/index.vue'
-import {MsgTemplateApi} from "@/api/mp/template";
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗是否展示
-const dialogTitle = ref('') // 弹窗标题
-const multipleSelection = ref<any[]>([])
-const total = ref(0)
-const loading = ref(false)
-
-let dataForm = reactive({
-  pageNo: 1,
-  pageSize: 10,
-  accountId: -1,
-  openid: '',
-  nickname: '',
-  unionId: '',
-  openidList: [] as string[],
-  appId: '',
-  templateId: ''
-})
-
-/** 打开mpUser弹窗 */
-const mpUserRef = ref()
-const open = async (accountId: number, appId: string, templateId: string) => {
-  // 清空dataForm
-  Object.keys(dataForm).forEach((key) => {
-    dataForm[key] = ''
-  })
-  loading.value = false
-  dialogVisible.value = true
-  dialogTitle.value = "批量推送消息"
-  await nextTick()
-  mpUserRef.value.open(accountId)
-  dataForm.accountId = accountId
-  dataForm.appId = appId
-  dataForm.templateId = templateId
-}
-defineExpose({open}) // 暴露open方法
-
-const submit = async () => {
-  try {
-    await message.confirm(`已选择${multipleSelection.value.length > 0 ? multipleSelection.value.length : total.value}个用户,请确认是否推送?`)
-    loading.value = true
-    await MsgTemplateApi.sendMsgBatch(dataForm)
-    message.success('推送成功')
-    dialogVisible.value = false
-    loading.value = false
-  } catch (e) {
-    console.error(e);
-  }
-}
-
-const mpUserChange = (changeEventData: any) => {
-  total.value = changeEventData.total;
-  multipleSelection.value = changeEventData.multipleSelection;
-  dataForm = {...dataForm, ...changeEventData.queryParams};
-  dataForm.openidList = changeEventData.multipleSelection.map((item: any) => item.openid);
-}
-
-</script>
-
-<style scoped lang="scss"></style>