商品管理
(商品列表)
<template>
<div>
<!-- 面包屑导航区域 -->
<bread/>
<!-- 卡片视图区域 -->
<el-card>
<el-row :gutter="20">
<el-col :span="8">
<el-input placeholder="请输入内容" v-model="queryInfo.query" clearable @clear="getGoodsList">
<el-button slot="append" icon="el-icon-search" @click="getGoodsList"></el-button>
</el-input>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="goAddpage">添加商品</el-button>
</el-col>
</el-row>
<!-- table表格区域 -->
<el-table :data="goodslist" border stripe>
<el-table-column type="index"></el-table-column>
<el-table-column label="商品名称" prop="goods_name"></el-table-column>
<el-table-column label="商品价格(元)" prop="goods_price" width="95px"></el-table-column>
<el-table-column label="商品重量" prop="goods_weight" width="70px"></el-table-column>
<el-table-column label="创建时间" prop="add_time" width="140px">
<template slot-scope="scope">
{{scope.row.add_time | dateFormat}}
</template>
</el-table-column>
<el-table-column label="操作" width="130px">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" size="mini"></el-button>
<el-button type="danger" icon="el-icon-delete" size="mini" @click="removeById(scope.row.goods_id)"></el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页区域 -->
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="queryInfo.pagenum" :page-sizes="[5, 10, 15, 20]" :page-size="queryInfo.pagesize" layout="total, sizes, prev, pager, next, jumper" :total="total" background>
</el-pagination>
</el-card>
</div>
</template>
<script>
import bread from '../bread.vue'
export default {
components:{bread},
data() {
return {
// 查询参数对象
queryInfo: {
query: '',
pagenum: 1,
pagesize: 10
},
// 商品列表
goodslist: [],
// 总数据条数
total: 0
}
},
created() {
this.getGoodsList()
},
methods: {
// 根据分页获取对应的商品列表
async getGoodsList() {
const { data: res } = await this.$http.get('goods', {
params: this.queryInfo
})
if (res.meta.status !== 200) {
return this.$message.error('获取商品列表失败!')
}
this.$message.success('获取商品列表成功!')
console.log(res.data)
this.goodslist = res.data.goods
this.total = res.data.total
},
handleSizeChange(newSize) {
this.queryInfo.pagesize = newSize
this.getGoodsList()
},
handleCurrentChange(newPage) {
this.queryInfo.pagenum = newPage
this.getGoodsList()
},
async removeById(id) {
const confirmResult = await this.$confirm(
'此操作将永久删除该商品, 是否继续?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(err => err)
if (confirmResult !== 'confirm') {
return this.$message.info('已经取消删除!')
}
const { data: res } = await this.$http.delete(`goods/${id}`)
if (res.meta.status !== 200) {
return this.$message.error('删除失败!')
}
this.$message.success('删除成功!')
this.getGoodsList()
},
goAddpage() {
this.$router.push('/goods/add')
}
}
}
</script>
<style lang="scss" scoped>
</style>
(分类参数)
<template>
<div>
<!-- 面包屑导航区域 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品管理</el-breadcrumb-item>
<el-breadcrumb-item>参数列表</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片视图区域 -->
<el-card>
<!-- 警告区域 -->
<el-alert show-icon title="注意:只允许为第三级分类设置相关参数!" type="warning" :closable="false"></el-alert>
<!-- 选择商品分类区域 -->
<el-row class="cat_opt">
<el-col>
<span>选择商品分类:</span>
<!-- 选择商品分类的级联选择框 -->
<el-cascader expand-trigger="hover" :options="catelist" :props="cateProps" v-model="selectedCateKeys" @change="handleChange">
</el-cascader>
</el-col>
</el-row>
<!-- tab 页签区域 -->
<el-tabs v-model="activeName" @tab-click="handleTabClick">
<!-- 添加动态参数的面板 -->
<el-tab-pane label="动态参数" name="many">
<!-- 添加参数的按钮 -->
<el-button type="primary" size="mini" :disabled="isBtnDisabled" @click="addDialogVisible=true">添加参数</el-button>
<!-- 动态参数表格 -->
<el-table :data="manyTableData" border stripe>
<!-- 展开行 -->
<el-table-column type="expand">
<template slot-scope="scope">
<!-- 循环渲染Tag标签 -->
<el-tag v-for="(item, i) in scope.row.attr_vals" :key="i" closable @close="handleClose(i, scope.row)">{{item}}</el-tag>
<!-- 输入的文本框 -->
<el-input class="input-new-tag" v-if="scope.row.inputVisible" v-model="scope.row.inputValue" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(scope.row)" @blur="handleInputConfirm(scope.row)">
</el-input>
<!-- 添加按钮 -->
<el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
</template>
</el-table-column>
<!-- 索引列 -->
<el-table-column type="index"></el-table-column>
<el-table-column label="参数名称" prop="attr_name"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="primary" icon="el-icon-edit" @click="showEditDialog(scope.row.attr_id)">编辑</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete" @click="removeParams(scope.row.attr_id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<!-- 添加静态属性的面板 -->
<el-tab-pane label="静态属性" name="only">
<!-- 添加属性的按钮 -->
<el-button type="primary" size="mini" :disabled="isBtnDisabled" @click="addDialogVisible=true">添加属性</el-button>
<!-- 静态属性表格 -->
<el-table :data="onlyTableData" border stripe>
<!-- 展开行 -->
<el-table-column type="expand">
<template slot-scope="scope">
<!-- 循环渲染Tag标签 -->
<el-tag v-for="(item, i) in scope.row.attr_vals" :key="i" closable @close="handleClose(i, scope.row)">{{item}}</el-tag>
<!-- 输入的文本框 -->
<el-input class="input-new-tag" v-if="scope.row.inputVisible" v-model="scope.row.inputValue" ref="saveTagInput" size="small" @keyup.enter.native="handleInputConfirm(scope.row)" @blur="handleInputConfirm(scope.row)">
</el-input>
<!-- 添加按钮 -->
<el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
</template>
</el-table-column>
<!-- 索引列 -->
<el-table-column type="index"></el-table-column>
<el-table-column label="属性名称" prop="attr_name"></el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="primary" icon="el-icon-edit" @click="showEditDialog(scope.row.attr_id)">编辑</el-button>
<el-button size="mini" type="danger" icon="el-icon-delete" @click="removeParams(scope.row.attr_id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</el-card>
<!-- 添加参数的对话框 -->
<el-dialog :title="'添加' + titleText" :visible.sync="addDialogVisible" width="50%" @close="addDialogClosed">
<!-- 添加参数的对话框 -->
<el-form :model="addForm" :rules="addFormRules" ref="addFormRef" label-width="100px">
<el-form-item :label="titleText" prop="attr_name">
<el-input v-model="addForm.attr_name"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addParams">确 定</el-button>
</span>
</el-dialog>
<!-- 修改参数的对话框 -->
<el-dialog :title="'修改' + titleText" :visible.sync="editDialogVisible" width="50%" @close="editDialogClosed">
<!-- 添加参数的对话框 -->
<el-form :model="editForm" :rules="editFormRules" ref="editFormRef" label-width="100px">
<el-form-item :label="titleText" prop="attr_name">
<el-input v-model="editForm.attr_name"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="editDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="editParams">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import paramsApi from "../../api/goods.js/params";
export default {
data() {
return {
// 商品分类列表
catelist: [],
// 级联选择框的配置对象
cateProps: {
value: 'cat_id',
label: 'cat_name',
children: 'children'
},
// 级联选择框双向绑定到的数组
selectedCateKeys: [],
// 被激活的页签的名称
activeName: 'many',
// 动态参数的数据
manyTableData: [],
// 静态属性的数据
onlyTableData: [],
// 控制添加对话框的显示与隐藏
addDialogVisible: false,
// 添加参数的表单数据对象
addForm: {
attr_name: ''
},
// 添加表单的验证规则对象
addFormRules: {
attr_name: [
{ required: true, message: '请输入参数名称', trigger: 'blur' }
]
},
// 控制修改对话框的显示与隐藏
editDialogVisible: false,
// 修改的表单数据对象
editForm: {},
// 修改表单的验证规则对象
editFormRules: {
attr_name: [
{ required: true, message: '请输入参数名称', trigger: 'blur' }
]
}
}
},
created() {
this.getCateList()
},
methods: {
// 获取所有的商品分类列表
async getCateList() {
// const { data: res } = await this.$http.get('categories')
const { data: res } = await paramsApi.getCateList()
console.log(res);
if (res.meta.status !== 200) {
return this.$message.error('获取商品分类失败!')
}
this.catelist = res.data
console.log(this.catelist)
},
// 级联选择框选中项变化,会触发这个函数
handleChange() {
this.getParamsData()
},
// tab 页签点击事件的处理函数
handleTabClick() {
console.log(this.activeName)
this.getParamsData()
},
// 获取参数的列表数据
async getParamsData() {
// 证明选中的不是三级分类
if (this.selectedCateKeys.length !== 3) {
this.selectedCateKeys = []
this.manyTableData = []
this.onlyTableData = []
return
}
// 证明选中的是三级分类
console.log(this.selectedCateKeys)
// 根据所选分类的Id,和当前所处的面板,获取对应的参数
// const { data: res } = await this.$http.get(
// `categories/${this.cateId}/attributes`,
// {
// params: { sel: this.activeName }
// }
// )
const { data: res } = paramsApi.getParamsData(
this.cateId,
{
params: { sel: this.activeName }
}
)
if (res.meta.status !== 200) {
return this.$message.error('获取参数列表失败!')
}
res.data.forEach(item => {
item.attr_vals = item.attr_vals ? item.attr_vals.split(' ') : []
// 控制文本框的显示与隐藏
item.inputVisible = false
// 文本框中输入的值
item.inputValue = ''
})
console.log(res.data)
if (this.activeName === 'many') {
this.manyTableData = res.data
} else {
this.onlyTableData = res.data
}
},
// 监听添加对话框的关闭事件
addDialogClosed() {
this.$refs.addFormRef.resetFields()
},
// 点击按钮,添加参数
addParams() {
this.$refs.addFormRef.validate(async valid => {
if (!valid) return
// const { data: res } = await this.$http.post(
// `categories/${this.cateId}/attributes`,
// {
// attr_name: this.addForm.attr_name,
// attr_sel: this.activeName
// }
// )
const { data: res } = await paramsApi.addParams(
this.cateId,
{
attr_name: this.addForm.attr_name,
attr_sel: this.activeName
}
)
if (res.meta.status !== 201) {
return this.$message.error('添加参数失败!')
}
this.$message.success('添加参数成功!')
this.addDialogVisible = false
this.getParamsData()
})
},
// 点击按钮,展示修改的对话框
async showEditDialog(attr_id) {
// 查询当前参数的信息
const { data: res } = await this.$http.get(
`categories/${this.cateId}/attributes/${attr_id}`,
{
params: { attr_sel: this.activeName }
}
)
if (res.meta.status !== 200) {
return this.$message.error('获取参数信息失败!')
}
this.editForm = res.data
this.editDialogVisible = true
},
// 重置修改的表单
editDialogClosed() {
this.$refs.editFormRef.resetFields()
},
// 点击按钮,修改参数信息
editParams() {
this.$refs.editFormRef.validate(async valid => {
if (!valid) return
const { data: res } = await this.$http.put(
`categories/${this.cateId}/attributes/${this.editForm.attr_id}`,
{ attr_name: this.editForm.attr_name, attr_sel: this.activeName }
)
if (res.meta.status !== 200) {
return this.$message.error('修改参数失败!')
}
this.$message.success('修改参数成功!')
this.getParamsData()
this.editDialogVisible = false
})
},
// 根据Id删除对应的参数项
async removeParams(attr_id) {
const confirmResult = await this.$confirm(
'此操作将永久删除该参数, 是否继续?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
).catch(err => err)
// 用户取消了删除的操作
if (confirmResult !== 'confirm') {
return this.$message.info('已取消删除!')
}
// 删除的业务逻辑
const { data: res } = await this.$http.delete(
`categories/${this.cateId}/attributes/${attr_id}`
)
if (res.meta.status !== 200) {
return this.$message.error('删除参数失败!')
}
this.$message.success('删除参数成功!')
this.getParamsData()
},
// 文本框失去焦点,或摁下了 Enter 都会触发
async handleInputConfirm(row) {
if (row.inputValue.trim().length === 0) {
row.inputValue = ''
row.inputVisible = false
return
}
// 如果没有return,则证明输入的内容,需要做后续处理
row.attr_vals.push(row.inputValue.trim())
row.inputValue = ''
row.inputVisible = false
// 需要发起请求,保存这次操作
this.saveAttrVals(row)
},
// 将对 attr_vals 的操作,保存到数据库
async saveAttrVals(row) {
// 需要发起请求,保存这次操作
const { data: res } = await this.$http.put(
`categories/${this.cateId}/attributes/${row.attr_id}`,
{
attr_name: row.attr_name,
attr_sel: row.attr_sel,
attr_vals: row.attr_vals.join(' ')
}
)
if (res.meta.status !== 200) {
return this.$message.error('修改参数项失败!')
}
this.$message.success('修改参数项成功!')
},
// 点击按钮,展示文本输入框
showInput(row) {
row.inputVisible = true
// 让文本框自动获得焦点
// $nextTick 方法的作用,就是当页面上元素被重新渲染之后,才会指定回调函数中的代码
this.$nextTick(() => {
this.$refs.saveTagInput.$refs.input.focus()
})
},
// 删除对应的参数可选项
handleClose(i, row) {
row.attr_vals.splice(i, 1)
this.saveAttrVals(row)
}
},
computed: {
// 如果按钮需要被禁用,则返回true,否则返回false
isBtnDisabled() {
if (this.selectedCateKeys.length !== 3) {
return true
}
return false
},
// 当前选中的三级分类的Id
cateId() {
if (this.selectedCateKeys.length === 3) {
return this.selectedCateKeys[2]
}
return null
},
// 动态计算标题的文本
titleText() {
if (this.activeName === 'many') {
return '动态参数'
}
return '静态属性'
}
}
}
</script>
<style lang="scss" scoped>
.cat_opt {
margin: 15px 0;
}
.el-tag {
margin: 10px;
}
.input-new-tag {
width: 120px;
}
</style>
(api)param.js
import request from '../../utile/axios'
export default{
getCateList(){
return request.get('categories')
},
getParamsData(cateId,activeName){
return request.get( `categories/${cateId}/attributes`,activeName)
},
addParams(cateId,attr_name,activeName){
return request.post( `categories/${cateId}/attributes`,attr_name,activeName)
}
}
(商品分类)
<template>
<div>
<bread />
<!-- 卡片试图 -->
<el-card>
<el-row>
<el-col>
<el-button type="primary" @click="showAddCate">添加分类</el-button>
</el-col>
</el-row>
<!-- 表格 -->
<tree-table
:data="cateList"
:columns="columns"
:selection-type="false"
:expand-type="false"
show-index
index-text="#"
border
class="treeTable"
>
<!-- 是否有效 -->
<tmplate slot="isOk" slot-scope="scope">
<i
class="el-icon-success"
style="color:lightgreen;"
v-if="scope.row.cat_deleted === false"
></i>
<i class="el-icon-error" style="color:red;" v-else></i>
</tmplate>
<!-- 排序 -->
<template slot="order" slot-scope="scope">
<el-tag size="mini" v-if="scope.row.cat_level===0">一级</el-tag>
<el-tag size="mini" type="success" v-else-if="scope.row.cat_level===1">二级</el-tag>
<el-tag size="mini" type="warning" v-else>三级</el-tag>
</template>
<!-- 操作 -->
<template slot="opt" slot-scope="scope">
<el-button type="primary" size="mini" icon="el-icon-edit" @click="editDate(scope.row)">编辑</el-button>
<el-button type="danger" size="mini" icon="el-icon-delete" @click="del(scope.row)">删除</el-button>
</template>
</tree-table>
<!-- 分页区域 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="querInfo.pagenum"
:page-sizes="[3, 5, 10, 15]"
:page-size="querInfo.pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</el-card>
<!-- 添加分类 对话框-->
<el-dialog
title="添加分类"
:visible.sync="addCateDialogVisible"
width="50%"
@close="addCateDialogClosed"
>
<el-form
:model="addCateForm"
:rules="addCateFormRules"
ref="addCateFormRef"
label-width="100px"
>
<el-form-item label="分类名称:" prop="cat_name">
<el-input v-model="addCateForm.cat_name"></el-input>
</el-form-item>
<el-form-item label="父级分类:">
<el-cascader
expand-trigger="hover"
:options="parentCateList"
:props="cascaderProps"
v-model="selectedKeys"
@change="parentCateChanged"
clearable
change-on-select
></el-cascader>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addCateDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addCate">确 定</el-button>
</span>
</el-dialog>
<!-- 编辑对话框 -->
<el-dialog title="提示" :visible.sync="EditDialogVisibleDate" width="30%">
<el-form
:model="editRuleForm"
:rules="editRules"
ref="editRef"
label-width="100px"
class="demo-ruleForm"
>
<el-form-item label="分类名称" prop="cat_name">
<el-input v-model="editRuleForm.cat_name"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="EditDialogVisibleDate = false">取 消</el-button>
<el-button type="primary" @click="editSure">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import bread from "../bread.vue";
import cateApi from "../../api/goods.js/categories";
export default {
components: { bread },
data() {
return {
// 修改
editRuleForm: {},
// 商品分类的数据列表,默认为空
cateList: [],
// 查询条件
querInfo: {
type: 3,
pagenum: 1,
pagesize: 5
},
// 总数据条数
total: 0,
// 为table指定列的名称
columns: [
{
label: "分类名称",
prop: "cat_name"
},
{
label: "是否有效",
// 表示,当前列为模板列
type: "template",
// 表示当前这一列使用模板名称
template: "isOk"
},
{
label: "排序",
// 表示,当前列为模板列
type: "template",
// 表示当前这一列使用模板名称
template: "order"
},
{
label: "操作",
// 表示,当前列为模板列
type: "template",
// 表示当前这一列使用模板名称
template: "opt"
}
],
addCateDialogVisible: false,
// 添加表单分类的数据对象
addCateForm: {
// 将要添加分类的名称
cat_name: "",
cat_pid: 0,
// 分类的等级,默认添加的一级分类
cat_level: 0
},
// 添加分类表单的验证规则对象
addCateFormRules: {
cat_name: [
{ required: true, message: "请输入添加分类的名称", trigger: "blur" },
{ min: 3, max: 10, message: "长度在 3 到 10 个字符", trigger: "blur" }
]
},
// 父级分类的列表
parentCateList: [],
// 指定级联选择器的配置选择器
cascaderProps: {
value: "cat_id",
label: "cat_name",
children: "children"
},
// 选中的父级分类的id数组
selectedKeys: [],
EditDialogVisibleDate: false,
editRules: {
cat_name: [
{ required: true, message: "请输入活动名称", trigger: "blur" },
{ min: 3, max: 10, message: "长度在 3 到 10 个字符", trigger: "blur" }
]
}
};
},
mounted() {
this.getCateList();
},
methods: {
// 获取商品分类数据
async getCateList() {
// const { data: res } = await this.$http.get("categories", {
// params: this.querInfo
// });
const { data: res } = await cateApi.getCateList({
params: this.querInfo
});
if (res.meta.status !== 200) {
return this.$message.error("获取商品分类失败");
}
console.log(res.data);
// 把数据列表赋值给列表
this.cateList = res.data.result;
// 为总数居条数赋值
this.total = res.data.total;
},
// 监听pagesize改变事件
handleSizeChange(newSize) {
this.querInfo.pagesize = newSize;
this.getCateList();
},
// 监听pagenum改变事件
handleCurrentChange(newPage) {
this.querInfo.pagenum = newPage;
this.getCateList();
},
// 点击按钮 弹框显示
showAddCate() {
this.getParentCateList();
this.addCateDialogVisible = true;
},
// 获取父级分类的数据列表
async getParentCateList() {
// const { data: res } = await this.$http.get("categories", {
// params: { type: 2 }
// });
const { data: res } = await cateApi.getParentList({
params: { type: 2 }
});
if (res.meta.status !== 200) {
return this.$message.error("获取父级分类数据失败");
}
this.parentCateList = res.data;
},
// 选择项发生变化触发这个函数
parentCateChanged() {
console.log(this.selectedKeys);
// 如果selectedKey 数组中的length 大于0 证明选中的父级分类
// 反之 ,就说明没有选中任何父级分类
if (this.selectedKeys.length > 0) {
// 父级分类id
this.addCateForm.cat_pid = this.selectedKeys[
this.selectedKeys.length - 1
];
this.addCateForm.cat_level = this.selectedKeys.length;
return;
} else {
this.addCateForm.cat_pid = 0;
this.addCateForm.cat_level = 0;
}
},
// 点击按钮 添加分类
addCate() {
this.$refs.addCateFormRef.validate(async valid => {
if (!valid) return;
// const { data: res } = await this.$http.post(
// "categories",
// this.addCateForm
// );
const { data: res } = await cateApi.addCate(this.addCateForm);
console.log(res);
if (res.meta.status !== 201) {
return this.$message.error("添加分类失败");
}
this.$message.success("添加分类成功");
this.getCateList();
this.addCateDialogVisible = false;
});
},
// 监听对话框关闭事件 重置表单
addCateDialogClosed() {
this.$refs.addCateFormRef.resetFields();
this.selectedKeys = [];
this.addCateForm.cat_level = 0;
this.addCateForm.cat_pid = 0;
},
// 控制编辑的对话框
async editDate(scope) {
this.EditDialogVisibleDate = true;
console.log(scope);
this.editRuleForm = scope;
console.log(this.editRuleForm);
},
editSure() {
this.$refs.editRef.validate(async valid => {
console.log(valid);
if (!valid) return;
// const { data: res } = await this.$http.put(
// `categories/${this.editRuleForm.cat_id}`,
// this.editRuleForm
// );
const { data: res } = await cateApi.editSure(
this.editRuleForm.cat_id,
this.editRuleForm
);
if (res.meta.status !== 200) {
this.$message.error("修改失败");
}
this.$message.success("修改成功");
this.getCateList();
});
this.EditDialogVisibleDate = false;
},
// 删除
async del(scope) {
console.log(scope);
const result = await this.$confirm(
"此操作将永久删除该用户, 是否继续?",
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}
).catch(err => err);
console.log(result);
/*
$confirm方法返回的是一个Promise对象,可以通过async/await的方式结束返回值;
如果返回值的结果是cancel证明点击的是取消按钮;
如果返回值的结果是confirm证明点击的是确定按钮
*/
if (result === "cancel") {
// 证明咱们现在点击的是取消按钮
return;
} else if (result === "confirm") {
// 证明点击的是确定按钮
// const res = await this.$http.delete(`categories/${scope.cat_id}`);
const res = await cateApi.del(scope.cat_id);
console.log(res);
const { meta } = res.data;
if (meta.status !== 200) {
this.$message.error(meta.msg);
} else {
this.$message.success("用户删除成功");
// 重新向服务器发起请求,获取最新用户列表数据
this.getCateList();
}
}
}
},
computed: {},
watch: {}
};
</script>
<style>
.el-card {
border-radius: 5px;
margin-top: 20px;
}
.treeTable {
margin-top: 15px;
}
.el-cascader {
width: 100%;
}
</style>
<template>
<div>
<!-- 面包屑导航区域 -->
<el-breadcrumb separator-class="el-icon-arrow-right">
<el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
<el-breadcrumb-item>商品管理</el-breadcrumb-item>
<el-breadcrumb-item>添加商品</el-breadcrumb-item>
</el-breadcrumb>
<!-- 卡片视图 -->
<el-card>
<!-- 提示区域 -->
<el-alert title="添加商品信息" type="info" center show-icon :closable="false"></el-alert>
<!-- 步骤条区域 -->
<el-steps :space="200" :active="activeIndex - 0" finish-status="success" align-center>
<el-step title="基本信息"></el-step>
<el-step title="商品参数"></el-step>
<el-step title="商品属性"></el-step>
<el-step title="商品图片"></el-step>
<el-step title="商品内容"></el-step>
<el-step title="完成"></el-step>
</el-steps>
<!-- tab栏区域 -->
<el-form
:model="addForm"
:rules="addFormRules"
ref="addFormRef"
label-width="100px"
label-position="top"
>
<el-tabs
v-model="activeIndex"
:tab-position="'left'"
:before-leave="beforeTabLeave"
@tab-click="tabClicked"
>
<el-tab-pane label="基本信息" name="0">
<el-form-item label="商品名称" prop="goods_name">
<el-input v-model="addForm.goods_name"></el-input>
</el-form-item>
<el-form-item label="商品价格" prop="goods_price">
<el-input v-model="addForm.goods_price" type="number"></el-input>
</el-form-item>
<el-form-item label="商品重量" prop="goods_weight">
<el-input v-model="addForm.goods_weight" type="number"></el-input>
</el-form-item>
<el-form-item label="商品数量" prop="goods_number">
<el-input v-model="addForm.goods_number" type="number"></el-input>
</el-form-item>
<el-form-item label="商品分类" prop="goods_cat">
<el-cascader
expand-trigger="hover"
:options="catelist"
:props="cateProps"
v-model="addForm.goods_cat"
@change="handleChange"
></el-cascader>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="商品参数" name="1">
<!-- 渲染表单的Item项 -->
<el-form-item :label="item.attr_name" v-for="item in manyTableData" :key="item.attr_id">
<!-- 复选框组 -->
<el-checkbox-group v-model="item.attr_vals">
<el-checkbox :label="cb" v-for="(cb, i) in item.attr_vals" :key="i" border></el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="商品属性" name="2">
<el-form-item :label="item.attr_name" v-for="item in onlyTableData" :key="item.attr_id">
<el-input v-model="item.attr_vals"></el-input>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="商品图片" name="3">
<el-upload
:action="uploadURL"
:on-preview="handlePreview"
:on-remove="handleRemove"
list-type="picture"
:headers="headerObj"
:on-success="handleSuccess"
>
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</el-tab-pane>
<el-tab-pane label="商品内容" name="4">
<!-- 富文本编辑器组件 -->
<quill-editor v-model="addForm.goods_introduce"></quill-editor>
<!-- 添加商品的按钮 -->
<el-button type="primary" class="btn_add" @click="add">添加商品</el-button>
</el-tab-pane>
</el-tabs>
</el-form>
</el-card>
<!-- 图片预览弹出框 -->
<el-dialog title="图片预览" :visible.sync="previewVisible" width="50%">
<img :src="previewPath" alt class="previewImg" />
</el-dialog>
</div>
</template>
<script>
import _ from "lodash";
export default {
data() {
return {
activeIndex: "0",
// 添加商品的表单数据对象
addForm: {
goods_name: "",
goods_price: 0,
goods_weight: 0,
goods_number: 0,
// 商品所属的分类数组
goods_cat: [],
pics: [],
// 商品的详情描述
goods_introduce: "",
attrs: []
},
addFormRules: {
goods_name: [
{ required: true, message: "请输入商品名称", trigger: "blur" }
],
goods_price: [
{ required: true, message: "请输入商品价格", trigger: "blur" }
],
goods_weight: [
{ required: true, message: "请输入商品重量", trigger: "blur" }
],
goods_number: [
{ required: true, message: "请输入商品数量", trigger: "blur" }
],
goods_cat: [
{ required: true, message: "请选择商品分类", trigger: "blur" }
]
},
// 商品分类列表
catelist: [],
cateProps: {
label: "cat_name",
value: "cat_id",
children: "children"
},
// 动态参数列表数据
manyTableData: [],
// 静态属性列表数据
onlyTableData: [],
// 上传图片的文件地址
uploadURL: "https://www.liulongbin.top:8888/api/private/v1/upload",
//图片上传组件的请求头
headerObj: {
Authorization: window.sessionStorage.getItem("token")
},
// 图片的数组
previewPath: "",
previewVisible: false
// 商品的详情描述
};
},
created() {
this.getCateList();
},
methods: {
// 获取所有商品分类数据
async getCateList() {
const { data: res } = await this.$http.get("categories");
if (res.meta.status !== 200) {
return this.$message.error("获取商品分类数据失败!");
}
console.log(res.data);
this.catelist = res.data;
console.log(this.catelist);
},
// 级联选择器选中项变化,会触发这个函数
handleChange() {
console.log(this.addForm.goods_cat);
if (this.addForm.goods_cat.length !== 3) {
this.addForm.goods_cat = [];
}
},
beforeTabLeave(activeName, oldActiveName) {
// console.log('即将离开的标签页名字是:' + oldActiveName)
// console.log('即将进入的标签页名字是:' + activeName)
// return false
if (oldActiveName === "0" && this.addForm.goods_cat.length !== 3) {
this.$message.error("请先选择商品分类!");
return false;
}
},
async tabClicked() {
// console.log(this.activeIndex)
// 证明访问的是动态参数面板
if (this.activeIndex === "1") {
const { data: res } = await this.$http.get(
`categories/${this.cateId}/attributes`,
{
params: { sel: "many" }
}
);
if (res.meta.status !== 200) {
return this.$message.error("获取动态参数列表失败!");
}
console.log(res.data);
res.data.forEach(item => {
item.attr_vals =
item.attr_vals.length === 0 ? [] : item.attr_vals.split(" ");
});
this.manyTableData = res.data;
} else if (this.activeIndex === "2") {
const { data: res } = await this.$http.get(
`categories/${this.cateId}/attributes`,
{
params: { sel: "only" }
}
);
if (res.meta.status !== 200) {
return this.$message.error("获取静态属性失败!");
}
console.log(res.data);
this.onlyTableData = res.data;
}
},
// 处理图片的预览结果
handlePreview(file) {
this.previewPath = file.response.data.url;
this.previewVisible = true;
},
// 处理移出图片的操作
handleRemove(file) {
const filePath = file.response.data.tmp_path;
const i = this.addForm.pics.findIndex(x => x.pic === filePath);
this.addForm.pics.splice(i, 1);
},
// 监听图片上传成功的事件
handleSuccess(response) {
// 1.拼接得到一个图片信息对象
// 2 讲图片信息对象,push到pics中
const picInfo = { pic: response.data.tmp_path };
this.addForm.pics.push(picInfo);
},
// 添加商品
add() {
this.$refs.addFormRef.validate(async (valid) => {
if (!valid) {
return this.$message.error("请填写必要的表单项");
}
// 否则就执行相应的业务逻辑
// 先把addForm深拷贝一份,否则会与级联选择器绑定的goods_cat发生矛盾
const form = _.cloneDeep(this.addForm);
form.goods_cat = form.goods_cat.join(",");
// 处理动态参数
this.manyTableData.forEach((item) => {
const newInfo = {
attr_id: item.attr_id,
attr_value: item.attr_vals.join(","),
};
this.addForm.attrs.push(newInfo);
});
// 处理静态属性
this.onlyTableData.forEach((item) => {
const newInfo = {
attr_id: item.attr_id,
attr_value: item.attr_vals,
};
this.addForm.attrs.push(newInfo);
});
form.attrs = this.addForm.attrs;
// 请求添加商品的接口数据
const { data: res } = await this.$http.post("goods", form);
if (res.meta.status != 201) {
return this.$message.error("添加商品失败");
}
this.$message.success("添加商品成功");
this.$router.push("/goods");
});
},
// add() {
// this.$refs.addFormRef.validate(async valid => {
// if (!valid) {
// return this.$message.error("请填写必要的表单项");
// }
// // 执行添加的业务逻辑
// const form = _.cloneDeep(this.addForm);
// form.goods_cat = form.goods_cat.join(',');
// // 处理动态参数
// this.manyTableData.forEach(item => {
// const newInfo = {
// attr_id: item.attr_id,
// attr_value: item.attr_vals.join('')
// };
// this.addForm.attrs.push(newInfo);
// });
// // 处理静态属性
// this.onlyTableData.forEach(item => {
// const newInfo = { attr_id: item.attr_id, attr_value: item.attr_vals };
// this.addForm.attrs.push(newInfo);
// });
// form.attrs = this.addForm.attrs;
// // 发起请求添加商品
// // 商品的名称,必须是唯一的
// const {data:res}= await this.$http.post('goods',form)
// if(res.meta.status !== 201){
// return this.$message.error('添加商品失败')
// }
// this.$message.success('添加商品成功!')
// this.$router.push('/goods')
// });
// }
},
computed: {
cateId() {
if (this.addForm.goods_cat.length === 3) {
return this.addForm.goods_cat[2];
}
return null;
}
}
};
</script>
<style lang="scss" scoped>
.el-checkbox {
margin: 0 10px 0 0 !important;
}
.previewImg {
width: 100%;
}
.btn_add {
margin-top: 15px;
}
</style>
(api)categories.js
import request from '../../utile/axios'
export default{
getCateList(querInfo){
return request.get('/categories',querInfo)
},
getParentList(type){
return request.get('/categories',type)
},
addCate(addCateForm){
return request.post('/categories',addCateForm)
},
editSure(cat_id,editRuleForm){
return request.put('/categories',cat_id,editRuleForm)
},
del(cat_id){
return request.delete(`/categories/${cat_id}`,)
}
}
订单管理
(订单列表)
<template>
<div>
<!-- 面包屑导航 -->
<bread></bread>
<!-- 卡片区域 -->
<el-card>
<el-row>
<el-col :span="8">
<el-input
placeholder="请输入内容"
v-model="ordersInfo.query"
class="input-with-select"
>
<el-button
slot="append"
icon="el-icon-search"
@click="getList"
></el-button>
</el-input>
</el-col>
</el-row>
<!-- 表格区域 -->
<el-table :data="ordersList" border style="width: 100%">
<el-table-column type="index" label="#"> </el-table-column>
<el-table-column prop="order_number" label="订单编号">
</el-table-column>
<el-table-column prop="order_price" label="订单价格"> </el-table-column>
<el-table-column label="是否付款">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.pay_status === '1'"
>已付款</el-tag
>
<el-tag type="danger" v-else>未付款</el-tag>
</template>
</el-table-column>
<el-table-column prop="is_send" label="是否发货"></el-table-column>
<el-table-column label="下单时间">
<template v-slot="data">
<span>
{{ data.row.create_time | formatDate }}
</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template>
<!-- 修改地址按钮 -->
<el-tooltip
class="item"
effect="dark"
content="修改订单地址"
placement="top"
>
<el-button
type="primary"
icon="el-icon-edit"
size="mini"
@click="editAddress"
></el-button>
</el-tooltip>
<!-- 物流信息 -->
<el-tooltip
class="item"
effect="dark"
content="物流信息"
placement="top"
>
<el-button
type="success"
icon="el-icon-location-outline"
size="mini"
@click="logistics"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<!-- 分页区域 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="ordersInfo.pagenum"
:page-sizes="[10, 20, 30, 40]"
:page-size="ordersInfo.pagesize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</el-card>
<!-- 修改地址的对话框 -->
<el-dialog title="修改地址" :visible.sync="editShow" @close="closedDialog">
<el-form :model="editData" :rules="rules" ref="editForm">
<el-form-item label="省市区/县" :label-width="'100px'" prop="address1">
<el-cascader
v-model="editData.address1"
:options="cityData"
style="width: 100%"
></el-cascader>
</el-form-item>
<el-form-item label="详细地址" :label-width="'100px'" prop="address2">
<el-input autocomplete="off" v-model="editData.address2"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="editShow = false">取 消</el-button>
<el-button type="primary" @click="editShow = false">确 定</el-button>
</div>
</el-dialog>
<!-- 物流弹窗 -->
<el-dialog title="物流进度" :visible.sync="dialogVisible" width="5 0%">
<el-timeline>
<el-timeline-item
v-for="(activity, index) in logisticsList"
:key="index"
:timestamp="activity.time"
>
{{ activity.context }}
</el-timeline-item>
</el-timeline>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
</div>
</template>
<script>
import bread from "../bread.vue";
import cityData from "./data.js";
// import usersApi from "..//../api/orders";
// import report from '../../api/report';
import orders from '..//../api/orders';
export default {
components: { bread },
data() {
return {
ordersInfo: {
query: "", //查询参数
pagenum: 1, //当前页码
pagesize: 10, //每页显示条数
},
ordersList: [],
total: 0, //数据总条数
dialogVisible: false, //物流数据弹窗
reverse: true,
logisticsList: [], //物流数据信息
editShow: false,
activities: [
{
content: "活动按期开始",
timestamp: "2018-04-15",
},
{
content: "通过审核",
timestamp: "2018-04-13",
},
{
content: "创建成功",
timestamp: "2018-04-11",
},
],
editData: {
//修改的相关数据
address1: [],
address2: "",
},
rules: {
address1: [
{ required: true, message: "请选择省市区县", trigger: "blur" },
],
address2: [
{ required: true, message: "请填写详细地址", trigger: "blur" },
],
},
cityData: cityData,
};
},
created() {
this.getList();
},
methods: {
//获取列表数据
async getList() {
let res = await orders.getList({ params: this.ordersInfo });
let { data, meta } = res.data;
this.total = data.total;
if (meta.status !== 200) {
this.$message.error(meta.msg);
} else {
this.ordersList = data.goods;
}
},
handleSizeChange(val) {
this.ordersInfo.pagesize = val;
this.getList();
},
handleCurrentChange(val) {
this.ordersInfo.pagenum = val;
this.getList();
},
async logistics() {
// let res = await this.$http.get("/kuaidi/1106975712662");
let res = await orders.logistics();
let { data } = res.data;
this.logisticsList = data;
this.dialogVisible = true;
},
// 关闭修改地址的对话框
closedDialog() {
this.$refs.editForm.resetFields();
},
// 点击修改地址的操作按钮
editAddress() {
this.editShow = true;
},
// 展示物流进度的对话框
async showProgress() {
this.progressShow = true; //显示物流信息对话框
// 请求物流信息数据
// const { data: res } = await this.$http.get("kuaidi/${id}");
const { data: res } = await orders.showProgress();
console.log(res);
if (res.meta.status !== 200) {
return this.$message.error("获取物流进度失败");
}
this.progressData = res.data;
},
},
filters: {
//过滤器
//时间戳转日期
formatDate: function(value) {
let date = new Date(value * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
let y = date.getFullYear();
let MM = date.getMonth() + 1;
MM = MM < 10 ? "0" + MM : MM;
let d = date.getDate();
d = d < 10 ? "0" + d : d;
let h = date.getHours();
h = h < 10 ? "0" + h : h;
let m = date.getMinutes();
m = m < 10 ? "0" + m : m;
let s = date.getSeconds();
s = s < 10 ? "0" + s : s;
return y + "-" + MM + "-" + d + " " + h + ":" + m + ":" + s; //多种时间格式的拼接
// return y + "-" + MM + "-" + d;
},
},
// components: {
// bread,
// },
};
</script>
<style lang="scss" scoped>
.el-row {
margin-bottom: 10px;
}
.el-card {
border-radius: 5px;
margin-top: 20px;
}
</style>
模拟的data.js
(api)order.js
import request from '../utile/axios'
export default{
getList(ordersInfo){
return request.get('/orders',ordersInfo)
},
logistics(){
return request.get('/kuaidi/1106975712662')
},
showProgress(){
return request.get('kuaidi/${id}"')
}
}
数据统计
<template>
<div class="reports-wrapper">
<!-- 面包屑导航 -->
<bread/>
<!-- 卡片视图区域 -->
<el-card>
<!-- 2. 准备一个容器 -->
<div id="main" style="width: 750px; height: 400px"></div>
</el-card>
</div>
</template>
<script>
import reportApi from "..//../api/report";
// 1. 引入echarts
const echarts = require("echarts");
import _ from 'lodash';
import bread from '../bread.vue'
export default {
components:{bread},
data() {
return {
// 4. 指定图表的配置项和数据
option: {
title: {
text: "用户来源",
},
tooltip: {
trigger: "axis",
axisPointer: {
type: "cross",
label: {
backgroundColor: "#E9EEF3",
},
},
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
},
xAxis: [
{
boundaryGap: false,
},
],
yAxis: [
{
type: "value",
},
],
}
}
},
async mounted() {
// 当DOM元素加载完毕以后
// console.log(echarts)
// 3. 基于准备好的dom,初始化echarts实例
const myChart = echarts.init(document.getElementById("main"));
// const res = await this.$http.get('reports/type/1');
const res = await reportApi.mounted();
const { data, meta } = res.data;
if(meta.status !== 200) {
this.$message.error(meta.msg)
} else {
// 合并对象
// const obj = Object.assign(data, this.option);
const obj = _.merge(data, this.option);
myChart.setOption(obj);
}
},
};
</script>
<style lang="scss" scoped>
.el-card {
margin-top: 15px;
}
</style>
(api)report.js
import request from '../utile/axios'
export default{
mounted(){
return request.get('reports/type/1')
}
}