chore: 冻结资金功能开工前客服后台检查点
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
345
src/views/club/RechargePageCopy.vue
Normal file
345
src/views/club/RechargePageCopy.vue
Normal file
@@ -0,0 +1,345 @@
|
||||
<template>
|
||||
<div class="recharge-copy-page">
|
||||
<el-alert
|
||||
v-if="isAllClubScope"
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
title="充值页文案需在具体俱乐部视图下配置,请切换顶栏俱乐部。"
|
||||
class="scope-alert"
|
||||
/>
|
||||
<ClubScopeHint v-else />
|
||||
|
||||
<div v-if="!hasPermission" class="no-permission">
|
||||
<div>无充值页文案配置权限(需 8080a)</div>
|
||||
</div>
|
||||
|
||||
<div v-else>
|
||||
<div class="header-bar">
|
||||
<h2>充值页文案配置</h2>
|
||||
<p class="desc">按俱乐部配置会员页 / 履约金页规则、权益、平台优势文案与图标。关闭启用或条目为空时,小程序回退默认写死文案。价格与支付逻辑不受影响。</p>
|
||||
</div>
|
||||
|
||||
<el-tabs v-model="pageKey" @tab-change="loadRegions">
|
||||
<el-tab-pane label="会员页" name="huiyuan" />
|
||||
<el-tab-pane label="履约金页" name="yajin" />
|
||||
</el-tabs>
|
||||
|
||||
<div v-loading="loading" class="regions">
|
||||
<el-card
|
||||
v-for="rk in regionKeys"
|
||||
:key="rk"
|
||||
class="region-card"
|
||||
shadow="never"
|
||||
>
|
||||
<template #header>
|
||||
<div class="region-header">
|
||||
<strong>{{ regionLabel(rk) }}</strong>
|
||||
<div class="region-actions">
|
||||
<span class="enabled-label">启用</span>
|
||||
<el-switch v-model="forms[rk].enabled" :disabled="isAllClubScope" />
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
:loading="savingKey === rk"
|
||||
:disabled="isAllClubScope"
|
||||
@click="saveRegion(rk)"
|
||||
>保存本区</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-form label-width="88px" :disabled="isAllClubScope">
|
||||
<el-form-item label="区域标题">
|
||||
<el-input
|
||||
v-model="forms[rk].title"
|
||||
maxlength="64"
|
||||
show-word-limit
|
||||
:placeholder="defaultTitle(rk)"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<div class="item-toolbar">
|
||||
<span>条目列表</span>
|
||||
<el-button size="small" :disabled="isAllClubScope" @click="addItem(rk)">+ 添加</el-button>
|
||||
</div>
|
||||
|
||||
<el-table :data="forms[rk].items" border size="small">
|
||||
<el-table-column type="index" label="#" width="50" />
|
||||
<template v-if="rk === 'rules'">
|
||||
<el-table-column label="规则文案">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.text" type="textarea" :rows="2" placeholder="规则说明" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<template v-else-if="pageKey === 'yajin' && rk === 'benefits'">
|
||||
<el-table-column label="权益名称" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.label" placeholder="如:平台订单优先" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="图标 URL" min-width="200">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.icon_url" placeholder="OSS 相对路径或完整 URL" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-table-column label="标题" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.title" placeholder="标题" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="描述" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.desc" type="textarea" :rows="2" placeholder="描述文案" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="图标 URL" min-width="180">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.icon_url" placeholder="OSS 相对路径或完整 URL" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="rk === 'benefits'" label="强调色" width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input v-model="row.accent_color" placeholder="#E8A317" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column label="操作" width="140" fixed="right">
|
||||
<template #default="{ $index }">
|
||||
<el-button link :disabled="isAllClubScope || $index === 0" @click="moveItem(rk, $index, -1)">上</el-button>
|
||||
<el-button
|
||||
link
|
||||
:disabled="isAllClubScope || $index >= forms[rk].items.length - 1"
|
||||
@click="moveItem(rk, $index, 1)"
|
||||
>下</el-button>
|
||||
<el-button type="danger" link :disabled="isAllClubScope" @click="removeItem(rk, $index)">删</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<p v-if="rk === 'rules'" class="hint">会员页规则建议最多 4 条,与现有 UI 一致。</p>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import request from '@/utils/request'
|
||||
import { JITUAN_API, getAdminClubScope } from '@/utils/club-context'
|
||||
import ClubScopeHint from '@/components/ClubScopeHint.vue'
|
||||
|
||||
const REGIONS = {
|
||||
huiyuan: ['rules', 'benefits', 'advantages'],
|
||||
yajin: ['rules', 'benefits'],
|
||||
}
|
||||
|
||||
const REGION_LABELS = {
|
||||
rules: '规则',
|
||||
benefits: '专属权益',
|
||||
advantages: '平台优势',
|
||||
}
|
||||
|
||||
const DEFAULT_TITLES = {
|
||||
huiyuan: { rules: '会员规则', benefits: '专属权益', advantages: '平台优势' },
|
||||
yajin: { rules: '履约金规则', benefits: '平台履约金权益' },
|
||||
}
|
||||
|
||||
const username = ref(localStorage.getItem('username') || '')
|
||||
const hasPermission = ref(true)
|
||||
const isAllClubScope = computed(() => getAdminClubScope() === 'all')
|
||||
const pageKey = ref('huiyuan')
|
||||
const loading = ref(false)
|
||||
const savingKey = ref('')
|
||||
const forms = reactive({
|
||||
rules: emptyForm(),
|
||||
benefits: emptyForm(),
|
||||
advantages: emptyForm(),
|
||||
})
|
||||
|
||||
const regionKeys = computed(() => REGIONS[pageKey.value] || [])
|
||||
|
||||
function emptyForm() {
|
||||
return { title: '', items: [], enabled: false, sort_order: 0 }
|
||||
}
|
||||
|
||||
function regionLabel(rk) {
|
||||
return REGION_LABELS[rk] || rk
|
||||
}
|
||||
|
||||
function defaultTitle(rk) {
|
||||
return (DEFAULT_TITLES[pageKey.value] || {})[rk] || ''
|
||||
}
|
||||
|
||||
function blankItem(rk) {
|
||||
if (rk === 'rules') return { text: '' }
|
||||
if (pageKey.value === 'yajin' && rk === 'benefits') return { label: '', icon_url: '' }
|
||||
if (rk === 'benefits') return { title: '', desc: '', icon_url: '', accent_color: '' }
|
||||
return { title: '', desc: '', icon_url: '' }
|
||||
}
|
||||
|
||||
function applyRegions(regions) {
|
||||
for (const rk of ['rules', 'benefits', 'advantages']) {
|
||||
const src = regions?.[rk]
|
||||
if (!src) {
|
||||
Object.assign(forms[rk], emptyForm())
|
||||
continue
|
||||
}
|
||||
forms[rk].title = src.title || ''
|
||||
forms[rk].enabled = !!src.enabled
|
||||
forms[rk].sort_order = src.sort_order || 0
|
||||
forms[rk].items = Array.isArray(src.items)
|
||||
? src.items.map((it) => ({ ...blankItem(rk), ...it }))
|
||||
: []
|
||||
}
|
||||
}
|
||||
|
||||
const loadRegions = async () => {
|
||||
if (isAllClubScope.value) {
|
||||
applyRegions({})
|
||||
return
|
||||
}
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await request.post(JITUAN_API.rechargePageCopyGet, {
|
||||
phone: username.value,
|
||||
page_key: pageKey.value,
|
||||
})
|
||||
if (res.code === 0) {
|
||||
hasPermission.value = true
|
||||
applyRegions(res.data?.regions || {})
|
||||
} else if (res.code === 403) {
|
||||
hasPermission.value = false
|
||||
} else {
|
||||
ElMessage.error(res.msg || '加载失败')
|
||||
}
|
||||
} catch {
|
||||
ElMessage.error('加载充值页文案失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const addItem = (rk) => {
|
||||
forms[rk].items.push(blankItem(rk))
|
||||
}
|
||||
|
||||
const removeItem = (rk, index) => {
|
||||
forms[rk].items.splice(index, 1)
|
||||
}
|
||||
|
||||
const moveItem = (rk, index, delta) => {
|
||||
const list = forms[rk].items
|
||||
const next = index + delta
|
||||
if (next < 0 || next >= list.length) return
|
||||
const tmp = list[index]
|
||||
list[index] = list[next]
|
||||
list[next] = tmp
|
||||
}
|
||||
|
||||
const saveRegion = async (rk) => {
|
||||
if (isAllClubScope.value) return
|
||||
savingKey.value = rk
|
||||
try {
|
||||
const form = forms[rk]
|
||||
const res = await request.post(JITUAN_API.rechargePageCopySave, {
|
||||
phone: username.value,
|
||||
page_key: pageKey.value,
|
||||
region_key: rk,
|
||||
title: form.title,
|
||||
enabled: form.enabled,
|
||||
sort_order: form.sort_order,
|
||||
items: form.items,
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(`${regionLabel(rk)}已保存`)
|
||||
if (res.data?.region) {
|
||||
const r = res.data.region
|
||||
forms[rk].title = r.title || ''
|
||||
forms[rk].enabled = !!r.enabled
|
||||
forms[rk].items = Array.isArray(r.items)
|
||||
? r.items.map((it) => ({ ...blankItem(rk), ...it }))
|
||||
: []
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res.msg || '保存失败')
|
||||
}
|
||||
} catch {
|
||||
ElMessage.error('保存失败')
|
||||
} finally {
|
||||
savingKey.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
watch(pageKey, () => {
|
||||
// tab-change 也会触发 load;此处兜底
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadRegions()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.recharge-copy-page {
|
||||
padding: 16px 20px 40px;
|
||||
}
|
||||
.scope-alert {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.header-bar h2 {
|
||||
margin: 0 0 6px;
|
||||
font-size: 20px;
|
||||
}
|
||||
.desc {
|
||||
margin: 0 0 16px;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.regions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
.region-card {
|
||||
border: 1px solid #ebeef5;
|
||||
}
|
||||
.region-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
}
|
||||
.region-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
.enabled-label {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
}
|
||||
.item-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 4px 0 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
.hint {
|
||||
margin: 8px 0 0;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
.no-permission {
|
||||
padding: 48px;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
@@ -16,9 +16,16 @@
|
||||
<el-option v-for="opt in pageOptions" :key="opt.key" :label="opt.label" :value="opt.key" />
|
||||
</el-select>
|
||||
</div>
|
||||
<el-alert
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="page-alert"
|
||||
title="点单小程序(UFO)首页公告/主轮播只读「点单页主轮播」,不读「抢单池」。改公告前请确认右上角已切到 ufo,且下拉选中「点单页主轮播」。"
|
||||
/>
|
||||
<p class="page-hint">
|
||||
UFO 点单端:主轮播选「点单页主轮播」;公告下第二横幅选「点单页第二横幅(可多图)」;
|
||||
「我的」顶区背景选「点单个人中心背景(可多图)」。改图前请切到具体俱乐部(如 ufo),勿在集团视图下上传。
|
||||
UFO:主轮播+首页公告 →「点单页主轮播」;公告下第二横幅 →「点单页第二横幅」;「我的」顶区 →「点单个人中心背景」。
|
||||
勿在集团视图下修改。星阙抢单端才用「抢单池」。
|
||||
</p>
|
||||
|
||||
<el-card class="section-card" shadow="never">
|
||||
@@ -143,13 +150,15 @@ function mergePageOptions(fromServer) {
|
||||
|
||||
const username = ref(localStorage.getItem('username') || '')
|
||||
const hasPermission = ref(true)
|
||||
const pageKey = ref('order_pool')
|
||||
/** 默认点单页:UFO/点单端改公告最容易误停在「抢单池」 */
|
||||
const pageKey = ref('accept_order')
|
||||
const pageOptions = ref(mergePageOptions([]))
|
||||
const gonggaoTitle = computed(() => {
|
||||
const opt = pageOptions.value.find((o) => o.key === pageKey.value)
|
||||
const label = opt ? opt.label : pageKey.value
|
||||
return `${label} · 页面公告`
|
||||
})
|
||||
const activeClubId = ref('')
|
||||
const lunboList = ref([])
|
||||
const gonggaoContent = ref('')
|
||||
const scopeHint = ref('')
|
||||
@@ -174,10 +183,11 @@ const fetchGonggao = async () => {
|
||||
})
|
||||
if (res.code === 0) {
|
||||
gonggaoContent.value = res.data?.content || ''
|
||||
activeClubId.value = res.data?.club_id || ''
|
||||
if (res.data?.scope === 'ALL_CLUBS') {
|
||||
scopeHint.value = '集团视图下仅可查看;修改轮播/公告请切换到具体子公司'
|
||||
} else if (res.data?.club_id) {
|
||||
scopeHint.value = `以下配置仅作用于俱乐部 ${res.data.club_id}`
|
||||
scopeHint.value = `以下配置仅作用于俱乐部 ${res.data.club_id} · 当前页 ${pageKey.value}`
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
@@ -227,7 +237,10 @@ const saveGonggao = async () => {
|
||||
content,
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success('保存成功')
|
||||
const opt = pageOptions.value.find((o) => o.key === pageKey.value)
|
||||
const label = opt ? opt.label : pageKey.value
|
||||
const club = activeClubId.value || '当前俱乐部'
|
||||
ElMessage.success(`已保存到 ${club} · ${label}`)
|
||||
} else {
|
||||
ElMessage.error(res.msg || '保存失败')
|
||||
}
|
||||
@@ -384,6 +397,9 @@ onMounted(async () => {
|
||||
font-size: 13px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
.page-alert {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.header-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
@@ -168,6 +168,35 @@
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="section-card" shadow="never">
|
||||
<template #header><strong>打手「我的」- VIP条背景/图标</strong></template>
|
||||
<p class="hint">仅影响「我的」页 VIP 会员条。未上传时小程序继续用黑金硬编码样式;上传后按俱乐部覆盖(云溪/小西等各自独立)。</p>
|
||||
<div class="icon-grid">
|
||||
<div v-for="item in fighterMineVipIcons" :key="item.icon_key" class="icon-cell">
|
||||
<div class="icon-label">{{ item.label }}</div>
|
||||
<div class="icon-key">{{ item.icon_key }}</div>
|
||||
<el-image
|
||||
v-if="previewUrl(item)"
|
||||
:src="previewUrl(item)"
|
||||
fit="contain"
|
||||
class="poster-preview"
|
||||
/>
|
||||
<div v-else class="empty-preview">暂无图片</div>
|
||||
<el-upload
|
||||
action="#"
|
||||
:auto-upload="false"
|
||||
:show-file-list="false"
|
||||
:on-change="(f) => uploadIcon(f, item.icon_key)"
|
||||
accept="image/jpeg,image/png,image/jpg,image/webp"
|
||||
>
|
||||
<el-button size="small" type="primary" :loading="uploadingKey === item.icon_key">
|
||||
{{ item.is_uploaded ? '更换' : '上传' }}
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="section-card" shadow="never">
|
||||
<template #header><strong>打手「我的」- 会员/保证金充值页大背景</strong></template>
|
||||
<p class="hint">会员充值页顶图、保证金页顶图与右侧装饰。未上传时小程序用默认样式;此处始终可直接上传。</p>
|
||||
@@ -314,9 +343,16 @@ const FIGHTER_PAGE_BG_META = [
|
||||
{ icon_key: 'fighter_deposit_hero', label: '打手保证金页-卡片右侧装饰图' },
|
||||
]
|
||||
const FIGHTER_PAGE_BG_KEYS = new Set(FIGHTER_PAGE_BG_META.map((i) => i.icon_key))
|
||||
/** 「我的」VIP 条:新增背景/图标,未上传不下发,小程序走硬编码 */
|
||||
const FIGHTER_MINE_VIP_META = [
|
||||
{ icon_key: 'fighter_mine_vip_bg', label: '打手「我的」-VIP条背景图' },
|
||||
{ icon_key: 'fighter_mine_vip_icon', label: '打手「我的」-VIP条左侧图标' },
|
||||
]
|
||||
const FIGHTER_MINE_VIP_KEYS = new Set(FIGHTER_MINE_VIP_META.map((i) => i.icon_key))
|
||||
const CONFIG_ONLY_PREVIEW_KEYS = new Set([
|
||||
...GRAB_CARD_BG_KEYS,
|
||||
...FIGHTER_PAGE_BG_KEYS,
|
||||
...FIGHTER_MINE_VIP_KEYS,
|
||||
])
|
||||
const FIGHTER_BANNER_KEYS = new Set(['fighter_recharge_member', 'fighter_recharge_deposit'])
|
||||
const FIGHTER_MINE_PAGE_KEYS = new Set([
|
||||
@@ -349,15 +385,17 @@ const cuserMineIcons = computed(() => icons.value.filter((i) => CUSER_MINE_KEYS.
|
||||
const merchantIcons = computed(() => icons.value.filter((i) => i.icon_key.startsWith('merchant_')))
|
||||
const grabCardBgIcons = computed(() => mergeFixedIcons(GRAB_CARD_BG_META, icons.value))
|
||||
const fighterPageBgIcons = computed(() => mergeFixedIcons(FIGHTER_PAGE_BG_META, icons.value))
|
||||
const fighterMineVipIcons = computed(() => mergeFixedIcons(FIGHTER_MINE_VIP_META, icons.value))
|
||||
const fighterBannerIcons = computed(() => icons.value.filter((i) => FIGHTER_BANNER_KEYS.has(i.icon_key)))
|
||||
const fighterMinePageIcons = computed(() => icons.value.filter((i) => FIGHTER_MINE_PAGE_KEYS.has(i.icon_key)))
|
||||
const fighterMoreFuncIcons = computed(() => icons.value.filter((i) => {
|
||||
const k = i.icon_key
|
||||
if (FIGHTER_MINE_VIP_KEYS.has(k)) return false
|
||||
return k.startsWith('fighter_mine_') && !FIGHTER_MINE_PAGE_KEYS.has(k)
|
||||
}))
|
||||
const fighterRechargeIcons = computed(() => icons.value.filter((i) => {
|
||||
const k = i.icon_key
|
||||
if (FIGHTER_BANNER_KEYS.has(k) || FIGHTER_PAGE_BG_KEYS.has(k)) return false
|
||||
if (FIGHTER_BANNER_KEYS.has(k) || FIGHTER_PAGE_BG_KEYS.has(k) || FIGHTER_MINE_VIP_KEYS.has(k)) return false
|
||||
return k.startsWith('fighter_recharge_') || k.startsWith('fighter_deposit_')
|
||||
}))
|
||||
const commonIcons = computed(() => icons.value.filter((i) => COMMON_KEYS.has(i.icon_key)))
|
||||
|
||||
@@ -394,9 +394,16 @@ const enterEditMode = () => {
|
||||
zhuanqu_id: product.value.zhuanqu_id,
|
||||
yaoqiuleixing: product.value.yaoqiuleixing,
|
||||
huiyuan_id: product.value.huiyuan_id || '',
|
||||
yongjin: product.value.yongjin !== null ? product.value.yongjin : null,
|
||||
kaioi_ewai_dashou_fencheng: product.value.kaioi_ewai_dashou_fencheng,
|
||||
ewai_dashou_fencheng: product.value.ewai_dashou_fencheng || 0,
|
||||
yongjin: product.value.yongjin !== null && product.value.yongjin !== undefined ? Number(product.value.yongjin) : null,
|
||||
kaioi_ewai_dashou_fencheng: !!(
|
||||
product.value.kaioi_ewai_dashou_fencheng
|
||||
?? product.value.kaioi_ewai_PlayerCommission
|
||||
),
|
||||
ewai_dashou_fencheng: Number(
|
||||
product.value.ewai_dashou_fencheng
|
||||
?? product.value.ewai_PlayerCommission
|
||||
?? 0
|
||||
),
|
||||
jieshao: product.value.jieshao || '',
|
||||
xiadan_xuzhi: product.value.xiadan_xuzhi || '',
|
||||
tupian_url: product.value.tupian_url,
|
||||
@@ -414,9 +421,16 @@ const enterEditMode = () => {
|
||||
zhuanqu_id: product.value.zhuanqu_id,
|
||||
yaoqiuleixing: product.value.yaoqiuleixing,
|
||||
huiyuan_id: product.value.huiyuan_id || '',
|
||||
yongjin: product.value.yongjin !== null ? product.value.yongjin : null,
|
||||
kaioi_ewai_dashou_fencheng: product.value.kaioi_ewai_dashou_fencheng,
|
||||
ewai_dashou_fencheng: product.value.ewai_dashou_fencheng || 0,
|
||||
yongjin: product.value.yongjin !== null && product.value.yongjin !== undefined ? Number(product.value.yongjin) : null,
|
||||
kaioi_ewai_dashou_fencheng: !!(
|
||||
product.value.kaioi_ewai_dashou_fencheng
|
||||
?? product.value.kaioi_ewai_PlayerCommission
|
||||
),
|
||||
ewai_dashou_fencheng: Number(
|
||||
product.value.ewai_dashou_fencheng
|
||||
?? product.value.ewai_PlayerCommission
|
||||
?? 0
|
||||
),
|
||||
jieshao: product.value.jieshao || '',
|
||||
xiadan_xuzhi: product.value.xiadan_xuzhi || '',
|
||||
tupian_url: product.value.tupian_url,
|
||||
@@ -480,8 +494,11 @@ const saveProduct = async () => {
|
||||
} else {
|
||||
formData.append('yongjin', form.yongjin !== null ? form.yongjin : 0)
|
||||
}
|
||||
formData.append('kaioi_ewai_dashou_fencheng', form.kaioi_ewai_dashou_fencheng)
|
||||
formData.append('kaioi_ewai_dashou_fencheng', form.kaioi_ewai_dashou_fencheng ? 'true' : 'false')
|
||||
formData.append('ewai_dashou_fencheng', form.ewai_dashou_fencheng)
|
||||
// 兼容旧后端字段名
|
||||
formData.append('kaioi_ewai_PlayerCommission', form.kaioi_ewai_dashou_fencheng ? 'true' : 'false')
|
||||
formData.append('ewai_PlayerCommission', form.ewai_dashou_fencheng)
|
||||
formData.append('jieshao', form.jieshao || '')
|
||||
formData.append('xiadan_xuzhi', form.xiadan_xuzhi || '')
|
||||
formData.append('shenhezhuangtai', form.shenhezhuangtai)
|
||||
@@ -628,9 +645,16 @@ const fetchProductDetail = async () => {
|
||||
zhuanqu_id: product.value.zhuanqu_id,
|
||||
yaoqiuleixing: product.value.yaoqiuleixing,
|
||||
huiyuan_id: product.value.huiyuan_id || '',
|
||||
yongjin: product.value.yongjin !== null ? product.value.yongjin : null,
|
||||
kaioi_ewai_dashou_fencheng: product.value.kaioi_ewai_dashou_fencheng,
|
||||
ewai_dashou_fencheng: product.value.ewai_dashou_fencheng || 0,
|
||||
yongjin: product.value.yongjin !== null && product.value.yongjin !== undefined ? Number(product.value.yongjin) : null,
|
||||
kaioi_ewai_dashou_fencheng: !!(
|
||||
product.value.kaioi_ewai_dashou_fencheng
|
||||
?? product.value.kaioi_ewai_PlayerCommission
|
||||
),
|
||||
ewai_dashou_fencheng: Number(
|
||||
product.value.ewai_dashou_fencheng
|
||||
?? product.value.ewai_PlayerCommission
|
||||
?? 0
|
||||
),
|
||||
jieshao: product.value.jieshao || '',
|
||||
xiadan_xuzhi: product.value.xiadan_xuzhi || '',
|
||||
tupian_url: product.value.tupian_url,
|
||||
|
||||
@@ -744,6 +744,7 @@ const submitAddProduct = async () => {
|
||||
}
|
||||
if (addForm.fencheng_type === 'custom') {
|
||||
formData.append('ewai_dashou_fencheng', addForm.ewai_dashou_fencheng)
|
||||
formData.append('ewai_PlayerCommission', addForm.ewai_dashou_fencheng)
|
||||
}
|
||||
formData.append('file', addForm.imageFile)
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
</template>
|
||||
</el-input>
|
||||
<el-button type="primary" @click="handleSearch" :loading="loading">搜索</el-button>
|
||||
<el-button type="success" @click="openAddDialog">添加商家</el-button>
|
||||
<el-button :icon="Refresh" @click="handleResetFilters" circle />
|
||||
</div>
|
||||
|
||||
@@ -151,6 +152,31 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="addDialogVisible" title="添加商家" width="420px" destroy-on-close>
|
||||
<el-form label-width="88px" @submit.prevent>
|
||||
<el-form-item label="用户ID" required>
|
||||
<el-input
|
||||
v-model="addForm.yonghuid"
|
||||
placeholder="填写小程序用户 UID"
|
||||
clearable
|
||||
maxlength="16"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商家昵称">
|
||||
<el-input
|
||||
v-model="addForm.nicheng"
|
||||
placeholder="可选,默认用用户昵称"
|
||||
clearable
|
||||
maxlength="50"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="addDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="addLoading" @click="submitAddMerchant">确认添加</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -175,6 +201,9 @@ const username = ref(localStorage.getItem('username') || '')
|
||||
const hasPermission = ref(true)
|
||||
const totalCount = ref(0) // 商家总数
|
||||
const validMerchantCount = ref(0) // 有效商家数(状态为正常的商家数)
|
||||
const addDialogVisible = ref(false)
|
||||
const addLoading = ref(false)
|
||||
const addForm = ref({ yonghuid: '', nicheng: '' })
|
||||
|
||||
// 筛选条件
|
||||
const balanceOp = ref('gte') // 余额比较符: gte(>=) / lte(<=)
|
||||
@@ -284,6 +313,40 @@ const goToDetail = (yonghuid) => {
|
||||
}
|
||||
}
|
||||
|
||||
const openAddDialog = () => {
|
||||
addForm.value = { yonghuid: '', nicheng: '' }
|
||||
addDialogVisible.value = true
|
||||
}
|
||||
|
||||
const submitAddMerchant = async () => {
|
||||
const yonghuid = (addForm.value.yonghuid || '').trim()
|
||||
if (!yonghuid) {
|
||||
ElMessage.warning('请填写用户ID')
|
||||
return
|
||||
}
|
||||
addLoading.value = true
|
||||
try {
|
||||
const res = await request.post(JITUAN_API.shangjiaAdd, {
|
||||
username: username.value,
|
||||
yonghuid,
|
||||
nicheng: (addForm.value.nicheng || '').trim(),
|
||||
})
|
||||
if (res.code === 0) {
|
||||
ElMessage.success(res.msg || '商家添加成功')
|
||||
addDialogVisible.value = false
|
||||
page.value = 1
|
||||
fetchMerchants()
|
||||
} else {
|
||||
ElMessage.error(res.msg || '添加失败')
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
ElMessage.error('添加商家失败,请稍后重试')
|
||||
} finally {
|
||||
addLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化加载
|
||||
onMounted(() => {
|
||||
fetchMerchants()
|
||||
|
||||
Reference in New Issue
Block a user