From 0c6e3a39c95190bb54538d548c4df4f0ff4d57b4 Mon Sep 17 00:00:00 2001 From: puhui999 <puhui999@163.com> Date: Thu, 4 May 2023 01:38:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=95=86=E5=93=81=E7=AE=A1=E7=90=86:=20?= =?UTF-8?q?=E6=89=93=E9=80=9A=E6=89=80=E6=9C=89=E6=8E=A5=E5=8F=A3=EF=BC=88?= =?UTF-8?q?=E7=AC=AC=E4=B8=80=E7=89=88=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/mall/product/management/spu.ts | 12 + src/utils/constants.ts | 17 ++ src/views/mall/product/management/addForm.vue | 9 +- .../components/OtherSettingsForm.vue | 1 + .../product/management/components/SkuList.vue | 3 - src/views/mall/product/management/index.vue | 234 +++++++++++++----- 6 files changed, 206 insertions(+), 70 deletions(-) diff --git a/src/api/mall/product/management/spu.ts b/src/api/mall/product/management/spu.ts index 007963bb..2aa83e7a 100644 --- a/src/api/mall/product/management/spu.ts +++ b/src/api/mall/product/management/spu.ts @@ -5,6 +5,10 @@ import type { SpuType } from './type/spuType' export const getSpuList = (params: any) => { return request.get({ url: '/product/spu/page', params }) } +// 获得spu列表tabsCount +export const getTabsCount = () => { + return request.get({ url: '/product/spu/tabsCount' }) +} // 创建商品spu export const createSpu = (data: SpuType) => { return request.post({ url: '/product/spu/create', data }) @@ -13,7 +17,15 @@ export const createSpu = (data: SpuType) => { export const updateSpu = (data: SpuType) => { return request.put({ url: '/product/spu/update', data }) } +// 更新商品spu status +export const updateStatus = (data: { id: number; status: number }) => { + return request.put({ url: '/product/spu/updateStatus', data }) +} // 获得商品spu export const getSpu = (id: number) => { return request.get({ url: `/product/spu/get-detail?id=${id}` }) } +// 删除商品Spu +export const deleteSpu = (id: number) => { + return request.delete({ url: `/product/spu/delete?id=${id}` }) +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 5cda391f..597064ee 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -220,3 +220,20 @@ export const PayRefundStatusEnum = { name: '退款关闭' } } +/** + * 商品SPU枚举类 + */ +export const ProductSpuStatusEnum = { + RECYCLE: { + status: -1, + name: '回收站' + }, + DISABLE: { + status: 0, + name: '下架' + }, + ENABLE: { + status: 1, + name: '上架' + } +} diff --git a/src/views/mall/product/management/addForm.vue b/src/views/mall/product/management/addForm.vue index 27f8a8ae..7f31871f 100644 --- a/src/views/mall/product/management/addForm.vue +++ b/src/views/mall/product/management/addForm.vue @@ -144,7 +144,7 @@ const getDetail = async () => { const submitForm = async () => { // 提交请求 formLoading.value = true - const newSkus = [...formData.value.skus] //复制一份skus保存失败时使用 + const newSkus = JSON.parse(JSON.stringify(formData.value.skus)) //深拷贝一份skus保存失败时使用 // TODO 三个表单逐一校验,如果有一个表单校验不通过则切换到对应表单,如果有两个及以上的情况则切换到最前面的一个并弹出提示消息 // 校验各表单 try { @@ -184,9 +184,12 @@ const submitForm = async () => { await managementApi.updateSpu(data) message.success(t('common.updateSuccess')) } + close() } catch (e) { - console.log(e) - console.log(newSkus) + // 如果是后端校验失败,恢复skus数据 + if (typeof e === 'string') { + formData.value.skus = newSkus + } } finally { formLoading.value = false } diff --git a/src/views/mall/product/management/components/OtherSettingsForm.vue b/src/views/mall/product/management/components/OtherSettingsForm.vue index 4469962d..bd0ca26d 100644 --- a/src/views/mall/product/management/components/OtherSettingsForm.vue +++ b/src/views/mall/product/management/components/OtherSettingsForm.vue @@ -117,6 +117,7 @@ watch( (data) => { if (!data) return copyValueToTarget(formData.value, data) + // TODO 如果先修改其他设置的值,再改变商品详情或是商品信息会重置其他设置页面中的相关值 下一个版本修复 checkboxGroup.value = [] formData.value.recommendHot ? checkboxGroup.value.push('recommendHot') : '' formData.value.recommendBenefit ? checkboxGroup.value.push('recommendBenefit') : '' diff --git a/src/views/mall/product/management/components/SkuList.vue b/src/views/mall/product/management/components/SkuList.vue index 2a7441cc..3311202a 100644 --- a/src/views/mall/product/management/components/SkuList.vue +++ b/src/views/mall/product/management/components/SkuList.vue @@ -206,9 +206,6 @@ const generateTableData = (data: any[]) => { } const buildList = build(propertiesItemList) // 如果构建后的组合数跟sku数量一样的话则不用处理,添加新属性没有属性值也不做处理 (解决编辑表单时或查看详情时数据回显问题) - console.log( - buildList.length === formData.value.skus.length || data.some((item) => item.values.length === 0) - ) if ( buildList.length === formData.value.skus.length || data.some((item) => item.values.length === 0) diff --git a/src/views/mall/product/management/index.vue b/src/views/mall/product/management/index.vue index f2e480f5..7b5fb0c1 100644 --- a/src/views/mall/product/management/index.vue +++ b/src/views/mall/product/management/index.vue @@ -57,39 +57,38 @@ <!-- 列表 --> <ContentWrap> - <el-tabs v-model="queryParams.type" @tab-click="getList"> + <el-tabs v-model="queryParams.tabType" @tab-click="handleClick"> <el-tab-pane - v-for="(item, index) in headerNum" - :key="index" + v-for="item in tabsData" + :key="item.type" :label="item.name + '(' + item.count + ')'" - :name="item.type.toString()" + :name="item.type" /> </el-tabs> <el-table v-loading="loading" :data="list"> - <el-table-column type="expand"> - <template #default="{ row }"> - <el-form inline label-position="left"> - <el-form-item label="市场价:"> - <span>{{ row.marketPrice }}</span> - </el-form-item> - <el-form-item label="成本价:"> - <span>{{ row.costPrice }}</span> - </el-form-item> - <el-form-item label="虚拟销量:"> - <span>{{ row.virtualSalesCount }}</span> - </el-form-item> - </el-form> - </template> - </el-table-column> + <!-- TODO 暂时不做折叠数据 --> + <!-- <el-table-column type="expand">--> + <!-- <template #default="{ row }">--> + <!-- <el-form inline label-position="left">--> + <!-- <el-form-item label="市场价:">--> + <!-- <span>{{ row.marketPrice }}</span>--> + <!-- </el-form-item>--> + <!-- <el-form-item label="成本价:">--> + <!-- <span>{{ row.costPrice }}</span>--> + <!-- </el-form-item>--> + <!-- <el-form-item label="虚拟销量:">--> + <!-- <span>{{ row.virtualSalesCount }}</span>--> + <!-- </el-form-item>--> + <!-- </el-form>--> + <!-- </template>--> + <!-- </el-table-column>--> <el-table-column label="商品图" min-width="80"> <template #default="{ row }"> - <div class="demo-image__preview z-100"> - <el-image - :src="row.picUrl" - style="width: 36px; height: 36px" - @click="imagePreview(row.picUrl)" - /> - </div> + <el-image + :src="row.picUrl" + style="width: 36px; height: 36px" + @click="imagePreview(row.picUrl)" + /> </template> </el-table-column> <el-table-column :show-overflow-tooltip="true" label="商品名称" min-width="300" prop="name" /> @@ -108,9 +107,9 @@ <template #default="{ row }"> <el-switch v-model="row.status" - :active-value="0" + :active-value="1" :disabled="Number(row.status) < 0" - :inactive-value="1" + :inactive-value="0" active-text="上架" inactive-text="下架" inline-prompt @@ -120,22 +119,42 @@ </el-table-column> <el-table-column align="center" fixed="right" label="操作" min-width="150"> <template #default="{ row }"> - <el-button - v-hasPermi="['product:spu:query']" - link - type="primary" - @click="openForm(row.id)" - > - 修改 - </el-button> - <el-button - v-hasPermi="['product:spu:update']" - link - type="primary" - @click="changeStatus(row)" - > - 加入回收站 - </el-button> + <template v-if="queryParams.tabType === 4"> + <el-button + v-hasPermi="['product:spu:delete']" + link + type="danger" + @click="handleDelete(row.id)" + > + 删除 + </el-button> + <el-button + v-hasPermi="['product:spu:update']" + link + type="primary" + @click="addToTrash(row, ProductSpuStatusEnum.DISABLE.status)" + > + 恢复到仓库 + </el-button> + </template> + <template v-else> + <el-button + v-hasPermi="['product:spu:update']" + link + type="primary" + @click="openForm(row.id)" + > + 修改 + </el-button> + <el-button + v-hasPermi="['product:spu:update']" + link + type="primary" + @click="addToTrash(row, ProductSpuStatusEnum.RECYCLE.status)" + > + 加入回收站 + </el-button> + </template> </template> </el-table-column> </el-table> @@ -158,64 +177,141 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { dateFormatter } from '@/utils/formatTime' // 业务api import * as managementApi from '@/api/mall/product/management/spu' -// const message = useMessage() // 消息弹窗 -// const { t } = useI18n() // 国际化 -const { push } = useRouter() // 路由跳转 +import { ProductSpuStatusEnum } from '@/utils/constants' +import { TabsPaneContext } from 'element-plus' + +const message = useMessage() // 消息弹窗 +const { t } = useI18n() // 国际化 +const { currentRoute, push } = useRouter() // 路由跳转 const loading = ref(false) // 列表的加载中 const total = ref(0) // 列表的总页数 const list = ref<any[]>([]) // 列表的数据 -const headerNum = ref([ +// tabs数据 +const tabsData = ref([ { - count: 8, + count: 0, name: '出售中商品', - type: 1 + type: 0 }, { count: 0, name: '仓库中商品', + type: 1 + }, + { + count: 0, + name: '已经售空商品', type: 2 }, { count: 0, - name: '已经售馨商品', + name: '警戒库存', type: 3 }, - { - count: 0, - name: '警戒库存', - type: 4 - }, { count: 0, name: '商品回收站', - type: 5 + type: 4 } ]) +const getTabsCount = async () => { + try { + const res = await managementApi.getTabsCount() + for (let objName in res) { + tabsData.value[Number(objName)].count = res[objName] + } + } catch {} +} const imgViewVisible = ref(false) // 商品图预览 const imageViewerList = ref<string[]>([]) // 商品图预览列表 -const queryParams = reactive({ +const queryParams = ref({ pageNo: 1, - pageSize: 10 + pageSize: 10, + tabType: 0 }) const queryFormRef = ref() // 搜索的表单 - +const handleClick = (tab: TabsPaneContext) => { + queryParams.value.tabType = tab.paneName + getList() +} /** 查询列表 */ const getList = async () => { loading.value = true try { - const data = await managementApi.getSpuList(queryParams) + const data = await managementApi.getSpuList(queryParams.value) list.value = data.list total.value = data.total } finally { loading.value = false } } + /** * 更改SPU状态 * @param row + * @param status 更改前的值 */ -const changeStatus = (row) => { - console.log(row) +const changeStatus = async (row, status?: number) => { + // TODO 测试过程中似乎有点问题,下一版修复 + try { + let text = '' + switch (row.status) { + case ProductSpuStatusEnum.DISABLE.status: + text = ProductSpuStatusEnum.DISABLE.name + break + case ProductSpuStatusEnum.ENABLE.status: + text = ProductSpuStatusEnum.ENABLE.name + break + case ProductSpuStatusEnum.RECYCLE.status: + text = `加入${ProductSpuStatusEnum.RECYCLE.name}` + break + } + await message.confirm( + row.status === -1 ? `确认要将[${row.name}]${text}吗?` : `确认要${text}[${row.name}]吗?` + ) + await managementApi.updateStatus({ id: row.id, status: row.status }) + message.success('更新状态成功') + // 刷新tabs数据 + await getTabsCount() + // 刷新列表 + await getList() + } catch { + // 取消加入回收站时回显数据 + if (typeof status !== 'undefined') { + row.status = status + return + } + // 取消更改状态时回显数据 + row.status = + row.status === ProductSpuStatusEnum.DISABLE.status + ? ProductSpuStatusEnum.ENABLE.status + : ProductSpuStatusEnum.DISABLE.status + } +} +/** + * 加入回收站 + * @param row + * @param status + */ +const addToTrash = (row, status) => { + // 复制一份原值 + const num = Number(`${row.status}`) + row.status = status + changeStatus(row, num) +} +/** 删除按钮操作 */ +const handleDelete = async (id: number) => { + try { + // 删除的二次确认 + await message.delConfirm() + // 发起删除 + await managementApi.deleteSpu(id) + message.success(t('common.delSuccess')) + // 刷新tabs数据 + await getTabsCount() + // 刷新列表 + await getList() + } catch {} } /** * 商品图预览 @@ -247,9 +343,19 @@ const openForm = (id?: number) => { } push('/product/productManagementAdd') } - +// 监听路由变化更新列表 +watch( + () => currentRoute.value, + () => { + getList() + }, + { + immediate: true + } +) /** 初始化 **/ onMounted(() => { + getTabsCount() getList() }) </script>