Ver código fonte

投票管理

Xiao_123 4 meses atrás
pai
commit
886ff83a93

+ 58 - 0
src/api/menduner/system/vote/index.ts

@@ -0,0 +1,58 @@
+import request from '@/config/axios'
+
+export const VotingActivityApi = {
+	// 查询投票活动分页
+	getVotingActivityPage: async (params: any) => {
+		return await request.get({ url: `/menduner/system/mde/voting-activity/page`, params })
+	},
+
+	// 查询投票活动
+	getVotingActivity: async (id: number) => {
+		return await request.get({ url: `/menduner/system/mde/voting-activity/get?id=` + id })
+	},
+
+	// 获取候选人类型
+	getVotingActivityCategories: async (id: number) => {
+		return await request.get({ url: `/menduner/system/mde/voting-activity-join-item/categorys?votingActivityId=` + id })
+	},
+
+	// 创建投票活动
+	createVotingActivity: async (data: any) => {
+		return await request.post({ url: `/menduner/system/mde/voting-activity/create`, data })
+	},
+
+	// 更新投票活动
+	updateVotingActivity: async (data: any) => {
+		return await request.put({ url: `/menduner/system/mde/voting-activity/update`, data })
+	},
+
+	// 删除投票活动
+	deleteVotingActivity: async (id: number) => {
+		return await request.delete({ url: `/menduner/system/mde/voting-activity/delete?id=` + id })
+	},
+
+	// 查询投票活动候选人分页
+	getVotingActivityJoinItemPage: async (params: any) => {
+		return await request.get({ url: `/menduner/system/mde/voting-activity-join-item/page`, params })
+	},
+
+	// 查询投票活动候选人
+	getVotingActivityJoinItem: async (id: number) => {
+		return await request.get({ url: `/menduner/system/mde/voting-activity-join-item/get?id=` + id })
+	},
+	
+	// 创建投票活动候选人
+	createVotingActivityJoinItem: async (data: any) => {
+		return await request.post({ url: `/menduner/system/mde/voting-activity-join-item/create`, data })
+	},
+
+	// 更新投票活动候选人
+	updateVotingActivityJoinItem: async (data: any) => {
+		return await request.put({ url: `/menduner/system/mde/voting-activity-join-item/update`, data })
+	},
+
+	// 删除投票活动候选人
+	deleteVotingActivityJoinItem: async (id: number) => {
+		return await request.delete({ url: `/menduner/system/mde/voting-activity-join-item/delete?id=` + id })
+	},
+}

+ 17 - 0
src/router/modules/remaining.ts

@@ -538,6 +538,23 @@ const remainingRouter: AppRouteRecordRaw[] = [
         component: () => import('@/views/menduner/system/jobFair/manage/details/index.vue')
       }
     ]
