feat: 添加商品分类管理页面

This commit is contained in:
郝先瑞
2022-01-02 10:14:29 +08:00
parent 1bad64490d
commit 4dad286f18
5 changed files with 392 additions and 11 deletions

View File

@@ -1,6 +1,11 @@
import request from "@/utils/request";
export const list=(queryParams:object)=>{
/**
* 获取商品分类列表
*
* @param queryParams
*/
export function listCategories(queryParams:object){
return request({
url: '/mall-pms/api/v1/categories',
method: 'get',
@@ -8,7 +13,12 @@ export const list=(queryParams:object)=>{
})
}
export const cascadeList=(queryParams:object)=> {
/**
* 获取商品分类级联器树形列表
*
* @param queryParams
*/
export function listCascadeCategories(queryParams:object) {
return request({
url: '/mall-pms/api/v1/categories/cascade',
method: 'get',
@@ -16,16 +26,24 @@ export const cascadeList=(queryParams:object)=> {
})
}
export const detail=(id:number)=> {
/**
* 获取商品分类详情
*
* @param id
*/
export function getCategoryDetail(id:number){
return request({
url: '/mall-pms/api/v1/categories/' + id,
method: 'get'
})
}
export const add=(data:object)=> {
/**
* 添加商品分类
*
* @param data
*/
export function addCategory(data:object){
return request({
url: '/mall-pms/api/v1/categories',
method: 'post',
@@ -33,7 +51,13 @@ export const add=(data:object)=> {
})
}
export function update(id:number, data:object) {
/**
* 修改商品分类
*
* @param id
* @param data
*/
export function updateCategory(id:number, data:object) {
return request({
url: '/mall-pms/api/v1/categories/' + id,
method: 'put',
@@ -41,14 +65,25 @@ export function update(id:number, data:object) {
})
}
export function del(ids:string) {
/**
* 删除商品分类
*
* @param ids
*/
export function deleteCategories(ids:string) {
return request({
url: '/mall-pms/api/v1/categories/' + ids,
method: 'delete'
})
}
export function patch(id:number, data:object) {
/**
* 选择性修改商品分类
*
* @param id
* @param data
*/
export function updateCategoryPart(id:number, data:object) {
return request({
url: '/mall-pms/api/v1/categories/' + id,
method: 'patch',

View File

@@ -0,0 +1,13 @@
<template>
</template>
<script>
export default {
name: "Attribute"
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,278 @@
<!-- 商品分类层级最多为三层level字段标识 -->
<template>
<div class="component-container">
<el-tree
v-loading="loading"
ref="categoryTreeRef"
:data="categoryOptions"
:props="{ label: 'name', children: 'children' }"
node-key="id"
:expand-on-click-node="false"
default-expand-all
:accordion="true"
@node-click="handleNodeClick"
>
<template #default="scope">
<div class="custom-tree-node">
<span>
<el-image
v-show="scope.data.level == 3"
:src="scope.data.iconUrl"
style="width: 30px; height: 30px;
vertical-align: middle"
/>
{{ scope.data.name }}
</span>
<span>
<el-button
v-show="scope.data.level != 3 "
type="primary"
size="mini"
icon="Plus"
circle
plain
@click.stop="handleAdd(scope.data)"/>
<el-button
v-show="scope.data.id !== 0"
type="warning"
:icon="Edit"
size="mini"
circle
plain
@click.stop="handleUpdate(scope.data)"/>
<el-button
v-show="scope.data.id && (!scope.data.children || scope.data.children.length <= 0)"
type="danger"
size="mini"
:icon="Delete"
circle
plain
@click.stop="handleDelete(scope.node, scope.data)"/>
</span>
</div>
</template>
</el-tree>
<el-dialog
:title="dialog.title"
v-model="dialog.visible"
width="750px"
>
<el-form
ref="dataFormRef"
:model="formData"
:rules="rules"
>
<el-form-item label="上级分类" prop="parentId">
<el-input v-model="parent.name" readonly/>
</el-form-item>
<el-form-item label="分类名称" prop="name">
<el-input v-model="formData.name"/>
</el-form-item>
<el-form-item label="分类图标" prop="iconUrl">
<single-upload v-model="formData.iconUrl"/>
</el-form-item>
<el-form-item label="显示状态" prop="visible">
<el-radio-group v-model="formData.visible">
<el-radio :label="1">显示</el-radio>
<el-radio :label="0">隐藏</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort"></el-input>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import {listCategories, addCategory, updateCategory, deleteCategories} from '@/api/pms/category'
import {Search, Plus, Edit, Refresh, Delete} from '@element-plus/icons'
import SingleUpload from '@/components/Upload/SingleUpload.vue'
import {getCurrentInstance, onMounted, reactive, ref, toRefs, unref} from "vue";
import {ElForm, ElMessage, ElMessageBox, ElTree} from "element-plus";
const emit = defineEmits(['categoryClick'])
const categoryTreeRef=ref(ElTree)
const dataFormRef=ref(ElForm)
const state = reactive({
// 遮罩层
loading: true,
ids:[],
queryParam: {},
categoryOptions: [] as Array<any>,
formData: {
id: undefined,
name: undefined,
parentId: 0,
level: undefined,
iconUrl: undefined,
visible: 1,
sort: 100
},
rules: {
parentId: [{
required: true, message: '请选择上级分类', trigger: 'blur'
}],
name: [{
required: true, message: '请输入分类名称', trigger: 'blur'
}]
},
dialog: {
title: '',
visible: false
},
parent: {},
current: {}
})
const {loading, categoryOptions, formData, rules, dialog} = toRefs(state)
function handleQuery() {
state.loading = true
listCategories(state.queryParam).then(response => {
state.categoryOptions = [{
id: 0,
name: '全部分类',
parentId: 0,
level: 0,
children: response.data
}]
state.loading = false
})
}
function handleNodeClick(row:any) {
const categoryTree=unref(categoryTreeRef)
const parentNode = categoryTree.getNode(row.parentId)
state.parent = {
id: parentNode.key,
name: parentNode.label,
level: row.level
}
state.current = JSON.parse(JSON.stringify(row))
emit('categoryClick', row)
}
function handleAdd(row: any) {
resetForm()
state.dialog = {
title: '新增商品分类',
visible: true
}
if (row.id != null) { // 行点击新增
state.parent = {
id: row.id,
name: row.name,
level: row.level
}
}
}
function handleUpdate(row: any) {
resetForm()
handleNodeClick(row)
state.dialog = {
title: '修改商品分类',
visible: true
}
Object.assign( state.formData ,state.current)
}
function submitForm() {
const form = unref(dataFormRef)
form.validate((valid: any) => {
if (valid) {
if (state.formData.id) {
updateCategory(state.formData.id, state.formData).then(response => {
ElMessage.success('修改成功')
state.dialog.visible = false
handleQuery()
})
} else {
addCategory(state.formData).then(response => {
ElMessage.success('新增成功')
state.dialog.visible = false
handleQuery()
})
}
}
})
}
function handleDelete(row: any) {
const ids = [row.id || state.ids].join(',')
ElMessageBox.confirm('确认删除已选中的数据项?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteCategories(ids).then(() => {
ElMessage.success('删除成功')
handleQuery()
})
}).catch(() =>
ElMessage.info('已取消删除')
)
}
function resetForm() {
state.formData = {
id: undefined,
name: undefined,
parentId: 0,
level: undefined,
iconUrl: undefined,
visible: 1,
sort: 100
}
}
function cancel() {
resetForm()
state.dialog.visible = false
}
onMounted(() => {
handleQuery()
})
</script>
<style>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-tree-node__content {
height: 40px;
}
.el-divider--horizontal {
margin: 30px 0 15px;
}
</style>

View File

@@ -0,0 +1,55 @@
<template>
<div class="app-container">
<el-row :gutter="10">
<el-col :span="14" :xs="24">
<el-card class="box-card" shadow="always">
<template #header>
<svg-icon color="#333" icon-class="menu"/>
商品分类
</template>
<category ref="categoryRef" @categoryClick="handleCategoryClick"/>
</el-card>
</el-col>
<el-col :span="10" :xs="24">
<el-card class="box-card" shadow="always">
<template #header>
<svg-icon color="#333" icon-class="menu"/>
商品属性
</template>
<!-- 商品规格 -->
<attribute ref="specificationRef" :attributeType="1"/>
<!-- 商品属性 -->
<attribute ref="attributeRef" :attributeType="2"/>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script setup lang="ts">
import Category from './components/Category.vue'
import Attribute from './components/Attribute.vue'
import {reactive} from "vue";
const state = reactive({
categoryId: undefined,
categoryName: ''
})
function handleCategoryClick(categoryRow: any) {
if (categoryRow) {
state.categoryId = categoryRow.id
state.categoryName = categoryRow.name
} else {
state.categoryId = undefined
state.categoryName =''
}
}
</script>
<style scoped>
</style>

View File

@@ -108,7 +108,7 @@
<script setup lang="ts">
import {Search, Refresh} from '@element-plus/icons'
import {page, removeGoods} from '@/api/pms/goods'
import {cascadeList} from '@/api/pms/category'
import {listCascadeCategories} from '@/api/pms/category'
import {reactive, ref,onMounted, toRefs} from 'vue'
import {ElMessage, ElMessageBox, ElTree} from 'element-plus'
import { getCurrentInstance } from 'vue'
@@ -152,7 +152,7 @@ function loadData() {
}
function loadCategoryOptions() {
cascadeList({}).then(response => {
listCascadeCategories({}).then(response => {
state.categoryOptions = ref(response.data)
})
}