fix: 类型专区页支持俱乐部上架下架;商品数据分析仅集团可见

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-07-21 03:33:55 +08:00
parent 23f7263996
commit 7c51b1f38b
3 changed files with 92 additions and 6 deletions

View File

@@ -123,7 +123,7 @@
</template>
<el-menu-item v-if="canShow('product.list')" index="/product/list">商品列表</el-menu-item>
<el-menu-item v-if="canShow('product.type-zone')" index="/product/type-zone">商品类型专区管理</el-menu-item>
<el-menu-item v-if="canShow('product.data')" index="/product/data">商品数据分析</el-menu-item>
<el-menu-item v-if="canShow('product.data') && isAllClubScope" index="/product/data">商品数据分析</el-menu-item>
<el-menu-item v-if="canShow('product.fake-orders')" index="/product/fake-orders">假单管理</el-menu-item>
</el-sub-menu>

View File

@@ -282,7 +282,6 @@
<el-button type="primary" @click="submitAddProduct" :loading="submitting">确认发布</el-button>
</template>
</el-dialog>
</div>
</div>
</template>

View File

@@ -15,7 +15,7 @@
show-icon
class="scope-tip"
title="当前为具体小程序视图"
description="可管理本俱乐部专区(增删改)。商品类型为集团共享定义,添加/编辑/删除类型请切到「集团汇总」;本俱乐部上架类型请用「小程序配置 → 抢单商品类型」。"
description="可上架/下架集团商品类型(与抢单端一致,名称不可改),并可管理本俱乐部专区。新增/编辑/删除类型定义请切到「集团汇总」。"
/>
<el-alert
v-else
@@ -24,7 +24,7 @@
show-icon
class="scope-tip"
title="当前为集团汇总视图"
description="可维护全局商品类型。专区会写入当前请求头对应俱乐部;管理某小程序专区请切到该小程序。"
description="可维护全局商品类型定义。专区请求头俱乐部写入;管理某小程序专区与上架类型请切到该小程序。"
/>
<!-- 费率展示区域集团汇总才改费率 -->
@@ -55,6 +55,7 @@
<h3>商品类型</h3>
<div class="header-actions">
<el-button v-if="isAllClubScope" type="primary" size="small" @click="addType">+ 添加类型</el-button>
<el-button v-else type="primary" size="small" @click="openShelfCatalog">+ 上架类型</el-button>
<div class="audit-toggle">
<span>显示审核专用</span>
<el-switch v-model="showAuditType" @change="refreshTypeList" />
@@ -83,8 +84,13 @@
<el-button type="primary" link size="small" @click.stop="editType(type)">编辑</el-button>
<el-button type="danger" link size="small" @click.stop="deleteType(type)">删除</el-button>
</div>
<div class="type-actions" v-else>
<el-button type="danger" link size="small" @click.stop="disableClubType(type)">下架</el-button>
</div>
</div>
<div v-if="filteredTypeList.length === 0" class="empty-tip">
{{ isAllClubScope ? '暂无商品类型' : '本俱乐部尚未上架类型点击上架类型' }}
</div>
<div v-if="filteredTypeList.length === 0" class="empty-tip">暂无商品类型</div>
</div>
</div>
@@ -243,6 +249,17 @@
<el-button type="primary" @click="submitRate" :loading="rateSubmitting">保存</el-button>
</template>
</el-dialog>
<!-- 俱乐部上架类型目录 -->
<el-dialog v-model="shelfCatalogVisible" title="上架商品类型" width="520px">
<div v-loading="shelfCatalogLoading">
<el-empty v-if="!shelfCatalogLoading && shelfCatalog.length === 0" description="暂无可上架类型(请集团先创建,或已全部上架)" />
<div v-for="c in shelfCatalog" :key="c.id" class="shelf-catalog-row">
<span>{{ c.jieshao }} (ID {{ c.id }})</span>
<el-button size="small" type="primary" @click="enableClubType(c)">上架</el-button>
</div>
</div>
</el-dialog>
</div>
</template>
@@ -251,7 +268,7 @@ import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import request from '@/utils/request'
import upload from '@/utils/upload'
import { getAdminClubScope } from '@/utils/club-context'
import { getAdminClubScope, JITUAN_API } from '@/utils/club-context'
const isAllClubScope = computed(() => getAdminClubScope() === 'all')
@@ -268,6 +285,10 @@ const showAuditZone = ref(false)
const ratePlatform = ref(0)
const rateMerchant = ref(0)
const shelfCatalogVisible = ref(false)
const shelfCatalogLoading = ref(false)
const shelfCatalog = ref([])
const formatRate = (val) => (val * 100).toFixed(2) + '%'
const filteredTypeList = computed(() => {
@@ -323,6 +344,65 @@ const refreshTypeList = () => {
const refreshZoneList = () => {}
const selectType = (id) => { selectedTypeId.value = id }
/** 俱乐部:打开可上架类型目录 */
const openShelfCatalog = async () => {
shelfCatalogVisible.value = true
shelfCatalogLoading.value = true
try {
const res = await request.post(JITUAN_API.clubLeixingCatalog, { phone: username.value })
if (res.code === 0) {
if (res.data?.scope_error) {
ElMessage.warning(res.data.scope_error)
shelfCatalog.value = []
return
}
shelfCatalog.value = res.data?.catalog || []
} else {
ElMessage.error(res.msg || '加载目录失败')
}
} catch (e) {
ElMessage.error('网络错误')
} finally {
shelfCatalogLoading.value = false
}
}
const enableClubType = async (c) => {
const res = await request.post(JITUAN_API.clubLeixingEnable, {
phone: username.value,
leixing_id: c.id,
})
if (res.code === 0) {
ElMessage.success('上架成功')
shelfCatalogVisible.value = false
await fetchBaseData()
} else {
ElMessage.error(res.msg || '上架失败')
}
}
const disableClubType = async (type) => {
try {
await ElMessageBox.confirm(
`下架「${type.jieshao}」?点单/抢单将不再展示该类型(本俱乐部专区数据保留)。`,
'确认下架',
{ type: 'warning' }
)
const res = await request.post(JITUAN_API.clubLeixingDisable, {
phone: username.value,
leixing_id: type.id,
})
if (res.code === 0) {
ElMessage.success('已下架')
await fetchBaseData()
} else {
ElMessage.error(res.msg || '下架失败')
}
} catch (e) {
/* cancel */
}
}
// 类型管理
const typeDialogVisible = ref(false)
const typeDialogTitle = ref('')
@@ -687,6 +767,13 @@ onMounted(() => {
.scope-tip {
margin-bottom: 16px;
}
.shelf-catalog-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.no-permission {
text-align: center;
padding: 80px 20px;