搭建后台系统基本前端页面

develop
ddyd 2 weeks ago
parent b60915d02c
commit 3598f265b2

@ -1,4 +1,11 @@
package com.bookstore.bookmall.product.config;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@MapperScan("com.baomidou.cloud.service.*.mapper")
public class MybatisConfig {
}

@ -0,0 +1,80 @@
<template>
<div>
<el-select placeholder="请选择" v-model="brandId" filterable clearable>
<el-option
v-for="item in brands"
:key="item.brandId"
:label="item.brandName"
:value="item.brandId"
></el-option>
</el-select>
</div>
</template>
<script>
//jsjsjson
//import  from '';
export default {
//import使
components: {},
props: {},
data() {
//
return {
catId: 0,
brands: [
{
label: "a",
value: 1
}
],
brandId: "",
subscribe: null
};
},
// data
computed: {},
//data
watch: {
brandId(val) {
this.PubSub.publish("brandId", val);
}
},
//
methods: {
getCatBrands() {
this.$http({
url: this.$http.adornUrl("/product/categorybrandrelation/brands/list"),
method: "get",
params: this.$http.adornParams({
catId: this.catId
})
}).then(({ data }) => {
this.brands = data.data;
});
}
},
// - 访this
created() {},
// - 访DOM
mounted() {
//
this.subscribe = PubSub.subscribe("catPath", (msg, val) => {
this.catId = val[val.length - 1];
this.getCatBrands();
});
},
beforeCreate() {}, // - 
beforeMount() {}, // - 
beforeUpdate() {}, // - 
updated() {}, // - 
beforeDestroy() {
PubSub.unsubscribe(this.subscribe); //
}, // - 
destroyed() {}, // - 
activated() {} //keep-alive
};
</script>
<style scoped>
</style>

@ -0,0 +1,78 @@
<template>
<!--
使用说明
1引入category-cascader.vue
2语法<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
解释
catelogPath指定的值是cascader初始化需要显示的值应该和父组件的catelogPath绑定;
由于有sync修饰符所以cascader路径变化以后自动会修改父的catelogPath这是结合子组件this.$emit("update:catelogPath",v);做的
-->
<div>
<el-cascader
filterable
clearable
placeholder="试试搜索:手机"
v-model="paths"
:options="categorys"
:props="setting"
></el-cascader>
</div>
</template>
<script>
//jsjsjson
//import  from '';
export default {
//import使
components: {},
//
props: {
catelogPath: {
type: Array,
default(){
return [];
}
}
},
data() {
//
return {
setting: {
value: "catId",
label: "name",
children: "children"
},
categorys: [],
paths: this.catelogPath
};
},
watch:{
catelogPath(v){
this.paths = this.catelogPath;
},
paths(v){
this.$emit("update:catelogPath",v);
//使pubsub-js
this.PubSub.publish("catPath",v);
}
},
//
methods: {
getCategorys() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get"
}).then(({ data }) => {
this.categorys = data.data;
});
}
},
// - 访this
created() {
this.getCategorys();
}
};
</script>
<style scoped>
</style>

@ -1,68 +1,79 @@
<!-- -->
<template>
<!-- 每一个节点用catid区分 -->
<el-tree :data="menus" :props="defaultProps" node-key="catId" ref="menuTree" @node-click="nodeClick">
</el-tree>
</template>
<script>
//jsjsjson
//import from '';
export default {
//import使
components: {},
data() {
//
return {
name: 'Category',
menus: [],
expandedKey: [],
defaultProps: { //
children: 'children',
label: 'name'
},
};
},
// data
computed: {},
//data
watch: {},
//
methods: {
//
getDataList() {
this.$http({
url: this.$http.adornUrl('/product/category/list/tree'),
method: 'get',
}).then(({ data }) => {
console.log("成功获取到菜单数据。。。", data.data);
this.menus = data.data;
})
},
nodeClick(data, node, component){
console.log("子组件的节点被点击:", data, node, component);
//
this.$emit("tree-node-click", data, node, component);
},
},
// - 访this
created() {
this.getDataList();
},
// - 访DOM
mounted() {
},
beforeCreate() { }, // -
beforeMount() { }, // -
beforeUpdate() { }, // -
updated() { }, // -
beforeDestroy() { }, // -
destroyed() { }, // -
activated() { }, //keep-alive
}
</script>
<template>
<div>
<el-input placeholder="输入关键字进行过滤" v-model="filterText"></el-input>
<el-tree
:data="menus"
:props="defaultProps"
node-key="catId"
ref="menuTree"
@node-click="nodeclick"
:filter-node-method="filterNode"
:highlight-current = "true"
></el-tree>
</div>
</template>
<script>
//jsjsjson
//import  from '';
export default {
//import使
components: {},
props: {},
data() {
//
return {
filterText: "",
menus: [],
expandedKey: [],
defaultProps: {
children: "children",
label: "name"
}
};
},
// data
computed: {},
//data
watch: {
filterText(val) {
this.$refs.menuTree.filter(val);
}
},
//
methods: {
//
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
getMenus() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get"
}).then(({ data }) => {
this.menus = data.data;
});
},
nodeclick(data, node, component) {
console.log("子组件category的节点被点击", data, node, component);
//
this.$emit("tree-node-click", data, node, component);
}
},
// - 访this
created() {
this.getMenus();
},
// - 访DOM
mounted() {},
beforeCreate() {}, // - 
beforeMount() {}, // - 
beforeUpdate() {}, // - 
updated() {}, // - 
beforeDestroy() {}, // - 
destroyed() {}, // - 
activated() {} //keep-alive
};
</script>

@ -0,0 +1,283 @@
<template>
<el-dialog
:title="!dataForm.id ? '新增' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible"
@closed="dialogClose"
>
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" label-width="120px">
<!-- @keyup.enter.native="dataFormSubmit()" -->
<el-form-item label="属性名" prop="attrName">
<el-input v-model="dataForm.attrName" placeholder="属性名"></el-input>
</el-form-item>
<el-form-item label="属性类型" prop="attrType">
<el-select v-model="dataForm.attrType" placeholder="请选择">
<el-option label="规格参数" :value="1"></el-option>
<el-option label="销售属性" :value="0"></el-option>
</el-select>
</el-form-item>
<el-form-item label="值类型" prop="valueType">
<el-switch
v-model="dataForm.valueType"
active-text="允许多个值"
inactive-text="只能单个值"
active-color="#13ce66"
inactive-color="#ff4949"
:inactive-value="0"
:active-value="1"
></el-switch>
</el-form-item>
<el-form-item label="可选值" prop="valueSelect">
<!-- <el-input v-model="dataForm.valueSelect"></el-input> -->
<el-select
v-model="dataForm.valueSelect"
multiple
filterable
allow-create
placeholder="请输入内容"
></el-select>
</el-form-item>
<el-form-item label="属性图标" prop="icon">
<el-input v-model="dataForm.icon" placeholder="属性图标"></el-input>
</el-form-item>
<el-form-item label="所属分类" prop="catelogId">
<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
</el-form-item>
<el-form-item label="所属分组" prop="attrGroupId" v-if="type == 1">
<el-select ref="groupSelect" v-model="dataForm.attrGroupId" placeholder="请选择">
<el-option
v-for="item in attrGroups"
:key="item.attrGroupId"
:label="item.attrGroupName"
:value="item.attrGroupId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="可检索" prop="searchType" v-if="type == 1">
<el-switch
v-model="dataForm.searchType"
active-color="#13ce66"
inactive-color="#ff4949"
:active-value="1"
:inactive-value="0"
></el-switch>
</el-form-item>
<el-form-item label="快速展示" prop="showDesc" v-if="type == 1">
<el-switch
v-model="dataForm.showDesc"
active-color="#13ce66"
inactive-color="#ff4949"
:active-value="1"
:inactive-value="0"
></el-switch>
</el-form-item>
<el-form-item label="启用状态" prop="enable">
<el-switch
v-model="dataForm.enable"
active-color="#13ce66"
inactive-color="#ff4949"
:active-value="1"
:inactive-value="0"
></el-switch>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataFormSubmit()"></el-button>
</span>
</el-dialog>
</template>
<script>
import CategoryCascader from "../common/category-cascader";
export default {
data() {
return {
visible: false,
dataForm: {
attrId: 0,
attrName: "",
searchType: 0,
valueType: 1,
icon: "",
valueSelect: "",
attrType: 1,
enable: 1,
catelogId: "",
attrGroupId: "",
showDesc: 0
},
catelogPath: [],
attrGroups: [],
dataRule: {
attrName: [
{ required: true, message: "属性名不能为空", trigger: "blur" }
],
searchType: [
{
required: true,
message: "是否需要检索不能为空",
trigger: "blur"
}
],
valueType: [
{
required: true,
message: "值类型不能为空",
trigger: "blur"
}
],
icon: [
{ required: true, message: "属性图标不能为空", trigger: "blur" }
],
attrType: [
{
required: true,
message: "属性类型不能为空",
trigger: "blur"
}
],
enable: [
{
required: true,
message: "启用状态不能为空",
trigger: "blur"
}
],
catelogId: [
{
required: true,
message: "需要选择正确的三级分类数据",
trigger: "blur"
}
],
showDesc: [
{
required: true,
message: "快速展示不能为空",
trigger: "blur"
}
]
}
};
},
props:{
type:{
type: Number,
default: 1
}
},
watch: {
catelogPath(path) {
//
console.log("路径变了", path);
this.attrGroups = [];
this.dataForm.attrGroupId = "";
this.dataForm.catelogId = path[path.length - 1];
if (path && path.length == 3) {
this.$http({
url: this.$http.adornUrl(
`/product/attrgroup/list/${path[path.length - 1]}`
),
method: "get",
params: this.$http.adornParams({ page: 1, limit: 10000000 })
}).then(({ data }) => {
if (data && data.code === 0) {
this.attrGroups = data.page.list;
} else {
this.$message.error(data.msg);
}
});
} else if (path.length == 0) {
this.dataForm.catelogId = "";
} else {
this.$message.error("请选择正确的分类");
this.dataForm.catelogId = "";
}
}
},
components: { CategoryCascader },
methods: {
init(id) {
this.dataForm.attrId = id || 0;
this.dataForm.attrType = this.type;
this.visible = true;
this.$nextTick(() => {
this.$refs["dataForm"].resetFields();
if (this.dataForm.attrId) {
this.$http({
url: this.$http.adornUrl(
`/product/attr/info/${this.dataForm.attrId}`
),
method: "get",
params: this.$http.adornParams()
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataForm.attrName = data.attr.attrName;
this.dataForm.searchType = data.attr.searchType;
this.dataForm.valueType = data.attr.valueType;
this.dataForm.icon = data.attr.icon;
this.dataForm.valueSelect = data.attr.valueSelect.split(";");
this.dataForm.attrType = data.attr.attrType;
this.dataForm.enable = data.attr.enable;
this.dataForm.catelogId = data.attr.catelogId;
this.dataForm.showDesc = data.attr.showDesc;
//attrGroupId
//catelogPath
this.catelogPath = data.attr.catelogPath;
this.$nextTick(() => {
this.dataForm.attrGroupId = data.attr.attrGroupId;
});
}
});
}
});
},
//
dataFormSubmit() {
this.$refs["dataForm"].validate(valid => {
if (valid) {
this.$http({
url: this.$http.adornUrl(
`/product/attr/${!this.dataForm.attrId ? "save" : "update"}`
),
method: "post",
data: this.$http.adornData({
attrId: this.dataForm.attrId || undefined,
attrName: this.dataForm.attrName,
searchType: this.dataForm.searchType,
valueType: this.dataForm.valueType,
icon: this.dataForm.icon,
valueSelect: this.dataForm.valueSelect.join(";"),
attrType: this.dataForm.attrType,
enable: this.dataForm.enable,
catelogId: this.dataForm.catelogId,
attrGroupId: this.dataForm.attrGroupId,
showDesc: this.dataForm.showDesc
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.visible = false;
this.$emit("refreshDataList");
}
});
} else {
this.$message.error(data.msg);
}
});
}
});
},
//dialogClose
dialogClose() {
this.catelogPath = [];
}
}
};
</script>

