feat: 打手详情赠送会员 UI,并改善后台错误提示
新增赠送会员送/改期/移除;请求失败优先展示后端 msg;考核官添加防重复提交。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -53,7 +53,7 @@ service.interceptors.response.use(
|
||||
ElMessage.error('没有权限')
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(error.response.data?.message || '请求失败')
|
||||
ElMessage.error(error.response.data?.msg || error.response.data?.message || '请求失败')
|
||||
}
|
||||
} else {
|
||||
ElMessage.error('网络错误')
|
||||
|
||||
@@ -835,6 +835,10 @@ const confirmAddUser = async () => {
|
||||
ElMessage.warning('密码和二级密码至少6位')
|
||||
return
|
||||
}
|
||||
if (newUserRoleCodes.value.length === 0) {
|
||||
ElMessage.warning('请至少选择一个角色')
|
||||
return
|
||||
}
|
||||
addingUser.value = true
|
||||
try {
|
||||
const res = await request.post('/houtai/tjyhjs', {
|
||||
|
||||
@@ -282,7 +282,7 @@ const saveChenghao = async () => {
|
||||
ElMessage.error(res.msg || '操作失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
ElMessage.error(e?.response?.data?.msg || e?.message || '网络错误')
|
||||
} finally {
|
||||
saving.value = false
|
||||
}
|
||||
@@ -311,7 +311,7 @@ const deleteChenghao = async () => {
|
||||
ElMessage.error(res.msg || '删除失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
ElMessage.error(e?.response?.data?.msg || e?.message || '网络错误')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -510,6 +510,7 @@ const closeAddDialog = () => {
|
||||
}
|
||||
|
||||
const submitAddExaminer = async () => {
|
||||
if (addSaving.value) return
|
||||
const uid = (addForm.yonghuid || '').trim()
|
||||
if (!uid) {
|
||||
ElMessage.warning('请输入用户ID')
|
||||
@@ -535,7 +536,7 @@ const submitAddExaminer = async () => {
|
||||
ElMessage.error(res.msg || '添加失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error('网络错误')
|
||||
ElMessage.error(e?.response?.data?.msg || e?.message || '网络错误')
|
||||
} finally {
|
||||
addSaving.value = false
|
||||
}
|
||||
|
||||
@@ -325,6 +325,46 @@
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 赠送会员(免费接单,独立表) -->
|
||||
<el-card class="info-card" shadow="hover">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>🎁 赠送会员(免费接单)</span>
|
||||
<el-button
|
||||
type="success"
|
||||
size="small"
|
||||
@click="openGiftDialog()"
|
||||
:disabled="!hasGiftPermission"
|
||||
>送会员</el-button>
|
||||
</div>
|
||||
<div v-if="!hasGiftPermission" class="member-hint warn">需要打手基础管理或加积分权限</div>
|
||||
<div v-else class="member-hint">与上方购买会员分开;仅用于抢单资格,不写购买表</div>
|
||||
</template>
|
||||
<div class="member-list">
|
||||
<div v-for="gift in giftMemberList" :key="'g-' + gift.id" class="member-item gift-item">
|
||||
<el-tag :type="gift.is_active ? 'success' : 'info'" effect="plain">
|
||||
{{ gift.huiyuan_name }} 到期: {{ gift.daoqi_time || '--' }}
|
||||
</el-tag>
|
||||
<span class="gift-meta">赠送人 {{ gift.song_ren || '--' }} · {{ gift.song_time || '--' }}</span>
|
||||
<el-button
|
||||
type="warning"
|
||||
size="small"
|
||||
link
|
||||
@click="openGiftDialog(gift)"
|
||||
:disabled="!hasGiftPermission"
|
||||
>改期</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="removeGiftMember(gift)"
|
||||
:disabled="!hasGiftPermission"
|
||||
>移除</el-button>
|
||||
</div>
|
||||
<div v-if="giftMemberList.length === 0" class="empty-message">暂无赠送会员</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 其他信息卡片 -->
|
||||
<el-card class="info-card" shadow="hover">
|
||||
<template #header>
|
||||
@@ -377,24 +417,64 @@
|
||||
|
||||
<!-- 添加会员弹窗 -->
|
||||
<el-dialog v-model="memberDialogVisible" title="添加会员" width="400px">
|
||||
<el-form :model="memberForm" label-width="80px">
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="会员类型" required>
|
||||
<el-select v-model="memberForm.huiyuan_id" placeholder="请选择会员" style="width: 100%">
|
||||
<el-select v-model="memberForm.huiyuan_id" placeholder="请选择" filterable style="width: 100%">
|
||||
<el-option
|
||||
v-for="item in allMembers"
|
||||
:key="item.huiyuan_id"
|
||||
:label="item.jieshao"
|
||||
:value="item.huiyuan_id"
|
||||
v-for="m in allMembers"
|
||||
:key="m.huiyuan_id"
|
||||
:label="`${m.jieshao} (${m.huiyuan_id})`"
|
||||
:value="m.huiyuan_id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="天数" required>
|
||||
<el-input-number v-model="memberForm.days" :min="1" :step="1" style="width: 100%" />
|
||||
<el-input-number v-model="memberForm.days" :min="1" :max="3650" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="memberDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="addMember" :loading="memberAdding">确认</el-button>
|
||||
<el-button type="primary" :loading="memberAdding" @click="addMember">确认</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 赠送会员弹窗 -->
|
||||
<el-dialog
|
||||
v-model="giftDialogVisible"
|
||||
:title="giftForm.id ? '修改赠送会员到期时间' : '送会员(免费接单)'"
|
||||
width="420px"
|
||||
>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="会员类型" required>
|
||||
<el-select
|
||||
v-model="giftForm.huiyuan_id"
|
||||
placeholder="请选择真实会员类型"
|
||||
filterable
|
||||
style="width: 100%"
|
||||
:disabled="!!giftForm.id"
|
||||
>
|
||||
<el-option
|
||||
v-for="m in allMembers"
|
||||
:key="'g-' + m.huiyuan_id"
|
||||
:label="`${m.jieshao} (${m.huiyuan_id})`"
|
||||
:value="m.huiyuan_id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="到期日期" required>
|
||||
<el-date-picker
|
||||
v-model="giftForm.daoqi_time"
|
||||
type="datetime"
|
||||
placeholder="选择到期时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<div class="member-hint">赠送时若积分不是 10,将自动改成 10 并写入操作日志</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="giftDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="giftSaving" @click="submitGiftMember">确认</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -418,6 +498,7 @@ const username = ref(localStorage.getItem('username') || '')
|
||||
const playerInfo = ref({})
|
||||
const originalInfo = ref({})
|
||||
const memberList = ref([])
|
||||
const giftMemberList = ref([])
|
||||
const allMembers = ref([])
|
||||
const isEditMode = ref(false)
|
||||
const editData = ref({})
|
||||
@@ -427,6 +508,11 @@ const memberDialogVisible = ref(false)
|
||||
const memberForm = reactive({ huiyuan_id: '', days: 30 })
|
||||
const memberAdding = ref(false)
|
||||
|
||||
// 赠送会员弹窗
|
||||
const giftDialogVisible = ref(false)
|
||||
const giftSaving = ref(false)
|
||||
const giftForm = reactive({ id: null, huiyuan_id: '', daoqi_time: '' })
|
||||
|
||||
// 权限控制
|
||||
const userPermissions = ref([])
|
||||
|
||||
@@ -436,6 +522,14 @@ const hasMemberPermission = computed(() =>
|
||||
userPermissions.value.includes('001ff') ||
|
||||
userPermissions.value.includes('001gg')
|
||||
)
|
||||
const hasGiftPermission = computed(() =>
|
||||
userPermissions.value.includes('000001') ||
|
||||
userPermissions.value.includes('001aa') ||
|
||||
userPermissions.value.includes('001bb') ||
|
||||
userPermissions.value.includes('001cc') ||
|
||||
userPermissions.value.includes('001dd') ||
|
||||
userPermissions.value.includes('001ee')
|
||||
)
|
||||
const hasChenghaoPermission = computed(() => userPermissions.value.includes('001hh'))
|
||||
const canChangeInviter = computed(() => userPermissions.value.includes('001ee') || userPermissions.value.includes('000001'))
|
||||
|
||||
@@ -536,6 +630,7 @@ const fetchDetail = async () => {
|
||||
}
|
||||
originalInfo.value = JSON.parse(JSON.stringify(playerInfo.value))
|
||||
memberList.value = data.member_list || []
|
||||
giftMemberList.value = data.gift_member_list || []
|
||||
allMembers.value = data.all_members || []
|
||||
userPermissions.value = data.permissions || []
|
||||
} else if (res.code === 403) {
|
||||
@@ -714,6 +809,82 @@ const removeMember = async (member) => {
|
||||
}
|
||||
|
||||
// 关键:从路由参数中获取 playerId(参数名必须为 playerId)
|
||||
const openGiftDialog = (gift = null) => {
|
||||
if (!hasGiftPermission.value) {
|
||||
ElMessage.warning('无赠送会员权限')
|
||||
return
|
||||
}
|
||||
if (gift) {
|
||||
giftForm.id = gift.id
|
||||
giftForm.huiyuan_id = gift.huiyuan_id
|
||||
giftForm.daoqi_time = gift.daoqi_time || ''
|
||||
} else {
|
||||
giftForm.id = null
|
||||
giftForm.huiyuan_id = ''
|
||||
giftForm.daoqi_time = ''
|
||||
}
|
||||
giftDialogVisible.value = true
|
||||
}
|
||||
|
||||
const submitGiftMember = async () => {
|
||||
if (!giftForm.huiyuan_id) {
|
||||
ElMessage.warning('请选择会员类型')
|
||||
return
|
||||
}
|
||||
if (!giftForm.daoqi_time) {
|
||||
ElMessage.warning('请选择到期时间')
|
||||
return
|
||||
}
|
||||
giftSaving.value = true
|
||||
try {
|
||||
const payload = {
|
||||
phone: username.value,
|
||||
dashou_id: playerId.value,
|
||||
huiyuan_id: giftForm.huiyuan_id,
|
||||
daoqi_time: giftForm.daoqi_time,
|
||||
}
|
||||
if (giftForm.id) payload.id = giftForm.id
|
||||
const res = await request.post('/houtai/dszsonghy', payload)
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(res.msg || '操作成功')
|
||||
giftDialogVisible.value = false
|
||||
await fetchDetail()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '操作失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error(e?.response?.data?.msg || '操作失败')
|
||||
} finally {
|
||||
giftSaving.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const removeGiftMember = async (gift) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定移除赠送会员“${gift.huiyuan_name}”吗?移除后将无法用该赠送资格抢单。`,
|
||||
'提示',
|
||||
{ type: 'warning' }
|
||||
)
|
||||
} catch { return }
|
||||
try {
|
||||
const res = await request.post('/houtai/dsycsonghy', {
|
||||
phone: username.value,
|
||||
dashou_id: playerId.value,
|
||||
id: gift.id,
|
||||
huiyuan_id: gift.huiyuan_id,
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('移除成功')
|
||||
await fetchDetail()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '移除失败')
|
||||
}
|
||||
} catch (e) {
|
||||
ElMessage.error(e?.response?.data?.msg || '移除失败')
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
playerId.value = route.params.playerId
|
||||
if (!playerId.value) {
|
||||
@@ -737,6 +908,15 @@ onMounted(() => {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
.gift-item {
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
.gift-meta {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin: 0 4px;
|
||||
}
|
||||
.member-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
Reference in New Issue
Block a user