diff --git a/src/views/mp/account/form.vue b/src/views/mp/account/form.vue new file mode 100644 index 00000000..37ffb888 --- /dev/null +++ b/src/views/mp/account/form.vue @@ -0,0 +1,158 @@ +<template> + <Dialog :title="modelTitle" v-model="modelVisible"> + <el-form ref="formRef" :model="formData" :rules="rules" label-width="120px"> + <el-form-item label="名称" prop="name"> + <el-input v-model="formData.name" placeholder="请输入名称" /> + </el-form-item> + <el-form-item label="微信号" prop="account"> + <template #label> + <span> + <el-tooltip + content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 账号详情] 中能找到「微信号」" + placement="top" + > + <Icon icon="ep:question-filled" style="vertical-align: middle" /> + </el-tooltip> + 微信号 + </span> + </template> + <el-input v-model="formData.account" placeholder="请输入微信号" /> + </el-form-item> + <el-form-item label="appId" prop="appId"> + <template #label> + <span> + <el-tooltip + content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 基本设置] 中能找到「开发者ID(AppID)」" + placement="top" + > + <Icon icon="ep:question-filled" style="vertical-align: middle" /> + </el-tooltip> + appId + </span> + </template> + <el-input v-model="formData.appId" placeholder="请输入公众号 appId" /> + </el-form-item> + <el-form-item label="appSecret" prop="appSecret"> + <template #label> + <span> + <el-tooltip + content="在微信公众平台(mp.weixin.qq.com)的菜单 [设置与开发 - 公众号设置 - 基本设置] 中能找到「开发者密码(AppSecret)」" + placement="top" + > + <Icon icon="ep:question-filled" style="vertical-align: middle" /> + </el-tooltip> + appSecret + </span> + </template> + <el-input v-model="formData.appSecret" placeholder="请输入公众号 appSecret" /> + </el-form-item> + <el-form-item label="token" prop="token"> + <el-input v-model="formData.token" placeholder="请输入公众号token" /> + </el-form-item> + <el-form-item label="消息加解密密钥" prop="aesKey"> + <el-input v-model="formData.aesKey" placeholder="请输入消息加解密密钥" /> + </el-form-item> + <el-form-item label="备注" prop="remark"> + <el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" /> + </el-form-item> + </el-form> + <template #footer> + <div class="dialog-footer"> + <el-button type="primary" @click="submitForm">确 定</el-button> + <el-button @click="modelVisible = false">取 消</el-button> + </div> + </template> + </Dialog> +</template> +<script setup lang="ts"> +import * as AccountApi from '@/api/mp/account' + +const { t } = useI18n() // 国际化 +const message = useMessage() // 消息弹窗 + +const modelVisible = ref(false) // 弹窗的是否展示 +const modelTitle = ref('') // 弹窗的标题 +const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 +const formType = ref('') // 表单的类型:create - 新增;update - 修改 +// 表单参数 +const formData = ref({ + id: undefined, + name: '', + account: '', + appId: '', + appSecret: '', + token: '', + aesKey: '', + remark: '' +}) +// 表单校验 +const rules = reactive({ + name: [{ required: true, message: '名称不能为空', trigger: 'blur' }], + account: [{ required: true, message: '公众号账号不能为空', trigger: 'blur' }], + appId: [{ required: true, message: '公众号 appId 不能为空', trigger: 'blur' }], + appSecret: [{ required: true, message: '公众号密钥不能为空', trigger: 'blur' }], + token: [{ required: true, message: '公众号 token 不能为空', trigger: 'blur' }] +}) +const formRef = ref() // 表单 Ref + +/** 打开弹窗 */ +const openModal = async (type: string, id?: number) => { + modelVisible.value = true + modelTitle.value = t('action.' + type) + formType.value = type + resetForm() + // 修改时,设置数据 + if (id) { + formLoading.value = true + try { + formData.value = await AccountApi.getAccount(id) + } finally { + formLoading.value = false + } + } +} +defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 + +/** 提交表单 */ +const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 + +/** 提交按钮 */ +const submitForm = async () => { + // 校验表单 + if (!formRef) return + const valid = await formRef.value.validate() + if (!valid) return + // 提交请求 + formLoading.value = true + try { + const data = formData.value + if (formType.value === 'create') { + await AccountApi.createAccount(data) + message.success(t('common.createSuccess')) + } else { + await AccountApi.updateAccount(data) + message.success(t('common.updateSuccess')) + } + modelVisible.value = false + // 发送操作成功的事件 + emit('success') + } finally { + formLoading.value = false + } +} + +/** 表单重置 */ +const resetForm = () => { + formData.value = { + id: undefined, + name: '', + account: '', + appId: '', + appSecret: '', + token: '', + aesKey: '', + remark: '' + } + formRef.value?.resetFields() +} +</script> diff --git a/src/views/mp/account/index.vue b/src/views/mp/account/index.vue index 497f72ec..04a7efe5 100644 --- a/src/views/mp/account/index.vue +++ b/src/views/mp/account/index.vue @@ -1,3 +1,187 @@ <template> - <span>开发中</span> + <!-- 搜索工作栏 --> + <content-wrap> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="90px" + > + <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> + <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" @click="openModal('create')" v-hasPermi="['mp:account:create']" + ><Icon icon="ep:plus" class="mr-5px" />新增 + </el-button> + </el-form-item> + </el-form> + </content-wrap> + + <!-- 列表 --> + <content-wrap> + <el-table v-loading="loading" :data="list"> + <el-table-column label="名称" align="center" prop="name" /> + <el-table-column label="微信号" align="center" prop="account" width="180" /> + <el-table-column label="appId" align="center" prop="appId" width="180" /> + <el-table-column label="服务器地址(URL)" align="center" prop="appId" width="360"> + <template #default="scope"> + {{ 'http://服务端地址/mp/open/' + scope.row.appId }} + </template> + </el-table-column> + <el-table-column label="二维码" align="center" prop="qrCodeUrl"> + <template #default="scope"> + <img + v-if="scope.row.qrCodeUrl" + :src="scope.row.qrCodeUrl" + alt="二维码" + style="height: 100px; display: inline-block" + /> + </template> + </el-table-column> + <el-table-column label="备注" align="center" prop="remark" /> + <el-table-column label="操作" align="center"> + <template #default="scope"> + <el-button + link + type="primary" + @click="openModal('update', scope.row.id)" + v-hasPermi="['mp:account:update']" + >编辑 + </el-button> + <el-button + link + type="danger" + @click="handleDelete(scope.row.id)" + v-hasPermi="['mp:account:delete']" + >删除 + </el-button> + <el-button + link + type="primary" + @click="handleGenerateQrCode(scope.row)" + v-hasPermi="['mp:account:qr-code']" + >生成二维码 + </el-button> + <el-button + link + type="danger" + @click="handleCleanQuota(scope.row)" + v-hasPermi="['mp:account:clear-quota']" + >清空 API 配额 + </el-button> + </template> + </el-table-column> + </el-table> + <!-- 分页组件 --> + <pagination + v-show="total > 0" + :total="total" + v-model:page="queryParams.pageNo" + v-model:limit="queryParams.pageSize" + @pagination="getList" + /> + </content-wrap> + <!-- 对话框(添加 / 修改) --> + <account-form ref="modalRef" @success="getList" /> </template> + +<script setup lang="ts" name="MpAccount"> +import * as AccountApi from '@/api/mp/account' +import AccountForm from './form.vue' + +const message = useMessage() // 消息弹窗 +const { t } = useI18n() // 国际化 +// 遮罩层 +const loading = ref(true) +// 总条数 +const total = ref(0) +// 公众号账号列表 +const list = ref([]) +// 查询参数 +const queryParams = reactive({ + pageNo: 1, + pageSize: 10, + name: null, + account: null, + appId: null +}) +const queryFormRef = ref() // 搜索的表单 + +/** 查询列表 */ +const getList = async () => { + loading.value = true + // 处理查询参数 + let params = { ...queryParams } + // 执行查询 + const data = await AccountApi.getAccountPage(params) + list.value = data.list + total.value = data.total + loading.value = false +} + +/** 搜索按钮操作 */ +const handleQuery = () => { + queryParams.pageNo = 1 + getList() +} +/** 重置按钮操作 */ +const resetQuery = () => { + queryFormRef.value.resetFields() + handleQuery() +} + +/** 添加/修改操作 */ +const modalRef = ref() +const openModal = (type: string, id?: number) => { + modalRef.value.openModal(type, id) +} + +/** 删除按钮操作 */ +const handleDelete = async (id) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await AccountApi.deleteAccount(id) + message.success(t('common.delSuccess')) + // 刷新列表 + await getList() + } catch {} +} +/** 生成二维码的按钮操作 */ +const handleGenerateQrCode = async (row) => { + try { + // 生成二维码的二次确认 + await message.confirm('是否确认生成公众号账号编号为"' + row.name + '"的二维码?') + // 发起生成二维码 + await AccountApi.generateAccountQrCode(row.id) + message.success('生成二维码成功') + // 刷新列表 + await getList() + } catch {} +} +/** 清空二维码 API 配额的按钮操作 */ +const handleCleanQuota = async (row) => { + try { + // 清空 API 配额的二次确认 + await message.confirm('是否确认清空生成公众号账号编号为"' + row.name + '"的 API 配额?') + // 发起清空 API 配额 + await AccountApi.clearAccountQuota(row.id) + message.success('清空 API 配额成功') + } catch {} +} + +onMounted(() => { + getList() +}) +</script>