156 lines
4.5 KiB
Vue
156 lines
4.5 KiB
Vue
<template>
|
||
<div class="page-container">
|
||
<el-card shadow="never" class="gift-card">
|
||
<template #header>
|
||
<span>赠送会员 / 积分</span>
|
||
</template>
|
||
|
||
<el-form ref="formRef" :model="form" :rules="rules" label-width="110px">
|
||
<el-form-item label="用户 ID" prop="user_ids">
|
||
<el-input v-model="form.user_ids" type="textarea" :rows="4"
|
||
placeholder="多个用户 ID 用逗号 / 换行 / 空格分隔" />
|
||
<div class="text-muted tip">将向解析出的有效数字 ID 去重后赠送</div>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="赠送类型" prop="gift_type">
|
||
<el-radio-group v-model="form.gift_type">
|
||
<el-radio value="membership">赠送会员</el-radio>
|
||
<el-radio value="points">赠送积分</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
|
||
<el-form-item v-if="form.gift_type === 'membership'" label="会员套餐" prop="plan_code">
|
||
<el-select v-model="form.plan_code" placeholder="请选择会员套餐" style="width: 260px">
|
||
<el-option v-for="(text, code) in PLAN_TEXT" :key="code" :label="text" :value="code" />
|
||
</el-select>
|
||
</el-form-item>
|
||
|
||
<el-form-item v-if="form.gift_type === 'points'" label="积分数量" prop="points">
|
||
<el-input-number v-model="form.points" :min="1" :step="100" style="width: 260px" />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="赠送原因" prop="reason">
|
||
<el-input v-model="form.reason" type="textarea" :rows="3" maxlength="200" show-word-limit
|
||
placeholder="请填写赠送原因(必填)" />
|
||
</el-form-item>
|
||
|
||
<el-form-item>
|
||
<el-button type="primary" :loading="submitting" @click="submit">提交赠送</el-button>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<div class="text-muted note">
|
||
说明:赠送会员写入 membership_orders(source=2),赠送积分写入积分流水(biz_type=5)。
|
||
</div>
|
||
</el-card>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||
import { reactive, ref } from 'vue'
|
||
|
||
import { giftUsers } from '@/api/gift'
|
||
|
||
const PLAN_TEXT = {
|
||
trial: '体验会员',
|
||
month: '月卡',
|
||
year: '年卡',
|
||
lifetime: '终身卡',
|
||
}
|
||
|
||
const formRef = ref()
|
||
const submitting = ref(false)
|
||
|
||
const form = reactive({
|
||
user_ids: '',
|
||
gift_type: 'membership',
|
||
plan_code: 'month',
|
||
points: 100,
|
||
reason: '',
|
||
})
|
||
|
||
const rules = {
|
||
user_ids: [{ required: true, message: '请输入用户 ID', trigger: 'blur' }],
|
||
gift_type: [{ required: true, message: '请选择赠送类型', trigger: 'change' }],
|
||
plan_code: [{ required: true, message: '请选择会员套餐', trigger: 'change' }],
|
||
points: [{ required: true, type: 'number', min: 1, message: '积分需大于 0', trigger: 'blur' }],
|
||
reason: [{ required: true, message: '请填写赠送原因', trigger: 'blur' }],
|
||
}
|
||
|
||
/** 解析用户 ID:支持逗号/换行/空格等分隔,过滤非数字并去重 */
|
||
function parseUserIds(raw) {
|
||
return [
|
||
...new Set(
|
||
(raw || '')
|
||
.split(/[\s,,、;;]+/)
|
||
.map((s) => Number(s))
|
||
.filter((n) => Number.isInteger(n) && n > 0),
|
||
),
|
||
]
|
||
}
|
||
|
||
async function submit() {
|
||
const valid = await formRef.value.validate().catch(() => false)
|
||
if (!valid) return
|
||
|
||
const userIds = parseUserIds(form.user_ids)
|
||
if (!userIds.length) {
|
||
ElMessage.warning('请填写有效的用户 ID')
|
||
return
|
||
}
|
||
|
||
const desc =
|
||
form.gift_type === 'membership'
|
||
? `会员(${PLAN_TEXT[form.plan_code]})`
|
||
: `${form.points} 积分`
|
||
|
||
try {
|
||
await ElMessageBox.confirm(`将向 ${userIds.length} 个用户赠送 ${desc},确认继续?`, '赠送确认', {
|
||
type: 'warning',
|
||
})
|
||
} catch {
|
||
return
|
||
}
|
||
|
||
const payload = {
|
||
user_ids: userIds,
|
||
gift_type: form.gift_type,
|
||
reason: form.reason.trim(),
|
||
}
|
||
if (form.gift_type === 'membership') {
|
||
payload.plan_code = form.plan_code
|
||
} else {
|
||
payload.points = form.points
|
||
}
|
||
|
||
submitting.value = true
|
||
try {
|
||
const res = await giftUsers(payload)
|
||
const ok = Array.isArray(res?.success) ? res.success.length : res?.success || 0
|
||
const fail = Array.isArray(res?.failed) ? res.failed.length : res?.failed || 0
|
||
ElMessage.success(`成功 ${ok} 个,失败 ${fail} 个`)
|
||
// 表单保留,仅清空用户 ID
|
||
form.user_ids = ''
|
||
} finally {
|
||
submitting.value = false
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.gift-card {
|
||
max-width: 720px;
|
||
}
|
||
|
||
.tip {
|
||
font-size: 12px;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.note {
|
||
font-size: 12px;
|
||
padding-left: 110px;
|
||
}
|
||
</style>
|