@ -0,0 +1,241 @@
<template>
<div>
<el-dialog :close-on-click-modal="false" :visible.sync="visible" @closed="dialogClose">
<el-dialog width="40%" title="选择属性" :visible.sync="innerVisible" append-to-body>
<div>
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form-item>
<el-input v-model="dataForm.key" placeholder="参数名" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()"></el-button>
</el-form-item>
</el-form>
<el-table
:data="dataList"
border
v-loading="dataListLoading"
@selection-change="innerSelectionChangeHandle"
style="width: 100%;"
>
<el-table-column type="selection" header-align="center" align="center"></el-table-column>
<el-table-column prop="attrId" header-align="center" align="center" label="属性id"></el-table-column>
<el-table-column prop="attrName" header-align="center" align="center" label="属性名"></el-table-column>
<el-table-column prop="icon" header-align="center" align="center" label="属性图标"></el-table-column>
<el-table-column prop="valueSelect" header-align="center" align="center" label="可选值列表"></el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="innerVisible = false"> </el-button>
<el-button type="primary" @click="submitAddRealtion"></el-button>
</div>
</el-dialog>
<el-row>
<el-col :span="24">
<el-button type="primary" @click="addRelation"></el-button>
<el-button
type="danger"
@click="batchDeleteRelation"
:disabled="dataListSelections.length <= 0"
>批量删除</el-button>
<!-- -->
<el-table
:data="relationAttrs"
style="width: 100%"
@selection-change="selectionChangeHandle"
border
>
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
<el-table-column prop="attrId" label="#"></el-table-column>
<el-table-column prop="attrName" label="属性名"></el-table-column>
<el-table-column prop="valueSelect" label="可选值">
<template slot-scope="scope">
<el-tooltip placement="top">
<div slot="content">
<span v-for="(i,index) in scope.row.valueSelect.split(';')" :key="index">
{{i}}
<br />
</span>
</div>
<el-tag>{{scope.row.valueSelect.split(";")[0]+" ..."}}</el-tag>
</el-tooltip>
</template>
</el-table-column>
<el-table-column fixed="right" header-align="center" align="center" label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="relationRemove(scope.row.attrId)"></el-button>
</template>
</el-table-column>
</el-table>
</el-col>
</el-row>
</el-dialog>
</div>
</template>
<script>
//jsjsjson
//import  from '';
export default {
//import使
components: {},
props: {},
data() {
//
return {
attrGroupId: 0,
visible: false,
innerVisible: false,
relationAttrs: [],
dataListSelections: [],
dataForm: {
key: ""
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
innerdataListSelections: []
};
},
// data
computed: {},
//data
watch: {},
//
methods: {
selectionChangeHandle(val) {
this.dataListSelections = val;
},
innerSelectionChangeHandle(val) {
this.innerdataListSelections = val;
},
addRelation() {
this.getDataList();
this.innerVisible = true;
},
batchDeleteRelation(val) {
let postData = [];
this.dataListSelections.forEach(item => {
postData.push({ attrId: item.attrId, attrGroupId: this.attrGroupId });
});
this.$http({
url: this.$http.adornUrl("/product/attrgroup/attr/relation/delete"),
method: "post",
data: this.$http.adornData(postData, false)
}).then(({ data }) => {
if (data.code == 0) {
this.$message({ type: "success", message: "删除成功" });
this.init(this.attrGroupId);
} else {
this.$message({ type: "error", message: data.msg });
}
});
},
//
relationRemove(attrId) {
let data = [];
data.push({ attrId, attrGroupId: this.attrGroupId });
this.$http({
url: this.$http.adornUrl("/product/attrgroup/attr/relation/delete"),
method: "post",
data: this.$http.adornData(data, false)
}).then(({ data }) => {
if (data.code == 0) {
this.$message({ type: "success", message: "删除成功" });
this.init(this.attrGroupId);
} else {
this.$message({ type: "error", message: data.msg });
}
});
},
submitAddRealtion() {
this.innerVisible = false;
//
console.log("准备新增的数据", this.innerdataListSelections);
if (this.innerdataListSelections.length > 0) {
let postData = [];
this.innerdataListSelections.forEach(item => {
postData.push({ attrId: item.attrId, attrGroupId: this.attrGroupId });
});
this.$http({
url: this.$http.adornUrl("/product/attrgroup/attr/relation"),
method: "post",
data: this.$http.adornData(postData, false)
}).then(({ data }) => {
if (data.code == 0) {
this.$message({ type: "success", message: "新增关联成功" });
}
this.$emit("refreshData");
this.init(this.attrGroupId);
});
} else {
}
},
init(id) {
this.attrGroupId = id || 0;
this.visible = true;
this.$http({
url: this.$http.adornUrl(
"/product/attrgroup/" + this.attrGroupId + "/attr/relation"
),
method: "get",
params: this.$http.adornParams({})
}).then(({ data }) => {
this.relationAttrs = data.data;
});
},
dialogClose() {},
//========
//
getDataList() {
this.dataListLoading = true;
this.$http({
url: this.$http.adornUrl(
"/product/attrgroup/" + this.attrGroupId + "/noattr/relation"
),
method: "get",
params: this.$http.adornParams({
page: this.pageIndex,
limit: this.pageSize,
key: this.dataForm.key
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list;
this.totalPage = data.page.totalCount;
} else {
this.dataList = [];
this.totalPage = 0;
}
this.dataListLoading = false;
});
},
//
sizeChangeHandle(val) {
this.pageSize = val;
this.pageIndex = 1;
this.getDataList();
},
//
currentChangeHandle(val) {
this.pageIndex = val;
this.getDataList();
}
}
};
</script>
<style scoped>
</style>

@ -1,7 +1,17 @@
<template>
<el-dialog :title="!dataForm.attrGroupId ? '新增' : '修改'" :close-on-click-modal="false" :visible.sync="visible" @closed="dialogClose">
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()"
label-width="80px">
<el-dialog
:title="!dataForm.id ? '新增' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible"
@closed="dialogClose"
>
<el-form
:model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
label-width="120px"
>
<el-form-item label="组名" prop="attrGroupName">
<el-input v-model="dataForm.attrGroupName" placeholder="组名"></el-input>
</el-form-item>
@ -14,9 +24,11 @@
<el-form-item label="组图标" prop="icon">
<el-input v-model="dataForm.icon" placeholder="组图标"></el-input>
</el-form-item>
<el-form-item label="所属分类id" prop="catelogId">
<!-- <el-input v-model="dataForm.catelogId" placeholder="所属分类id"></el-input> -->
<el-cascader filterable v-model="dataForm.catelogPath" :options="options" :props="props"></el-cascader>
<el-form-item label="所属分类" prop="catelogId">
<!-- <el-input v-model="dataForm.catelogId" placeholder="所属分类id"></el-input> @change="handleChange" -->
<!-- <el-cascader filterable placeholder="试试搜索:手机" v-model="catelogPath" :options="categorys" :props="props"></el-cascader> -->
<!-- :catelogPath="catelogPath"自定义绑定的属性可以给子组件传值 -->
<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
@ -27,117 +39,121 @@
</template>
<script>
import CategoryCascader from '../common/category-cascader'
export default {
data() {
return {
props:{
value: "catId",
label: "name",
children: "children"
value:"catId",
label:"name",
children:"children"
},
options: [],
visible: false,
categorys: [],
catelogPath: [],
dataForm: {
attrGroupId: 0,
attrGroupName: '',
sort: '',
descript: '',
icon: '',
catelogPath: [],
attrGroupName: "",
sort: "",
descript: "",
icon: "",
catelogId: 0
},
dataRule: {
attrGroupName: [
{ required: true, message: '组名不能为空', trigger: 'blur' }
],
sort: [
{ required: true, message: '排序不能为空', trigger: 'blur' }
{ required: true, message: "组名不能为空", trigger: "blur" }
],
sort: [{ required: true, message: "排序不能为空", trigger: "blur" }],
descript: [
{ required: true, message: '描述不能为空', trigger: 'blur' }
],
icon: [
{ required: true, message: '组图标不能为空', trigger: 'blur' }
{ required: true, message: "描述不能为空", trigger: "blur" }
],
icon: [{ required: true, message: "组图标不能为空", trigger: "blur" }],
catelogId: [
{ required: true, message: '所属分类id不能为空', trigger: 'blur' }
{ required: true, message: "所属分类id不能为空", trigger: "blur" }
]
}
}
};
},
components:{CategoryCascader},
methods: {
dialogClose() {
this.dataForm.catelogPath=[];
dialogClose(){
this.catelogPath = [];
},
getCategory() {
getCategorys(){
this.$http({
url: this.$http.adornUrl('/product/category/list/tree'),
method: 'get',
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get"
}).then(({ data }) => {
console.log("成功获取到菜单数据。。。", data.data);
this.options = data.data;
})
this.categorys = data.data;
});
},
init(id) {
this.dataForm.attrGroupId = id || 0
this.visible = true
this.dataForm.attrGroupId = id || 0;
this.visible = true;
this.$nextTick(() => {
this.$refs['dataForm'].resetFields()
this.$refs["dataForm"].resetFields();
if (this.dataForm.attrGroupId) {
this.$http({
url: this.$http.adornUrl(`/product/attrgroup/info/${this.dataForm.attrGroupId}`),
method: 'get',
url: this.$http.adornUrl(
`/product/attrgroup/info/${this.dataForm.attrGroupId}`
),
method: "get",
params: this.$http.adornParams()
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataForm.attrGroupName = data.attrGroup.attrGroupName
this.dataForm.sort = data.attrGroup.sort
this.dataForm.descript = data.attrGroup.descript
this.dataForm.icon = data.attrGroup.icon
this.dataForm.catelogId = data.attrGroup.catelogId
this.dataForm.catelogPath= data.attrGroup.catelogPath
this.dataForm.attrGroupName = data.attrGroup.attrGroupName;
this.dataForm.sort = data.attrGroup.sort;
this.dataForm.descript = data.attrGroup.descript;
this.dataForm.icon = data.attrGroup.icon;
this.dataForm.catelogId = data.attrGroup.catelogId;
//catelogId
this.catelogPath = data.attrGroup.catelogPath;
}
})
});
}
})
});
},
//
dataFormSubmit() {
this.$refs['dataForm'].validate((valid) => {
this.$refs["dataForm"].validate(valid => {
if (valid) {
this.$http({
url: this.$http.adornUrl(`/product/attrgroup/${!this.dataForm.attrGroupId ? 'save' : 'update'}`),
method: 'post',
url: this.$http.adornUrl(
`/product/attrgroup/${
!this.dataForm.attrGroupId ? "save" : "update"
}`
),
method: "post",
data: this.$http.adornData({
'attrGroupId': this.dataForm.attrGroupId || undefined,
'attrGroupName': this.dataForm.attrGroupName,
'sort': this.dataForm.sort,
'descript': this.dataForm.descript,
'icon': this.dataForm.icon,
'catelogId': this.dataForm.catelogPath[this.dataForm.catelogPath.length-1]
attrGroupId: this.dataForm.attrGroupId || undefined,
attrGroupName: this.dataForm.attrGroupName,
sort: this.dataForm.sort,
descript: this.dataForm.descript,
icon: this.dataForm.icon,
catelogId: this.catelogPath[this.catelogPath.length-1]
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.visible = false
this.$emit('refreshDataList')
this.visible = false;
this.$emit("refreshDataList");
}
})
});
} else {
this.$message.error(data.msg)
this.$message.error(data.msg);
}
})
});
}
})
});
}
},
created() {
this.getCategory();
created(){
this.getCategorys();
}
}
};
</script>

