feat(admin): merge stash changes into comclib-analytics (order/finance/product + rpc sql)
This commit is contained in:
@@ -149,59 +149,99 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import {
|
||||
fetchAdminCategoryList,
|
||||
createAdminCategory,
|
||||
updateAdminCategory,
|
||||
deleteAdminCategory,
|
||||
type AdminCategory
|
||||
} from '@/services/admin/productCategoryService.uts'
|
||||
|
||||
interface CateItem {
|
||||
id: number;
|
||||
id: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
sort: number;
|
||||
status: boolean;
|
||||
expanded?: boolean;
|
||||
children?: CateItem[];
|
||||
parentId?: number;
|
||||
parentId?: string | null;
|
||||
}
|
||||
|
||||
const list = reactive<CateItem[]>([
|
||||
{
|
||||
id: 100, name: '家用电器', icon: '/static/logo.png', sort: 1, status: true, expanded: true,
|
||||
children: [
|
||||
{ id: 101, name: '电视机', icon: '/static/logo.png', sort: 1, status: true, parentId: 100 },
|
||||
{ id: 102, name: '电冰箱', icon: '/static/logo.png', sort: 2, status: true, parentId: 100 }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 200, name: '手机数码', icon: '/static/logo.png', sort: 2, status: true, expanded: false,
|
||||
children: [
|
||||
{ id: 201, name: '手机', icon: '/static/logo.png', sort: 1, status: true, parentId: 200 },
|
||||
{ id: 202, name: '耳机', icon: '/static/logo.png', sort: 2, status: true, parentId: 200 }
|
||||
]
|
||||
}
|
||||
])
|
||||
const list = ref<Array<CateItem>>([])
|
||||
|
||||
const showDrawerMask = ref(false)
|
||||
const showDrawer = ref(false)
|
||||
const isEdit = ref(false)
|
||||
const editingId = ref<string | null>(null)
|
||||
|
||||
const form = reactive({
|
||||
name: '',
|
||||
parentId: null as string | null,
|
||||
parentName: '',
|
||||
sort: 0,
|
||||
status: true
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadList()
|
||||
})
|
||||
|
||||
function buildTree(items: Array<AdminCategory>): Array<CateItem> {
|
||||
const map: Record<string, CateItem> = {}
|
||||
const roots: Array<CateItem> = []
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const c = items[i]
|
||||
map[c.id] = {
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
icon: c.icon ?? '',
|
||||
sort: c.sort ?? 0,
|
||||
status: c.is_active === true,
|
||||
expanded: false,
|
||||
children: [],
|
||||
parentId: c.parent_id ?? null
|
||||
}
|
||||
}
|
||||
|
||||
const ids = Object.keys(map)
|
||||
for (let i = 0; i < ids.length; i++) {
|
||||
const id = ids[i]
|
||||
const node = map[id]
|
||||
if (node.parentId != null && map[node.parentId] != null) {
|
||||
map[node.parentId].children = map[node.parentId].children ?? []
|
||||
map[node.parentId].children!.push(node)
|
||||
} else {
|
||||
roots.push(node)
|
||||
}
|
||||
}
|
||||
|
||||
return roots
|
||||
}
|
||||
|
||||
async function loadList() {
|
||||
const items = await fetchAdminCategoryList({})
|
||||
list.value = buildTree(items)
|
||||
}
|
||||
|
||||
function openDrawer(item: CateItem | null = null) {
|
||||
if (item != null) {
|
||||
isEdit.value = true
|
||||
editingId.value = item.id
|
||||
form.name = item.name
|
||||
form.sort = item.sort
|
||||
form.status = item.status
|
||||
form.parentId = item.parentId ?? null
|
||||
form.parentName = item.parentId != null ? '子分类' : '顶级分类'
|
||||
} else {
|
||||
isEdit.value = false
|
||||
editingId.value = null
|
||||
form.name = ''
|
||||
form.sort = 0
|
||||
form.status = true
|
||||
form.parentId = null
|
||||
form.parentName = '顶级分类'
|
||||
}
|
||||
showDrawerMask.value = true
|
||||
@@ -217,22 +257,49 @@ showDrawerMask.value = false
|
||||
}, 300)
|
||||
}
|
||||
|
||||
function saveCate() {
|
||||
async function saveCate() {
|
||||
if (isEdit.value && editingId.value != null) {
|
||||
await updateAdminCategory({
|
||||
id: editingId.value,
|
||||
parentId: form.parentId,
|
||||
name: form.name,
|
||||
sortOrder: form.sort,
|
||||
isActive: form.status
|
||||
})
|
||||
} else {
|
||||
await createAdminCategory({
|
||||
parentId: form.parentId,
|
||||
name: form.name,
|
||||
sortOrder: form.sort,
|
||||
isActive: form.status
|
||||
})
|
||||
}
|
||||
|
||||
uni.showToast({ title: '保存成功', icon: 'success' })
|
||||
closeDrawer()
|
||||
loadList()
|
||||
}
|
||||
|
||||
function toggleStatus(item: CateItem) {
|
||||
async function toggleStatus(item: CateItem) {
|
||||
await updateAdminCategory({
|
||||
id: item.id,
|
||||
parentId: item.parentId,
|
||||
name: item.name,
|
||||
sortOrder: item.sort,
|
||||
isActive: !item.status
|
||||
})
|
||||
item.status = !item.status
|
||||
}
|
||||
|
||||
function deleteItem(item: CateItem) {
|
||||
async function deleteItem(item: CateItem) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确定删除该分类吗?',
|
||||
success: (res) => {
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showToast({ title: '已模拟删除', icon: 'none' })
|
||||
await deleteAdminCategory(item.id)
|
||||
uni.showToast({ title: '删除成功', icon: 'success' })
|
||||
loadList()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -160,91 +160,97 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="uts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { openRoute } from '@/layouts/admin/store/adminNavStore.uts'
|
||||
import { fetchAdminProductPage, updateAdminProductStatus, type AdminProduct } from '@/services/admin/productService.uts'
|
||||
|
||||
const total = ref(49)
|
||||
const activeStatus = ref('selling')
|
||||
const activeDropdownId = ref<number | null>(null)
|
||||
const total = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = ref(10)
|
||||
const activeStatus = ref<number | null>(1) // 1:出售中
|
||||
const activeDropdownId = ref<string | null>(null)
|
||||
const productList = ref<Array<AdminProduct>>([])
|
||||
const searchName = ref('')
|
||||
|
||||
const statusTabs = ref([
|
||||
{ key: 'selling', label: '出售中的商品', count: 49 },
|
||||
{ key: 'warehouse', label: '仓库中的商品', count: 4 },
|
||||
{ key: 'soldout', label: '已经售罄商品', count: 11 },
|
||||
{ key: 'alarm', label: '警戒库存商品', count: 27 },
|
||||
{ key: 'recycle', label: '回收站的商品', count: 176 },
|
||||
{ key: 1, label: '出售中的商品', count: 0 },
|
||||
{ key: 2, label: '仓库中的商品', count: 0 },
|
||||
{ key: 3, label: '草稿箱', count: 0 },
|
||||
{ key: 4, label: '回收站', count: 0 },
|
||||
])
|
||||
|
||||
const productList = ref([
|
||||
{
|
||||
id: 963,
|
||||
image: 'https://img1.baidu.com/it/u=254065646,3100346083&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
|
||||
name: 'UR2024夏季新款女装复古纯欲氛围感一字肩短款T恤衫UWG440060',
|
||||
activities: ['kj', 'pt'],
|
||||
typeName: '普通商品',
|
||||
price: '0.01',
|
||||
sales: 639,
|
||||
stock: 1602,
|
||||
sort: 9999,
|
||||
status: 1
|
||||
},
|
||||
{
|
||||
id: 108,
|
||||
image: 'https://img2.baidu.com/it/u=3033501986,2204481084&fm=253&fmt=auto&app=138&f=JPEG?w=569&h=500',
|
||||
name: 'FOMIX 蛋壳椅 进口头层牛皮橙色单人沙发椅Egg chair设计师师单椅单沙头层牛皮/单椅',
|
||||
activities: ['pt', 'ms'],
|
||||
typeName: '普通商品',
|
||||
price: '7580.00',
|
||||
sales: 14,
|
||||
stock: 16638,
|
||||
sort: 9999,
|
||||
status: 1
|
||||
},
|
||||
{
|
||||
id: 48,
|
||||
image: 'https://img0.baidu.com/it/u=1762118431,3101886131&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500',
|
||||
name: '阿迪达斯官网 adidas BBALL CAP COT 男女训练运动帽子FQ5270 传奇墨水蓝/传奇墨水蓝/白 XL',
|
||||
activities: ['kj', 'pt', 'ms'],
|
||||
typeName: '普通商品',
|
||||
price: '100.00',
|
||||
sales: 841,
|
||||
stock: 2318,
|
||||
sort: 9998,
|
||||
status: 1
|
||||
}
|
||||
])
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
|
||||
function getActivityName(tag: string): string {
|
||||
if (tag === 'kj') return '砍价'
|
||||
if (tag === 'pt') return '拼团'
|
||||
if (tag === 'ms') return '秒杀'
|
||||
return tag
|
||||
async function loadData() {
|
||||
const res = await fetchAdminProductPage(page.value, pageSize.value, {
|
||||
name: searchName.value,
|
||||
status: activeStatus.value ?? undefined
|
||||
})
|
||||
productList.value = res.items
|
||||
total.value = res.total
|
||||
}
|
||||
|
||||
function goEdit(id: number | null) {
|
||||
openRoute('product_edit')
|
||||
function handleSearch() {
|
||||
page.value = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function goReviews(id: number) {
|
||||
openRoute('product_productReply')
|
||||
function handleReset() {
|
||||
searchName.value = ''
|
||||
page.value = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function goMemberPrice(id: number) {
|
||||
openRoute('product_member_price')
|
||||
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' })
|
||||
}
|
||||
}
|
||||
|
||||
function moveToRecycle(id: number) {
|
||||
const action = activeStatus.value === 'recycle' ? '恢复' : '移到回收站';
|
||||
async function moveToRecycle(item: AdminProduct) {
|
||||
const isDelete = activeStatus.value !== 4
|
||||
const targetStatus = isDelete ? 4 : 2 // 移到回收站或恢复到下架
|
||||
|
||||
const action = isDelete ? '移到回收站' : '恢复'
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: `确认要将该商品${action}吗?`,
|
||||
success: (res) => {
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
uni.showToast({ title: '操作成功', icon: 'success' });
|
||||
const ok = await updateAdminProductStatus(item.id, targetStatus)
|
||||
if (ok) {
|
||||
uni.showToast({ title: '操作成功', icon: 'success' })
|
||||
loadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function changeStatus(key: number) {
|
||||
activeStatus.value = key
|
||||
page.value = 1
|
||||
loadData()
|
||||
}
|
||||
|
||||
function goEdit(id: string | null) {
|
||||
openRoute('product_edit')
|
||||
}
|
||||
|
||||
function goReviews(id: string) {
|
||||
openRoute('product_productReply')
|
||||
}
|
||||
|
||||
function goMemberPrice(id: string) {
|
||||
openRoute('product_member_price')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
Reference in New Issue
Block a user