feat:商品管理

This commit is contained in:
weiwei committed 2025-09-12 12:19:58 +08:00
1 parent 0071f79580
commit dcf971dd8d
6 files changed
+120 -29

No files matched your search

+16 -7
View File
@@ -19,7 +19,7 @@ const query = (page: number, pagesize: number) => {
pageHook.startPage(page, pagesize, false, state.pa)
}
onLoad(() => { })
onLoad(() => {})
onShow(() => {
if (pageRef.value) {
pageRef.value.reload(false)
@@ -49,9 +49,20 @@ const doDel = (id: string) => {
<template>
<crud-layout title="人脸管理" bg="/static/page/blue-bg.png">
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="10"
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<view class="h-20rpx" />
<view class="flex-col card p-x-20rpx p-y-30rpx m-b-20rpx" v-for="(v, i) in pageHook.list" :key="v.id">
<view class="flex items-center justify-between second-text-26">
@@ -70,9 +81,7 @@ const doDel = (id: string) => {
</view>
</view>
<template #bottom>
<view v-if="false"
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-t-60rpx sub-text-30 color-white!"
@tap="doAdd">
<view v-if="false" class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-t-60rpx sub-text-30 color-white!" @tap="doAdd">
添加
</view>
<view class="h-30rpx" />
+37 -5
View File
@@ -144,7 +144,7 @@
<tm-button block size="s" skin="dashed" color="#E5F1FF" @click.stop="addSkuListItem()">添 加</tm-button>
</view>
<tm-button form-type="submit" block>提交</tm-button>
<tm-button form-type="submit" block>提 交</tm-button>
</tm-form>
<tm-drawer
@@ -170,8 +170,10 @@ import { hooks } from "@@/index"
import { prosperityShopApi } from "@/sheep/api"
import ShopCategaryPicker from "@/sheep/components/shop-categary-picker.vue"
import { onLoad } from "@dcloudio/uni-app"
import { filePath } from "@/sheep/utils/file"
const form = reactive<any>({
id: "",
title: "",
unit: "",
categoryId: "",
@@ -202,6 +204,7 @@ const _saleStartTimeStr = ref("")
const _saleEndTimeStr = ref("")
const showCategaryPicker = ref(false)
const categoryTree = ref([])
const categoryList = ref<any>([])
const rules: Record<string, TM.FORM_RULE[]> = {
title: [{ required: true, message: "请输入商品标题" }],
@@ -213,16 +216,41 @@ const rules: Record<string, TM.FORM_RULE[]> = {
coverImage: [{ required: true, message: "请上传商品图" }],
}
onLoad((options: any) => {
onLoad(async (options: any) => {
const { id = "" } = options
if (!id) return
getGoodsDetail(id)
await getGoodsCategory()
await getGoodsDetail(id)
})
const getGoodsDetail = async (id: string) => {
uni.showLoading({ title: "加载中..." })
const { code, data, msg } = await prosperityShopApi.getGoodsDetail(id)
if (code != 0 || !data) return uni.showToast({ title: msg || "商品详情获取失败", icon: "none" })
Object.assign(form, data, { status: data.status.toString(), priceType: data.priceType.toString() })
const skuList = data.skuList.map((item: any) => ({ ...item, status: item.status.toString() }))
const coverImage = [{ path: filePath(data.coverImage), response: JSON.stringify({ data: { url: data.coverImage } }) }]
const categoryName = categoryList.value.find((item: any) => item.id == data.categoryId)?.name
const saleStartTime = data.saleStartTime.split(" ")[0]
const saleEndTime = data.saleEndTime.split(" ")[0]
_saleStartTimeStr.value = saleStartTime
_saleEndTimeStr.value = saleEndTime
Object.assign(form, {
...data,
status: data.status.toString(),
priceType: data.priceType.toString(),
coverImage,
categoryName,
saleStartTime,
saleEndTime,
skuList,
})
uni.hideLoading()
}
const getGoodsCategory = async () => {
const { code, data, msg } = await prosperityShopApi.getGoodsCategory()
if (code != 0) return uni.showToast({ title: msg || "商品分类获取失败", icon: "none" })
categoryList.value = data
}
const selectCategary = () => {
@@ -280,12 +308,16 @@ const onsubmit = async (evt: TM.FORM_SUBMIT_RESULT) => {
}
try {
const { code, msg } = await prosperityShopApi.addGoods({ ...form, coverImage: JSON.parse(form.coverImage[0].response).data.url })
const params = { ...form, coverImage: JSON.parse(form.coverImage[0].response).data.url }
uni.showLoading({ title: "提交中..." })
const { code, msg } = await (form.id ? prosperityShopApi.editGoods(params) : prosperityShopApi.addGoods(params))
if (code != 0) return uni.showToast({ title: msg || "提交失败", icon: "none" })
uni.showToast({ title: "提交成功", icon: "success" })
uni.navigateBack()
} catch (error: any) {
uni.showToast({ title: error.message || "提交失败", icon: "none" })
} finally {
uni.hideLoading()
}
}
</script>
+2 -1
View File
@@ -69,7 +69,8 @@
<text>{{ v.email }}</text>
</view>
<view>
<text class="c-#0094ff! sub-text-26 px-2 bg-#0094ff22 rounded-2">营业:{{ v.businessHours }}</text>
<text class="c-#0094ff! sub-text-26 px-2 bg-#0094ff22 rounded-2 mr-2">营业</text>
<text class="c-#0094ff! sub-text-26 px-2 bg-#0094ff22 rounded-2">{{ v.businessHours }}</text>
</view>
<view class="second-text-26">
<image class="w-24rpx h-24rpx mr-1" src="@/static/page/address.svg" />
+8
View File
@@ -70,4 +70,12 @@ export default {
data,
})
},
// 修改商品
editGoods: (data: any): Promise<any> => {
return request({
url: `/supermarket/app/mall/merchant/product/update`,
method: "PUT",
data,
})
},
}
+5 -16
View File
@@ -1,19 +1,6 @@
<template>
<view class="max-h-[60vh] overflow-y-auto mb-20rpx">
<view
class="flex items-center p-2 bg-#eeeeee mb-2 mx-4 rounded-2 sub-text-26"
v-for="(item, index) in categoryTree"
:key="item.id"
:class="{ 'bg-#0779fd! c-white!': selectedCategary && selectedCategary.id === item.id }"
@click="onSelect(item)"
>
<view v-if="item.children.length" class="w-40rpx mr-2 text-center">
<!-- <text>{{ expandedIds.has(item.id) ? "▾" : "▸" }}</text> -->
<text>▾</text>
</view>
<view v-else class="w-40rpx mr-2" />
<view>{{ item.name }}</view>
</view>
<shop-categary-tree :node-data="categoryTree" @currentNode="currentNode" />
<view v-if="categoryTree.length === 0" class="text-center text-[#888] py-[40rpx]">暂无数据</view>
</view>
<view class="px-[20rpx] py-2 flex justify-between sticky bottom-0 bg-white">
@@ -25,6 +12,7 @@
<script setup lang="ts">
import { ref } from "vue"
import ShopCategaryTree from "./shop-categary-tree.vue"
defineProps({
categoryTree: {
@@ -32,12 +20,13 @@ defineProps({
default: () => [],
},
})
const emit = defineEmits(["confirm", "cancel"])
const selectedCategary = ref<any>({})
const onSelect = (item: any) => {
const currentNode = (item) => {
console.log(item)
selectedCategary.value = item
}
@@ -0,0 +1,52 @@
<template>
<view class="tree-container">
<view v-for="item in nodeData" :key="item.id">
<view class="tree-item" @click.stop="toCurrentNode(item)">
<text>{{ item.name }}</text>
</view>
<shop-categary-tree
v-if="item.children && item.children.length"
:node-data="item.children"
:style="{ marginLeft: `${getLevel() * 60}rpx` }"
@currentNode="(v) => emit('currentNode', v)"
/>
</view>
</view>
</template>
<script setup lang="ts">
import ShopCategaryTree from "./shop-categary-tree.vue"
defineProps({
nodeData: {
type: Array<any>,
default: () => [],
},
})
const emit = defineEmits(["currentNode"])
const toCurrentNode = (item) => {
emit("currentNode", item)
}
const getLevel = () => {
return 1
}
</script>
<style scoped>
.tree-container {
padding: 0 40rpx;
}
.tree-item {
border-bottom: 1rpx solid #e4e7ed;
display: flex;
padding: 10rpx 0 10rpx 20rpx;
}
.tree-item:hover {
background-color: #4b93ff;
border-radius: 10rpx;
color: #fff;
}
</style>