Files
2026-10-15 20:36:59 +08:00

156 lines
4.5 KiB
Vue
Raw Permalink 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="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>