feat(admin): full integration of order, product, and finance modules with real RPC data streams

This commit is contained in:
comlibmb
2026-02-11 16:59:38 +08:00
parent cd7b92d496
commit 7e2246fec5
33 changed files with 2535 additions and 2093 deletions

View File

@@ -5,7 +5,7 @@
<view class="search-row">
<view class="search-item">
<text class="label">商品搜索:</text>
<input class="mock-input" placeholder="请输入商品名称/关键字/ID" />
<input class="mock-input" placeholder="请输入商品名称/关键字/ID" v-model="searchName" @confirm="handleSearch" />
</view>
<view class="search-item">
<text class="label">商品类型:</text>
@@ -16,14 +16,19 @@
</view>
<view class="search-item">
<text class="label">商品分类:</text>
<view class="mock-select">
<text>请选择</text>
<text class="arrow">▼</text>
</view>
<picker :value="categoryIndex" :range="categoryOptions" range-key="label" @change="e => {
categoryIndex = e.detail.value;
selectedCategoryId = categoryOptions[categoryIndex].value;
}">
<view class="mock-select">
<text>{{ categoryOptions[categoryIndex].label }}</text>
<text class="arrow">▼</text>
</view>
</picker>
</view>
<view class="search-btns">
<button class="btn-primary">查询</button>
<button class="btn-reset">重置</button>
<button class="btn-primary" @click="handleSearch">查询</button>
<button class="btn-reset" @click="handleReset">重置</button>
<view class="expand-control">
<text class="expand-txt">展开</text>
<text class="expand-arrow">▼</text>
@@ -49,7 +54,7 @@
:key="index"
class="tab-item"
:class="{ active: activeStatus === tab.key }"
@click="activeStatus = tab.key"
@click="changeStatus(tab.key)"
>
<text>{{ tab.label }}({{ tab.count }})</text>
</view>
@@ -115,7 +120,7 @@
<view class="td col-stock"><text>{{ item.stock }}</text></view>
<view class="td col-sort"><text>{{ item.sort }}</text></view>
<view class="td col-status">
<view class="mock-switch" :class="{ on: item.status === 1 }">
<view class="mock-switch" :class="{ on: item.status === 1 }" @click="toggleStatus(item)">
<text class="switch-txt">{{ item.status === 1 ? '上架' : '下架' }}</text>
<view class="switch-dot"></view>
</view>
@@ -137,7 +142,7 @@
<text class="menu-item" @click.stop="goReviews(item.id)">查看评论</text>
<text class="menu-item" @click.stop="goMemberPrice(item.id)">会员价管理</text>
<text class="menu-item" @click.stop="uni.showToast({title:'佣金管理开发中', icon:'none'})">佣金管理</text>
<text class="menu-item danger-item" @click.stop="moveToRecycle(item.id)">{{ activeStatus === 'recycle' ? '恢复商品' : '移到回收站' }}</text>
<text class="menu-item danger-item" @click.stop="moveToRecycle(item)">{{ activeStatus === 4 ? '恢复商品' : '移到回收站' }}</text>
</view>
</view>
</view>
@@ -149,10 +154,9 @@
<view class="pagination-row">
<text class="total">共 {{ total }} 条</text>
<view class="page-ctrl">
<text class="page-btn disabled">{"<"}</text>
<text class="page-num active">1</text>
<text class="page-num">2</text>
<text class="page-btn">{">"}</text>
<text class="page-btn" :class="{ disabled: page <= 1 }" @click="page > 1 && (page--, loadData())">{"<"}</text>
<text class="page-num active">{{ page }}</text>
<text class="page-btn" :class="{ disabled: productList.length < pageSize }" @click="productList.length == pageSize && (page++, loadData())">{">"}</text>
</view>
</view>
</view>
@@ -162,15 +166,21 @@
<script setup lang="uts">
import { ref, onMounted } from 'vue'
import { openRoute } from '@/layouts/admin/store/adminNavStore.uts'
import { fetchAdminProductPage, updateAdminProductStatus, type AdminProduct } from '@/services/admin/productService.uts'
import { fetchAdminProductPage, updateAdminProductStatus, fetchAdminProductCountStats, type AdminProduct } from '@/services/admin/productService.uts'
import { fetchAdminCategoryList, type AdminCategory } from '@/services/admin/productCategoryService.uts'
const total = ref(0)
const page = ref(1)
const pageSize = ref(10)
const activeStatus = ref<number | null>(1) // 1:出售中
const activeStatus = ref<number>(1) // 1:出售中
const activeDropdownId = ref<string | null>(null)
const productList = ref<Array<AdminProduct>>([])
const searchName = ref('')
const selectedCategoryId = ref<string | null>(null)
const categoryOptions = ref<Array<{label: string, value: string | null}>>([
{ label: '全部', value: null }
])
const categoryIndex = ref(0)
const statusTabs = ref([
{ key: 1, label: '出售中的商品', count: 0 },
@@ -180,13 +190,40 @@ const statusTabs = ref([
])
onMounted(() => {
loadCounts()
loadCategories()
loadData()
})
async function loadCategories() {
try {
const categories = await fetchAdminCategoryList({ isActive: true })
categories.forEach(item => {
categoryOptions.value.push({
label: item.name,
value: item.id
})
})
} catch (e) {
console.error('加载分类失败:', e)
}
}
async function loadCounts() {
const stats = await fetchAdminProductCountStats()
if (stats != null) {
statusTabs.value[0].count = parseInt(String(stats['selling'] ?? '0'))
statusTabs.value[1].count = parseInt(String(stats['warehouse'] ?? '0'))
statusTabs.value[2].count = parseInt(String(stats['draft'] ?? '0'))
statusTabs.value[3].count = parseInt(String(stats['recycle'] ?? '0'))
}
}
async function loadData() {
const res = await fetchAdminProductPage(page.value, pageSize.value, {
name: searchName.value,
status: activeStatus.value ?? undefined
status: activeStatus.value,
categoryId: selectedCategoryId.value ?? undefined
})
productList.value = res.items
total.value = res.total
@@ -195,43 +232,15 @@ async function loadData() {
function handleSearch() {
page.value = 1
loadData()
loadCounts()
}
function handleReset() {
searchName.value = ''
selectedCategoryId.value = null
page.value = 1
loadData()
}
async function toggleStatus(item: AdminProduct) {
const newStatus = item.status === 1 ? 2 : 1
const ok = await updateAdminProductStatus(item.id, newStatus)
if (ok) {
uni.showToast({ title: '操作成功', icon: 'success' })
loadData()
} else {
uni.showToast({ title: '操作失败', icon: 'none' })
}
}
async function moveToRecycle(item: AdminProduct) {
const isDelete = activeStatus.value !== 4
const targetStatus = isDelete ? 4 : 2 // 移到回收站或恢复到下架
const action = isDelete ? '移到回收站' : '恢复'
uni.showModal({
title: '提示',
content: `确认要将该商品${action}吗?`,
success: async (res) => {
if (res.confirm) {
const ok = await updateAdminProductStatus(item.id, targetStatus)
if (ok) {
uni.showToast({ title: '操作成功', icon: 'success' })
loadData()
}
}
}
})
loadCounts()
}
function changeStatus(key: number) {