@ -1,184 +1,217 @@
<!-- -->
<template>
<el-row :gutter="20">
<el-col :span="6">
<category @tree-node-click="treeNodeClick"></category>
</el-col>
<el-col :span="18">
<div class="mod-config">
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form-item>
<el-input v-model="dataForm.key" placeholder="参数名" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()"></el-button>
<el-button v-if="isAuth('product:attrgroup:save')" type="primary"
@click="addOrUpdateHandle()">新增</el-button>
<el-button v-if="isAuth('product:attrgroup:delete')" type="danger" @click="deleteHandle()"
:disabled="dataListSelections.length <= 0">批量删除</el-button>
</el-form-item>
</el-form>
<el-table :data="dataList" border v-loading="dataListLoading" @selection-change="selectionChangeHandle"
style="width: 100%;">
<el-table-column type="selection" header-align="center" align="center" width="50">
</el-table-column>
<el-table-column prop="attrGroupId" header-align="center" align="center" label="分组id">
</el-table-column>
<el-table-column prop="attrGroupName" header-align="center" align="center" label="组名">
</el-table-column>
<el-table-column prop="sort" header-align="center" align="center" label="排序">
</el-table-column>
<el-table-column prop="descript" header-align="center" align="center" label="描述">
</el-table-column>
<el-table-column prop="icon" header-align="center" align="center" label="组图标">
</el-table-column>
<el-table-column prop="catelogId" header-align="center" align="center" label="所属分类id">
</el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="150" label="操作">
<template slot-scope="scope">
<el-button type="text" size="small"
@click="addOrUpdateHandle(scope.row.attrGroupId)">修改</el-button>
<el-button type="text" size="small"
@click="deleteHandle(scope.row.attrGroupId)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle"
:current-page="pageIndex" :page-sizes="[10, 20, 50, 100]" :page-size="pageSize" :total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
</el-pagination>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate"
@refreshDataList="getDataList"></add-or-update>
</div>
</el-col>
</el-row>
</template>
<script>
/*
父子组件传递数据
1子组件给父组件传递数据事件机制
子组件给父子件发送一个事件携带上数据
*/
//jsjsjson
//import from '';
import Category from "../common/category.vue";
import AddOrUpdate from "./attrgroup-add-or-update.vue";
export default {
//import使
components: { Category, AddOrUpdate },
data() {
return {
catId: 0,
dataForm: {
key: ''
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false
}
},
// data
//data
watch: {},
//
methods: {
//
treeNodeClick(data, node, component) {
console.log("attrgroup感知到节点被点击", data, node, component);
console.log("菜单id:", data.catId);
if(node.childNodes.length == 0) {
this.catId=data.catId;
this.getDataList();
}
},
//
getDataList() {
console.log("菜单id:", this.catId);
this.dataListLoading = true
this.$http({
url: this.$http.adornUrl(`/product/attrgroup/list/${this.catId}`),
method: 'get',
params: this.$http.adornParams({
'page': this.pageIndex,
'limit': this.pageSize,
'key': this.dataForm.key
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list
this.totalPage = data.page.totalCount
} else {
this.dataList = []
this.totalPage = 0
}
this.dataListLoading = false
})
},
//
sizeChangeHandle(val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
//
currentChangeHandle(val) {
this.pageIndex = val
this.getDataList()
},
//
selectionChangeHandle(val) {
this.dataListSelections = val
},
// /
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id)
})
},
//
deleteHandle(id) {
var ids = id ? [id] : this.dataListSelections.map(item => {
return item.attrGroupId
})
this.$confirm(`确定对[id=${ids.join(',')}]进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$http({
url: this.$http.adornUrl('/product/attrgroup/delete'),
method: 'post',
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.getDataList()
}
})
} else {
this.$message.error(data.msg)
}
})
})
}
},
}
</script>
<template>
<el-row :gutter="20">
<el-col :span="6">
<category @tree-node-click="treenodeclick"></category>
</el-col>
<el-col :span="18">
<div class="mod-config">
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form-item>
<el-input v-model="dataForm.key" placeholder="参数名" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()"></el-button>
<el-button type="success" @click="getAllDataList()"></el-button>
<el-button
v-if="isAuth('product:attrgroup:save')"
type="primary"
@click="addOrUpdateHandle()"
>新增</el-button>
<el-button
v-if="isAuth('product:attrgroup:delete')"
type="danger"
@click="deleteHandle()"
:disabled="dataListSelections.length <= 0"
>批量删除</el-button>
</el-form-item>
</el-form>
<el-table
:data="dataList"
border
v-loading="dataListLoading"
@selection-change="selectionChangeHandle"
style="width: 100%;"
>
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
<el-table-column prop="attrGroupId" header-align="center" align="center" label="分组id"></el-table-column>
<el-table-column prop="attrGroupName" header-align="center" align="center" label="组名"></el-table-column>
<el-table-column prop="sort" header-align="center" align="center" label="排序"></el-table-column>
<el-table-column prop="descript" header-align="center" align="center" label="描述"></el-table-column>
<el-table-column prop="icon" header-align="center" align="center" label="组图标"></el-table-column>
<el-table-column prop="catelogId" header-align="center" align="center" label="所属分类id"></el-table-column>
<el-table-column
fixed="right"
header-align="center"
align="center"
width="150"
label="操作"
>
<template slot-scope="scope">
<el-button type="text" size="small" @click="relationHandle(scope.row.attrGroupId)"></el-button>
<el-button
type="text"
size="small"
@click="addOrUpdateHandle(scope.row.attrGroupId)"
>修改</el-button>
<el-button type="text" size="small" @click="deleteHandle(scope.row.attrGroupId)"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
<!-- 修改关联关系 -->
<relation-update v-if="relationVisible" ref="relationUpdate" @refreshData="getDataList"></relation-update>
</div>
</el-col>
</el-row>
</template>
<script>
/**
* 父子组件传递数据
* 1)子组件给父组件传递数据事件机制
* 子组件给父组件发送一个事件携带上数据
* // this.$emit("",...)
*/
//jsjsjson
//import  from '';
import Category from "../common/category";
import AddOrUpdate from "./attrgroup-add-or-update";
import RelationUpdate from "./attr-group-relation";
export default {
//import使
components: { Category, AddOrUpdate, RelationUpdate },
props: {},
data() {
return {
catId: 0,
dataForm: {
key: ""
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false,
relationVisible: false
};
},
activated() {
this.getDataList();
},
methods: {
//
relationHandle(groupId) {
this.relationVisible = true;
this.$nextTick(() => {
this.$refs.relationUpdate.init(groupId);
});
},
//
treenodeclick(data, node, component) {
if (node.level == 3) {
this.catId = data.catId;
this.getDataList(); //
}
},
getAllDataList(){
this.catId = 0;
this.getDataList();
},
//
getDataList() {
this.dataListLoading = true;
this.$http({
url: this.$http.adornUrl(`/product/attrgroup/list/${this.catId}`),
method: "get",
params: this.$http.adornParams({
page: this.pageIndex,
limit: this.pageSize,
key: this.dataForm.key
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list;
this.totalPage = data.page.totalCount;
} else {
this.dataList = [];
this.totalPage = 0;
}
this.dataListLoading = false;
});
},
//
sizeChangeHandle(val) {
this.pageSize = val;
this.pageIndex = 1;
this.getDataList();
},
//
currentChangeHandle(val) {
this.pageIndex = val;
this.getDataList();
},
//
selectionChangeHandle(val) {
this.dataListSelections = val;
},
// /
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true;
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id);
});
},
//
deleteHandle(id) {
var ids = id
? [id]
: this.dataListSelections.map(item => {
return item.attrGroupId;
});
this.$confirm(
`确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}
).then(() => {
this.$http({
url: this.$http.adornUrl("/product/attrgroup/delete"),
method: "post",
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.getDataList();
}
});
} else {
this.$message.error(data.msg);
}
});
});
}
}
};
</script>
<style scoped>
</style>

@ -0,0 +1,191 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="16">
<el-card class="box-card">
<el-tabs tab-position="left" style="width:98%">
<el-tab-pane
:label="group.attrGroupName"
v-for="(group,gidx) in dataResp.attrGroups"
:key="group.attrGroupId"
>
<!-- 遍历属性,每个tab-pane对应一个表单每个属性是一个表单项 spu.baseAttrs[0] = [{attrId:xx,val:}]-->
<el-form ref="form" :model="dataResp">
<el-form-item
:label="attr.attrName"
v-for="(attr,aidx) in group.attrs"
:key="attr.attrId"
>
<el-input
v-model="dataResp.baseAttrs[gidx][aidx].attrId"
type="hidden"
v-show="false"
></el-input>
<el-select
v-model="dataResp.baseAttrs[gidx][aidx].attrValues"
:multiple="attr.valueType == 1"
filterable
allow-create
default-first-option
placeholder="请选择或输入值"
>
<el-option
v-for="(val,vidx) in attr.valueSelect.split(';')"
:key="vidx"
:label="val"
:value="val"
></el-option>
</el-select>
<el-checkbox
v-model="dataResp.baseAttrs[gidx][aidx].showDesc"
:true-label="1"
:false-label="0"
>快速展示</el-checkbox>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<div style="margin:auto">
<el-button type="success" style="float:right" @click="submitSpuAttrs"></el-button>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
components: {},
props: {},
data() {
return {
spuId: "",
catalogId: "",
dataResp: {
//
attrGroups: [],
baseAttrs: []
},
spuAttrsMap: {}
};
},
computed: {},
methods: {
clearData(){
this.dataResp.attrGroups = [];
this.dataResp.baseAttrs = [];
this.spuAttrsMap = {};
},
getSpuBaseAttrs() {
this.$http({
url: this.$http.adornUrl(`/product/attr/base/listforspu/${this.spuId}`),
method: "get"
}).then(({ data }) => {
data.data.forEach(item => {
this.spuAttrsMap["" + item.attrId] = item;
});
console.log("~~~~", this.spuAttrsMap);
});
},
getQueryParams() {
this.spuId = this.$route.query.spuId;
this.catalogId = this.$route.query.catalogId;
console.log("----", this.spuId, this.catalogId);
},
showBaseAttrs() {
let _this = this;
this.$http({
url: this.$http.adornUrl(
`/product/attrgroup/${this.catalogId}/withattr`
),
method: "get",
params: this.$http.adornParams({})
}).then(({ data }) => {
//baseAttrs
data.data.forEach(item => {
let attrArray = [];
item.attrs.forEach(attr => {
let v = "";
if (_this.spuAttrsMap["" + attr.attrId]) {
v = _this.spuAttrsMap["" + attr.attrId].attrValue.split(";");
if (v.length == 1) {
v = v[0] + "";
}
}
attrArray.push({
attrId: attr.attrId,
attrName: attr.attrName,
attrValues: v,
showDesc: _this.spuAttrsMap["" + attr.attrId]
? _this.spuAttrsMap["" + attr.attrId].quickShow
: attr.showDesc
});
});
this.dataResp.baseAttrs.push(attrArray);
});
this.dataResp.attrGroups = data.data;
});
},
submitSpuAttrs() {
console.log("·····", this.dataResp.baseAttrs);
//spu_id attr_id attr_name attr_value attr_sort quick_show
let submitData = [];
this.dataResp.baseAttrs.forEach(item => {
item.forEach(attr => {
let val = "";
if (attr.attrValues instanceof Array) {
val = attr.attrValues.join(";");
} else {
val = attr.attrValues;
}
if (val != "") {
submitData.push({
attrId: attr.attrId,
attrName: attr.attrName,
attrValue: val,
quickShow: attr.showDesc
});
}
});
});
this.$confirm("修改商品规格信息, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$http({
url: this.$http.adornUrl(`/product/attr/update/${this.spuId}`),
method: "post",
data: this.$http.adornData(submitData, false)
}).then(({ data }) => {
this.$message({
type: "success",
message: "属性修改成功!"
});
});
})
.catch((e) => {
this.$message({
type: "info",
message: "已取消修改"+e
});
});
}
},
created() {},
activated() {
this.clearData();
this.getQueryParams();
if (this.spuId && this.catalogId) {
this.showBaseAttrs();
this.getSpuBaseAttrs();
}
}
};
</script>
<style scoped>
</style>

