소스 검색

商品管理: 打通所有接口(第一版)

puhui999 2 년 전
부모
커밋
0c6e3a39c9

+ 12 - 0
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}` })
+}

+ 17 - 0
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: '上架'
+  }
+}

+ 6 - 3
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
   }

+ 1 - 0
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') : ''

+ 0 - 3
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)

+ 168 - 62
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: 2
+    type: 1
   },
   {
     count: 0,
-    name: '已经售商品',
-    type: 3
+    name: '已经售商品',
+    type: 2
   },
   {
     count: 0,
     name: '警戒库存',
-    type: 4
+    type: 3
   },
   {
     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 = 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 changeStatus = (row) => {
-  console.log(row)
+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>