|
|
@@ -0,0 +1,316 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container course-random-red-packet">
|
|
|
+ <el-card shadow="never">
|
|
|
+ <div slot="header" class="card-header">
|
|
|
+ <div>
|
|
|
+ <div class="title">配置中心 - 课程随机红包</div>
|
|
|
+ <div class="desc">
|
|
|
+ 绑定课程项目fs_user_course.project,仅白名单企业可参与;权重总和需为100%,多个企业ID逗号分隔,填写ALL代表全部企业随机红包
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-tag type="info" size="small">红包模块 v2.0</el-tag>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-form ref="form" :model="form" :rules="rules" label-width="120px" v-loading="loading">
|
|
|
+ <el-form-item label="课程项目" prop="project">
|
|
|
+ <el-select
|
|
|
+ v-model="form.project"
|
|
|
+ placeholder="请选择课程项目"
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ style="width: 420px"
|
|
|
+ @change="handleProjectChange"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in projectOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="Number(item.dictValue)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-divider content-position="left">红包开关配置</el-divider>
|
|
|
+
|
|
|
+ <el-form-item label="开启随机红包">
|
|
|
+ <el-switch
|
|
|
+ v-model="form.enableRandom"
|
|
|
+ active-color="#13ce66"
|
|
|
+ inactive-color="#ff4949"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <template v-if="form.enableRandom">
|
|
|
+ <div v-for="(tier, index) in form.tiers" :key="index" class="tier-row">
|
|
|
+ <el-form-item
|
|
|
+ label="红包金额"
|
|
|
+ :prop="'tiers.' + index + '.amount'"
|
|
|
+ :rules="[{ required: true, message: '请填写金额', trigger: 'blur' }]"
|
|
|
+ >
|
|
|
+ <el-input-number
|
|
|
+ v-model="tier.amount"
|
|
|
+ :min="0.01"
|
|
|
+ :max="200"
|
|
|
+ :step="0.01"
|
|
|
+ :precision="2"
|
|
|
+ controls-position="right"
|
|
|
+ />
|
|
|
+ <span class="unit">元</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="权重占比"
|
|
|
+ :prop="'tiers.' + index + '.weight'"
|
|
|
+ :rules="[
|
|
|
+ { required: true, message: '请填写权重', trigger: 'blur' },
|
|
|
+ { type: 'number', min: 1, message: '权重不能小于0', trigger: 'blur' }
|
|
|
+ ]"
|
|
|
+ >
|
|
|
+ <el-input-number
|
|
|
+ v-model="tier.weight"
|
|
|
+ :min="1"
|
|
|
+ :max="100"
|
|
|
+ controls-position="right"
|
|
|
+ />
|
|
|
+ <span class="unit">%</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-button
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-delete"
|
|
|
+ class="delete-btn"
|
|
|
+ :disabled="form.tiers.length <= 1"
|
|
|
+ @click="removeTier(index)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" plain icon="el-icon-plus" @click="addTier">新增档位</el-button>
|
|
|
+ <span class="weight-total" :class="{ error: totalWeight !== 100 }">
|
|
|
+ 权重总和:{{ totalWeight }}%
|
|
|
+ </span>
|
|
|
+ </el-form-item>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <el-divider content-position="left">企业白名单</el-divider>
|
|
|
+
|
|
|
+ <el-form-item label="允许企业">
|
|
|
+ <el-select
|
|
|
+ v-model="whitelistCompanyIds"
|
|
|
+ multiple
|
|
|
+ filterable
|
|
|
+ clearable
|
|
|
+ collapse-tags
|
|
|
+ placeholder="不选择代表全部企业走随机红包"
|
|
|
+ style="width: 100%"
|
|
|
+ >
|
|
|
+ <el-option
|
|
|
+ v-for="item in companyOptions"
|
|
|
+ :key="item.dictValue"
|
|
|
+ :label="item.dictLabel"
|
|
|
+ :value="String(item.dictValue)"
|
|
|
+ />
|
|
|
+ </el-select>
|
|
|
+ <div class="tip">多个企业ID逗号分隔,内部存储ALL代表全部企业可参与红包</div>
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" :loading="submitting" @click="submitForm">保存配置</el-button>
|
|
|
+ <el-button @click="resetForm">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getCourseRandomRedPacket, saveCourseRandomRedPacket } from '@/api/course/courseRandomRedPacket'
|
|
|
+import { allList } from '@/api/company/company'
|
|
|
+
|
|
|
+const defaultTier = () => ({ amount: 1.88, weight: 50 })
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'CourseRandomRedPacket',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ loading: false,
|
|
|
+ submitting: false,
|
|
|
+ projectOptions: [],
|
|
|
+ companyOptions: [],
|
|
|
+ whitelistCompanyIds: [],
|
|
|
+ form: {
|
|
|
+ project: null,
|
|
|
+ enableRandom: false,
|
|
|
+ companyWhitelist: '',
|
|
|
+ tiers: [defaultTier()]
|
|
|
+ },
|
|
|
+ rules: {
|
|
|
+ project: [{ required: true, message: '请选择课程项目', trigger: 'change' }]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ totalWeight() {
|
|
|
+ return (this.form.tiers || []).reduce((sum, item) => sum + (Number(item.weight) || 0), 0)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.getDicts('sys_course_project').then(response => {
|
|
|
+ this.projectOptions = response.data || []
|
|
|
+ })
|
|
|
+ allList().then(res => {
|
|
|
+ this.companyOptions = res.rows || []
|
|
|
+ })
|
|
|
+ if (this.$route.query.project) {
|
|
|
+ this.form.project = Number(this.$route.query.project)
|
|
|
+ this.loadConfig()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ handleProjectChange() {
|
|
|
+ if (this.form.project) {
|
|
|
+ this.loadConfig()
|
|
|
+ } else {
|
|
|
+ this.resetForm(false)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ loadConfig() {
|
|
|
+ if (!this.form.project) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.loading = true
|
|
|
+ getCourseRandomRedPacket(this.form.project).then(res => {
|
|
|
+ const data = res.data
|
|
|
+ if (data) {
|
|
|
+ this.form.enableRandom = !!data.enableRandom
|
|
|
+ this.form.companyWhitelist = data.companyWhitelist || ''
|
|
|
+ this.form.tiers = (data.tiers && data.tiers.length)
|
|
|
+ ? data.tiers.map(item => ({
|
|
|
+ amount: Number(item.amount),
|
|
|
+ weight: Number(item.weight)
|
|
|
+ }))
|
|
|
+ : [defaultTier()]
|
|
|
+ this.parseWhitelist()
|
|
|
+ } else {
|
|
|
+ this.form.enableRandom = false
|
|
|
+ this.form.companyWhitelist = ''
|
|
|
+ this.form.tiers = [defaultTier()]
|
|
|
+ this.whitelistCompanyIds = []
|
|
|
+ }
|
|
|
+ }).finally(() => {
|
|
|
+ this.loading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ parseWhitelist() {
|
|
|
+ const whitelist = (this.form.companyWhitelist || '').trim()
|
|
|
+ if (!whitelist || whitelist.toUpperCase() === 'ALL') {
|
|
|
+ this.whitelistCompanyIds = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.whitelistCompanyIds = whitelist.split(',').map(item => item.trim()).filter(Boolean)
|
|
|
+ },
|
|
|
+ buildWhitelist() {
|
|
|
+ if (!this.whitelistCompanyIds || this.whitelistCompanyIds.length === 0) {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ return this.whitelistCompanyIds.join(',')
|
|
|
+ },
|
|
|
+ addTier() {
|
|
|
+ this.form.tiers.push({ amount: 1.88, weight: 10 })
|
|
|
+ },
|
|
|
+ removeTier(index) {
|
|
|
+ this.form.tiers.splice(index, 1)
|
|
|
+ },
|
|
|
+ resetForm(clearProject = true) {
|
|
|
+ if (clearProject) {
|
|
|
+ this.form.project = null
|
|
|
+ }
|
|
|
+ this.form.enableRandom = false
|
|
|
+ this.form.companyWhitelist = ''
|
|
|
+ this.form.tiers = [defaultTier()]
|
|
|
+ this.whitelistCompanyIds = []
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.form) {
|
|
|
+ this.$refs.form.clearValidate()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ submitForm() {
|
|
|
+ this.$refs.form.validate(valid => {
|
|
|
+ if (!valid) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.form.enableRandom) {
|
|
|
+ if (this.totalWeight !== 100) {
|
|
|
+ this.$message.warning('权重总和必须为 100%')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.form.tiers.length) {
|
|
|
+ this.$message.warning('至少保留一个红包档位')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.submitting = true
|
|
|
+ const payload = {
|
|
|
+ project: this.form.project,
|
|
|
+ enableRandom: this.form.enableRandom,
|
|
|
+ companyWhitelist: this.buildWhitelist(),
|
|
|
+ tiers: this.form.enableRandom ? this.form.tiers : []
|
|
|
+ }
|
|
|
+ saveCourseRandomRedPacket(payload).then(() => {
|
|
|
+ this.$message.success('保存成功')
|
|
|
+ }).finally(() => {
|
|
|
+ this.submitting = false
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.course-random-red-packet .card-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: flex-start;
|
|
|
+}
|
|
|
+
|
|
|
+.course-random-red-packet .title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.course-random-red-packet .desc,
|
|
|
+.course-random-red-packet .tip {
|
|
|
+ color: #909399;
|
|
|
+ font-size: 13px;
|
|
|
+ line-height: 1.6;
|
|
|
+}
|
|
|
+
|
|
|
+.course-random-red-packet .tier-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 8px;
|
|
|
+ margin-bottom: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.course-random-red-packet .unit {
|
|
|
+ margin-left: 8px;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+
|
|
|
+.course-random-red-packet .delete-btn {
|
|
|
+ margin-top: 6px;
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
+
|
|
|
+.course-random-red-packet .weight-total {
|
|
|
+ margin-left: 16px;
|
|
|
+ color: #67c23a;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+
|
|
|
+.course-random-red-packet .weight-total.error {
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
+</style>
|