2026-04-15 01:11:50 +08:00

350 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="system-menu-container layout-padding">
<ProTable ref="tableRef" :request-api="couponPage" :columns="columns" :pagination="true" :tool-button="false"
:initParam="initParam">
<template #tools>
<el-button v-auth="'coupon:add'" type="primary" icon="ele-Plus" @click="onOpenMenu()"> 新增 </el-button>
</template>
<template #index="scope">
{{ scope.$index + 1 }}
</template>
<template #name="scope">
<SvgIcon :name="scope.row.icon" />
<span class="ml10">{{ $t(scope.row.name) }}</span>
</template>
<template #type="scope">
{{ scope.row.type == 0 ? '折扣券' : '定额券' }}
</template>
<template #value="scope">
{{ scope.row.type == 0 ? scope.row.value + '%' : scope.row.value + '元' }}
</template>
<template #startTime="scope">
{{ formatDate(scope.row.startTime) }} - {{ formatDate(scope.row.endTime) }}
</template>
<template #action="scope">
<el-button v-auth="'coupon:edit'" icon="ele-Edit" size="small" text type="primary"
@click="onOpenMenu(scope.row)"> 编辑 </el-button>
<el-popconfirm title="确认删除吗?" @confirm="onDeleteMenu(scope.row.id)">
<template #reference>
<el-button v-auth="'coupon:delete'" icon="ele-Delete" size="small" text type="danger"> 删除
</el-button>
</template>
</el-popconfirm>
<el-button size="small" v-auth="'coupon:data:personal'" text type="primary"
@click="getSdk(scope.row.id)"> 生成兑换码
</el-button>
</template>
</ProTable>
<!-- 弹窗 -->
<el-dialog :title="dialogTitle" v-model="isShowDialog">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="150px"
style="max-width: 600px;margin-bottom: 30px;" v-if="isShowDialog">
<!-- 商户名称 -->
<el-form-item label="优惠券名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入优惠券名称"></el-input>
</el-form-item>
<!-- 优惠券类型 -->
<el-form-item label="优惠券类型" prop="type">
<el-select v-model="formData.type" placeholder="请选择优惠券类型">
<el-option label="折扣" :value="0"></el-option>
<el-option label="定额" :value="1"></el-option>
</el-select>
</el-form-item>
<!-- 填写折扣 -->
<el-form-item label="填写折扣" prop="value" v-if="formData.type === 0">
<el-input v-model="formData.value" placeholder="请输入折扣百分比">
<template #append>%</template>
</el-input>
</el-form-item>
<!-- 填写优惠金额 -->
<el-form-item label="填写优惠金额" prop="value" v-if="formData.type === 1">
<el-input v-model="formData.value" placeholder="请输入优惠金额" class="fee-input">
<template #append>元</template>
</el-input>
</el-form-item>
<!-- 选择有效期 -->
<el-form-item label="选择有效期" prop="startTime">
<el-date-picker type="datetimerange" v-model="formData.time" start-placeholder="开始日期时间"
end-placeholder="结束日期时间" style="width: 100%;" value-format="YYYY-MM-DD HH:mm" @change="(val) => {
console.log('选择的日期时间范围:', val);
formData.startTime = val[0];
formData.endTime = val[1];
}"></el-date-picker>
</el-form-item>
<!-- 可用赛事 -->
<el-form-item label="可用赛事" prop="phone">
<el-select v-model="formData.eventIds" placeholder="请选择项目类型" multiple style="width: 100%;">
<el-option v-for="item in eventList" :key="item.id" :label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="onCancel">取消</el-button>
<el-button type="primary" @click="onSubmit">确定</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="sdkDialog" title="兑换码" width="500" center>
<div style="text-align: center; font-size: 18px; margin: 20px 50px;">
{{ sdkCode }}
<el-button type="primary" @click="copyText" style="margin-left: 20px;">复制</el-button>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="sdkDialog = false">取消</el-button>
<el-button type="primary" @click="sdkDialog = false">
确定
</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="sysMenu">
import { defineAsyncComponent, ref, reactive } from 'vue';
import { ElMessage, ElForm } from 'element-plus';
import SysMenuApi from '/@/api/SysMenuApi';
import { auths } from '/@/utils/authFunction';
import ProTable from '/@/components/ProTable/index.vue';
import { couponPage, couponAdd, couponEdit, couponDelete, couponEventlistGet, couponGeneratecodePost } from '/@/api/match/coupon';
// 格式化日期,显示完整时间(YYYY-MM-DD HH:MM)
const formatDate = (dateStr) => {
if (!dateStr) return '';
// 如果已经是日期时间格式,直接返回(或调整格式)
try {
const date = new Date(dateStr);
if (isNaN(date.getTime())) return dateStr;
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}`;
} catch (e) {
return dateStr;
}
};
// 格式化日期为选择器用的格式
const formatDateTimePicker = (dateStr) => {
if (!dateStr) return '';
try {
const date = new Date(dateStr);
if (isNaN(date.getTime())) return dateStr;
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}`;
} catch (e) {
return dateStr;
}
};
// 定义表单引用类型
const formRef = ref();
const eventList = ref([]);
const formData = ref({
name: '',
type: '',
value: '',
startTime: '',
endTime: '',
eventIds: [],
totalQuantity: '',
time: '',
})
const sdkDialog = ref(false)
const sdkCode = ref('')
const copyText = () => {
navigator.clipboard.writeText(sdkCode.value).then(() => {
ElMessage.success('兑换码已复制到剪贴板');
}).catch(err => {
ElMessage.error('复制失败,请重试');
});
};
const initParam = ref(true)
const formRules = ref({
name: [
{ required: true, message: '请输入优惠券名称', trigger: 'blur' }
],
type: [
{ required: true, message: '请选择优惠券类型', trigger: 'change' }
],
value: [
{ required: true, message: '请输入优惠额度', trigger: 'blur' }
],
// description: [
// { required: true, message: '请输入优惠金额', trigger: 'blur' }
// ],
startTime: [
{ required: true, message: '请选择有效期', trigger: 'change' }
],
endTime: [
{ required: true, message: '请选择有效期', trigger: 'change' }
],
});
const columns = ref([
{
prop: 'index',
label: '序号',
align: 'center',
},
{
prop: 'name',
label: '优惠券名称',
align: 'center',
search: {
el: 'input',
},
},
{ prop: 'type', label: '优惠券类型', search: { el: 'select', }, enum: [{ label: '全部', value: '' }, { label: '折扣', value: 0 }, { label: '定额', value: 1 },] },
{ prop: 'value', label: '详情', },
{ prop: 'startTime', label: '有效期' },
{ prop: 'eventNames', label: '可用赛事' },
{ prop: 'action', label: '操作', width: 260, align: 'center', fixed: 'right', isShow: auths(['coupon:delete', 'coupon:edit']) },
]);
const isShowDialog = ref(false);
const dialogTitle = ref('新增');
const onOpenMenu = async (row) => {
console.log('打开菜单,数据:', row);
if (eventList.value.length === 0) {
const { data } = await couponEventlistGet();
eventList.value = data;
}
dialogTitle.value = row ? '编辑' : '新增';
if (row) {
formData.value = {
...row,
startTime: formatDateTimePicker(row.startTime),
endTime: formatDateTimePicker(row.endTime),
time: [formatDateTimePicker(row.startTime), formatDateTimePicker(row.endTime)],
};
} else {
formData.value = {
name: '',
type: '',
value: '',
startTime: '',
endTime: '',
eventIds: [],
totalQuantity: '',
time: ''
};
}
isShowDialog.value = true;
};
const getSdk = async (id) => {
const { data } = await couponGeneratecodePost(id);
sdkCode.value = data;
sdkDialog.value = true;
};
//删除菜单
const onDeleteMenu = async (id) => {
const { succeeded, errors } = await couponDelete([id]);
if (succeeded) {
initParam.value = !initParam.value;
ElMessage.success('删除成功');
} else {
ElMessage.error(errors);
}
};
// 表单提交
const onSubmit = () => {
if (!formRef.value) return;
formRef.value.validate(async (valid) => {
if (!valid) return;
try {
let res;
if (formData.value.id) {
res = await couponEdit(formData.value);
} else {
res = await couponAdd(formData.value);
}
if (res.succeeded) {
initParam.value = !initParam.value;
ElMessage.success(dialogTitle.value + '成功');
isShowDialog.value = false;
} else {
ElMessage.error(res.errors);
}
} catch (error) {
console.error(error);
}
});
};
// 取消
const onCancel = () => {
isShowDialog.value = false;
};
</script>
<style scoped lang="scss">
/* 时长组合框样式 */
.duration-row {
display: flex;
align-items: center;
gap: 8px;
}
.duration-row .el-input {
width: 120px;
}
.duration-separator {
color: #606266;
font-size: 14px;
}
.duration-label {
color: #909399;
font-size: 14px;
}
</style>
<style>
.avatar-uploader .el-upload {
border: 1px dashed var(--el-border-color);
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
text-align: center;
}
</style>