+  },{
+    path: '/voting-management',
+    component: Layout,
+    name: 'VotingActivityManage',
+    meta: { hidden: true },
+    children: [
+      {
+        path: ':id',
+        name: 'VotingActivityJoinItem',
+        meta: {
+          title: '投票活动详情',
+          noCache: true,
+          hidden: true
+        },
+        component: () => import('@/views/menduner/system/vote/VotingActivityJoinItem.vue')
+      }
+    ]
   },
   {
     path: '/order',

+ 178 - 0
src/views/menduner/system/vote/VotingActivityJoinItem.vue

@@ -0,0 +1,178 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="90px">
+			<el-form-item label="投票活动" prop="votingActivityJoinItemCategory">
+				<el-select v-model="queryParams.votingActivityId" filterable placeholder="投票活动" class="!w-240px" @change="handleVotingActivityChange">
+					<el-option v-for="item in votingActivityList" :key="item.votingActivityId" :label="item.activityTitle" :value="item.votingActivityId" />
+				</el-select>
+      </el-form-item>
+      <el-form-item label="候选人名称" prop="votingActivityJoinItemTitle">
+        <el-input v-model="queryParams.votingActivityJoinItemTitle" placeholder="请输入候选人名称" clearable @keyup.enter="handleQuery" class="!w-240px" />
+      </el-form-item>
+			<el-form-item label="候选人类型" prop="votingActivityJoinItemCategory">
+        <el-input v-model="queryParams.votingActivityJoinItemCategory" 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-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" plain @click="openForm('create', queryParams.votingActivityId)">
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true">
+			<el-table-column label="序号" align="center" prop="num" />
+			<el-table-column label="候选人封面" align="center" prop="headImg" width="200">
+        <template #default="scope">
+          <el-image v-if="scope.row.headImg" class="h-100px w-200px" :initial-index="0" :src="scope.row.headImg" lazy preview-teleported :preview-src-list="[scope.row.headImg]" fit="scale-down" />
+        </template>
+      </el-table-column>
+      <el-table-column label="候选人名称" align="center" prop="votingActivityJoinItemTitle" />
+      <el-table-column label="候选人类型" align="center" prop="votingActivityJoinItemCategory" />
+      <el-table-column label="票数" align="center" prop="votingActivityJoinItemNum" />
+      <el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="170px" />
+      <el-table-column label="操作" align="center" fixed="right" width="170px">
+        <template #default="scope">
+          <el-button link type="primary" @click="openForm('update', queryParams.votingActivityId, scope.row.votingActivityJoinItemId)">编辑</el-button>
+          <el-button link type="danger" @click="handleDelete(scope.row.votingActivityId)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <VotingActivityJoinItemForm ref="formRef" :candidate="candidate" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import { VotingActivityApi } from '@/api/menduner/system/vote'
+import VotingActivityJoinItemForm from './VotingActivityJoinItemForm.vue'
+import { useTagsViewStore } from '@/store/modules/tagsView'
+import { ElMessage } from 'element-plus'
+
+/** 专业 列表 */
+defineOptions({ name: 'VotingActivityJoinItem' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+	votingActivityId: undefined,
+	votingActivityJoinItemTitle: undefined,
+	votingActivityJoinItemCategory: undefined,
+	createTime: []
+})
+const queryFormRef = ref() // 搜索的表单
+
+// 候选人列表
+const candidate = ref([])
+const getCandidateList = async (votingActivityId) => {
+  try {
+		const data = await VotingActivityApi.getVotingActivityCategories(votingActivityId)
+		candidate.value = data
+	} catch {}
+}
+
+const votingActivityList = ref([])
+const getVotingActivityList = async () => {
+  try {
+		const { list } = await VotingActivityApi.getVotingActivityPage({ pageNo: 1, pageSize: 100 })
+		votingActivityList.value = list
+	} catch {}
+}
+
+/** 查询列表 */
+const getList = async () => {
+	// 候选人列表
+	getCandidateList(queryParams.votingActivityId)
+  loading.value = true
+  try {
+    const data = await VotingActivityApi.getVotingActivityJoinItemPage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+const handleVotingActivityChange = () => {
+	queryParams.pageNo = 1
+	getList()
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, votingActivityId: number, votingActivityJoinItemId?: number) => {
+  formRef.value.open(type, votingActivityId, votingActivityJoinItemId)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await VotingActivityApi.deleteVotingActivityJoinItem(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 初始化 */
+const { currentRoute } = useRouter() // 路由
+const { delView } = useTagsViewStore() // 视图操作
+const route = useRoute()
+const { id } = route.params
+onMounted(() => {
+  if (!id) {
+    ElMessage.warning('参数错误,投票活动id不能为空!')
+    delView(unref(currentRoute))
+    return
+  }
+  queryParams.votingActivityId = id
+  getList()
+	getVotingActivityList()
+})
+</script>

+ 140 - 0
src/views/menduner/system/vote/VotingActivityJoinItemForm.vue

@@ -0,0 +1,140 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible" class="!w-50%">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="150px"
+      v-loading="formLoading"
+      :validate-on-rule-change="false"
+    >
+      <el-form-item label="候选人名称" prop="votingActivityJoinItemTitle">
+        <el-input v-model="formData.votingActivityJoinItemTitle" placeholder="请输入候选人名称" class="!w-240px"/>
+      </el-form-item>
+			<el-form-item label="候选人类型" prop="votingActivityJoinItemCategory">
+				<el-select
+					v-model="formData.votingActivityJoinItemCategory"
+					filterable
+					allow-create
+					default-first-option
+					:reserve-keyword="false"
+					class="!w-240px"
+					placeholder="请输入候选人类型"
+				>
+					<el-option v-for="(item, index) in candidate" :key="index" :label="item" :value="item" />
+				</el-select>
+      </el-form-item>
+			<el-form-item label="候选人封面图" prop="headImg">
+        <UploadImg v-model="formData.headImg" height="150px" width="150px" :fileSize="20" />
+      </el-form-item>
+			<el-form-item label="候选人轮播图" prop="votingActivityJoinItemContent.banners">
+        <UploadImgs v-model="formData.votingActivityJoinItemContent.banners" />
+      </el-form-item>
+      <el-form-item label="候选人介绍" prop="votingActivityJoinItemContent.content">
+        <Editor v-model="formData.votingActivityJoinItemContent.content" height="150px" />
+      </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 { VotingActivityApi } from '@/api/menduner/system/vote'
+
+defineOptions({ name: 'VotingActivityJoinItemForm' })
+defineProps({
+  area: Array,
+  position: Array,
+	candidate: Array
+})
+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({
+	votingActivityJoinItemId: undefined,
+	votingActivityId: undefined as number | undefined,
+	votingActivityJoinItemTitle: undefined,
+	votingActivityJoinItemCategory: undefined,
+	votingActivityJoinItemContent: {
+		banners: [],
+		content: undefined,
+		video: undefined
+	},
+	headImg: undefined
+})
+
+const formRules = reactive({
+  votingActivityJoinItemTitle: [{ required: true, message: '候选人名称不能为空', trigger: 'blur' }],
+  votingActivityJoinItemCategory: [{ required: true, message: '候选人类型不能为空', trigger: 'change' }],
+  headImg: [{ required: true, message: '候选人封面图不能为空', trigger: 'change' }],
+	'votingActivityJoinItemContent.banners': [{ required: true, message: '候选人轮播图不能为空', trigger: 'change' }],
+	'votingActivityJoinItemContent.content': [{ required: true, message: '候选人介绍不能为空', trigger: 'blur' }],
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, votingActivityId: number, votingActivityJoinItemId?: number) => {
+  dialogVisible.value = true
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+	formData.value.votingActivityId = votingActivityId
+  // 修改时,设置数据
+  if (votingActivityJoinItemId) {
+    formLoading.value = true
+    try {
+      formData.value = await VotingActivityApi.getVotingActivityJoinItem(votingActivityJoinItemId)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  await formRef.value.validate()
+  // 提交请求
+  formLoading.value = true
+  try {
+    if (formType.value === 'create') {
+      await VotingActivityApi.createVotingActivityJoinItem(formData.value)
+      message.success(t('common.createSuccess'))
+    } else {
+      await VotingActivityApi.updateVotingActivityJoinItem(formData.value)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+		votingActivityJoinItemId: undefined,
+		votingActivityId: undefined,
+		votingActivityJoinItemTitle: undefined,
+		votingActivityJoinItemCategory: undefined,
+		votingActivityJoinItemContent: {
+			banners: [],
+			content: undefined,
+			video: undefined
+		},
+		headImg: undefined
+	}
+  formRef.value?.resetFields()
+}
+</script>

+ 152 - 0
src/views/menduner/system/vote/index.vue

@@ -0,0 +1,152 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
+      <el-form-item label="活动名称" prop="activityTitle">
+        <el-input v-model="queryParams.activityTitle" placeholder="请输入活动名称" clearable @keyup.enter="handleQuery" class="!w-240px" />
+      </el-form-item>
+			<el-form-item label="举办机构" prop="activityOrganizer">
+        <el-input v-model="queryParams.activityOrganizer" placeholder="请输入举办机构" clearable @keyup.enter="handleQuery" class="!w-240px" />
+      </el-form-item>
+			<el-form-item label="开始时间" prop="activityStartDate">
+        <el-date-picker v-model="queryParams.activityStartDate" value-format="x" type="date" placeholder="请选择活动开始时间" class="!w-240px" />
+      </el-form-item>
+			<el-form-item label="结束时间" prop="activityEndDate">
+        <el-date-picker v-model="queryParams.activityEndDate" value-format="x" type="date" placeholder="请选择活动结束时间" 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-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" plain @click="openForm('create')">
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true">
+      <el-table-column label="活动名称" align="center" prop="activityTitle" />
+      <el-table-column label="举办机构" align="center" prop="activityOrganizer" />
+			<el-table-column label="开始时间" align="center" prop="activityStartDate" :formatter="dateFormatter2" width="110px" />
+			<el-table-column label="结束时间" align="center" prop="activityEndDate" :formatter="dateFormatter2" width="110px" />
+			<el-table-column label="投票频率" align="center">
+        <template #default="{ row }">
+          {{ row.votingRule.dateType === 'day' ? '每天' : row.votingRule.dateType === 'month' ? '每月' : row.votingRule.dateType === 'year' ? '每年' : '' }}
+        </template>
+      </el-table-column>
+      <el-table-column label="指定频率内可投票数" align="center" prop="votingRule.num" />
+      <el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="170px" />
+      <el-table-column label="操作" align="center" fixed="right" width="170px">
+        <template #default="scope">
+          <el-button link type="success" @click="openCandidateDetail(scope.row.votingActivityId)">候选人</el-button>
+          <el-button link type="primary" @click="openForm('update', scope.row.votingActivityId)">编辑</el-button>
+          <el-button link type="danger" @click="handleDelete(scope.row.votingActivityId)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <VotingActivityForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+// import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
+import { dateFormatter, dateFormatter2 } from '@/utils/formatTime'
+import { VotingActivityApi } from '@/api/menduner/system/vote'
+import VotingActivityForm from './votingActivityForm.vue'
+
+/** 专业 列表 */
+defineOptions({ name: 'Vote' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+	activityTitle: undefined,
+	activityStartDate: undefined,
+	activityEndDate: undefined,
+	activityOrganizer: undefined,
+	createTime: []
+})
+const queryFormRef = ref() // 搜索的表单
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await VotingActivityApi.getVotingActivityPage(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 { push } = useRouter()
+const openCandidateDetail = (id) => {
+  push({ name: 'VotingActivityJoinItem', params: { id } })
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await VotingActivityApi.deleteVotingActivity(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>

+ 163 - 0
src/views/menduner/system/vote/votingActivityForm.vue

@@ -0,0 +1,163 @@
+<template>
+  <Dialog :title="dialogTitle" v-model="dialogVisible" class="!w-50%">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="150px"
+      v-loading="formLoading"
+      :validate-on-rule-change="false"
+    >
+      <el-form-item label="活动名称" prop="activityTitle">
+        <el-input v-model="formData.activityTitle" placeholder="请输入活动名称" class="!w-240px"/>
+      </el-form-item>
+			<el-form-item label="举办机构" prop="activityOrganizer">
+        <el-input v-model="formData.activityOrganizer" placeholder="请输入举办机构名称" class="!w-240px"/>
+      </el-form-item>
+      <el-form-item label="开始时间" prop="activityStartDate">
+        <el-date-picker v-model="formData.activityStartDate" :disabledDate="disabledDates" value-format="x" type="date" placeholder="请选择活动开始时间" class="!w-240px" />
+      </el-form-item>
+			<el-form-item label="结束时间" prop="activityEndDate">
+        <el-date-picker v-model="formData.activityEndDate" :disabledDate="disabledDates" value-format="x" type="date" placeholder="请选择活动结束时间" class="!w-240px" />
+      </el-form-item>
+			<el-form-item label="投票频率" prop="votingRule.dateType">
+				<el-radio-group v-model="formData.votingRule.dateType">
+					<el-radio value="day">每天</el-radio>
+					<el-radio value="month">每月</el-radio>
+					<el-radio value="year">每年</el-radio>
+				</el-radio-group>
+			</el-form-item>
+			<el-form-item label="指定频率内可投票数" prop="votingRule.num">
+				<el-input-number v-model="formData.votingRule.num" :min="1" :step="1" />
+			</el-form-item>
+			<el-form-item label="活动图片" prop="headImg">
+        <UploadImg v-model="formData.headImg" height="150px" width="150px" :fileSize="20" />
+      </el-form-item>
+			<el-form-item label="活动背景图" prop="activityContent.backgroundImg">
+        <UploadImg v-model="formData.activityContent.backgroundImg" height="150px" width="150px" :fileSize="20" />
+      </el-form-item>
+      <el-form-item label="活动内容" prop="activityContent.content">
+        <Editor v-model="formData.activityContent.content" height="150px" />
+      </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 { VotingActivityApi } from '@/api/menduner/system/vote'
+
+defineOptions({ name: 'VotingActivityForm' })
+defineProps({
+  area: Array,
+  position: Array
+})
+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({
+	votingActivityId: undefined,
+	activityTitle: undefined,
+	activityStartDate: undefined,
+	activityEndDate: undefined,
+	activityContent: {
+		backgroundImg: undefined,
+		content: undefined
+	},
+	activityOrganizer: undefined,
+	votingRule: {
+		dateType: 'day', // 投票频率:day - 日,month - 月,year - 年
+		num: 1 // 指定频率内最多投票次数
+	},
+	headImg: undefined
+})
+
+const formRules = reactive({
+  activityTitle: [{ required: true, message: '活动名称不能为空', trigger: 'blur' }],
+  activityStartDate: [{ required: true, message: '活动开始时间', trigger: 'change' }],
+  activityEndDate: [{ required: true, message: '活动结束时间', trigger: 'change' }],
+  activityOrganizer: [{ required: true, message: '举办机构不能为空', trigger: 'blur' }],
+  headImg: [{ required: true, message: '活动图片不能为空', trigger: 'change' }],
+	'activityContent.backgroundImg': [{ required: true, message: '活动背景图不能为空', trigger: 'change' }],
+	'activityContent.content': [{ required: true, message: '活动内容不能为空', trigger: 'blur' }],
+	'votingRule.dateType': [{ required: true, message: '投票频率不能为空', trigger: 'change' }],
+	'votingRule.num': [{ required: true, message: '投票频率不能为空', trigger: 'change' }],
+})
+const formRef = ref() // 表单 Ref
+
+// 过去的日期不可选
+const disabledDates = (date) => {
+  const currentDate = new Date()
+  currentDate.setDate(currentDate.getDate() - 1)
+  return date.getTime() < currentDate.getTime()
+}
+
+/** 打开弹窗 */
+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 VotingActivityApi.getVotingActivity(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  await formRef.value.validate()
+  // 提交请求
+  formLoading.value = true
+  try {
+    if (formType.value === 'create') {
+      await VotingActivityApi.createVotingActivity(formData.value)
+      message.success(t('common.createSuccess'))
+    } else {
+      await VotingActivityApi.updateVotingActivity(formData.value)
+      message.success(t('common.updateSuccess'))
+    }
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+		votingActivityId: undefined,
+		activityTitle: undefined,
+		activityStartDate: undefined,
+		activityEndDate: undefined,
+		activityContent: {
+			backgroundImg: undefined,
+			content: undefined
+		},
+		activityOrganizer: undefined,
+		votingRule: {
+			dateType: 'day',
+			num: 1
+		},
+		headImg: undefined
+	}
+  formRef.value?.resetFields()
+}
+</script>