| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544 |
- <template>
- <div class="p-2">
- <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
- <div v-show="showSearch" class="mb-[10px]">
- <!-- <el-card shadow="hover">
- <el-form ref="queryFormRef" :model="queryParams" :inline="true">
- <el-form-item label="模板ID" prop="templateId">
- <el-input v-model="queryParams.templateId" placeholder="请输入模板ID" clearable @keyup.enter="handleQuery" />
- </el-form-item>
- <el-form-item label="创建方案ID" prop="creationSchemeId">
- <el-input v-model="queryParams.creationSchemeId" placeholder="请输入创建方案ID" clearable @keyup.enter="handleQuery" />
- </el-form-item>
- <el-form-item label="开始日期" prop="startDate">
- <el-date-picker clearable v-model="queryParams.startDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择开始日期" />
- </el-form-item>
- <el-form-item label="结束日期" prop="endDate">
- <el-date-picker clearable v-model="queryParams.endDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择结束日期" />
- </el-form-item>
- <el-form-item label="创建时间" prop="createdAt">
- <el-date-picker clearable v-model="queryParams.createdAt" type="date" value-format="YYYY-MM-DD" placeholder="请选择创建时间" />
- </el-form-item>
- <el-form-item label="更新时间" prop="updatedAt">
- <el-date-picker clearable v-model="queryParams.updatedAt" type="date" value-format="YYYY-MM-DD" placeholder="请选择更新时间" />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
- <el-button icon="Refresh" @click="resetQuery">重置</el-button>
- </el-form-item>
- </el-form>
- </el-card>-->
- </div>
- </transition>
- <el-card shadow="never">
- <template #header>
- <el-row :gutter="10" class="mb8">
- <el-col :span="1.5">
- <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['system:config:add']">新增投放方案</el-button>
- </el-col>
- <router-link to="/business/tournamentsTemplate">
- <el-button type="success" plain icon="Edit">自动比赛模版</el-button>
- </router-link>
- <!-- <el-col :span="1.5">
- <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['system:config:remove']"
- >删除</el-button
- >
- </el-col>
- <el-col :span="1.5">
- <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['system:config:export']">导出</el-button>
- </el-col>-->
- <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
- </el-row>
- </template>
- <el-table v-loading="loading" border :data="configList" @selection-change="handleSelectionChange">
- <!-- <el-table-column type="selection" width="55" align="center" />-->
- <el-table-column label="" align="center" prop="id" v-if="false" />
- <el-table-column label="比赛名" align="center" prop="name" />
- <el-table-column label="比赛Logo" align="center">
- <template #default="scope">
- <el-image
- v-if="scope.row.competitionIcon"
- :src="scope.row.competitionIcon"
- style="width: 40px; height: 40px; border-radius: 4px; cursor: zoom-in"
- :preview-src-list="[scope.row.competitionIcon]"
- :preview-teleported="true"
- fit="cover"
- />
- <span v-else></span>
- </template>
- </el-table-column>
- <el-table-column label="频率" align="center">
- <template #default="scope">
- <span v-html="formatFrequency(scope.row)"></span>
- </template>
- </el-table-column>
- <el-table-column label="报名要求" align="center">
- <template #default="scope">
- {{
- scope.row.itemsName && scope.row.itemsNum
- ? `${scope.row.itemsName} x ${scope.row.itemsNum}`
- : scope.row.itemsName || scope.row.itemsNum || '—'
- }}
- </template>
- </el-table-column>
- <el-table-column label="报名截止盲注等级" align="center" prop="lateRegistrationLevel" />
- <el-table-column label="盲注表" align="center" prop="blindStructuresName" />
- <el-table-column label="奖励" align="center">
- <template #default="scope">
- <div v-for="(prize, index) in scope.row.itemsPrizeList" :key="index">
- 第{{ prize.ranking }}名:{{ prize.quantity }} {{ prize.itemsName }}
- </div>
- </template>
- </el-table-column>
- <el-table-column label="状态" align="center" prop="statusText" />
- <el-table-column label="创建时间" align="center" prop="createdAt" width="180">
- <template #default="scope">
- <span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
- </template>
- </el-table-column>
- <el-table-column label="操作" align="center" width="320">
- <template #default="scope">
- <!-- 查看按钮 -->
- <el-tooltip content="查看" placement="top">
- <el-button link type="primary" size="small" @click="handleUpdate(scope.row, 'view')" v-hasPermi="['system:config:edit']">
- <el-icon><View /></el-icon>
- 查看
- </el-button>
- </el-tooltip>
- <!-- 投放配置按钮 -->
- <el-tooltip content="投放配置" placement="top">
- <el-button link type="success" size="small" @click="handleUpdate(scope.row, 'edit')" v-hasPermi="['system:config:edit']">
- <el-icon><Setting /></el-icon>
- 投放配置
- </el-button>
- </el-tooltip>
- <!-- 停止按钮 -->
- <!-- 动态:停止 或 开始 按钮 -->
- <template v-if="scope.row.enabled">
- <!-- 已启用,显示:停止按钮 -->
- <el-tooltip content="停止" placement="top">
- <el-button link type="warning" size="small" @click="handleStop(scope.row)" v-hasPermi="['system:config:remove']">
- <el-icon><VideoPause /></el-icon> 停止
- </el-button>
- </el-tooltip>
- </template>
- <template v-else>
- <!-- 已禁用,显示:开始按钮 -->
- <el-tooltip content="开始" placement="top">
- <el-button link type="success" size="small" @click="handleStart(scope.row)" v-hasPermi="['system:config:add']">
- <el-icon><VideoPlay /></el-icon> 开始
- </el-button>
- </el-tooltip>
- </template>
- <!-- 删除按钮 -->
- <el-tooltip content="删除" placement="top">
- <el-button link type="danger" size="small" @click="handleDelete(scope.row)" v-hasPermi="['system:config:remove']">
- <el-icon><Delete /></el-icon>
- 删除
- </el-button>
- </el-tooltip>
- </template>
- </el-table-column>
- </el-table>
- <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
- </el-card>
- <!-- 添加或修改排期配置:用于保存具体的排期实例配置对话框 -->
- <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
- <el-form ref="configFormRef" :model="form" :rules="mode === 'view' ? {} : rules" label-width="80px">
- <!-- 选择模版 -->
- <el-form-item label="选择模版" prop="templateId">
- <div style="display: flex; align-items: center">
- <el-select v-model="form.templateId" :disabled="mode === 'view'" placeholder="选择模版" style="width: 200px">
- <el-option v-for="item in itemOptionsTemplateList" :key="item.id" :label="item.label" :value="item.id" />
- </el-select>
- </div>
- </el-form-item>
- <!-- 重复设置 -->
- <el-form-item label="重复设置" prop="repeatTypes">
- <el-select v-model="form.repeatTypes" :disabled="mode === 'view'" placeholder="请选择重复类型" multiple style="width: 100%">
- <el-option v-for="dict in repeat_type" :key="dict.value" :label="dict.label" :value="dict.value" />
- </el-select>
- </el-form-item>
- <!-- 时间设置 -->
- <el-form-item label="时间设置">
- <div style="margin-bottom: 8px">设置投放方案后,系统会依据设置时间和方案自动创建当天比赛;</div>
- <div v-for="(reward, index) in formPrize.rewards" :key="index" style="display: flex; align-items: center; margin-bottom: 8px">
- <span style="margin-right: 16px">场次{{ index + 1 }}:</span>
- <!-- 时间选择器 -->
- <el-time-picker
- v-model="reward.execDates"
- :disabled="mode === 'view'"
- format="HH:mm"
- value-format="HH:mm"
- :picker-options="{
- disabledMinutes: handleDisabledMinutes,
- selectableRange: '00:00:00 - 23:59:59'
- }"
- placeholder="请选择时间"
- style="width: 220px; margin-right: 8px"
- />
- <!-- 操作按钮:查看时不显示 +/- -->
- <el-button v-if="mode !== 'view' && index === 0" type="primary" @click="addReward" size="small"> + </el-button>
- <el-button v-if="mode !== 'view' && index !== 0" type="primary" @click="removeReward(index)" size="small"> - </el-button>
- </div>
- </el-form-item>
- <!-- 创建方案 -->
- <el-form-item label="创建方案" prop="creationSchemeCode">
- <div style="display: flex; align-items: center">
- <el-select v-model="form.creationSchemeCode" :disabled="mode === 'view'" placeholder="选择创建方案" style="width: 200px">
- <el-option v-for="item in itemOptionsSchemeList" :key="item.id" :label="item.label" :value="item.code" />
- </el-select>
- </div>
- </el-form-item>
- </el-form>
- <!-- 底部按钮 -->
- <template #footer>
- <div class="dialog-footer">
- <!-- 查看模式下不显示确定按钮 -->
- <el-button v-if="mode !== 'view'" :loading="buttonLoading" type="primary" @click="submitForm"> 确 定 </el-button>
- <el-button @click="cancel">
- {{ mode === 'view' ? '关 闭' : '取 消' }}
- </el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup name="Config" lang="ts">
- import {
- listConfig,
- getConfig,
- delConfig,
- createSchedule,
- updateConfig,
- selectTemplateTourList,
- updateScheduleConfig,
- deleteScheduleConfig,
- stopScheduleConfig,
- startScheduleConfig
- } from '@/api/system/business/config';
- import { selectAllCreationSchemesAllList } from '@/api/system/business/scheme';
- import { ConfigVO, ConfigQuery, ConfigForm } from '@/api/system/business/config/types';
- const { proxy } = getCurrentInstance() as ComponentInternalInstance;
- const { repeat_type } = toRefs<any>(proxy?.useDict('repeat_type'));
- const configList = ref<ConfigVO[]>([]);
- const buttonLoading = ref(false);
- const loading = ref(true);
- const showSearch = ref(true);
- const ids = ref<Array<string | number>>([]);
- const single = ref(true);
- const multiple = ref(true);
- const total = ref(0);
- const queryFormRef = ref<ElFormInstance>();
- const configFormRef = ref<ElFormInstance>();
- const dialog = reactive<DialogOption>({
- visible: false,
- title: ''
- });
- // 新增 mode 字段:'add' | 'edit' | 'view'
- const mode = ref('add'); // 默认为添加
- const initFormData: ConfigForm = {
- id: undefined,
- templateId: undefined,
- creationSchemeId: undefined,
- startDate: undefined,
- endDate: undefined,
- enabled: undefined,
- createdAt: undefined,
- updatedAt: undefined
- };
- const data = reactive<PageData<ConfigForm, ConfigQuery>>({
- form: { ...initFormData },
- queryParams: {
- pageNum: 1,
- pageSize: 10,
- templateId: undefined,
- creationSchemeId: undefined,
- startDate: undefined,
- endDate: undefined,
- enabled: undefined,
- createdAt: undefined,
- updatedAt: undefined,
- params: {}
- },
- rules: {
- id: [{ required: true, message: '不能为空', trigger: 'blur' }],
- templateId: [{ required: true, message: '模板ID不能为空', trigger: 'blur' }],
- startDate: [{ required: true, message: '开始日期不能为空', trigger: 'blur' }],
- endDate: [{ required: true, message: '结束日期不能为空', trigger: 'blur' }]
- }
- });
- const { queryParams, form, rules } = toRefs(data);
- /** 查询排期配置:用于保存具体的排期实例配置列表 */
- const getList = async () => {
- loading.value = true;
- const res = await listConfig(queryParams.value);
- configList.value = res.rows;
- total.value = res.total;
- loading.value = false;
- };
- /** 取消按钮 */
- const cancel = () => {
- reset();
- resetFormPrize();
- dialog.visible = false;
- };
- /** 表单重置 */
- const reset = () => {
- form.value = { ...initFormData };
- configFormRef.value?.resetFields();
- resetFormPrize();
- };
- /** 搜索按钮操作 */
- const handleQuery = () => {
- queryParams.value.pageNum = 1;
- getList();
- };
- /** 重置按钮操作 */
- const resetQuery = () => {
- queryFormRef.value?.resetFields();
- handleQuery();
- };
- /** 多选框选中数据 */
- const handleSelectionChange = (selection: ConfigVO[]) => {
- ids.value = selection.map((item) => item.id);
- single.value = selection.length != 1;
- multiple.value = !selection.length;
- };
- /** 新增按钮操作 */
- const handleAdd = () => {
- reset();
- resetFormPrize();
- mode.value = 'add';
- dialog.visible = true;
- dialog.title = '新增投放方案';
- };
- /**
- * 处理修改或查看操作
- * @param row 当前行数据
- * @param action 'edit' | 'view'
- */
- const handleUpdate = async (row, action = 'edit') => {
- reset();
- resetFormPrize();
- mode.value = action; // 设置模式
- dialog.title = action === 'view' ? '查看投放设置' : '编辑投放设置';
- const _id = row?.id || ids.value[0];
- const res = await getConfig(_id);
- // 1. 赋值 form
- Object.assign(form.value, res.data);
- // 2. 处理 execTimes -> formPrize.rewards
- if (res.data.execTimes && Array.isArray(res.data.execTimes)) {
- formPrize.rewards = res.data.execTimes.filter((time) => time).map((time) => ({ execDates: time }));
- } else {
- formPrize.rewards = [{ execDates: '' }]; // 默认一个空行
- }
- dialog.visible = true;
- };
- /** 提交按钮 */
- const submitForm = () => {
- configFormRef.value?.validate(async (valid: boolean) => {
- if (valid) {
- buttonLoading.value = true;
- // ✅ 关键步骤:将 formPrize.rewards 中的时间提取为 execTimes 数组
- form.value.execTimes = formPrize.rewards.map((reward) => reward.execDates).filter((time) => time); // 可选:过滤掉空值或 null
- if (form.value.id) {
- await updateScheduleConfig(form.value).finally(() => (buttonLoading.value = false));
- } else {
- await createSchedule(form.value).finally(() => (buttonLoading.value = false));
- }
- proxy?.$modal.msgSuccess('操作成功');
- dialog.visible = false;
- await getList();
- }
- });
- };
- /** 删除按钮操作 */
- const handleDelete = async (row?: ConfigVO) => {
- const _ids = row?.id || ids.value;
- await proxy?.$modal.confirm('是否确认删除排期配置,编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
- await deleteScheduleConfig(row.configId);
- proxy?.$modal.msgSuccess('删除成功');
- await getList();
- };
- //停止操作
- const handleStop = async (row?: ConfigVO) => {
- const _ids = row?.id || ids.value;
- await proxy?.$modal.confirm('是否确认停止排期配置,编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
- await stopScheduleConfig(row.configId);
- proxy?.$modal.msgSuccess('操作成功');
- await getList();
- };
- const handleStart = async (row?: ConfigVO) => {
- const _ids = row?.id || ids.value;
- await proxy?.$modal.confirm('是否开启排期配置,编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
- await startScheduleConfig(row.configId);
- proxy?.$modal.msgSuccess('操作成功');
- await getList();
- };
- /** 导出按钮操作 */
- const handleExport = () => {
- proxy?.download(
- 'system/config/export',
- {
- ...queryParams.value
- },
- `config_${new Date().getTime()}.xlsx`
- );
- };
- onMounted(() => {
- getList();
- handleOptionsTemplateChange();
- handleOptionsSchemeChange();
- });
- // 下拉选项数据
- const itemOptionsTemplateList = ref<{ id: number; label: string }[]>([]);
- // 加载报名条件选项
- const handleOptionsTemplateChange = async () => {
- try {
- const res = await selectTemplateTourList();
- if (res.code === 200) {
- // 使用 unknown 中间类型进行类型转换
- const data = res.data as unknown as { id: number; name: number }[];
- const list = [];
- for (let i = 0; i < data.length; i++) {
- const item = data[i];
- list.push({
- id: item.id,
- label: item.name
- });
- }
- itemOptionsTemplateList.value = list;
- } else {
- alert('加载失败:' + res.msg);
- }
- } catch (error) {
- console.error('请求出错:', error);
- }
- };
- // 下拉选项数据
- const itemOptionsSchemeList = ref<{ id: number; label: string; code: string }[]>([]);
- // 加载报名条件选项
- const handleOptionsSchemeChange = async () => {
- try {
- const res = await selectAllCreationSchemesAllList();
- if (res.code === 200) {
- // 使用 unknown 中间类型进行类型转换
- const data = res.data as unknown as { id: number; name: string; code: string }[];
- const list = [];
- for (let i = 0; i < data.length; i++) {
- const item = data[i];
- list.push({
- id: item.id,
- label: item.name,
- code: item.code
- });
- }
- itemOptionsSchemeList.value = list;
- } else {
- alert('加载失败:' + res.msg);
- }
- } catch (error) {
- console.error('请求出错:', error);
- }
- };
- const formPrize = reactive({
- // ...其他表单字段
- rewards: [
- {
- execDates: null
- }
- ]
- });
- const addReward = () => {
- formPrize.rewards.push({
- execDates: null
- });
- };
- const removeReward = (index: number) => {
- formPrize.rewards.splice(index, 1);
- };
- // 下拉选项数据
- const itemOptionsTimeList = ref<{ label: string; value: string }[]>([]);
- const handleDisabledMinutes = () => {
- const minutes = [];
- for (let i = 0; i < 60; i++) {
- if (i % 30 !== 0) {
- minutes.push(i);
- }
- }
- return minutes;
- };
- // 用于保存原始的默认奖励结构
- const defaultTimes = {
- execDates: null
- };
- // 重置函数
- const resetFormPrize = () => {
- // 清空 rewards 并添加默认项
- formPrize.rewards.splice(0); // 清空数组
- formPrize.rewards.push({ ...defaultTimes }); // 添加初始项
- };
- // 格式化频率逻辑
- const formatFrequency = (row) => {
- const { weekDayList = [], weekDaySize = 0 } = row;
- // 1. 截取指定数量的周几
- const selectedWeekDays = weekDayList;
- // 2. 拼接最终文本
- if (selectedWeekDays.length === 0) {
- return '无'; // 如果没有周几信息
- } else {
- return `每日${weekDaySize}场<br>${selectedWeekDays.join('、')}每天${weekDaySize}场`;
- }
- };
- </script>
|