@ -0,0 +1,251 @@
<template>
<el-row :gutter="20">
<el-col :span="6">
<category @tree-node-click="treenodeclick"></category>
</el-col>
<el-col :span="18">
<div class="mod-config">
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form-item>
<el-input v-model="dataForm.key" placeholder="参数名" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button @click="getDataList()"></el-button>
<el-button type="success" @click="getAllDataList()"></el-button>
<el-button
v-if="isAuth('product:attr:save')"
type="primary"
@click="addOrUpdateHandle()"
>新增</el-button>
<el-button
v-if="isAuth('product:attr:delete')"
type="danger"
@click="deleteHandle()"
:disabled="dataListSelections.length <= 0"
>批量删除</el-button>
</el-form-item>
</el-form>
<el-table
:data="dataList"
border
v-loading="dataListLoading"
@selection-change="selectionChangeHandle"
style="width: 100%;"
>
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
<el-table-column prop="attrId" header-align="center" align="center" label="id"></el-table-column>
<el-table-column prop="attrName" header-align="center" align="center" label="属性名"></el-table-column>
<el-table-column
v-if="attrtype == 1"
prop="searchType"
header-align="center"
align="center"
label="可检索"
>
<template slot-scope="scope">
<i class="el-icon-success" v-if="scope.row.searchType==1"></i>
<i class="el-icon-error" v-else></i>
</template>
</el-table-column>
<el-table-column prop="valueType" header-align="center" align="center" label="值类型">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.valueType==0"></el-tag>
<el-tag v-else></el-tag>
</template>
</el-table-column>
<el-table-column prop="icon" header-align="center" align="center" label="图标"></el-table-column>
<el-table-column prop="valueSelect" header-align="center" align="center" label="可选值">
<template slot-scope="scope">
<el-tooltip placement="top">
<div slot="content">
<span v-for="(i,index) in scope.row.valueSelect.split(';')" :key="index">{{i}}<br/></span>
</div>
<el-tag>{{scope.row.valueSelect.split(";")[0]+" ..."}}</el-tag>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="enable" header-align="center" align="center" label="启用">
<template slot-scope="scope">
<i class="el-icon-success" v-if="scope.row.enable==1"></i>
<i class="el-icon-error" v-else></i>
</template>
</el-table-column>
<el-table-column prop="catelogName" header-align="center" align="center" label="所属分类"></el-table-column>
<el-table-column
v-if="attrtype == 1"
prop="groupName"
header-align="center"
align="center"
label="所属分组"
></el-table-column>
<el-table-column v-if="attrtype == 1" prop="showDesc" header-align="center" align="center" label="快速展示">
<template slot-scope="scope">
<i class="el-icon-success" v-if="scope.row.showDesc==1"></i>
<i class="el-icon-error" v-else></i>
</template>
</el-table-column>
<el-table-column
fixed="right"
header-align="center"
align="center"
width="150"
label="操作"
>
<template slot-scope="scope">
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.attrId)"></el-button>
<el-button type="text" size="small" @click="deleteHandle(scope.row.attrId)"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update
:type="attrtype"
v-if="addOrUpdateVisible"
ref="addOrUpdate"
@refreshDataList="getDataList"
></add-or-update>
</div>
</el-col>
</el-row>
</template>
<script>
//jsjsjson
//import  from '';
import Category from "../common/category";
import AddOrUpdate from "./attr-add-or-update";
export default {
//import使
components: { Category, AddOrUpdate },
props: {
attrtype: {
type: Number,
default: 1
}
},
data() {
return {
catId: 0,
type: 1,
dataForm: {
key: ""
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false
};
},
activated() {
this.getDataList();
},
methods: {
//
treenodeclick(data, node, component) {
if (node.level == 3) {
this.catId = data.catId;
this.getDataList(); //
}
},
getAllDataList(){
this.catId = 0;
this.getDataList();
},
//
getDataList() {
this.dataListLoading = true;
let type = this.attrtype == 0 ? "sale" : "base";
this.$http({
url: this.$http.adornUrl(`/product/attr/${type}/list/${this.catId}`),
method: "get",
params: this.$http.adornParams({
page: this.pageIndex,
limit: this.pageSize,
key: this.dataForm.key
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list;
this.totalPage = data.page.totalCount;
} else {
this.dataList = [];
this.totalPage = 0;
}
this.dataListLoading = false;
});
},
//
sizeChangeHandle(val) {
this.pageSize = val;
this.pageIndex = 1;
this.getDataList();
},
//
currentChangeHandle(val) {
this.pageIndex = val;
this.getDataList();
},
//
selectionChangeHandle(val) {
this.dataListSelections = val;
},
// /
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true;
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id);
});
},
//
deleteHandle(id) {
var ids = id
? [id]
: this.dataListSelections.map(item => {
return item.attrId;
});
this.$confirm(
`确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}
).then(() => {
this.$http({
url: this.$http.adornUrl("/product/attr/delete"),
method: "post",
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.getDataList();
}
});
} else {
this.$message.error(data.msg);
}
});
});
}
}
};
</script>
<style scoped>
</style>

@ -1,28 +1,41 @@
<template>
<el-dialog
:title="!dataForm.brandId ? '新增' : '修改'"
:title="!dataForm.id ? '新增' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible">
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataFormSubmit()" label-width="140px">
<el-form-item label="品牌名" prop="name">
<el-input v-model="dataForm.name" placeholder="品牌名"></el-input>
</el-form-item>
<el-form-item label="品牌logo地址" prop="logo">
<!-- <el-input v-model="dataForm.logo" placeholder="品牌logo地址"></el-input> -->
<single-upload v-model="dataForm.logo"></single-upload>
</el-form-item>
<el-form-item label="介绍" prop="descript">
<el-input v-model="dataForm.descript" placeholder="介绍"></el-input>
</el-form-item>
<el-form-item label="显示状态" prop="showStatus">
<el-switch v-model="dataForm.showStatus" active-color="#13ce66" inactive-color="#ff4949" :active-value="1" :inactive-value="0"></el-switch>
</el-form-item>
<el-form-item label="检索首字母" prop="firstLetter">
<el-input v-model="dataForm.firstLetter" placeholder="检索首字母"></el-input>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="dataForm.sort" placeholder="排序"></el-input>
</el-form-item>
:visible.sync="visible"
>
<el-form
:model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
label-width="140px"
>
<el-form-item label="品牌名" prop="name">
<el-input v-model="dataForm.name" placeholder="品牌名"></el-input>
</el-form-item>
<el-form-item label="品牌logo地址" prop="logo">
<!-- <el-input v-model="dataForm.logo" placeholder="品牌logo地址"></el-input> -->
<single-upload v-model="dataForm.logo"></single-upload>
</el-form-item>
<el-form-item label="介绍" prop="descript">
<el-input v-model="dataForm.descript" placeholder="介绍"></el-input>
</el-form-item>
<el-form-item label="显示状态" prop="showStatus">
<el-switch
v-model="dataForm.showStatus"
active-color="#13ce66"
inactive-color="#ff4949"
:active-value="1"
:inactive-value="0"
></el-switch>
</el-form-item>
<el-form-item label="检索首字母" prop="firstLetter">
<el-input v-model="dataForm.firstLetter" placeholder="检索首字母"></el-input>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model.number="dataForm.sort" placeholder="排序"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
@ -32,102 +45,129 @@
</template>
<script>
import singleUpload from '../../../components/upload/singleUpload.vue'
export default {
components: { singleUpload },
data () {
return {
visible: false,
dataForm: {
brandId: 0,
name: '',
logo: '',
descript: '',
showStatus: '',
firstLetter: '',
sort: ''
},
dataRule: {
name: [
{ required: true, message: '品牌名不能为空', trigger: 'blur' }
],
logo: [
{ required: true, message: '品牌logo地址不能为空', trigger: 'blur' }
],
descript: [
{ required: true, message: '介绍不能为空', trigger: 'blur' }
],
showStatus: [
{ required: true, message: '显示状态[0-不显示1-显示]不能为空', trigger: 'blur' }
],
firstLetter: [
{ required: true, message: '检索首字母不能为空', trigger: 'blur' }
],
sort: [
{ required: true, message: '排序不能为空', trigger: 'blur' }
]
}
}
},
methods: {
init (id) {
this.dataForm.brandId = id || 0
this.visible = true
this.$nextTick(() => {
this.$refs['dataForm'].resetFields()
if (this.dataForm.brandId) {
this.$http({
url: this.$http.adornUrl(`/product/brand/info/${this.dataForm.brandId}`),
method: 'get',
params: this.$http.adornParams()
}).then(({data}) => {
if (data && data.code === 0) {
this.dataForm.name = data.brand.name
this.dataForm.logo = data.brand.logo
this.dataForm.descript = data.brand.descript
this.dataForm.showStatus = data.brand.showStatus
this.dataForm.firstLetter = data.brand.firstLetter
this.dataForm.sort = data.brand.sort
import SingleUpload from "@/components/upload/singleUpload";
export default {
components: { SingleUpload },
data() {
return {
visible: false,
dataForm: {
brandId: 0,
name: "",
logo: "",
descript: "",
showStatus: 1,
firstLetter: "",
sort: 0
},
dataRule: {
name: [{ required: true, message: "品牌名不能为空", trigger: "blur" }],
logo: [
{ required: true, message: "品牌logo地址不能为空", trigger: "blur" }
],
descript: [
{ required: true, message: "介绍不能为空", trigger: "blur" }
],
showStatus: [
{
required: true,
message: "显示状态[0-不显示1-显示]不能为空",
trigger: "blur"
}
],
firstLetter: [
{
validator: (rule, value, callback) => {
if (value == "") {
callback(new Error("首字母必须填写"));
} else if (!/^[a-zA-Z]$/.test(value)) {
callback(new Error("首字母必须a-z或者A-Z之间"));
} else {
callback();
}
})
},
trigger: "blur"
}
})
},
//
dataFormSubmit () {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.$http({
url: this.$http.adornUrl(`/product/brand/${!this.dataForm.brandId ? 'save' : 'update'}`),
method: 'post',
data: this.$http.adornData({
'brandId': this.dataForm.brandId || undefined,
'name': this.dataForm.name,
'logo': this.dataForm.logo,
'descript': this.dataForm.descript,
'showStatus': this.dataForm.showStatus,
'firstLetter': this.dataForm.firstLetter,
'sort': this.dataForm.sort
})
}).then(({data}) => {
if (data && data.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.visible = false
this.$emit('refreshDataList')
}
})
],
sort: [
{
validator: (rule, value, callback) => {
if (value == "") {
callback(new Error("排序字段必须填写"));
} else if (!Number.isInteger(value) || value<0) {
callback(new Error("排序必须是一个大于等于0的整数"));
} else {
this.$message.error(data.msg)
callback();
}
})
},
trigger: "blur"
}
})
]
}
};
},
methods: {
init(id) {
this.dataForm.brandId = id || 0;
this.visible = true;
this.$nextTick(() => {
this.$refs["dataForm"].resetFields();
if (this.dataForm.brandId) {
this.$http({
url: this.$http.adornUrl(
`/product/brand/info/${this.dataForm.brandId}`
),
method: "get",
params: this.$http.adornParams()
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataForm.name = data.brand.name;
this.dataForm.logo = data.brand.logo;
this.dataForm.descript = data.brand.descript;
this.dataForm.showStatus = data.brand.showStatus;
this.dataForm.firstLetter = data.brand.firstLetter;
this.dataForm.sort = data.brand.sort;
}
});
}
});
},
//
dataFormSubmit() {
this.$refs["dataForm"].validate(valid => {
if (valid) {
this.$http({
url: this.$http.adornUrl(
`/product/brand/${!this.dataForm.brandId ? "save" : "update"}`
),
method: "post",
data: this.$http.adornData({
brandId: this.dataForm.brandId || undefined,
name: this.dataForm.name,
logo: this.dataForm.logo,
descript: this.dataForm.descript,
showStatus: this.dataForm.showStatus,
firstLetter: this.dataForm.firstLetter,
sort: this.dataForm.sort
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.visible = false;
this.$emit("refreshDataList");
}
});
} else {
this.$message.error(data.msg);
}
});
}
});
}
}
};
</script>

@ -6,175 +6,266 @@
</el-form-item>
<el-form-item>
<el-button @click="getDataList()"></el-button>
<el-button v-if="isAuth('product:brand:save')" type="primary" @click="addOrUpdateHandle()"></el-button>
<el-button v-if="isAuth('product:brand:delete')" type="danger" @click="deleteHandle()"
:disabled="dataListSelections.length <= 0">批量删除</el-button>
<el-button
v-if="isAuth('product:brand:save')"
type="primary"
@click="addOrUpdateHandle()"
>新增</el-button>
<el-button
v-if="isAuth('product:brand:delete')"
type="danger"
@click="deleteHandle()"
:disabled="dataListSelections.length <= 0"
>批量删除</el-button>
</el-form-item>
</el-form>
<el-table :data="dataList" border v-loading="dataListLoading" @selection-change="selectionChangeHandle"
style="width: 100%;">
<el-table-column type="selection" header-align="center" align="center" width="50">
</el-table-column>
<el-table-column prop="brandId" header-align="center" align="center" label="品牌id">
</el-table-column>
<el-table-column prop="name" header-align="center" align="center" label="品牌名">
</el-table-column>
<el-table
:data="dataList"
border
v-loading="dataListLoading"
@selection-change="selectionChangeHandle"
style="width: 100%;"
>
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
<el-table-column prop="brandId" header-align="center" align="center" label="品牌id"></el-table-column>
<el-table-column prop="name" header-align="center" align="center" label="品牌名"></el-table-column>
<el-table-column prop="logo" header-align="center" align="center" label="品牌logo地址">
<template slot-scope="scope">
<!-- <el-image
style="width: 100px; height: 80px"
:src="scope.row.logo"
fit="contain">
</el-image> -->
<img style="width: 100px; height: 80px" :src="scope.row.logo" >
<!-- <el-image
style="width: 100px; height: 80px"
:src="scope.row.logo"
fit="fill"></el-image>-->
<img :src="scope.row.logo" style="width: 100px; height: 80px" />
</template>
</el-table-column>
<el-table-column prop="descript" header-align="center" align="center" label="介绍">
</el-table-column>
<el-table-column prop="descript" header-align="center" align="center" label="介绍"></el-table-column>
<el-table-column prop="showStatus" header-align="center" align="center" label="显示状态">
<!-- scope 可以获取表格当前行或列所有的数据 -->
<template slot-scope="scope">
<el-switch v-model="scope.row.showStatus" active-color="#13ce66" inactive-color="#ff4949" :active-value="1"
:inactive-value="0" @change="updateBrandStatus(scope.row)">
</el-switch>
<el-switch
v-model="scope.row.showStatus"
active-color="#13ce66"
inactive-color="#ff4949"
:active-value="1"
:inactive-value="0"
@change="updateBrandStatus(scope.row)"
></el-switch>
</template>
</el-table-column>
<el-table-column prop="firstLetter" header-align="center" align="center" label="检索首字母">
</el-table-column>
<el-table-column prop="sort" header-align="center" align="center" label="排序">
</el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="150" label="操作">
<el-table-column prop="firstLetter" header-align="center" align="center" label="检索首字母"></el-table-column>
<el-table-column prop="sort" header-align="center" align="center" label="排序"></el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="250" label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="updateCatelogHandle(scope.row.brandId)"></el-button>
<el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.brandId)"></el-button>
<el-button type="text" size="small" @click="deleteHandle(scope.row.brandId)"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" :current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]" :page-size="pageSize" :total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
</el-pagination>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
<!-- 弹窗, 新增 / 修改 -->
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
<el-dialog title="关联分类" :visible.sync="cateRelationDialogVisible" width="30%">
<el-popover placement="right-end" v-model="popCatelogSelectVisible">
<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="popCatelogSelectVisible = false">取消</el-button>
<el-button type="primary" size="mini" @click="addCatelogSelect"></el-button>
</div>
<el-button slot="reference">新增关联</el-button>
</el-popover>
<el-table :data="cateRelationTableData" style="width: 100%">
<el-table-column prop="id" label="#"></el-table-column>
<el-table-column prop="brandName" label="品牌名"></el-table-column>
<el-table-column prop="catelogName" label="分类名"></el-table-column>
<el-table-column fixed="right" header-align="center" align="center" label="操作">
<template slot-scope="scope">
<el-button
type="text"
size="small"
@click="deleteCateRelationHandle(scope.row.id,scope.row.brandId)"
>移除</el-button>
</template>
</el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button @click="cateRelationDialogVisible = false"> </el-button>
<el-button type="primary" @click="cateRelationDialogVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import AddOrUpdate from './brand-add-or-update'
import AddOrUpdate from "./brand-add-or-update";
import CategoryCascader from "../common/category-cascader";
export default {
data() {
return {
dataForm: {
key: ''
key: ""
},
brandId: 0,
catelogPath: [],
dataList: [],
cateRelationTableData: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false
}
addOrUpdateVisible: false,
cateRelationDialogVisible: false,
popCatelogSelectVisible: false
};
},
components: {
AddOrUpdate
AddOrUpdate,
CategoryCascader
},
activated() {
this.getDataList()
this.getDataList();
},
methods: {
//
updateBrandStatus(data) {
console.log("最新状态", data);
let { brandId, showStatus } = data;
addCatelogSelect() {
//{"brandId":1,"catelogId":2}
this.popCatelogSelectVisible =false;
this.$http({
url: this.$http.adornUrl('/product/brand/update'),
method: 'post',
data: this.$http.adornData({ brandId, showStatus: showStatus ? 1 : 0 }, false)
url: this.$http.adornUrl("/product/categorybrandrelation/save"),
method: "post",
data: this.$http.adornData({brandId:this.brandId,catelogId:this.catelogPath[this.catelogPath.length-1]}, false)
}).then(({ data }) => {
this.$message({
type: "success",
message: "数据更新成功"
this.getCateRelation();
});
},
deleteCateRelationHandle(id, brandId) {
this.$http({
url: this.$http.adornUrl("/product/categorybrandrelation/delete"),
method: "post",
data: this.$http.adornData([id], false)
}).then(({ data }) => {
this.getCateRelation();
});
},
updateCatelogHandle(brandId) {
this.cateRelationDialogVisible = true;
this.brandId = brandId;
this.getCateRelation();
},
getCateRelation() {
this.$http({
url: this.$http.adornUrl("/product/categorybrandrelation/catelog/list"),
method: "get",
params: this.$http.adornParams({
brandId: this.brandId
})
}).then(({ data }) => {
this.cateRelationTableData = data.data;
});
},
//
getDataList() {
this.dataListLoading = true
this.dataListLoading = true;
this.$http({
url: this.$http.adornUrl('/product/brand/list'),
method: 'get',
url: this.$http.adornUrl("/product/brand/list"),
method: "get",
params: this.$http.adornParams({
'page': this.pageIndex,
'limit': this.pageSize,
'key': this.dataForm.key
page: this.pageIndex,
limit: this.pageSize,
key: this.dataForm.key
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list
this.totalPage = data.page.totalCount
this.dataList = data.page.list;
this.totalPage = data.page.totalCount;
} else {
this.dataList = []
this.totalPage = 0
this.dataList = [];
this.totalPage = 0;
}
this.dataListLoading = false
})
this.dataListLoading = false;
});
},
updateBrandStatus(data) {
console.log("最新信息", data);
let { brandId, showStatus } = data;
//
this.$http({
url: this.$http.adornUrl("/product/brand/update/status"),
method: "post",
data: this.$http.adornData({ brandId, showStatus }, false)
}).then(({ data }) => {
this.$message({
type: "success",
message: "状态更新成功"
});
});
},
//
sizeChangeHandle(val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
this.pageSize = val;
this.pageIndex = 1;
this.getDataList();
},
//
currentChangeHandle(val) {
this.pageIndex = val
this.getDataList()
this.pageIndex = val;
this.getDataList();
},
//
selectionChangeHandle(val) {
this.dataListSelections = val
this.dataListSelections = val;
},
// /
addOrUpdateHandle(id) {
this.addOrUpdateVisible = true
this.addOrUpdateVisible = true;
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id)
})
this.$refs.addOrUpdate.init(id);
});
},
//
deleteHandle(id) {
var ids = id ? [id] : this.dataListSelections.map(item => {
return item.brandId
})
this.$confirm(`确定对[id=${ids.join(',')}]进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var ids = id
? [id]
: this.dataListSelections.map(item => {
return item.brandId;
});
this.$confirm(
`确定对[id=${ids.join(",")}]进行[${id ? "删除" : "批量删除"}]操作?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}
).then(() => {
this.$http({
url: this.$http.adornUrl('/product/brand/delete'),
method: 'post',
url: this.$http.adornUrl("/product/brand/delete"),
method: "post",
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.getDataList()
this.getDataList();
}
})
});
} else {
this.$message.error(data.msg)
this.$message.error(data.msg);
}
})
})
});
});
}
}
}
};
</script>

@ -1,253 +1,383 @@
<!-- -->
<template>
<div>
<el-button type="danger" @click="batchDelete"></el-button>
<el-tree :data="menus" :props="defaultProps" :expand-on-click-node="false" show-checkbox node-key="catId"
:default-expanded-keys="expandedKey" ref="menuTree">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<span>
<el-button v-if="node.level <= 2" type="text" size="mini" @click="() => append(data)">
Append
</el-button>
<el-button type="text" size="mini" @click="() => edit(data)">
edit
</el-button>
<el-button v-if="node.childNodes.length <= 2" type="text" size="mini"
@click="() => remove(node, data)">
Delete
</el-button>
</span>
</span>
</el-tree>
<el-dialog :title="title" :visible.sync="dialogVisible" width="30%">
<el-form :model="category">
<el-form-item label="分类名称" :label-width="formLabelWidth">
<el-input v-model="category.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="图标" :label-width="formLabelWidth">
<el-input v-model="category.icon" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="计量单位" :label-width="formLabelWidth">
<el-input v-model="category.productUnit" autocomplete="off"></el-input>
</el-form-item>
<!-- <el-form-item label="活动区域" :label-width="formLabelWidth">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item> -->
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitData"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
//jsjsjson
//import from '';
export default {
//import使
components: {},
// data
computed: {},
//data
watch: {},
//
data() {
return {
title: "", //
category: {
name: "",
parentCid: 0,
catLevel: 0,
showStatus: 1,
sort: 0,
catId: null, //
icon: "", //
productUnit: "" //
}, //
menus: [],
defaultProps: { //
children: 'children',
label: 'name'
},
expandedKey: [], //
dialogVisible: false, //
dialogType: "", //
};
},
methods: {
// handleNodeClick(data) {
// console.log(data);
// },
//
batchDelete() {
let catIds = [];
let checkNodes = this.$refs.menuTree.getCheckedNodes();
console.log("被选中的node",checkNodes);
for (let i = 0; i<checkNodes.length; i++) {
catIds.push(checkNodes[i].catId);
}
this.$confirm(`是否批量删除【${catIds}】菜单?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
console.log(catIds);
this.$http({
url: this.$http.adornUrl('/product/category/delete'),
method: 'post',
data: this.$http.adornData(catIds, false)
}).then(({ data }) => {
this.$message({
message: '菜单删除成功',
type: 'success'
});
this.getDataList();
})
}).catch(()=>{});
},
submitData() {
if (this.dialogType == "add") {
this.addCategory();
}
if (this.dialogType = "edit") {
this.editCategory();
}
},
editCategory() {
var { name, catId, icon, productUnit } = this.category;
this.$http({
url: this.$http.adornUrl('/product/category/update'),
method: 'post',
data: this.$http.adornData({ name, catId, icon, productUnit }, false)
}).then(({ data }) => {
this.$message({
message: '菜单更新成功',
type: 'success'
});
this.dialogVisible = false;
this.getDataList();
this.expandedKey = [this.category.parentCid];
});
},
addCategory() {
console.log("提交的三级分类名称", this.category);
this.$http({
url: this.$http.adornUrl('/product/category/save'),
method: 'post',
data: this.$http.adornData(this.category, false)
}).then(({ data }) => {
this.$message({
message: '菜单添加成功',
type: 'success'
});
this.dialogVisible = false;
this.getDataList();
console.log("编辑更新的数据", this.menus);
this.expandedKey = [this.category.parentCid];
});
},
getDataList() {
this.$http({
url: this.$http.adornUrl('/product/category/list/tree'),
method: 'get',
}).then(({ data }) => {
console.log("成功获取到菜单数据。。。", data.data);
this.menus = data.data;
})
},
append(data) {
console.log("append", data);
this.title = "添加分类";
this.dialogType = "add";
this.dialogVisible = true;
this.category.parentCid = data.catId;
this.category.catLevel = data.catLevel * 1 + 1;
this.category.catId =null;
this.category.icon = "";
this.category.productUnit = "";
this.category.name="";
},
edit(data) {
console.log("append", data);
this.title = "修改分类";
this.dialogVisible = true;
this.dialogType = "edit";
//
this.$http({
url: this.$http.adornUrl(`/product/category/info/${data.catId}`),
method: 'get',
}).then(({ data }) => {
console.log("要回显的数据", data);
this.category.name = data.data.name;
this.category.catId = data.data.catId;
this.category.icon = data.data.icon;
this.category.productUnit = data.data.productUnit;
this.category.parentCid = data.data.parentCid;
})
},
remove(node, data) {
var ids = [data.catId];
this.$confirm(`是否删除【${data.name}】菜单?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
console.log(data.catId)
this.$http({
url: this.$http.adornUrl('/product/category/delete'),
method: 'post',
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
this.$message({
message: '菜单删除成功',
type: 'success'
});
this.getDataList();
this.expandedKey = [data.parent.data.catId];
})
})
},
},
// - 访this
created() {
this.getDataList();
},
// - 访DOM
mounted() {
},
beforeCreate() { }, // -
beforeMount() { }, // -
beforeUpdate() { }, // -
updated() { }, // -
beforeDestroy() { }, // -
destroyed() { }, // -
activated() { }, //keep-alive
}
</script>
<style scoped></style>
<template>
<div>
<el-switch v-model="draggable" active-text="开启拖拽" inactive-text="关闭拖拽"></el-switch>
<el-button v-if="draggable" @click="batchSave"></el-button>
<el-button type="danger" @click="batchDelete"></el-button>
<el-tree
:data="menus"
:props="defaultProps"
:expand-on-click-node="false"
show-checkbox
node-key="catId"
:default-expanded-keys="expandedKey"
:draggable="draggable"
:allow-drop="allowDrop"
@node-drop="handleDrop"
ref="menuTree"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<span>
<el-button
v-if="node.level <=2"
type="text"
size="mini"
@click="() => append(data)"
>Append</el-button>
<el-button type="text" size="mini" @click="edit(data)">edit</el-button>
<el-button
v-if="node.childNodes.length==0"
type="text"
size="mini"
@click="() => remove(node, data)"
>Delete</el-button>
</span>
</span>
</el-tree>
<el-dialog
:title="title"
:visible.sync="dialogVisible"
width="30%"
:close-on-click-modal="false"
>
<el-form :model="category">
<el-form-item label="分类名称">
<el-input v-model="category.name" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="图标">
<el-input v-model="category.icon" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="计量单位">
<el-input v-model="category.productUnit" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitData"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
//jsjsjson
//import  from '';
export default {
//import使
components: {},
props: {},
data() {
return {
pCid: [],
draggable: false,
updateNodes: [],
maxLevel: 0,
title: "",
dialogType: "", //edit,add
category: {
name: "",
parentCid: 0,
catLevel: 0,
showStatus: 1,
sort: 0,
productUnit: "",
icon: "",
catId: null
},
dialogVisible: false,
menus: [],
expandedKey: [],
defaultProps: {
children: "children",
label: "name"
}
};
},
// data
computed: {},
//data
watch: {},
//
methods: {
getMenus() {
this.$http({
url: this.$http.adornUrl("/product/category/list/tree"),
method: "get"
}).then(({ data }) => {
console.log("成功获取到菜单数据...", data.data);
this.menus = data.data;
});
},
batchDelete() {
let catIds = [];
let checkedNodes = this.$refs.menuTree.getCheckedNodes();
console.log("被选中的元素", checkedNodes);
for (let i = 0; i < checkedNodes.length; i++) {
catIds.push(checkedNodes[i].catId);
}
this.$confirm(`是否批量删除【${catIds}】菜单?`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$http({
url: this.$http.adornUrl("/product/category/delete"),
method: "post",
data: this.$http.adornData(catIds, false)
}).then(({ data }) => {
this.$message({
message: "菜单批量删除成功",
type: "success"
});
this.getMenus();
});
})
.catch(() => {});
},
batchSave() {
this.$http({
url: this.$http.adornUrl("/product/category/update/sort"),
method: "post",
data: this.$http.adornData(this.updateNodes, false)
}).then(({ data }) => {
this.$message({
message: "菜单顺序等修改成功",
type: "success"
});
//
this.getMenus();
//
this.expandedKey = this.pCid;
this.updateNodes = [];
this.maxLevel = 0;
// this.pCid = 0;
});
},
handleDrop(draggingNode, dropNode, dropType, ev) {
console.log("handleDrop: ", draggingNode, dropNode, dropType);
//1id
let pCid = 0;
let siblings = null;
if (dropType == "before" || dropType == "after") {
pCid =
dropNode.parent.data.catId == undefined
? 0
: dropNode.parent.data.catId;
siblings = dropNode.parent.childNodes;
} else {
pCid = dropNode.data.catId;
siblings = dropNode.childNodes;
}
this.pCid.push(pCid);
//2
for (let i = 0; i < siblings.length; i++) {
if (siblings[i].data.catId == draggingNode.data.catId) {
//
let catLevel = draggingNode.level;
if (siblings[i].level != draggingNode.level) {
//
catLevel = siblings[i].level;
//
this.updateChildNodeLevel(siblings[i]);
}
this.updateNodes.push({
catId: siblings[i].data.catId,
sort: i,
parentCid: pCid,
catLevel: catLevel
});
} else {
this.updateNodes.push({ catId: siblings[i].data.catId, sort: i });
}
}
//3
console.log("updateNodes", this.updateNodes);
},
updateChildNodeLevel(node) {
if (node.childNodes.length > 0) {
for (let i = 0; i < node.childNodes.length; i++) {
var cNode = node.childNodes[i].data;
this.updateNodes.push({
catId: cNode.catId,
catLevel: node.childNodes[i].level
});
this.updateChildNodeLevel(node.childNodes[i]);
}
}
},
allowDrop(draggingNode, dropNode, type) {
//13
//1
console.log("allowDrop:", draggingNode, dropNode, type);
//
this.countNodeLevel(draggingNode);
//+3
let deep = Math.abs(this.maxLevel - draggingNode.level) + 1;
console.log("深度:", deep);
// this.maxLevel
if (type == "inner") {
// console.log(
// `this.maxLevel${this.maxLevel}draggingNode.data.catLevel${draggingNode.data.catLevel}dropNode.level${dropNode.level}`
// );
return deep + dropNode.level <= 3;
} else {
return deep + dropNode.parent.level <= 3;
}
},
countNodeLevel(node) {
//
if (node.childNodes != null && node.childNodes.length > 0) {
for (let i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].level > this.maxLevel) {
this.maxLevel = node.childNodes[i].level;
}
this.countNodeLevel(node.childNodes[i]);
}
}
},
edit(data) {
console.log("要修改的数据", data);
this.dialogType = "edit";
this.title = "修改分类";
this.dialogVisible = true;
//
this.$http({
url: this.$http.adornUrl(`/product/category/info/${data.catId}`),
method: "get"
}).then(({ data }) => {
//
console.log("要回显的数据", data);
this.category.name = data.data.name;
this.category.catId = data.data.catId;
this.category.icon = data.data.icon;
this.category.productUnit = data.data.productUnit;
this.category.parentCid = data.data.parentCid;
this.category.catLevel = data.data.catLevel;
this.category.sort = data.data.sort;
this.category.showStatus = data.data.showStatus;
/**
* parentCid: 0,
catLevel: 0,
showStatus: 1,
sort: 0,
*/
});
},
append(data) {
console.log("append", data);
this.dialogType = "add";
this.title = "添加分类";
this.dialogVisible = true;
this.category.parentCid = data.catId;
this.category.catLevel = data.catLevel * 1 + 1;
this.category.catId = null;
this.category.name = "";
this.category.icon = "";
this.category.productUnit = "";
this.category.sort = 0;
this.category.showStatus = 1;
},
submitData() {
if (this.dialogType == "add") {
this.addCategory();
}
if (this.dialogType == "edit") {
this.editCategory();
}
},
//
editCategory() {
var { catId, name, icon, productUnit } = this.category;
this.$http({
url: this.$http.adornUrl("/product/category/update"),
method: "post",
data: this.$http.adornData({ catId, name, icon, productUnit }, false)
}).then(({ data }) => {
this.$message({
message: "菜单修改成功",
type: "success"
});
//
this.dialogVisible = false;
//
this.getMenus();
//
this.expandedKey = [this.category.parentCid];
});
},
//
addCategory() {
console.log("提交的三级分类数据", this.category);
this.$http({
url: this.$http.adornUrl("/product/category/save"),
method: "post",
data: this.$http.adornData(this.category, false)
}).then(({ data }) => {
this.$message({
message: "菜单保存成功",
type: "success"
});
//
this.dialogVisible = false;
//
this.getMenus();
//
this.expandedKey = [this.category.parentCid];
});
},
remove(node, data) {
var ids = [data.catId];
this.$confirm(`是否删除【${data.name}】菜单?`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$http({
url: this.$http.adornUrl("/product/category/delete"),
method: "post",
data: this.$http.adornData(ids, false)
}).then(({ data }) => {
this.$message({
message: "菜单删除成功",
type: "success"
});
//
this.getMenus();
//
this.expandedKey = [node.parent.data.catId];
});
})
.catch(() => {});
console.log("remove", node, data);
}
},
// - 访this
created() {
this.getMenus();
},
// - 访DOM
mounted() {},
beforeCreate() {}, // - 
beforeMount() {}, // - 
beforeUpdate() {}, // - 
updated() {}, // - 
beforeDestroy() {}, // - 
destroyed() {}, // - 
activated() {} //keep-alive
};
</script>
<style scoped>
</style>

@ -0,0 +1,197 @@
<template>
<div class="mod-config">
<el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
<el-form :inline="true" :model="dataForm">
<el-form-item label="分类">
<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
</el-form-item>
<el-form-item label="品牌">
<brand-select style="width:160px"></brand-select>
</el-form-item>
<el-form-item label="价格">
<el-input-number style="width:160px" v-model="dataForm.price.min" :min="0"></el-input-number>-
<el-input-number style="width:160px" v-model="dataForm.price.max" :min="0"></el-input-number>
</el-form-item>
<el-form-item label="检索">
<el-input style="width:160px" v-model="dataForm.key" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="searchSkuInfo"></el-button>
</el-form-item>
</el-form>
</el-form>
<el-table
:data="dataList"
border
v-loading="dataListLoading"
@selection-change="selectionChangeHandle"
style="width: 100%;"
@expand-change="getSkuDetails"
>
<el-table-column type="expand">
<template slot-scope="scope">
商品标题{{scope.row.skuTitle}}
<br />
商品副标题{{scope.row.skuSubtitle}}
<br />
商品描述{{scope.row.skuDesc}}
<br />
分类ID{{scope.row.catalogId}}
<br />
SpuID{{scope.row.spuId}}
<br />
品牌ID{{scope.row.brandId}}
<br />
</template>
</el-table-column>
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
<el-table-column prop="skuId" header-align="center" align="center" label="skuId"></el-table-column>
<el-table-column prop="skuName" header-align="center" align="center" label="名称"></el-table-column>
<el-table-column prop="skuDefaultImg" header-align="center" align="center" label="默认图片">
<template slot-scope="scope">
<img :src="scope.row.skuDefaultImg" style="width:80px;height:80px;" />
</template>
</el-table-column>
<el-table-column prop="price" header-align="center" align="center" label="价格"></el-table-column>
<el-table-column prop="saleCount" header-align="center" align="center" label="销量"></el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="150" label="操作">
<template slot-scope="scope">
<el-button type="text" size="small" @click="previewHandle(scope.row.skuId)"></el-button>
<el-button type="text" size="small" @click="commentHandle(scope.row.skuId)"></el-button>
<el-dropdown
@command="handleCommand(scope.row,$event)"
size="small"
split-button
type="text"
>
更多
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="uploadImages">上传图片</el-dropdown-item>
<el-dropdown-item command="seckillSettings">参与秒杀</el-dropdown-item>
<el-dropdown-item command="reductionSettings">满减设置</el-dropdown-item>
<el-dropdown-item command="discountSettings">折扣设置</el-dropdown-item>
<el-dropdown-item command="memberPriceSettings">会员价格</el-dropdown-item>
<el-dropdown-item command="stockSettings">库存管理</el-dropdown-item>
<el-dropdown-item command="couponSettings">优惠劵</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
</div>
</template>
<script>
import CategoryCascader from "../common/category-cascader";
import BrandSelect from "../common/brand-select";
export default {
data() {
return {
catPathSub: null,
brandIdSub: null,
dataForm: {
key: "",
brandId: 0,
catelogId: 0,
price: {
min: 0,
max: 0
}
},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false,
catelogPath: []
};
},
components: {
CategoryCascader,
BrandSelect
},
activated() {
this.getDataList();
},
methods: {
getSkuDetails(row, expand) {
//sku
console.log("展开某行...", row, expand);
},
//
handleCommand(row, command) {
console.log("~~~~~", row, command);
if ("stockSettings" == command) {
this.$router.push({ path: "/ware-sku", query: { skuId: row.skuId } });
}
},
searchSkuInfo() {
this.getDataList();
},
//
getDataList() {
this.dataListLoading = true;
this.$http({
url: this.$http.adornUrl("/product/skuinfo/list"),
method: "get",
params: this.$http.adornParams({
page: this.pageIndex,
limit: this.pageSize,
key: this.dataForm.key,
catelogId: this.dataForm.catelogId,
brandId: this.dataForm.brandId,
min: this.dataForm.price.min,
max: this.dataForm.price.max
})
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list;
this.totalPage = data.page.totalCount;
} else {
this.dataList = [];
this.totalPage = 0;
}
this.dataListLoading = false;
});
},
//
sizeChangeHandle(val) {
this.pageSize = val;
this.pageIndex = 1;
this.getDataList();
},
//
currentChangeHandle(val) {
this.pageIndex = val;
this.getDataList();
},
//
selectionChangeHandle(val) {
this.dataListSelections = val;
}
},
mounted() {
this.catPathSub = PubSub.subscribe("catPath", (msg, val) => {
this.dataForm.catelogId = val[val.length - 1];
});
this.brandIdSub = PubSub.subscribe("brandId", (msg, val) => {
this.dataForm.brandId = val;
});
},
beforeDestroy() {
PubSub.unsubscribe(this.catPathSub);
PubSub.unsubscribe(this.brandIdSub);
} // - 
};
</script>

@ -0,0 +1,37 @@
<template>
<div>
<base-attr :attrtype="0"></base-attr>
</div>
</template>
<script>
//jsjsjson
//import  from '';
import BaseAttr from './baseattr'
export default {
//import使
components: {BaseAttr},
props: {},
data() {
//
return {};
},
// data
computed: {},
//data
watch: {},
//
methods: {},
// - 访this
created() {},
// - 访DOM
mounted() {},
beforeCreate() {}, // - 
beforeMount() {}, // - 
beforeUpdate() {}, // - 
updated() {}, // - 
beforeDestroy() {}, // - 
destroyed() {}, // - 
activated() {} //keep-alive
};
</script>

@ -0,0 +1,95 @@
<template>
<div>
<el-row>
<el-col :span="24">
<el-form :inline="true" :model="dataForm">
<el-form-item label="分类">
<category-cascader :catelogPath.sync="catelogPath"></category-cascader>
</el-form-item>
<el-form-item label="品牌">
<brand-select style="width:160px"></brand-select>
</el-form-item>
<el-form-item label="状态">
<el-select style="width:160px" v-model="dataForm.status" clearable>
<el-option label="新建" :value="0"></el-option>
<el-option label="上架" :value="1"></el-option>
<el-option label="下架" :value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="检索">
<el-input style="width:160px" v-model="dataForm.key" clearable></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="searchSpuInfo"></el-button>
</el-form-item>
</el-form>
</el-col>
<el-col :span="24">
<spuinfo :catId="catId"></spuinfo>
</el-col>
</el-row>
</div>
</template>
<script>
//jsjsjson
//import  from '';
import CategoryCascader from "../common/category-cascader";
import BrandSelect from "../common/brand-select";
import Spuinfo from "./spuinfo";
export default {
//import使
components: { CategoryCascader, Spuinfo, BrandSelect },
props: {},
data() {
//
return {
catId: 0,
catelogPath: [],
dataForm: {
status: "",
key: "",
brandId: 0,
catelogId: 0
},
catPathSub: null,
brandIdSub: null
};
},
// data
computed: {},
//data
watch: {},
//
methods: {
searchSpuInfo() {
console.log("搜索条件", this.dataForm);
this.PubSub.publish("dataForm",this.dataForm);
}
},
// - 访this
created() {},
// - 访DOM
mounted() {
this.catPathSub = PubSub.subscribe("catPath", (msg, val) => {
this.dataForm.catelogId = val[val.length-1];
});
this.brandIdSub = PubSub.subscribe("brandId", (msg, val) => {
this.dataForm.brandId = val;
});
},
beforeCreate() {}, // - 
beforeMount() {}, // - 
beforeUpdate() {}, // - 
updated() {}, // - 
beforeDestroy() {
PubSub.unsubscribe(this.catPathSub);
PubSub.unsubscribe(this.brandIdSub);
}, // - 
destroyed() {}, // - 
activated() {} //keep-alive
};
</script>
<style scoped>
</style>

@ -0,0 +1,807 @@
<template>
<div>
<el-row>
<el-col :span="24">
<el-steps :active="step" finish-status="success">
<el-step title="基本信息"></el-step>
<el-step title="规格参数"></el-step>
<el-step title="销售属性"></el-step>
<el-step title="SKU信息"></el-step>
<el-step title="保存完成"></el-step>
</el-steps>
</el-col>
<el-col :span="24" v-show="step==0">
<el-card class="box-card" style="width:80%;margin:20px auto">
<el-form ref="spuBaseForm" :model="spu" label-width="120px" :rules="spuBaseInfoRules">
<el-form-item label="商品名称" prop="spuName">
<el-input v-model="spu.spuName"></el-input>
</el-form-item>
<el-form-item label="商品描述" prop="spuDescription">
<el-input v-model="spu.spuDescription"></el-input>
</el-form-item>
<el-form-item label="选择分类" prop="catalogId">
<category-cascader></category-cascader>
</el-form-item>
<el-form-item label="选择品牌" prop="brandId">
<brand-select></brand-select>
</el-form-item>
<el-form-item label="商品重量(Kg)" prop="weight">
<el-input-number v-model.number="spu.weight" :min="0" :precision="3" :step="0.1"></el-input-number>
</el-form-item>
<el-form-item label="设置积分" prop="bounds">
<label>金币</label>
<el-input-number
style="width:130px"
placeholder="金币"
v-model="spu.bounds.buyBounds"
:min="0"
controls-position="right"
></el-input-number>
<label style="margin-left:15px">成长值</label>
<el-input-number
style="width:130px"
placeholder="成长值"
v-model="spu.bounds.growBounds"
:min="0"
controls-position="right"
>
<template slot="prepend">成长值</template>
</el-input-number>
</el-form-item>
<el-form-item label="商品介绍" prop="decript">
<multi-upload v-model="spu.decript"></multi-upload>
</el-form-item>
<el-form-item label="商品图集" prop="images">
<multi-upload v-model="spu.images"></multi-upload>
</el-form-item>
<el-form-item>
<el-button type="success" @click="collectSpuBaseInfo"></el-button>
</el-form-item>
</el-form>
</el-card>
</el-col>
<el-col :span="24" v-show="step==1">
<el-card class="box-card" style="width:80%;margin:20px auto">
<el-tabs tab-position="left" style="width:98%">
<el-tab-pane
:label="group.attrGroupName"
v-for="(group,gidx) in dataResp.attrGroups"
:key="group.attrGroupId"
>
<!-- 遍历属性,每个tab-pane对应一个表单每个属性是一个表单项 spu.baseAttrs[0] = [{attrId:xx,val:}]-->
<el-form ref="form" :model="spu">
<el-form-item
:label="attr.attrName"
v-for="(attr,aidx) in group.attrs"
:key="attr.attrId"
>
<el-input
v-model="dataResp.baseAttrs[gidx][aidx].attrId"
type="hidden"
v-show="false"
></el-input>
<el-select
v-model="dataResp.baseAttrs[gidx][aidx].attrValues"
:multiple="attr.valueType == 1"
filterable
allow-create
default-first-option
placeholder="请选择或输入值"
>
<el-option
v-for="(val,vidx) in attr.valueSelect.split(';')"
:key="vidx"
:label="val"
:value="val"
></el-option>
</el-select>
<el-checkbox
v-model="dataResp.baseAttrs[gidx][aidx].showDesc"
:true-label="1"
:false-label="0"
>快速展示</el-checkbox>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
<div style="margin:auto">
<el-button type="primary" @click="step = 0">上一步</el-button>
<el-button type="success" @click="generateSaleAttrs"></el-button>
</div>
</el-card>
</el-col>
<el-col :span="24" v-show="step==2">
<el-card class="box-card" style="width:80%;margin:20px auto">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>选择销售属性</span>
<el-form ref="saleform" :model="spu">
<el-form-item
:label="attr.attrName"
v-for="(attr,aidx) in dataResp.saleAttrs"
:key="attr.attrId"
>
<el-input
v-model="dataResp.tempSaleAttrs[aidx].attrId"
type="hidden"
v-show="false"
></el-input>
<el-checkbox-group v-model="dataResp.tempSaleAttrs[aidx].attrValues">
<el-checkbox
v-if="dataResp.saleAttrs[aidx].valueSelect != ''"
:label="val"
v-for="val in dataResp.saleAttrs[aidx].valueSelect.split(';')"
:key="val"
></el-checkbox>
<div style="margin-left:20px;display:inline">
<el-button
v-show="!inputVisible[aidx].view"
class="button-new-tag"
size="mini"
@click="showInput(aidx)"
>+自定义</el-button>
<el-input
v-show="inputVisible[aidx].view"
v-model="inputValue[aidx].val"
:ref="'saveTagInput'+aidx"
size="mini"
style="width:150px"
@keyup.enter.native="handleInputConfirm(aidx)"
@blur="handleInputConfirm(aidx)"
></el-input>
</div>
</el-checkbox-group>
</el-form-item>
</el-form>
</div>
<el-button type="primary" @click="step = 1">上一步</el-button>
<el-button type="success" @click="generateSkus">SKU</el-button>
</el-card>
</el-card>
</el-col>
<el-col :span="24" v-show="step==3">
<el-card class="box-card" style="width:80%;margin:20px auto">
<el-table :data="spu.skus" style="width: 100%">
<el-table-column label="属性组合">
<el-table-column
:label="item.attrName"
v-for="(item,index) in dataResp.tableAttrColumn"
:key="item.attrId"
>
<template slot-scope="scope">
<span style="margin-left: 10px">{{ scope.row.attr[index].attrValue }}</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column label="商品名称" prop="skuName">
<template slot-scope="scope">
<el-input v-model="scope.row.skuName"></el-input>
</template>
</el-table-column>
<el-table-column label="标题" prop="skuTitle">
<template slot-scope="scope">
<el-input v-model="scope.row.skuTitle"></el-input>
</template>
</el-table-column>
<el-table-column label="副标题" prop="skuSubtitle">
<template slot-scope="scope">
<el-input v-model="scope.row.skuSubtitle"></el-input>
</template>
</el-table-column>
<el-table-column label="价格" prop="price">
<template slot-scope="scope">
<el-input v-model="scope.row.price"></el-input>
</template>
</el-table-column>
<el-table-column type="expand">
<template slot-scope="scope">
<el-row>
<el-col :span="24">
<label style="display:block;float:left">选择图集 </label>
<multi-upload
style="float:left;margin-left:10px;"
:showFile="false"
:listType="'text'"
v-model="uploadImages"
></multi-upload>
</el-col>
<el-col :span="24">
<el-divider></el-divider>
</el-col>
<el-col :span="24">
<el-card
style="width:170px;float:left;margin-left:15px;margin-top:15px;"
:body-style="{ padding: '0px' }"
v-for="(img,index) in spu.images"
:key="index"
>
<img :src="img" style="width:160px;height:120px" />
<div style="padding: 14px;">
<el-row>
<el-col :span="12">
<el-checkbox
v-model="scope.row.images[index].imgUrl"
:true-label="img"
false-label
></el-checkbox>
</el-col>
<el-col :span="12">
<el-tag v-if="scope.row.images[index].defaultImg == 1">
<input
type="radio"
checked
:name="scope.row.skuName"
@change="checkDefaultImg(scope.row,index,img)"
/>
</el-tag>
<el-tag v-else>
<input
type="radio"
:name="scope.row.skuName"
@change="checkDefaultImg(scope.row,index,img)"
/>
</el-tag>
</el-col>
</el-row>
</div>
</el-card>
</el-col>
</el-row>
<!-- 折扣满减会员价 -->
<el-form :model="scope.row">
<el-row>
<el-col :span="24">
<el-form-item label="设置折扣">
<label></label>
<el-input-number
style="width:160px"
:min="0"
controls-position="right"
v-model="scope.row.fullCount"
></el-input-number>
<label></label>
<label style="margin-left:15px;"></label>
<el-input-number
style="width:160px"
v-model="scope.row.discount"
:precision="2"
:max="1"
:min="0"
:step="0.01"
controls-position="right"
></el-input-number>
<label></label>
<el-checkbox
v-model="scope.row.countStatus"
:true-label="1"
:false-label="0"
>可叠加优惠</el-checkbox>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="设置满减">
<label></label>
<el-input-number
style="width:160px"
v-model="scope.row.fullPrice"
:step="100"
:min="0"
controls-position="right"
></el-input-number>
<label></label>
<label style="margin-left:15px;"></label>
<el-input-number
style="width:160px"
v-model="scope.row.reducePrice"
:step="10"
:min="0"
controls-position="right"
></el-input-number>
<label></label>
<el-checkbox
v-model="scope.row.priceStatus"
:true-label="1"
:false-label="0"
>可叠加优惠</el-checkbox>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="设置会员价" v-if="scope.row.memberPrice.length>0">
<br />
<!-- @change="handlePriceChange(scope,mpidx,$event)" -->
<el-form-item v-for="(mp,mpidx) in scope.row.memberPrice" :key="mp.id">
{{mp.name}}
<el-input-number
style="width:160px"
v-model="scope.row.memberPrice[mpidx].price"
:precision="2"
:min="0"
controls-position="right"
></el-input-number>
</el-form-item>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
</el-table-column>
</el-table>
<el-button type="primary" @click="step = 2">上一步</el-button>
<el-button type="success" @click="submitSkus"></el-button>
</el-card>
</el-col>
<el-col :span="24" v-show="step==4">
<el-card class="box-card" style="width:80%;margin:20px auto">
<h1>保存成功</h1>
<el-button type="primary" @click="addAgian"></el-button>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
//jsjsjson
//import  from '';
import CategoryCascader from "../common/category-cascader";
import BrandSelect from "../common/brand-select";
import MultiUpload from "@/components/upload/multiUpload";
export default {
//import使
components: { CategoryCascader, BrandSelect, MultiUpload },
props: {},
data() {
return {
catPathSub: null,
brandIdSub: null,
uploadDialogVisible: false,
uploadImages: [],
step: 0,
//spu_name spu_description catalog_id brand_id weight publish_status
spu: {
//
spuName: "",
spuDescription: "",
catalogId: 0,
brandId: "",
weight: "",
publishStatus: 0,
decript: [], //
images: [], //sku
bounds: {
//
buyBounds: 0,
growBounds: 0
},
baseAttrs: [], //
skus: [] //sku
},
spuBaseInfoRules: {
spuName: [
{ required: true, message: "请输入商品名字", trigger: "blur" }
],
spuDescription: [
{ required: true, message: "请编写一个简单描述", trigger: "blur" }
],
catalogId: [
{ required: true, message: "请选择一个分类", trigger: "blur" }
],
brandId: [
{ required: true, message: "请选择一个品牌", trigger: "blur" }
],
decript: [
{ required: true, message: "请上传商品详情图集", trigger: "blur" }
],
images: [
{ required: true, message: "请上传商品图片集", trigger: "blur" }
],
weight: [
{
type: "number",
required: true,
message: "请填写正确的重量值",
trigger: "blur"
}
]
},
dataResp: {
//
attrGroups: [],
baseAttrs: [],
saleAttrs: [],
tempSaleAttrs: [],
tableAttrColumn: [],
memberLevels: [],
steped: [false, false, false, false, false]
},
inputVisible: [],
inputValue: []
};
},
// data
computed: {},
//data
watch: {
uploadImages(val) {
//skusimgs
let imgArr = Array.from(new Set(this.spu.images.concat(val)));
//{imgUrl:"",defaultImg:0} concat+
this.spu.skus.forEach((item, index) => {
let len = imgArr.length - this.spu.skus[index].images.length; //
if (len > 0) {
let imgs = new Array(len);
imgs = imgs.fill({ imgUrl: "", defaultImg: 0 });
this.spu.skus[index].images = item.images.concat(imgs);
}
});
this.spu.images = imgArr; //
console.log("this.spu.skus", this.spu.skus);
}
},
//
methods: {
addAgian() {
this.step = 0;
this.resetSpuData();
},
resetSpuData() {
this.spu = {
spuName: "",
spuDescription: "",
catalogId: 0,
brandId: "",
weight: "",
publishStatus: 0,
decript: [],
images: [],
bounds: {
buyBounds: 0,
growBounds: 0
},
baseAttrs: [],
skus: []
};
},
handlePriceChange(scope, mpidx, e) {
this.spu.skus[scope.$index].memberPrice[mpidx].price = e;
},
getMemberLevels() {
this.$http({
url: this.$http.adornUrl("/member/memberlevel/list"),
method: "get",
params: this.$http.adornParams({
page: 1,
limit: 500
})
})
.then(({ data }) => {
this.dataResp.memberLevels = data.page.list;
})
.catch(e => {
console.log(e);
});
},
showInput(idx) {
console.log("``````", this.view);
this.inputVisible[idx].view = true;
// this.$refs['saveTagInput'+idx].$refs.input.focus();
},
checkDefaultImg(row, index, img) {
console.log("默认图片", row, index);
//
row.images[index].imgUrl = img; //
row.images[index].defaultImg = 1; //;
//
row.images.forEach((item, idx) => {
if (idx != index) {
row.images[idx].defaultImg = 0;
}
});
},
handleInputConfirm(idx) {
let inputValue = this.inputValue[idx].val;
if (inputValue) {
// this.dynamicTags.push(inputValue);
if (this.dataResp.saleAttrs[idx].valueSelect == "") {
this.dataResp.saleAttrs[idx].valueSelect = inputValue;
} else {
this.dataResp.saleAttrs[idx].valueSelect += ";" + inputValue;
}
}
this.inputVisible[idx].view = false;
this.inputValue[idx].val = "";
},
collectSpuBaseInfo() {
//spuBaseForm
this.$refs.spuBaseForm.validate(valid => {
if (valid) {
this.step = 1;
this.showBaseAttrs();
} else {
return false;
}
});
},
generateSaleAttrs() {
//attrspu,
this.spu.baseAttrs = [];
this.dataResp.baseAttrs.forEach(item => {
item.forEach(attr => {
let { attrId, attrValues, showDesc } = attr;
//
if (attrValues != "") {
if (attrValues instanceof Array) {
//;
attrValues = attrValues.join(";");
}
this.spu.baseAttrs.push({ attrId, attrValues, showDesc });
}
});
});
console.log("baseAttrs", this.spu.baseAttrs);
this.step = 2;
this.getShowSaleAttr();
},
generateSkus() {
this.step = 3;
//sku
let selectValues = [];
this.dataResp.tableAttrColumn = [];
this.dataResp.tempSaleAttrs.forEach(item => {
if (item.attrValues.length > 0) {
selectValues.push(item.attrValues);
this.dataResp.tableAttrColumn.push(item);
}
});
let descartes = this.descartes(selectValues);
//[["","6GB",""],["","6GB",""],["","8GB",""],["","8GB",""],
//["","6GB",""],["","6GB",""],["","8GB",""],["","8GB",""],
//["","6GB",""],["","6GB",""],["","8GB",""],["","8GB",""]]
console.log("生成的组合", JSON.stringify(descartes));
//descartessku
let skus = [];
descartes.forEach((descar, descaridx) => {
let attrArray = []; //sku
descar.forEach((de, index) => {
//saleAttr
let saleAttrItem = {
attrId: this.dataResp.tableAttrColumn[index].attrId,
attrName: this.dataResp.tableAttrColumn[index].attrName,
attrValue: de
};
attrArray.push(saleAttrItem);
});
//images
let imgs = [];
this.spu.images.forEach((img, idx) => {
imgs.push({ imgUrl: "", defaultImg: 0 });
});
//
let memberPrices = [];
if (this.dataResp.memberLevels.length > 0) {
for (let i = 0; i < this.dataResp.memberLevels.length; i++) {
if (this.dataResp.memberLevels[i].priviledgeMemberPrice == 1) {
memberPrices.push({
id: this.dataResp.memberLevels[i].id,
name: this.dataResp.memberLevels[i].name,
price: 0
});
}
}
}
//;descaridx;
let res = this.hasAndReturnSku(this.spu.skus, descar);
if (res === null) {
skus.push({
attr: attrArray,
skuName: this.spu.spuName + " " + descar.join(" "),
price: 0,
skuTitle: this.spu.spuName + " " + descar.join(" "),
skuSubtitle: "",
images: imgs,
descar: descar,
fullCount: 0,
discount: 0,
countStatus: 0,
fullPrice: 0.0,
reducePrice: 0.0,
priceStatus: 0,
memberPrice: new Array().concat(memberPrices)
});
} else {
skus.push(res);
}
});
this.spu.skus = skus;
console.log("结果!!!", this.spu.skus, this.dataResp.tableAttrColumn);
},
//skudescarsku
hasAndReturnSku(skus, descar) {
let res = null;
if (skus.length > 0) {
for (let i = 0; i < skus.length; i++) {
if (skus[i].descar.join(" ") == descar.join(" ")) {
res = skus[i];
}
}
}
return res;
},
getShowSaleAttr() {
//使
if (!this.dataResp.steped[1]) {
this.$http({
url: this.$http.adornUrl(
`/product/attr/sale/list/${this.spu.catalogId}`
),
method: "get",
params: this.$http.adornParams({
page: 1,
limit: 500
})
}).then(({ data }) => {
this.dataResp.saleAttrs = data.page.list;
data.page.list.forEach(item => {
this.dataResp.tempSaleAttrs.push({
attrId: item.attrId,
attrValues: [],
attrName: item.attrName
});
this.inputVisible.push({ view: false });
this.inputValue.push({ val: "" });
});
this.dataResp.steped[1] = true;
});
}
},
showBaseAttrs() {
if (!this.dataResp.steped[0]) {
this.$http({
url: this.$http.adornUrl(
`/product/attrgroup/${this.spu.catalogId}/withattr`
),
method: "get",
params: this.$http.adornParams({})
}).then(({ data }) => {
//baseAttrs
data.data.forEach(item => {
let attrArray = [];
item.attrs.forEach(attr => {
attrArray.push({
attrId: attr.attrId,
attrValues: "",
showDesc: attr.showDesc
});
});
this.dataResp.baseAttrs.push(attrArray);
});
this.dataResp.steped[0] = 0;
this.dataResp.attrGroups = data.data;
});
}
},
submitSkus() {
console.log("~~~~~", JSON.stringify(this.spu));
this.$confirm("将要提交商品数据,需要一小段时间,是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$http({
url: this.$http.adornUrl("/product/spuinfo/save"),
method: "post",
data: this.$http.adornData(this.spu, false)
}).then(({ data }) => {
if (data.code == 0) {
this.$message({
type: "success",
message: "新增商品成功!"
});
this.step = 4;
} else {
this.$message({
type: "error",
message: "保存失败,原因【" + data.msg + "】"
});
}
});
})
.catch(e => {
console.log(e);
this.$message({
type: "info",
message: "已取消"
});
});
},
//
descartes(list) {
//parent;count
var point = {};
var result = [];
var pIndex = null;
var tempCount = 0;
var temp = [];
//
for (var index in list) {
if (typeof list[index] == "object") {
point[index] = { parent: pIndex, count: 0 };
pIndex = index;
}
}
//
if (pIndex == null) {
return list;
}
//
while (true) {
for (var index in list) {
tempCount = point[index]["count"];
temp.push(list[index][tempCount]);
}
//
result.push(temp);
temp = [];
//
while (true) {
if (point[index]["count"] + 1 >= list[index].length) {
point[index]["count"] = 0;
pIndex = point[index]["parent"];
if (pIndex == null) {
return result;
}
//parent
index = pIndex;
} else {
point[index]["count"]++;
break;
}
}
}
}
},
// - 访this
created() {},
// - 访DOM
mounted() {
this.catPathSub = PubSub.subscribe("catPath", (msg, val) => {
this.spu.catalogId = val[val.length - 1];
});
this.brandIdSub = PubSub.subscribe("brandId", (msg, val) => {
this.spu.brandId = val;
});
this.getMemberLevels();
},
beforeCreate() {}, // - 
beforeMount() {}, // - 
beforeUpdate() {}, // - 
updated() {}, // - 
beforeDestroy() {
PubSub.unsubscribe(this.catPathSub);
PubSub.unsubscribe(this.brandIdSub);
}, // - 
destroyed() {}, // - 
activated() {} //keep-alive
};
</script>
<style scoped>
</style>

@ -0,0 +1,155 @@
<template>
<div class="mod-config">
<el-table
:data="dataList"
border
v-loading="dataListLoading"
@selection-change="selectionChangeHandle"
style="width: 100%;"
>
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
<el-table-column prop="id" header-align="center" align="center" label="id"></el-table-column>
<el-table-column prop="spuName" header-align="center" align="center" label="名称"></el-table-column>
<el-table-column prop="spuDescription" header-align="center" align="center" label="描述"></el-table-column>
<el-table-column prop="catalogId" header-align="center" align="center" label="分类"></el-table-column>
<el-table-column prop="brandId" header-align="center" align="center" label="品牌"></el-table-column>
<el-table-column prop="weight" header-align="center" align="center" label="重量"></el-table-column>
<el-table-column prop="publishStatus" header-align="center" align="center" label="上架状态">
<template slot-scope="scope">
<el-tag v-if="scope.row.publishStatus == 0"></el-tag>
<el-tag v-if="scope.row.publishStatus == 1"></el-tag>
<el-tag v-if="scope.row.publishStatus == 2"></el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" header-align="center" align="center" label="创建时间"></el-table-column>
<el-table-column prop="updateTime" header-align="center" align="center" label="修改时间"></el-table-column>
<el-table-column fixed="right" header-align="center" align="center" width="150" label="操作">
<template slot-scope="scope">
<el-button
v-if="scope.row.publishStatus == 0"
type="text"
size="small"
@click="productUp(scope.row.id)"
>上架</el-button>
<el-button type="text" size="small" @click="attrUpdateShow(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper"
></el-pagination>
</div>
</template>
<script>
export default {
data() {
return {
dataSub: null,
dataForm: {},
dataList: [],
pageIndex: 1,
pageSize: 10,
totalPage: 0,
dataListLoading: false,
dataListSelections: [],
addOrUpdateVisible: false
};
},
props: {
catId: {
type: Number,
default: 0
}
},
components: {},
activated() {
this.getDataList();
},
methods: {
productUp(id) {
this.$http({
url: this.$http.adornUrl("/product/spuinfo/" + id + "/up"),
method: "post"
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.getDataList();
}
});
} else {
this.$message.error(data.msg);
}
});
},
attrUpdateShow(row) {
console.log(row);
this.$router.push({
path: "/product-attrupdate",
query: { spuId: row.id, catalogId: row.catalogId }
});
},
//
getDataList() {
this.dataListLoading = true;
let param = {};
Object.assign(param, this.dataForm, {
page: this.pageIndex,
limit: this.pageSize
});
this.$http({
url: this.$http.adornUrl("/product/spuinfo/list"),
method: "get",
params: this.$http.adornParams(param)
}).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = data.page.list;
this.totalPage = data.page.totalCount;
} else {
this.dataList = [];
this.totalPage = 0;
}
this.dataListLoading = false;
});
},
//
sizeChangeHandle(val) {
this.pageSize = val;
this.pageIndex = 1;
this.getDataList();
},
//
currentChangeHandle(val) {
this.pageIndex = val;
this.getDataList();
},
//
selectionChangeHandle(val) {
this.dataListSelections = val;
},
// /
addOrUpdateHandle(id) {}
},
mounted() {
this.dataSub = PubSub.subscribe("dataForm", (msg, val) => {
console.log("~~~~~", val);
this.dataForm = val;
this.getDataList();
});
},
beforeDestroy() {
PubSub.unsubscribe(this.dataSub);
}
};
</script>
Loading…
Cancel
Save