sql数据流,amdin业务逻辑接入

This commit is contained in:
comlibmb
2026-02-15 16:37:37 +08:00
parent ec636dc703
commit e648ff0c22
43 changed files with 5412 additions and 1024 deletions

View File

@@ -25,7 +25,7 @@
<text class="stat-ic">👥</text>
</view>
<view class="stat-info">
<text class="stat-value">349</text>
<text class="stat-value">{{ statParticipants }}</text>
<text class="stat-label">参与人数(人)</text>
</view>
</view>
@@ -34,7 +34,7 @@
<text class="stat-ic">📦</text>
</view>
<view class="stat-info">
<text class="stat-value">44</text>
<text class="stat-value">{{ statSuccessGroups }}</text>
<text class="stat-label">成团数量(个)</text>
</view>
</view>
@@ -42,6 +42,10 @@
<view class="table-card border-shadow">
<view class="table-container">
<!-- Loading 遮罩 -->
<view v-if="isLoading" class="loading-mask">
<text class="loading-text">数据加载中...</text>
</view>
<view class="table-head">
<view class="th cell-avatar">头像</view>
<view class="th cell-leader">开团团长</view>
@@ -55,15 +59,18 @@
</view>
<view class="table-body">
<view v-if="combos.length === 0 && !isLoading" class="empty-row">
<text>暂无拼团记录</text>
</view>
<view v-for="item in combos" :key="item.id" class="table-row">
<view class="td cell-avatar">
<image class="thumb" :src="item.avatar" mode="aspectFill"></image>
<image class="thumb" :src="item.avatar || '/static/logo.png'" mode="aspectFill"></image>
</view>
<view class="td cell-leader">
<text class="td-txt">{{ item.nickname }} / {{ item.uid }}</text>
<text class="td-txt">{{ item.nickname || '未知用户' }} / {{ item.uid }}</text>
</view>
<view class="td cell-time">
<text class="td-txt-small">{{ item.start_time }}</text>
<text class="td-txt-small">{{ item.start_time.substring(0, 16).replace('T', ' ') }}</text>
</view>
<view class="td cell-product">
<text class="product-title line-clamp-2">{{ item.title }} / {{ item.cid }}</text>
@@ -75,7 +82,7 @@
<text class="td-txt-bold">{{ item.count_people }}</text>
</view>
<view class="td cell-time">
<text class="td-txt-small">{{ item.stop_time }}</text>
<text class="td-txt-small">{{ item.stop_time.substring(0, 16).replace('T', ' ') }}</text>
</view>
<view class="td cell-status">
<view :class="['status-tag', item.status]">
@@ -86,7 +93,7 @@
<view class="op-links">
<text class="op-link" @click="viewDetails(item)">查看详情</text>
<text class="op-split" v-if="item.status === 'ongoing'">|</text>
<text class="op-link" v-if="item.status === 'ongoing'" @click="completeGroup(item)">立即成团</text>
<text class="op-link" v-if="item.status === 'ongoing'" @click="handleCompleteGroup(item)">立即成团</text>
</view>
</view>
</view>
@@ -95,23 +102,12 @@
<view class="pagination-footer">
<view class="page-total">
<text class="total-txt">共 {{ combos.length }} 条</text>
</view>
<view class="page-select">
<view class="select-mock mini">
<text class="select-val">15条/页</text>
<text class="arrow">▼</text>
</view>
<text class="total-txt">共 {{ total }} 条</text>
</view>
<view class="page-btns">
<text class="p-btn"></text>
<text class="p-btn active">1</text>
<text class="p-btn"></text>
</view>
<view class="page-jump">
<text class="jump-txt">前往</text>
<input class="jump-input" placeholder="1" />
<text class="jump-txt">页</text>
<text class="p-btn" :class="{ disabled: page <= 1 }" @click="onPrevPage"></text>
<text class="p-btn active">{{ page }}</text>
<text class="p-btn" :class="{ disabled: combos.length < pageSize }" @click="onNextPage"></text>
</view>
</view>
</view>
@@ -119,114 +115,99 @@
</template>
<script setup lang="uts">
import { ref, reactive } from 'vue'
import { ref, onMounted } from 'vue'
import { fetchCombinationActivities, getCombinationStats, completeCombinationGroup, CombinationActivity } from '@/services/admin/marketingService.uts'
const statusLabels = {
const statusLabels : Record<string, string> = {
ongoing: '进行中',
pending: '未完成',
ended: '已成功',
}
const combos = ref([
{
id: 101,
avatar: 'https://img0.baidu.com/it/u=3033502919,1657850259&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
nickname: '1岁上班22岁退休',
uid: 82713,
start_time: '2026-02-03 10:09',
stop_time: '2026-02-04 10:09',
title: 'FOMIX 蛋壳椅 进口头层牛皮自然色单人沙发椅 Egg chair设计师蛋椅',
cid: 191,
people: 2,
count_people: 1,
status: 'ongoing',
},
{
id: 102,
avatar: 'https://img1.baidu.com/it/u=2295552459,2083538461&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
nickname: '132****8769',
uid: 82683,
start_time: '2026-02-01 13:29',
stop_time: '2026-02-02 13:29',
title: '阿迪达斯官网 adidas BBALL CAP COT 男女训练运动帽子FQ5270',
cid: 192,
people: 2,
count_people: 1,
status: 'ongoing',
},
{
id: 103,
avatar: 'https://img0.baidu.com/it/u=1550993072,4086699313&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
nickname: 'Jk',
uid: 82598,
start_time: '2026-01-28 16:10',
stop_time: '2026-01-29 16:10',
title: 'FOMIX 蛋壳椅 进口头层牛皮自然色单人沙发椅 Egg chair设计师蛋椅',
cid: 191,
people: 2,
count_people: 1,
status: 'ongoing',
},
{
id: 104,
avatar: 'https://img1.baidu.com/it/u=3175865615,2002599723&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
nickname: '177****1523',
uid: 82565,
start_time: '2026-01-27 07:19',
stop_time: '2026-01-28 07:19',
title: 'FOMIX 蛋壳椅 进口头层牛皮自然色单人沙发椅 Egg chair设计师蛋椅',
cid: 191,
people: 2,
count_people: 1,
status: 'ongoing',
},
{
id: 105,
avatar: 'https://img2.baidu.com/it/u=2719717192,3826027113&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
nickname: '0-1',
uid: 79417,
start_time: '2026-01-25 23:53',
stop_time: '2026-01-26 23:53',
title: 'FOMIX 蛋壳椅 进口头层牛皮自然色单人沙发椅 Egg chair设计师蛋椅',
cid: 191,
people: 2,
count_people: 1,
status: 'ongoing',
},
{
id: 106,
avatar: 'https://img0.baidu.com/it/u=1893322197,2940863863&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
nickname: 'abc',
uid: 75343,
start_time: '2026-01-22 21:29',
stop_time: '2026-01-23 21:29',
title: 'FOMIX 蛋壳椅 进口头层牛皮自然色单人沙发椅 Egg chair设计师蛋椅',
cid: 191,
people: 2,
count_people: 1,
status: 'ongoing',
},
{
id: 107,
avatar: 'https://img2.baidu.com/it/u=176219800,2487920112&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
nickname: '181****6910',
uid: 81141,
start_time: '2026-01-19 16:16',
stop_time: '2026-01-19 16:45',
title: 'UR2024夏季新款女装复古纯欲氛围感一字肩短款T恤UWG440060',
cid: 190,
people: 2,
count_people: 1,
status: 'pending',
},
])
const combos = ref<CombinationActivity[]>([])
const isLoading = ref(false)
const total = ref(0)
const page = ref(1)
const pageSize = 15
const viewDetails = (item: any) => {
console.log('查看详情', item.id)
const statParticipants = ref(0)
const statSuccessGroups = ref(0)
const activeStatus = ref<string | null>(null)
onMounted(() => {
loadData()
loadStats()
})
async function loadData() {
isLoading.value = true
try {
const res = await fetchCombinationActivities({
status: activeStatus.value ?? undefined,
page: page.value,
pageSize: pageSize
})
combos.value = res.items
total.value = res.total
} catch (e) {
uni.showToast({ title: '加载拼团列表失败', icon: 'none' })
} finally {
isLoading.value = false
}
}
const completeGroup = (item: any) => {
console.log('立即成团', item.id)
async function loadStats() {
try {
const stats = await getCombinationStats()
statParticipants.value = stats.participantCount
statSuccessGroups.value = stats.successCount
} catch (e) {}
}
const handleStatusChange = (e : any) => {
const index = parseInt(String(e.detail.value))
const options = [null, 'ongoing', 'pending', 'ended']
activeStatus.value = options[index]
page.value = 1
loadData()
}
const viewDetails = (item : CombinationActivity) => {
console.log('查看详情', item.id)
uni.showToast({ title: '详情功能开发中', icon: 'none' })
}
const handleCompleteGroup = (item : CombinationActivity) => {
if (item.id == null) return
uni.showModal({
title: '提示',
content: '确定要手动将其设为成团状态吗?',
success: async (res) => {
if (res.confirm) {
const success = await completeCombinationGroup(item.id!)
if (success) {
uni.showToast({ title: '操作成功', icon: 'success' })
loadData()
loadStats()
}
}
}
})
}
function onPrevPage() {
if (page.value > 1) {
page.value--
loadData()
}
}
function onNextPage() {
if (combos.value.length >= pageSize) {
page.value++
loadData()
}
}
</script>