feat(goods): 商品上架页面
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
import request from '@/utils/request'
|
||||
export const page = (queryParams:object)=> {
|
||||
|
||||
/**
|
||||
* 获取商品分页列表
|
||||
*
|
||||
* @param queryParams
|
||||
*/
|
||||
export function listGoodsWithPage(queryParams: object) {
|
||||
return request({
|
||||
url: '/mall-pms/api/v1/goods/page',
|
||||
method: 'get',
|
||||
@@ -7,14 +13,24 @@ export const page = (queryParams:object)=> {
|
||||
})
|
||||
}
|
||||
|
||||
export const detail=(id:number)=> {
|
||||
/**
|
||||
* 获取商品详情
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
export function getGoodsDetail(id: number) {
|
||||
return request({
|
||||
url: '/mall-pms/api/v1/goods/' + id,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
export const addGoods=(data:object)=> {
|
||||
/**
|
||||
* 添加商品
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
export function addGoods(data: object) {
|
||||
return request({
|
||||
url: '/mall-pms/api/v1/goods',
|
||||
method: 'post',
|
||||
@@ -22,7 +38,13 @@ export const addGoods=(data:object)=> {
|
||||
})
|
||||
}
|
||||
|
||||
export const updateGoods=(id:number, data:object)=> {
|
||||
/**
|
||||
* 修改商品
|
||||
*
|
||||
* @param id
|
||||
* @param data
|
||||
*/
|
||||
export function updateGoods(id: number, data: object) {
|
||||
return request({
|
||||
url: '/mall-pms/api/v1/goods/' + id,
|
||||
method: 'put',
|
||||
@@ -30,17 +52,14 @@ export const updateGoods=(id:number, data:object)=> {
|
||||
})
|
||||
}
|
||||
|
||||
export const removeGoods=(ids:string)=> {
|
||||
/**
|
||||
* 删除商品
|
||||
*
|
||||
* @param ids
|
||||
*/
|
||||
export function deleteGoods(ids: string) {
|
||||
return request({
|
||||
url: '/mall-pms/api/v1/goods/'+ids,
|
||||
url: '/mall-pms/api/v1/goods/' + ids,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
export const patch=(id:number, data:object)=> {
|
||||
return request({
|
||||
url: '/mall-pms/api/v1/goods/' + id,
|
||||
method: 'patch',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
132
src/views/pms/goods/components/GoodsAttribute.vue
Normal file
132
src/views/pms/goods/components/GoodsAttribute.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<!--
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<div class="components-container__main">
|
||||
<el-card class="box-card">
|
||||
<div slot="header">
|
||||
<span>商品属性</span>
|
||||
<el-button style="float: right;" type="primary" size="mini" @click="handleAttributeAdd">
|
||||
添加属性
|
||||
</el-button>
|
||||
</div>
|
||||
<el-form
|
||||
ref="attributeForm"
|
||||
:model="value"
|
||||
:rules="rules"
|
||||
size="mini"
|
||||
:inline="true"
|
||||
>
|
||||
<el-table
|
||||
:data="value.attrList"
|
||||
size="mini"
|
||||
highlight-current-row
|
||||
border
|
||||
>
|
||||
<el-table-column property="name" label="属性名称">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'attrList[' + scope.$index + '].name'"
|
||||
:rules="rules.attribute.name"
|
||||
>
|
||||
<el-input v-model="scope.row.name"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column property="value" label="属性值">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'attrList[' + scope.$index + '].value'"
|
||||
:rules="rules.attribute.value"
|
||||
>
|
||||
<el-input v-model="scope.row.value"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item>
|
||||
<el-button type="danger" icon="el-icon-minus" circle @click="handleAttributeRemove(scope.$index)"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
</div>
|
||||
<div class="components-container__footer">
|
||||
<el-button @click="handlePrev">上一步,填写商品信息</el-button>
|
||||
<el-button type="primary" @click="handleNext">下一步,设置商品库存</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {listAttribute} from "@/api/pms/attribute";
|
||||
|
||||
export default {
|
||||
name: "GoodsAttribute",
|
||||
props: {
|
||||
value: Object
|
||||
},
|
||||
watch:{
|
||||
// 监听选择的商品分类关联商品属性
|
||||
'value.categoryId':{
|
||||
handler(newVal,oldVal){
|
||||
listAttribute({categoryId: newVal, type: 2}).then(res => {
|
||||
this.value.attrList = res.data
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rules: {
|
||||
attribute: {
|
||||
name: [{required: true, message: '请填写属性名称', trigger: 'blur'}],
|
||||
value: [{required: true, message: '请填写属性值', trigger: 'blur'}]
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAttributeAdd: function () {
|
||||
this.value.attrList.push({})
|
||||
},
|
||||
handleAttributeRemove: function (index) {
|
||||
this.value.attrList.splice(index, 1)
|
||||
},
|
||||
handlePrev: function () {
|
||||
this.$emit('prev')
|
||||
},
|
||||
handleNext: function () {
|
||||
this.$refs["attributeForm"].validate((valid) => {
|
||||
if (valid) {
|
||||
this.$emit('next')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.components-container {
|
||||
&__main {
|
||||
margin: 20px auto
|
||||
}
|
||||
|
||||
&__footer {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
.el-form-item--mini.el-form-item{
|
||||
margin-top: 18px;
|
||||
}
|
||||
</style>
|
||||
-->
|
||||
94
src/views/pms/goods/components/GoodsCategory.vue
Normal file
94
src/views/pms/goods/components/GoodsCategory.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<div class="components-container__main">
|
||||
<el-cascader-panel
|
||||
ref="categoryRef"
|
||||
:options="categoryOptions"
|
||||
v-model="categoryId"
|
||||
:props="{emitPath:false}"
|
||||
@change="handleCategoryChange"
|
||||
|
||||
/>
|
||||
|
||||
<div style="margin-top: 20px">
|
||||
<el-link type="info" :underline="false" v-show="pathLabels.length>0">您选择的商品分类:</el-link>
|
||||
<el-link type="danger" :underline="false" v-for="(item,index) in pathLabels" style="margin-left: 5px">
|
||||
{{ item }}
|
||||
<i v-show="index<pathLabels.length-1" class=" el-icon-arrow-right"></i>
|
||||
</el-link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="components-container__footer">
|
||||
<el-button type="primary" @click="onNextStepClick">下一步,填写商品信息</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {listCascadeCategories} from "@/api/pms/category";
|
||||
import {nextTick, onMounted, reactive, ref, toRefs} from "vue";
|
||||
import {ElCascaderPanel, ElMessage} from "element-plus";
|
||||
const emit = defineEmits(['next'])
|
||||
|
||||
const props = defineProps({
|
||||
goodsId: Number,
|
||||
categoryId: Number
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
categoryOptions: [],
|
||||
pathLabels: [],
|
||||
categoryId: undefined
|
||||
})
|
||||
|
||||
const {categoryOptions, pathLabels, categoryId} = toRefs(state)
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
|
||||
function loadData() {
|
||||
listCascadeCategories({}).then(response => {
|
||||
state.categoryOptions = response.data
|
||||
if (props.goodsId) {
|
||||
state.categoryId = props.categoryId as any
|
||||
nextTick(() => {
|
||||
handleCategoryChange()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
const categoryRef = ref(ElCascaderPanel)
|
||||
|
||||
function handleCategoryChange() {
|
||||
const checkNode = categoryRef.value.getCheckedNodes()[0]
|
||||
state.pathLabels = checkNode.pathLabels // 商品分类选择层级提示
|
||||
state.categoryId = checkNode.value
|
||||
}
|
||||
|
||||
|
||||
function onNextStepClick() {
|
||||
if (!state.categoryId) {
|
||||
ElMessage.warning('请选择商品分类')
|
||||
return false
|
||||
}
|
||||
emit('next' )
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.components-container {
|
||||
&__main {
|
||||
margin: 20px auto
|
||||
}
|
||||
|
||||
&__footer {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
180
src/views/pms/goods/components/GoodsInfo.vue
Normal file
180
src/views/pms/goods/components/GoodsInfo.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<!--
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<div class="components-container__main">
|
||||
<el-form
|
||||
ref="goodsForm"
|
||||
:rules="rules"
|
||||
:model="value"
|
||||
label-width="150px">
|
||||
<el-form-item label="商品名称" prop="name">
|
||||
<el-input style="width: 400px" v-model="value.name"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="原价" prop="originPrice">
|
||||
<el-input style="width: 400px" v-model="value.originPrice"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="现价" prop="price">
|
||||
<el-input style="width: 400px" v-model="value.price"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品品牌" prop="brandId">
|
||||
<el-select
|
||||
v-model="value.brandId"
|
||||
clearable
|
||||
style="width:400px">
|
||||
<el-option v-for="item in brandOptions" :key="item.id" :label="item.name" :value="item.id"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品简介">
|
||||
<el-input type="textarea" style="width: 400px" v-model="value.description"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品相册">
|
||||
<el-row :gutter="10">
|
||||
<el-col style="width: 180px" v-for="(item,index) in pictures">
|
||||
<el-card :body-style="{ padding: '10px' }">
|
||||
<single-upload v-model="item.url"></single-upload>
|
||||
<div class="bottom" v-if="item.url">
|
||||
<el-button type="text" class="button" v-if="item.main==true" style="color:#ff4d51">商品主图</el-button>
|
||||
<el-button type="text" class="button" v-else @click="setMainPicture(index)">设为主图</el-button>
|
||||
<el-button type="text" class="button" @click="handlePictureRemove(index)">删除图片</el-button>
|
||||
</div>
|
||||
<div class="bottom" v-else>
|
||||
<el-button type="text" class="button"></el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="商品详情" prop="detail">
|
||||
<tinymce v-model="value.detail" :height="400"/>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
</div>
|
||||
<div class="components-container__footer">
|
||||
<el-button @click="handlePrev">上一步,选择商品分类</el-button>
|
||||
<el-button type="primary" @click="handleNext">下一步,设置商品属性</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
import {list as listBrand} from "@/api/pms/brand"
|
||||
import SingleUpload from '@/components/Upload/SingleUpload'
|
||||
import Tinymce from '@/components/Tinymce'
|
||||
|
||||
export default {
|
||||
name: "GoodsInfo",
|
||||
components: {SingleUpload, Tinymce},
|
||||
props: {
|
||||
value: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
brandOptions: [],
|
||||
pictures: [],
|
||||
rules: {
|
||||
name: [{required: true, message: '请填写商品名称', trigger: 'blur'}],
|
||||
originPrice: [{required: true, message: '请填写原价', trigger: 'blur'}],
|
||||
price: [{required: true, message: '请填写现价', trigger: 'blur'}],
|
||||
brandId: [{required: true, message: '请选择商品品牌', trigger: 'blur'}],
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.handleFormReset()
|
||||
|
||||
await listBrand().then(response => {
|
||||
this.brandOptions = response.data
|
||||
})
|
||||
|
||||
const goodsId = this.value.id
|
||||
if (goodsId) {
|
||||
|
||||
const mainPicUrl = this.value.picUrl
|
||||
if (mainPicUrl) {
|
||||
this.pictures.filter(item => item.main == true)[0].url = mainPicUrl
|
||||
}
|
||||
|
||||
const subPicUrls = this.value.subPicUrls
|
||||
if (subPicUrls && subPicUrls.length > 0) {
|
||||
for (let i = 1; i <= subPicUrls.length; i++) {
|
||||
this.pictures[i].url = subPicUrls[i - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 设置主图
|
||||
setMainPicture(changeIndex) {
|
||||
const mainPicture = JSON.parse(JSON.stringify( this.pictures[0]))
|
||||
const changePicture = JSON.parse(JSON.stringify( this.pictures[changeIndex]))
|
||||
|
||||
console.log(changeIndex,changePicture.url,mainPicture.url)
|
||||
|
||||
this.pictures[0].url = changePicture.url
|
||||
this.pictures[changeIndex].url = mainPicture.url
|
||||
|
||||
},
|
||||
handlePictureRemove(index) {
|
||||
this.pictures[index].url = undefined
|
||||
},
|
||||
handleFormReset: function () {
|
||||
this.pictures = [
|
||||
{url: undefined, main: true},
|
||||
{url: undefined, main: false},
|
||||
{url: undefined, main: false},
|
||||
{url: undefined, main: false},
|
||||
{url: undefined, main: false},
|
||||
]
|
||||
},
|
||||
handlePrev: function () {
|
||||
this.$emit('prev')
|
||||
},
|
||||
handleNext: function () {
|
||||
this.$refs["goodsForm"].validate((valid) => {
|
||||
if (valid) {
|
||||
// 商品图片处理
|
||||
const tempMainPicUrl = this.pictures.filter(item => item.main == true && item.url).map(item => item.url)
|
||||
if (tempMainPicUrl && tempMainPicUrl.length > 0) {
|
||||
this.value.picUrl = tempMainPicUrl[0]
|
||||
}
|
||||
const tempSubPicUrl = this.pictures.filter(item => item.main == false && item.url).map(item => item.url)
|
||||
if (tempSubPicUrl && tempSubPicUrl.length > 0) {
|
||||
this.value.subPicUrls = tempSubPicUrl
|
||||
}
|
||||
this.$emit('next')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.components-container {
|
||||
&__main {
|
||||
margin: 20px auto;
|
||||
|
||||
.button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
-->
|
||||
503
src/views/pms/goods/components/GoodsStock.vue
Normal file
503
src/views/pms/goods/components/GoodsStock.vue
Normal file
@@ -0,0 +1,503 @@
|
||||
<!--
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<div class="components-container__main">
|
||||
<el-card class="box-card">
|
||||
<div slot="header">
|
||||
<span>商品规格</span>
|
||||
<el-button style="float: right;" type="primary" size="mini" @click="handleSpecAdd">
|
||||
添加规格项
|
||||
</el-button>
|
||||
</div>
|
||||
<el-form
|
||||
size="mini"
|
||||
ref="specForm"
|
||||
:model="specForm"
|
||||
:inline="true">
|
||||
<el-table
|
||||
ref="specTable"
|
||||
:data="specForm.specList"
|
||||
row-key="id"
|
||||
size="mini"
|
||||
>
|
||||
<el-table-column align="center" width="50">
|
||||
<template>
|
||||
<svg-icon class="drag-handler" icon-class="drag"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格名" width="200">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
:prop="'specList[' + scope.$index + '].name'"
|
||||
:rules="rules.specification.name"
|
||||
>
|
||||
<el-input
|
||||
type="text"
|
||||
v-model="scope.row.name"
|
||||
size="mini"
|
||||
@input="changeSpec()"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column>
|
||||
<template slot="header">
|
||||
规格值
|
||||
<el-link type="danger" style="font-size:12px" :underline="false">(默认第一条规格包含图片)</el-link>
|
||||
</template>
|
||||
<template slot-scope="{row}">
|
||||
<div style="margin-right:15px;display: inline-block" v-for="item in row.values">
|
||||
<el-tag
|
||||
closable
|
||||
:type="colors[row.index%colors.length]"
|
||||
@close="handleSpecValueRemove(row.index,item.id)">
|
||||
{{ item.value }}
|
||||
</el-tag>
|
||||
<mini-card-upload v-if="row.index==0" style="margin-top: 5px" v-model="item.picUrl"/>
|
||||
</div>
|
||||
<el-input
|
||||
style="width: 80px;vertical-align: top"
|
||||
size="mini"
|
||||
v-if="tagInputs[row.index].visible"
|
||||
v-model="tagInputs[row.index].value"
|
||||
@keyup.enter.native="handleSpecValueInput(row.index)"
|
||||
@blur="handleSpecValueInput(row.index)"/>
|
||||
<el-button v-else size="mini" icon="el-icon-plus" style="vertical-align: top"
|
||||
@click="handleSpecValueAdd(row.index)">添加规格值
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column width="60" label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="danger"
|
||||
icon="el-icon-delete"
|
||||
size="mini"
|
||||
circle
|
||||
plain
|
||||
@click.stop="handleSpecRemove(scope.$index)"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
</el-card>
|
||||
<el-card class="box-card">
|
||||
<div slot="header">
|
||||
<span>商品库存</span>
|
||||
</div>
|
||||
<el-form
|
||||
:model="skuForm"
|
||||
size="mini"
|
||||
ref="skuForm"
|
||||
:inline="true"
|
||||
>
|
||||
<el-table
|
||||
:data="skuForm.skuList"
|
||||
:span-method="handleCellMerge"
|
||||
size="mini"
|
||||
fit highlight-current-row border
|
||||
>
|
||||
<el-table-column
|
||||
v-for="(title,index) in specTitleList"
|
||||
align="center"
|
||||
:prop="'specValue'+(index+1)"
|
||||
:label="title">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="商品编码"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'skuList['+scope.$index+'].sn'" :rules="rules.sku.sn">
|
||||
<el-input v-model="scope.row.sn"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="价格" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'skuList['+scope.$index+'].price'" :rules="rules.sku.price">
|
||||
<el-input v-model="scope.row.price"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-form-item :prop="'skuList['+scope.$index+'].stock'" :rules="rules.sku.stock">
|
||||
<el-input v-model="scope.row.stock"/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
<div class="components-container__footer">
|
||||
<el-button @click="handlePrev">上一步,设置商品属性</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">提交</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {listAttribute} from "@/api/pms/attribute";
|
||||
import MiniCardUpload from '@/components/Upload/MiniCardUpload'
|
||||
import Sortable from "sortablejs";
|
||||
import {addGoods, updateGoods} from "@/api/pms/goods";
|
||||
|
||||
|
||||
export default {
|
||||
name: "GoodsStock",
|
||||
components: {MiniCardUpload},
|
||||
props: {
|
||||
value: Object
|
||||
},
|
||||
watch: {
|
||||
// 监听选择的商品分类关联商品属性项
|
||||
'value.categoryId': {
|
||||
handler(newVal, oldVal) {
|
||||
listAttribute({categoryId: newVal, type: 1}).then(res => {
|
||||
res.data.forEach(item => {
|
||||
console.log('规格项目', item)
|
||||
this.specForm.specList.push({
|
||||
name: item.name,
|
||||
values: []
|
||||
})
|
||||
this.loadData()
|
||||
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 包装一层用于表单验证
|
||||
specForm: {
|
||||
specList: [],
|
||||
},
|
||||
skuForm: {
|
||||
skuList: []
|
||||
},
|
||||
specTitleList: [], // 规格项表格标题
|
||||
rules: {
|
||||
specification: {
|
||||
name: [{required: true, message: '请输入规格名称', trigger: 'blur'}],
|
||||
value: [{required: true, message: '请输入规格值', trigger: 'blur'}]
|
||||
},
|
||||
sku: {
|
||||
sn: [{required: true, message: '请输入商品编号', trigger: 'blur'}],
|
||||
price: [{required: true, message: '请输入商品价格', trigger: 'blur'}],
|
||||
stock: [{required: true, message: '请输入商品库存', trigger: 'blur'}],
|
||||
}
|
||||
},
|
||||
colors: ['', 'success', 'warning', 'danger'],
|
||||
tagInputs: [{value: undefined, visible: false}], // 规格值标签临时值和显隐控制
|
||||
loading: undefined
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.value.id) {
|
||||
this.loadData()
|
||||
}
|
||||
|
||||
},
|
||||
methods: {
|
||||
async loadData() {
|
||||
this.value.specList.forEach(spec => {
|
||||
const index = this.specForm.specList.findIndex(item => item.name == spec.name)
|
||||
if (index > -1) {
|
||||
this.specForm.specList[index].values.push({id: spec.id, value: spec.value, picUrl: spec.picUrl})
|
||||
} else {
|
||||
this.specForm.specList.push({
|
||||
name: spec.name,
|
||||
values: [{id: spec.id, value: spec.value, picUrl: spec.picUrl}]
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
// 每个规格项追加一个添加规格值按钮
|
||||
for (let i = 0; i < this.specForm.specList.length; i++) {
|
||||
this.tagInputs.push({'value': undefined, 'visible': false})
|
||||
}
|
||||
// SKU规格ID拼接字符串处理
|
||||
this.value.skuList.forEach(sku => {
|
||||
sku.specIdArr = sku.specIds.split('_')
|
||||
})
|
||||
|
||||
this.generateSku()
|
||||
this.changeSpec()
|
||||
this.sortSpec()
|
||||
this.$nextTick(() => {
|
||||
this.setSort()
|
||||
})
|
||||
},
|
||||
handleSpecAdd: function () {
|
||||
if (this.specForm.specList.length >= 3) {
|
||||
this.$message.warning('最多支持3组规格')
|
||||
return
|
||||
}
|
||||
this.specForm.specList.push({})
|
||||
this.tagInputs.push({'value': undefined, 'visible': false})
|
||||
this.sortSpec()
|
||||
},
|
||||
handleSpecRemove: function (index) {
|
||||
this.specForm.specList.splice(index, 1)
|
||||
this.tagInputs.splice(index, 1)
|
||||
this.generateSku()
|
||||
this.sortSpec()
|
||||
this.changeSpec()
|
||||
},
|
||||
sortSpec: function () {
|
||||
this.specForm.specList.forEach((item, index) => {
|
||||
item.index = index
|
||||
})
|
||||
},
|
||||
handleSpecValueRemove: function (rowIndex, specValueId) {
|
||||
const specList = JSON.parse(JSON.stringify(this.specForm.specList))
|
||||
const removeIndex = specList[rowIndex].values.map(item => item.id).indexOf(specValueId)
|
||||
console.log('removeIndex', removeIndex)
|
||||
|
||||
specList[rowIndex].values.splice(removeIndex, 1)
|
||||
this.specForm.specList = specList
|
||||
this.changeSpec()
|
||||
this.generateSku()
|
||||
},
|
||||
handleSpecValueInput: function (rowIndex) {
|
||||
const currSpecValue = this.tagInputs[rowIndex].value
|
||||
const specValues = this.specForm.specList[rowIndex].values
|
||||
if (specValues && specValues.length > 0 && specValues.map(item => item.value).includes(currSpecValue)) {
|
||||
this.$message.warning("规格值重复,请重新输入")
|
||||
return false
|
||||
}
|
||||
if (currSpecValue) {
|
||||
if (specValues && specValues.length > 0) {
|
||||
// 临时规格值ID tid_1_1
|
||||
let maxSpecValueIndex = specValues.filter(item => item.id.includes('tid_')).map(item => item.id.split('_')[2]).reduce((acc, curr) => {
|
||||
return acc > curr ? acc : curr
|
||||
}, 0)
|
||||
console.log('maxSpecValueIndex', maxSpecValueIndex)
|
||||
this.specForm.specList[rowIndex].values[specValues.length] = {
|
||||
'value': currSpecValue,
|
||||
'id': 'tid_' + (rowIndex + 1) + '_' + ++maxSpecValueIndex
|
||||
}
|
||||
} else {
|
||||
this.specForm.specList[rowIndex].values = [{'value': currSpecValue, 'id': 'tid_' + (rowIndex + 1) + '_1'}]
|
||||
}
|
||||
}
|
||||
this.tagInputs[rowIndex].value = undefined
|
||||
this.tagInputs[rowIndex].visible = false
|
||||
|
||||
// 生成SKU列表
|
||||
this.generateSku()
|
||||
},
|
||||
handleSpecValueAdd: function (rowIndex) {
|
||||
this.tagInputs[rowIndex].visible = true
|
||||
},
|
||||
setSort() {
|
||||
const el = this.$refs.specTable.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
|
||||
Sortable.create(el, {
|
||||
ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
|
||||
setData: function (dataTransfer) {
|
||||
dataTransfer.setData('Text', '')
|
||||
},
|
||||
onEnd: evt => {
|
||||
// oldIndex 拖拽行当前所在索引
|
||||
// newIndex 拖拽行目标索引
|
||||
const targetRow = this.specForm.specList.splice(evt.oldIndex, 1)[0] // 返回被删除的行
|
||||
this.specForm.specList.splice(evt.newIndex, 0, targetRow) // 拼接
|
||||
this.generateSku() // 重新生成sku
|
||||
this.sortSpec()
|
||||
this.changeSpec()
|
||||
}
|
||||
})
|
||||
},
|
||||
generateSku: function () {
|
||||
// [
|
||||
// { 'id':1,'name':'颜色','values':[{id:1,value:'白色'},{id:2,value:'黑色'},{id:3,value:'蓝色'}] },
|
||||
// { 'id':2,'name':'版本','values':[{id:1,value:'6+128G'},{id:2,value:'8+128G'},{id:3,value:'8G+256G'}] }
|
||||
// ]
|
||||
const specList = JSON.parse(JSON.stringify(this.specForm.specList.filter(item => item.values.length > 0))) // 深拷贝,取有属性的规格项,否则笛卡尔积运算得到的SKU列表值为空
|
||||
|
||||
const skuList = specList.reduce((acc, curr) => {
|
||||
let result = []
|
||||
acc.forEach(item => {
|
||||
// curr => { 'id':1,'name':'颜色','values':[{id:1,value:'白色'},{id:2,value:'黑色'},{id:3,value:'蓝色'}] }
|
||||
curr.values.forEach(v => { // v=>{id:1,value:'白色'}
|
||||
let temp = Object.assign({}, item)
|
||||
temp.specValues += v.value + '_' // 规格值拼接
|
||||
temp.specIds += v.id + '|' // 规格ID拼接
|
||||
result.push(temp)
|
||||
})
|
||||
})
|
||||
return result
|
||||
}, [{specValues: '', specIds: ''}])
|
||||
|
||||
skuList.forEach(item => {
|
||||
item.specIds = item.specIds.substring(0, item.specIds.length - 1)
|
||||
item.name = item.specValues.substring(0, item.specIds.length - 1).replaceAll('_', ' ')
|
||||
const specIdArr = item.specIds.split('|')
|
||||
const skus = this.value.skuList.filter(sku => sku.specIdArr.equals(specIdArr)) // 数据库的SKU列表
|
||||
if (skus && skus.length > 0) {
|
||||
const sku = skus[0]
|
||||
item.id = sku.id
|
||||
item.sn = sku.sn
|
||||
item.price = sku.price / 100
|
||||
item.stock = sku.stock
|
||||
}
|
||||
const specValueArr = item.specValues.substring(0, item.specValues.length - 1).split('_') // ['黑','6+128G','官方标配']
|
||||
specValueArr.forEach((v, i) => {
|
||||
const key = 'specValue' + (i + 1)
|
||||
item[key] = v
|
||||
if (i == 0 && this.specForm.specList.length > 0) {
|
||||
const valueIndex = this.specForm.specList[0].values.findIndex(specValue => specValue.value == v)
|
||||
if (valueIndex > -1) {
|
||||
item.picUrl = this.specForm.specList[0].values[valueIndex].picUrl
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
this.skuForm.skuList = JSON.parse(JSON.stringify(skuList))
|
||||
},
|
||||
changeSpec: function () {
|
||||
const specList = JSON.parse(JSON.stringify(this.specForm.specList))
|
||||
this.specTitleList = specList.map(item => item.name)
|
||||
},
|
||||
/**
|
||||
* 合并规格值单元格
|
||||
*/
|
||||
handleCellMerge({row, column, rowIndex, columnIndex}) {
|
||||
let mergeRows = [1, 1, 1] // 分别对应规格1、规格2、规格3列合并的行数
|
||||
const specLen = this.specForm.specList.filter(item => item.values && item.values.length > 0).length
|
||||
if (specLen == 2) {
|
||||
const values_len_2 = this.specForm.specList[1].values ? this.specForm.specList[1].values.length : 1 // 第2个规格项的规格值的数量
|
||||
mergeRows = [values_len_2, 1, 1]
|
||||
} else if (specLen == 3) {
|
||||
const values_len_2 = this.specForm.specList[1].values ? this.specForm.specList[1].values.length : 1 // 第2个规格项的规格值的数量
|
||||
const values_len_3 = this.specForm.specList[2].values ? this.specForm.specList[2].values.length : 1 // 第3个规格项的规格值的数量
|
||||
mergeRows = [values_len_2 * values_len_3, values_len_3, 1]
|
||||
}
|
||||
if (columnIndex == 0) {
|
||||
if (rowIndex % mergeRows[0] === 0) {
|
||||
return [mergeRows[0], 1]// 合并单元格
|
||||
} else {
|
||||
return [0, 0] // 隐藏单元格
|
||||
}
|
||||
}
|
||||
if (columnIndex == 1) {
|
||||
if (rowIndex % mergeRows[1] === 0) {
|
||||
return [mergeRows[1], 1]// 合并单元格
|
||||
} else {
|
||||
return [0, 0] // 隐藏单元格
|
||||
}
|
||||
}
|
||||
},
|
||||
handlePrev: function () {
|
||||
this.$emit('prev')
|
||||
},
|
||||
handleSubmit: function () {
|
||||
this.$refs.specForm.validate((specValid) => {
|
||||
if (specValid) {
|
||||
this.$refs.skuForm.validate((skuValid) => {
|
||||
if (skuValid) {
|
||||
this.openFullScreen()
|
||||
let submitGoodsData = Object.assign({}, this.value)
|
||||
delete submitGoodsData.specList
|
||||
delete submitGoodsData.skuList
|
||||
|
||||
let specList = []
|
||||
this.specForm.specList.forEach(item => {
|
||||
item.values.forEach(value => {
|
||||
value.name = item.name
|
||||
})
|
||||
specList = specList.concat(item.values)
|
||||
})
|
||||
submitGoodsData.specList = specList // 规格列表
|
||||
|
||||
submitGoodsData.price *= 100 // 金额转成分保存至数据库
|
||||
submitGoodsData.originPrice *= 100
|
||||
|
||||
let skuList = JSON.parse(JSON.stringify(this.skuForm.skuList))
|
||||
skuList.map(item => {
|
||||
item.price *= 100
|
||||
return item
|
||||
})
|
||||
submitGoodsData.skuList = skuList
|
||||
console.log('提交数据', submitGoodsData)
|
||||
const goodsId = this.value.id
|
||||
if (goodsId) { // 编辑商品提交
|
||||
updateGoods(goodsId, submitGoodsData).then((res) => {
|
||||
this.$router.push({path: '/pms/goods'})
|
||||
this.$notify.success('修改商品成功')
|
||||
this.closeFullScreen()
|
||||
}, (err) => {
|
||||
this.closeFullScreen()
|
||||
}
|
||||
)
|
||||
} else { // 新增商品提交
|
||||
addGoods(submitGoodsData).then(response => {
|
||||
this.$router.push({path: '/pms/goods'})
|
||||
this.$notify.success('新增商品成功')
|
||||
this.closeFullScreen()
|
||||
}, (err) => {
|
||||
this.closeFullScreen()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
openFullScreen: function () {
|
||||
this.loading = this.$loading({
|
||||
lock: true,
|
||||
text: '商品信息提交中,请等待...',
|
||||
spinner: 'el-icon-loading',
|
||||
background: 'rgba(0, 0, 0, 0.7)'
|
||||
});
|
||||
},
|
||||
closeFullScreen: function () {
|
||||
if (this.loading) {
|
||||
this.loading.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重写数组equals方法,数组元素完全相同不论顺序
|
||||
* @param target
|
||||
* @returns {boolean}
|
||||
*/
|
||||
Array.prototype.equals = function (target) {
|
||||
return this.length === target.length &&
|
||||
this.every(a => target.some(b => a === b)) &&
|
||||
target.every(x => this.some(y => x === y));
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.components-container {
|
||||
&__main {
|
||||
margin: 20px auto
|
||||
}
|
||||
|
||||
&__footer {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.box-card {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-form-item--mini.el-form-item{
|
||||
margin-top: 18px;
|
||||
}
|
||||
</style>
|
||||
-->
|
||||
111
src/views/pms/goods/detail.vue
Normal file
111
src/views/pms/goods/detail.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="components-container">
|
||||
<el-steps :active="active" process-status="finish" finish-status="success" simple>
|
||||
<el-step title="选择商品分类"></el-step>
|
||||
<el-step title="填写商品信息"></el-step>
|
||||
<el-step title="设置商品属性"></el-step>
|
||||
<el-step title="设置商品库存"></el-step>
|
||||
</el-steps>
|
||||
<goods-category
|
||||
v-show="active==0"
|
||||
v-model="goods"
|
||||
v-if="loaded==true"
|
||||
@prev="prev"
|
||||
@next="next">
|
||||
</goods-category>
|
||||
<goods-info
|
||||
v-show="active==1"
|
||||
v-model="goods"
|
||||
v-if="loaded==true"
|
||||
@prev="prev"
|
||||
@next="next">
|
||||
</goods-info>
|
||||
|
||||
<goods-attribute
|
||||
v-show="active==2"
|
||||
v-model="goods"
|
||||
v-if="loaded==true"
|
||||
@prev="prev"
|
||||
@next="next">
|
||||
</goods-attribute>
|
||||
|
||||
<goods-stock
|
||||
v-show="active==3"
|
||||
v-model="goods"
|
||||
v-if="loaded==true"
|
||||
@prev="prev"
|
||||
@next="next">
|
||||
</goods-stock>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import GoodsCategory from "./components/GoodsCategory.vue";
|
||||
import GoodsInfo from "./components/GoodsInfo.vue";
|
||||
import GoodsAttribute from "./components/GoodsAttribute.vue";
|
||||
import GoodsStock from "./components/GoodsStock.vue";
|
||||
|
||||
import {getGoodsDetail} from "@/api/pms/goods";
|
||||
|
||||
export default {
|
||||
name: "goods-detail",
|
||||
components: {GoodsStock, GoodsCategory, GoodsInfo, GoodsAttribute},
|
||||
props: ['goodsId'],
|
||||
data() {
|
||||
return {
|
||||
loaded: false,
|
||||
active: 0,
|
||||
goods: {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
categoryId: undefined,
|
||||
brandId: undefined,
|
||||
originPrice: undefined,
|
||||
price: undefined,
|
||||
picUrl: undefined,
|
||||
album: undefined,
|
||||
description: undefined,
|
||||
detail: undefined,
|
||||
attrList: [],
|
||||
specList: [],
|
||||
skuList: []
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
loadData() {
|
||||
const goodsId = this.$route.query.goodsId
|
||||
if (goodsId) {
|
||||
getGoodsDetail(goodsId).then(response => {
|
||||
this.goods = response.data
|
||||
this.goods.originPrice = this.goods.originPrice / 100
|
||||
this.goods.price = this.goods.price / 100
|
||||
this.loaded = true
|
||||
})
|
||||
} else {
|
||||
this.loaded = true
|
||||
}
|
||||
},
|
||||
prev() {
|
||||
if (this.active-- <= 0) {
|
||||
this.active = 0;
|
||||
}
|
||||
},
|
||||
next() {
|
||||
if (this.active++ >= 3) {
|
||||
this.active = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.form-container {
|
||||
width: 80%;
|
||||
margin: 30px auto;
|
||||
}
|
||||
</style>
|
||||
@@ -1,10 +1,13 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :inline="true" ref="queryForm">
|
||||
<el-form
|
||||
ref="queryForm"
|
||||
:inline="true"
|
||||
size="mini"
|
||||
>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleAdd">发布商品</el-button>
|
||||
<el-button type="success" @click="handleUpdate" :disabled="single">编辑商品</el-button>
|
||||
<el-button type="danger" @click="handleDelete" :disabled="multiple">删除</el-button>
|
||||
<el-button type="success" :icon="Plus" @click="handleAdd">发布商品</el-button>
|
||||
<el-button type="danger" :icon="Delete" @click="handleDelete" :disabled="multiple">删除</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-input v-model="queryParams.name" placeholder="商品名称" clearable></el-input>
|
||||
@@ -13,7 +16,7 @@
|
||||
<el-cascader
|
||||
v-model="queryParams.categoryId"
|
||||
placeholder="商品分类"
|
||||
:props="cascaderProps"
|
||||
:props="{emitPath: false, expandTrigger: 'hover'}"
|
||||
:options="categoryOptions"
|
||||
clearable
|
||||
style="width: 300px"
|
||||
@@ -21,18 +24,18 @@
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="handleQuery">查询</el-button>
|
||||
<el-button :icon="Refresh" @click="handleReset">重置</el-button>
|
||||
<el-button :icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
id="dataTable"
|
||||
ref="multipleTable"
|
||||
:data="pageList"
|
||||
@selection-change="handleSelectionChange"
|
||||
@row-click="handleRowClick"
|
||||
border>
|
||||
border
|
||||
>
|
||||
<el-table-column type="selection" min-width="5%" center/>
|
||||
<el-table-column type="expand" width="120" label="库存信息">
|
||||
|
||||
@@ -49,7 +52,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="现价" prop="price">
|
||||
<template #default="scope">{{ moneyFormatter(scope.row.price) }}</template>
|
||||
<template #default="scope">{{ moneyFormatter(scope.row.price) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="库存" prop="stock"/>
|
||||
</el-table>
|
||||
@@ -81,38 +84,46 @@
|
||||
<el-button type="primary" size="mini" @click="handleGoodsView(scope.row.detail)">查看</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" min-width="120">
|
||||
<el-table-column label="操作" width="120">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
@click="handleUpdate(scope.row)"
|
||||
type="primary"
|
||||
:icon="Edit"
|
||||
size="mini"
|
||||
@click="handleUpdate(scope.row)">编辑
|
||||
</el-button>
|
||||
circle
|
||||
plain
|
||||
/>
|
||||
<el-button
|
||||
size="mini"
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row)">删除
|
||||
</el-button>
|
||||
:icon="Delete"
|
||||
size="mini"
|
||||
circle
|
||||
plain
|
||||
@click="handleDelete(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
v-show="pagination.total>0"
|
||||
:total="pagination.total"
|
||||
:page.sync="pagination.page"
|
||||
:limit.sync="pagination.limit"
|
||||
@pagination="handleQuery">
|
||||
</el-pagination>
|
||||
|
||||
<!-- 分页工具条 -->
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {Search, Refresh} from '@element-plus/icons'
|
||||
import {page, removeGoods} from '@/api/pms/goods'
|
||||
import {Search, Plus, Edit, Refresh, Delete} from '@element-plus/icons'
|
||||
import {listGoodsWithPage, deleteGoods} from '@/api/pms/goods'
|
||||
import {listCascadeCategories} from '@/api/pms/category'
|
||||
import {reactive, ref,onMounted, toRefs} from 'vue'
|
||||
import {reactive, ref, onMounted, toRefs} from 'vue'
|
||||
import {ElMessage, ElMessageBox, ElTree} from 'element-plus'
|
||||
import { getCurrentInstance } from 'vue'
|
||||
|
||||
import {getCurrentInstance} from 'vue'
|
||||
import {moneyFormatter} from '@/utils/filter'
|
||||
|
||||
const {proxy}: any = getCurrentInstance();
|
||||
@@ -126,62 +137,55 @@ const state = reactive({
|
||||
single: true,
|
||||
// 非多个禁用
|
||||
multiple: true,
|
||||
pagination: {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0
|
||||
},
|
||||
total: 0,
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
categoryId: undefined,
|
||||
page:1,
|
||||
limit:10,
|
||||
total: 0
|
||||
categoryId: undefined
|
||||
},
|
||||
pageList: [],
|
||||
categoryOptions: [],
|
||||
goodDetail: undefined,
|
||||
dialogVisible: false,
|
||||
cascaderProps:{emitPath:false,expandTrigger:'hover'}
|
||||
dialogVisible: false
|
||||
})
|
||||
|
||||
|
||||
function loadData() {
|
||||
loadCategoryOptions()
|
||||
handleQuery()
|
||||
}
|
||||
const {
|
||||
loading,
|
||||
ids,
|
||||
single,
|
||||
multiple,
|
||||
queryParams,
|
||||
pageList,
|
||||
categoryOptions,
|
||||
goodDetail,
|
||||
total,
|
||||
dialogVisible
|
||||
} = toRefs(state);
|
||||
|
||||
function loadCategoryOptions() {
|
||||
listCascadeCategories({}).then(response => {
|
||||
state.categoryOptions = ref(response.data)
|
||||
})
|
||||
}
|
||||
|
||||
function handleQuery() {
|
||||
state.queryParams.page = state.pagination.page
|
||||
state.queryParams.limit = state.pagination.limit
|
||||
page(state.queryParams).then(response => {
|
||||
const {data, total} = response
|
||||
function handleQuery() {
|
||||
state.loading = true
|
||||
listGoodsWithPage(state.queryParams).then(response => {
|
||||
const {data, total} = response as any
|
||||
state.pageList = data
|
||||
state.pagination.total = total ? total : 0
|
||||
state.total = total
|
||||
state.loading = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleReset() {
|
||||
state.pagination = {
|
||||
page: 1,
|
||||
limit: 10,
|
||||
total: 0
|
||||
}
|
||||
function resetQuery() {
|
||||
state.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
categoryId: undefined,
|
||||
queryMode: 'page'
|
||||
categoryId: undefined
|
||||
}
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
|
||||
function handleGoodsView(detail: any) {
|
||||
state.goodDetail = detail
|
||||
state.dialogVisible = true
|
||||
@@ -192,7 +196,7 @@ function handleAdd() {
|
||||
}
|
||||
|
||||
function handleUpdate(row: any) {
|
||||
proxy.$router.push({path: 'goods-detail', query: {goodsId: row.id}})
|
||||
proxy.$router.push({path: 'goods-detail', query: {goodsId: row.id,categoryId:row.categoryId}})
|
||||
}
|
||||
|
||||
function handleDelete(row: any) {
|
||||
@@ -202,13 +206,11 @@ function handleDelete(row: any) {
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(function () {
|
||||
return removeGoods(ids)
|
||||
return deleteGoods(ids)
|
||||
}).then(() => {
|
||||
ElMessage.success("删除成功")
|
||||
handleQuery()
|
||||
}).catch(() =>
|
||||
ElMessage.info("已取消删除")
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
function handleRowClick(row: any) {
|
||||
@@ -221,34 +223,11 @@ function handleSelectionChange(selection: any) {
|
||||
state.multiple = !selection.length
|
||||
}
|
||||
|
||||
function formatAlbum(val: any) {
|
||||
const album = JSON.parse(val);
|
||||
if (album && album.length > 0) {
|
||||
return album[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const {
|
||||
// 遮罩层
|
||||
loading,
|
||||
// 选中数组
|
||||
ids,
|
||||
// 非单个禁用
|
||||
single,
|
||||
// 非多个禁用
|
||||
multiple,
|
||||
pagination,
|
||||
queryParams,
|
||||
pageList,
|
||||
categoryOptions,
|
||||
goodDetail,
|
||||
dialogVisible,
|
||||
cascaderProps
|
||||
} = toRefs(state);
|
||||
|
||||
onMounted(()=>{
|
||||
loadData()
|
||||
onMounted(() => {
|
||||
listCascadeCategories({}).then(response => {
|
||||
state.categoryOptions = ref(response.data)
|
||||
})
|
||||
handleQuery()
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user