From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/views/mp/autoReply/index.vue |  241 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 241 insertions(+), 0 deletions(-)

diff --git a/src/views/mp/autoReply/index.vue b/src/views/mp/autoReply/index.vue
new file mode 100644
index 0000000..0b00647
--- /dev/null
+++ b/src/views/mp/autoReply/index.vue
@@ -0,0 +1,241 @@
+<template>
+  <doc-alert title="鑷姩鍥炲" url="https://doc.iocoder.cn/mp/auto-reply/" />
+
+  <!-- 鎼滅储宸ヤ綔鏍� -->
+  <ContentWrap>
+    <el-form class="-mb-15px" :model="queryParams" :inline="true" label-width="68px">
+      <el-form-item label="鍏紬鍙�" prop="accountId">
+        <WxAccountSelect @change="onAccountChanged" />
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- tab 鍒囨崲 -->
+  <ContentWrap>
+    <el-tabs v-model="msgType" @tab-change="onTabChange">
+      <!-- 鎿嶄綔宸ュ叿鏍� -->
+      <el-row :gutter="10" class="mb8">
+        <el-col :span="1.5">
+          <el-button
+            type="primary"
+            plain
+            @click="onCreate"
+            v-hasPermi="['mp:auto-reply:create']"
+            v-if="msgType !== MsgType.Follow || list.length <= 0"
+          >
+            <Icon icon="ep:plus" />鏂板
+          </el-button>
+        </el-col>
+      </el-row>
+      <!-- tab 椤� -->
+      <el-tab-pane :name="MsgType.Follow">
+        <template #label>
+          <el-row align="middle"><Icon icon="ep:star" class="mr-2px" /> 鍏虫敞鏃跺洖澶�</el-row>
+        </template>
+      </el-tab-pane>
+      <el-tab-pane :name="MsgType.Message">
+        <template #label>
+          <el-row align="middle"><Icon icon="ep:chat-line-round" class="mr-2px" /> 娑堟伅鍥炲</el-row>
+        </template>
+      </el-tab-pane>
+      <el-tab-pane :name="MsgType.Keyword">
+        <template #label>
+          <el-row align="middle"><Icon icon="fa:newspaper-o" class="mr-2px" /> 鍏抽敭璇嶅洖澶�</el-row>
+        </template>
+      </el-tab-pane>
+    </el-tabs>
+    <!-- 鍒楄〃 -->
+    <ReplyTable
+      :loading="loading"
+      :list="list"
+      :msg-type="msgType"
+      @on-update="onUpdate"
+      @on-delete="onDelete"
+    />
+
+    <el-dialog
+      :title="isCreating ? '鏂板鑷姩鍥炲' : '淇敼鑷姩鍥炲'"
+      v-model="showDialog"
+      width="800px"
+      destroy-on-close
+    >
+      <ReplyForm v-model="replyForm" v-model:reply="reply" :msg-type="msgType" ref="formRef" />
+      <template #footer>
+        <el-button @click="cancel">鍙� 娑�</el-button>
+        <el-button type="primary" @click="onSubmit">纭� 瀹�</el-button>
+      </template>
+    </el-dialog>
+  </ContentWrap>
+</template>
+<script lang="ts" setup>
+import ReplyForm from '@/views/mp/autoReply/components/ReplyForm.vue'
+import { type Reply, ReplyType } from '@/views/mp/components/wx-reply'
+import WxAccountSelect from '@/views/mp/components/wx-account-select'
+import * as MpAutoReplyApi from '@/api/mp/autoReply'
+import { ContentWrap } from '@/components/ContentWrap'
+import type { TabPaneName } from 'element-plus'
+import ReplyTable from './components/ReplyTable.vue'
+import { MsgType } from './components/types'
+
+defineOptions({ name: 'MpAutoReply' })
+
+const message = useMessage() // 娑堟伅
+
+const accountId = ref(-1) // 鍏紬鍙稩D
+const msgType = ref<MsgType>(MsgType.Keyword) // 娑堟伅绫诲瀷
+const loading = ref(true) // 閬僵灞�
+const total = ref(0) // 鎬绘潯鏁�
+const list = ref<any[]>([]) // 鑷姩鍥炲鍒楄〃
+const formRef = ref<InstanceType<typeof ReplyForm> | null>(null) // 琛ㄥ崟 ref
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  accountId: accountId
+})
+
+const isCreating = ref(false) // 鏄惁鏂板缓锛堝惁鍒欑紪杈戯級
+const showDialog = ref(false) // 鏄惁鏄剧ず寮瑰嚭灞�
+const replyForm = ref<any>({}) // 琛ㄥ崟鍙傛暟
+// 鍥炲娑堟伅
+const reply = ref<Reply>({
+  type: ReplyType.Text,
+  accountId: -1
+})
+
+/** 渚﹀惉璐﹀彿鍙樺寲 */
+const onAccountChanged = (id: number) => {
+  accountId.value = id
+  reply.value.accountId = id
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 鏌ヨ鍒楄〃 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await MpAutoReplyApi.getAutoReplyPage({
+      ...queryParams,
+      type: msgType.value
+    })
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+const onTabChange = (tabName: TabPaneName) => {
+  msgType.value = tabName as MsgType
+  handleQuery()
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+const onCreate = () => {
+  reset()
+  // 鎵撳紑琛ㄥ崟锛屽苟璁剧疆鍒濆鍖�
+  reply.value = {
+    type: ReplyType.Text,
+    accountId: queryParams.accountId
+  }
+
+  isCreating.value = true
+  showDialog.value = true
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+const onUpdate = async (id: number) => {
+  reset()
+
+  const data = await MpAutoReplyApi.getAutoReply(id)
+  // 璁剧疆灞炴��
+  replyForm.value = { ...data }
+  delete replyForm.value['responseMessageType']
+  delete replyForm.value['responseContent']
+  delete replyForm.value['responseMediaId']
+  delete replyForm.value['responseMediaUrl']
+  delete replyForm.value['responseDescription']
+  delete replyForm.value['responseArticles']
+  reply.value = {
+    type: data.responseMessageType,
+    accountId: queryParams.accountId,
+    content: data.responseContent,
+    mediaId: data.responseMediaId,
+    url: data.responseMediaUrl,
+    title: data.responseTitle,
+    description: data.responseDescription,
+    thumbMediaId: data.responseThumbMediaId,
+    thumbMediaUrl: data.responseThumbMediaUrl,
+    articles: data.responseArticles,
+    musicUrl: data.responseMusicUrl,
+    hqMusicUrl: data.responseHqMusicUrl
+  }
+
+  // 鎵撳紑琛ㄥ崟
+  isCreating.value = false
+  showDialog.value = true
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+const onDelete = async (id: number) => {
+  await message.confirm('鏄惁纭鍒犻櫎姝ゆ暟鎹�?')
+  await MpAutoReplyApi.deleteAutoReply(id)
+  await getList()
+  message.success('鍒犻櫎鎴愬姛')
+}
+
+const onSubmit = async () => {
+  await formRef.value?.validate()
+
+  // 澶勭悊鍥炲娑堟伅
+  const submitForm: any = { ...replyForm.value }
+  submitForm.responseMessageType = reply.value.type
+  submitForm.responseContent = reply.value.content
+  submitForm.responseMediaId = reply.value.mediaId
+  submitForm.responseMediaUrl = reply.value.url
+  submitForm.responseTitle = reply.value.title
+  submitForm.responseDescription = reply.value.description
+  submitForm.responseThumbMediaId = reply.value.thumbMediaId
+  submitForm.responseThumbMediaUrl = reply.value.thumbMediaUrl
+  submitForm.responseArticles = reply.value.articles
+  submitForm.responseMusicUrl = reply.value.musicUrl
+  submitForm.responseHqMusicUrl = reply.value.hqMusicUrl
+
+  if (replyForm.value.id !== undefined) {
+    await MpAutoReplyApi.updateAutoReply(submitForm)
+    message.success('淇敼鎴愬姛')
+  } else {
+    await MpAutoReplyApi.createAutoReply(submitForm)
+    message.success('鏂板鎴愬姛')
+  }
+
+  showDialog.value = false
+  await getList()
+}
+
+// 琛ㄥ崟閲嶇疆
+const reset = () => {
+  replyForm.value = {
+    id: undefined,
+    accountId: queryParams.accountId,
+    type: msgType.value,
+    requestKeyword: undefined,
+    requestMatch: msgType.value === MsgType.Keyword ? 1 : undefined,
+    requestMessageType: undefined
+  }
+  formRef.value?.resetFields()
+}
+
+// 鍙栨秷鎸夐挳
+const cancel = () => {
+  showDialog.value = false
+  reset()
+}
+</script>

--
Gitblit v1.8.0