Commit c6751842 by 曾经

iconfont文件提交

parent bd8691db
<template>
<div class="test-com">
<h1 class="txt">{{msg}}</h1>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'hello'
};
}
};
</script>
<template>
<div>
<div class="filter-list">
<el-select v-model="cardType" style="width: 200px;" placeholder="卡券类型" clearable @change="handleChange">
<el-option
v-for="item in cardOptions"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
<el-input v-model="cardName" style="width: 200px; margin-left: 20px;" clear placeholder="输入卡券名称" @keyup.native.enter="handleSearch"></el-input>
</div>
<el-table
ref="multipleTable"
:data="cardData"
class="card-table"
tooltip-effect="dark"
style="width: 100%"
@row-click="handleCurrentChangeRow"
>
<el-table-column label width="55">
<template slot-scope="scope">
<el-radio class="radio-style" :label="scope.row.integralMallProId" v-model="radio">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column label="卡券名称" prop="cardName" >
</el-table-column>
<el-table-column prop="proSubName" label="备注名"></el-table-column>
<el-table-column prop="integralCost" label="兑换限制"></el-table-column>
<el-table-column prop="virtualStock" label="库存"></el-table-column>
</el-table>
<div class="pagination" v-if="total>0">
<dm-pagination
@current-change="cardCurrentChange"
:current-page="cardCurrentPage"
small
:page-size="cardPageSize"
layout="prev, pager, next"
:total="total"
></dm-pagination>
</div>
</div>
</template>
<script>
export default {
name: "card-list",
props: {
pname: String
},
data() {
return {
cardType: null, // 卡券类型
cardOptions: [
{ value: 1, label: '折扣券' },
{ value: 0, label: '抵金券' }
],
cardName: '',
radio: null,
cardCurrentPage: 1,
cardPageSize: 5,
cardLimitType: 1,
cardData: [],
total: 0
};
},
methods: {
// 当某行点击的时候
handleCurrentChangeRow(row) {
this.$nextTick(_ => {
// if (row.integralMallProId == this.radio) {
this.$emit('pass-id', row);
// }
});
},
getCardList() {
var param = {
currentPage: this.cardCurrentPage,
pageSize: this.cardPageSize,
requestProject: this.pname,
cardType: this.cardType,
proName: this.cardName
};
this.axios
.get(this.baseUrl + "/api-integral-mall/page-cards-plug", {params: param})
.then(res => {
const resData = res.data;
if (resData.errorCode == 0) {
if (!!resData.result) {
if (!!resData.result.rows) {
this.cardData = resData.result.rows;
} else {
this.cardData = [];
}
this.total = resData.result.total;
}
} else {
this.$message.error({ duration: 1000, message: resData.message });
}
})
.catch(error => {
this.$message.error({
duration: 10000,
message: error.message
});
});
},
// 当前切换分页
cardCurrentChange(val) {
this.cardCurrentPage = val;
this.getCardList();
},
handleChange(val) {
this.cardCurrentPage = 1;
this.getCardList();
},
handleSearch() {
this.cardCurrentPage = 1;
this.getCardList();
}
},
created() {
const host = window.location.origin;
this.baseUrl = host.indexOf("localhost") > -1 ? 'http://www.gicdev.com' : host;
},
mounted() {
this.getCardList();
}
};
</script>
<style scoped>
.filter-list {
margin-bottom: 10px;
}
.pagination {
text-align: right;
margin-top: 10px;
}
</style>
<template>
<div class="gift-list">
<div class="links-tools-row">
<el-select
v-model="giftVal"
style="width: 200px;"
placeholder="礼品类型"
clearable
@change="handleChange"
>
<el-option
v-for="item in giftOptions"
:key="item.integralMallCategoryId"
:label="item.categoryName"
:value="item.integralMallCategoryId"
></el-option>
</el-select>
<el-input
v-model="giftName"
style="width: 200px; margin-left: 20px;"
placeholder="输入礼品名称"
@keyup.native.enter="handleSearch"
></el-input>
</div>
<div class="goods-link-content">
<ul class="goods-link-list">
<li
class="goods-link-item"
v-for="(item, index) in goodsList"
:key="index"
:class="activeIndex == index ? 'good-highlight' : ''"
@click="selectGoodLinkItem(item, index)"
>
<img
:src="item.mainImageUrl"
class="img"
alt="商品图片"
>
<div class="inline-block goods-message">
<p class="limit-2 pro-name">{{item.proName}}</p>
<p class="gray-color pro-code pro-name">所需积分:{{item.integralCost}}</p>
<p class="pro-price pro-name">所需现金:{{item.cashCost}}</p>
</div>
</li>
</ul>
</div>
<div
class="links-tools-page"
v-if="total > 0"
>
<dm-pagination
@current-change="handleChangePage"
:current-page="currentPage"
:page-size="pageSize"
layout="prev, pager, next"
:total="total"
></dm-pagination>
</div>
</div>
</template>
<script>
import qs from "qs";
export default {
name: "gift-list",
props: {
pname: String
},
data() {
return {
currentPage: 1,
activeIndex: -1,
pageSize: 6,
total: 0,
giftVal: null,
giftOptions: [],
goodsList: [],
giftName: ""
};
},
created() {
const host = window.location.origin;
this.baseUrl = host.indexOf("localhost") > -1 ? 'http://www.gicdev.com' : host;
},
methods: {
// 分类
getGiftList() {
this.axios
.get(
`${
this.baseUrl
}/api-integral-mall/load-category?requestProject=gic-web`
)
.then(res => {
const resData = res.data;
if (resData.errorCode === 0) {
if (!!resData.result && resData.result.length) {
this.giftOptions = resData.result;
}
}
});
},
// 分页换页
handleChangePage(val) {
this.currentPage = val;
this.getData();
},
handleChange() {
this.currentPage = 1;
this.getData();
},
// 分页数据 integralCost积分费用 cashCost现金费用 proName
getData() {
const params = {
requestProject: "gic-web",
currentPage: this.currentPage,
pageSize: this.pageSize,
category: this.giftVal,
giftName: this.giftName,
changeType: -1,
releaseType: -1,
showStatus: 1,
porHot: -1
};
this.axios
.post(
`${this.baseUrl}/api-integral-mall/page-gift`,
qs.stringify(params)
)
.then(res => {
const data = res.data;
if (data.errorCode == 0) {
if (!!data.result && data.result.rows) {
this.goodsList = data.result.rows;
}
this.total = data.result.total || 0;
}
});
},
selectGoodLinkItem(item, i) {
this.activeIndex = i;
this.$emit("pass-gift", item);
},
handleSearch() {
this.currentPage = 1;
this.getData();
}
},
mounted() {
this.getGiftList();
this.getData();
}
};
</script>
<style scoped>
.links-tools-row {
margin-bottom: 10px;
}
.links-tools-row .goods-link-item {
display: inline-block;
vertical-align: middle;
width: 307px;
padding: 8px;
margin-right: 7px;
margin-bottom: 10px;
border: 1px solid #dcdfe6;
border-radius: 4px;
box-sizing: border-box;
}
.links-tools-row .goods-link-item .img {
display: inline-block;
vertical-align: middle;
width: 80px;
height: 80px;
}
.links-tools-page {
text-align: right;
}
.links-tools-row .goods-link-item:hover {
cursor: pointer;
border-color: #2F54EB;
}
.links-tools-row .goods-link-item .goods-message {
margin-left: 10px;
padding: 5px;
width: 198px;
box-sizing: border-box;
font-size: 12px;
}
.links-tools-row .good-highlight {
border-color: #2F54EB;
}
.goods-link-item .goods-message .pro-name {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
margin: 8px 0;
}
</style>
<template>
<div class="plug-sg">
<el-popover
popper-class="plug-sg__popover"
placement="bottom"
trigger="click"
v-model="treeVis"
>
<el-input
slot="reference"
suffix-icon="el-icon-arrow-down"
v-model="ategory"
placeholder="所有分类"
></el-input>
<el-tree
class="plug-sg__tree"
ref="tree"
:default-expand-all="true"
node-key="mallProTagId"
:data="treeData"
:props="defaultProps"
:highlight-current="true"
@node-click="handleNodeClick"
>
</el-tree>
<div class="good-tree-btn">
<el-button
@click.prevent.stop="hideTree"
type="text"
size="small"
style="color:#303133"
>取消</el-button>
<el-button
@click.prevent.stop="confirmBtn"
type="text"
size="small"
>确定</el-button>
</div>
</el-popover>
</div>
</template>
<script>
export default {
name: "goods-tree",
props: {
model: {
type: Object,
default() {
return {};
}
},
width: {
type: String,
default: "300"
},
treeData: Array
},
data() {
return {
treeVis: false,
ategory: "",
defaultProps: {
children: "childrenList",
label: "tagName"
}
};
},
methods: {
handleNodeClick(data) {
this.mallData = data;
this.ategory = data.tagName;
},
hideTree() {
this.treeVis = false;
},
confirmBtn() {
this.treeVis = false;
}
},
watch: {
treeVis(newval) {
if (!newval) {
本身是确保确定之后才传值出去
if (this.mallData) {
this.$emit("pass-mall", this.mallData);
}
}
}
}
};
</script>
<style lang="scss">
.plug-sg {
display: inline-block;
width: 200px;
&__popover {
padding: 10px 0 0 0;
}
&__btn {
height: 36px;
padding: 0 10px;
border-top: 1px solid #ebeef5;
line-height: 34px;
text-align: right;
&--cancel {
color: #606266;
}
}
&__tree {
height: 260px;
width: 200px;
overflow-y: auto;
.el-tree-node__label {
text-overflow: ellipsis;
display: inline-block;
white-space: nowrap;
width: 100%;
overflow: hidden;
}
&::-webkit-scrollbar {
width: 0px;
height: 0px;
}
}
}
.good-tree-btn {
float: right;
margin-right: 10px;
}
</style>
export function hasClass(el, cls) {
if (!el || !cls) return false;
if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.');
if (el.classList) {
return el.classList.contains(cls);
} else {
return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;
}
}
/* istanbul ignore next */
export function addClass(el, cls) {
if (!el) return;
let curClass = el.className;
let classes = (cls || '').split(' ');
for (let i = 0, j = classes.length; i < j; i++) {
let clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.add(clsName);
} else if (!hasClass(el, clsName)) {
curClass += ' ' + clsName;
}
}
if (!el.classList) {
el.className = curClass;
}
}
/* istanbul ignore next */
export function removeClass(el, cls) {
let i = 0;
let j;
let clsName;
if (!el || !cls) return;
let classes = cls.split(' ');
let curClass = ' ' + el.className + ' ';
for (i, j = classes.length; i < j; i++) {
clsName = classes[i];
if (!clsName) continue;
if (el.classList) {
el.classList.remove(clsName);
} else if (hasClass(el, clsName)) {
curClass = curClass.replace(' ' + clsName + ' ', ' ');
}
}
if (!el.classList) {
el.className = curClass;
}
}
// 向下查找
function broadcast(componentName, eventName, params) {
this.$children.forEach(child => {
const name = child.$options.name;
if (name === componentName) {
child.$emit.apply(child, [eventName].concat([params]));
} else {
broadcast.apply(child, [componentName, eventName].concat([params]));
}
});
}
// 向上查找组件
export default {
methods: {
dispatch(componentName, eventName, params) {
let parent = this.$parent || this.$root;
let name = parent.$options.name;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
if (parent) {
parent.$emit.apply(parent, [eventName, params]);
}
},
broadcast(componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params);
},
findComponentUpward(context, componentName) {
let parent = context.$parent;
let name = parent.$options.name;
while (parent && (!name || name !== componentName)) {
parent = parent.$parent;
if (parent) {
name = parent.$options.name;
}
}
return parent;
}
// findAnyComponent(componentName, root = null) {
// if (!root) {
// root = this.$root;
// }
// const childrens = root.$children;
// let children = null;
// if (childrens.length) {
// for (const child of childrens) {
// const name = child.$options.name;
// if (name === componentName) {
// children = child;
// break;
// } else {
// children = findAnyComponent.call(this, componentName, child);
// if (children) break;
// }
// }
// }
// return children;
// }
}
};
export function debounce(func, wait) {
let timeout;
return function(...args) {
let that = this;
clearTimeout(timeout);
timeout = setTimeout(_ => {
func.apply(that, args);
}, wait);
};
}
export function throttle(func, wait) {
let timeout;
// let previous = 0; // 时间戳
return function(...args) {
let that = this;
if (!timeout) {
timeout = setTimeout(_ => {
timeout = null;
func.apply(that, args);
}, wait);
}
};
}
<template>
<li :class="classes">
<span> {{ data.categoryName }} </span>
<i v-if="showArrow" class="el-icon-arrow-right fr"></i>
</li>
</template>
<script>
export default {
name: 'Casitem',
props: {
data: Object,
tmpItem: Object
},
computed: {
classes() {
return [
`cascader-menu__item`,
{
[`cascader-menu__item--extensible`]: this.data && this.data.isChildren,
[`is-active`]: this.tmpItem.categoryName === this.data.categoryName
}
];
},
showArrow() {
return this.data.isChildren;
}
},
watch: {
tmpItem(val) {
},
data(newval) {
}
}
};
</script>
<style lang="less" scoped>
.cascader-menu__item {
font-size: 14px;
padding: 8px 20px;
width: 152px;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #606266;
height: 34px;
line-height: 1.5;
box-sizing: border-box;
cursor: pointer;
outline: none;
&:hover {
color: #2F54EB;
}
.fr {
position: absolute;
font-size: 12px;
right: 15px;
top: 50%;
margin-top: -6px;
}
}
.is-active {
color: #2F54EB;
}
</style>
<template>
<div class="caspanel-box">
<span class="ate-keys-box">
<el-input placeholder="搜索关键字" prefix-icon="el-icon-search" v-model="keys" @keyup.native.enter="handleEnter($event)"> </el-input>
</span>
<div class="casitem-box">
<ul v-if="data && data.length" class="casitem-ul">
<Casitem v-for="(item, i) in data" :key="i" :data="item" :tmp-item="tmpItem" @click.native.stop="handleClickItem(item)" @dblclick.native.stop="handleDbClickItem(item)"> </Casitem>
</ul>
</div>
<Caspanel v-if="sublist && sublist.length" :data="sublist" :middle="sublist" :change-on-select="changeOnSelect"></Caspanel>
</div>
</template>
<script>
import Casitem from './casitem';
import Emitter from '../assist/emitter';
import { baseUrl } from '@/config/index.js';
let key = 1;
export default {
name: 'Caspanel',
components: {
Casitem
},
mixins: [Emitter],
props: {
data: {
type: Array,
default() {
return [];
}
},
middle: {
type: Array,
default() {
return [];
}
},
changeOnSelect: Boolean
},
data() {
return {
tmpItem: {},
result: [],
sublist: [],
keys: ''
};
},
methods: {
//
handleEnter(eve) {
let value = eve.target.value;
console.log(this.middle);
this.data = this.middle.filter(el => el.categoryName.indexOf(value) > -1);
},
handleClickItem(item) {
this.tmpItem = Object.assign({}, item);
this.getNextData(item.categoryId);
},
// 双击
handleDbClickItem(item) {
const goodItem = this.findComponentUpward(this, 'gooditem');
item.index = goodItem.goodsIndex;
const tags = Object.assign({}, item);
// 拿到tags比较是否有重复的id
const ategory = this.findComponentUpward(this, 'goods-ategory');
const Tags = ategory.tags;
let hasTag;
if (Tags && Tags.length) {
hasTag = Tags.findIndex(tag => {
return tag.categoryId === item.categoryId;
});
}
if (hasTag != void 0 && hasTag != -1) {
this.$message({
message: '已存在改品类,不能重复添加',
type: 'warning'
});
} else {
this.dispatch('vue-gic-goods-selector', 'handle-ategory', tags);
}
},
// 查找下级
getNextData(id) {
this.axios
.get(`${baseUrl}/api-mall/list-mall-goods-children-category?requestProject=mall&categoryId=${id}`)
.then(res => {
if (res.data.errorCode === 0) {
const data = res.data.result;
if (data && data.length) {
this.sublist = data;
} else if (data && data.length == 0) {
this.sublist = [];
}
} else {
// 占位
}
})
.catch(err => {
console.log(err);
});
},
getKey() {
return key++;
}
}
};
</script>
<style lang="less" scoped>
.caspanel-box {
position: relative;
display: inline-block;
vertical-align: top;
height: 240px;
.ate-keys-box {
display: inline-block;
height: 32px;
width: 138px;
padding: 8px 10px;
border: 1px solid #e8eaec;
border-bottom: none;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
background-color: #f5f7fa;
box-sizing: content-box;
}
.casitem-box {
position: absolute;
border: 1px solid #e8eaec;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
border-top: none;
background-color: #fff;
.casitem-ul {
display: inline-block;
vertical-align: top;
width: 158px;
height: 190px;
list-style: none;
margin: 0;
overflow: auto;
}
}
.caspanel-box {
position: absolute;
margin-left: 12px;
}
}
</style>
<template>
<transition name="transition-drop">
<div class="gic-caspanel">
<Caspanel :data="data" ref="caspanel" :middle="middle" :change-on-select="changeOnSelect"> </Caspanel>
</div>
</transition>
</template>
<script>
import Caspanel from './caspanel';
export default {
name: 'cascader',
components: {
Caspanel
},
props: {
data: {
type: Array,
default() {
return [];
}
},
middle: {
type: Array,
default() {
return [];
}
},
changeOnSelect: {
type: Boolean,
default: false
}
},
data() {
return {
// 占位
};
}
};
</script>
<style lang="less" scoped>
.gic-caspanel {
height: 240px;
padding-bottom: 12px;
overflow-x: auto;
overflow-y: hidden;
font-size: 0px;
}
</style>
import { addClass, removeClass } from './assist/dom';
const Transition = {
beforeEnter(el) {
addClass(el, 'collapse-transition');
if (!el.dataset) el.dataset = {};
el.dataset.oldPaddingTop = el.style.paddingTop;
el.dataset.oldPaddingBottom = el.style.paddingBottom;
el.style.height = '0';
el.style.paddingTop = 0;
el.style.paddingBottom = 0;
},
enter(el) {
el.dataset.oldOverflow = el.style.overflow;
if (el.scrollHeight !== 0) {
el.style.height = el.scrollHeight + 'px';
el.style.paddingTop = el.dataset.oldPaddingTop;
el.style.paddingBottom = el.dataset.oldPaddingBottom;
} else {
el.style.height = '';
el.style.paddingTop = el.dataset.oldPaddingTop;
el.style.paddingBottom = el.dataset.oldPaddingBottom;
}
el.style.overflow = 'hidden';
},
afterEnter(el) {
// for safari: remove class then reset height is necessary
removeClass(el, 'collapse-transition');
el.style.height = '';
el.style.overflow = el.dataset.oldOverflow;
},
beforeLeave(el) {
if (!el.dataset) el.dataset = {};
el.dataset.oldPaddingTop = el.style.paddingTop;
el.dataset.oldPaddingBottom = el.style.paddingBottom;
el.dataset.oldOverflow = el.style.overflow;
el.style.height = el.scrollHeight + 'px';
el.style.overflow = 'hidden';
},
leave(el) {
if (el.scrollHeight !== 0) {
// for safari: add class after set height, or it will jump to zero height suddenly, weired
addClass(el, 'collapse-transition');
el.style.height = 0;
el.style.paddingTop = 0;
el.style.paddingBottom = 0;
}
},
afterLeave(el) {
removeClass(el, 'collapse-transition');
el.style.height = '';
el.style.overflow = el.dataset.oldOverflow;
el.style.paddingTop = el.dataset.oldPaddingTop;
el.style.paddingBottom = el.dataset.oldPaddingBottom;
}
};
export default {
name: 'ElCollapseTransition',
functional: true,
render(h, { children }) {
const data = {
on: Transition
};
return h('transition', data, children);
}
};
<template>
<div class="complex-info">
<div class="complex-items" v-for="(item, i) in abbrInfos" :key="i">
<complex-item :data="item"></complex-item>
<strong class="complex-and" v-if="abbrInfos[i + 1] && abbrInfos[i + 1].length">并且</strong>
</div>
</div>
</template>
<script>
import ComplexItem from './complex-item';
export default {
name: 'complex-info',
props: {
complexData: Array
},
components: {
ComplexItem
},
computed: {
},
watch: {
complexData: {
immediate: true,
handler(newval) {
this.abbrInfos = newval;
}
}
},
data() {
return {
abbrInfos: []
};
}
};
</script>
<style lang="less" scoped>
.complex-items {
.complex-and {
display: inline-block;
margin: 10px 0;
padding: 10px 20px;
color: #64666a;
border-radius: 20px;
background-color: #e2e2e2;
}
}
</style>
<template>
<!-- 缩略信息递归组件的一部分 -->
<div class="complex-item">
<div class="selector-item-txt" v-for="(item, i) in items" :key="i">
<span class="condition" v-if="item.optName"> {{ item.optName }}</span>
<div class="txt">
{{ item.typeName }}{{ item.belong }}
<div class="child-name" v-if="item.childNames.length">
<span v-for="(child, index) in item.childNames" :key="index">
{{ child || '' }}
</span>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'complex-item',
props: {
data: Array
},
watch: {
data: {
immediate: true,
handler(newval) {
this.items = newval;
}
}
},
data() {
return {
items: []
};
}
};
</script>
<style lang="less" scoped>
.complex-item {
.selector-item-txt {
display: inline-block;
vertical-align: middle;
.txt {
display: inline-block;
padding: 5px 10px;
font-size: 12px;
color: #8d8d8d;
background-color: #f5f7fa;
border-radius: 5px;
.child-name {
display: inline-block;
}
}
.condition {
display: inline-block;
vertical-align: middle;
margin: 0 5px;
font-size: 12px;
}
}
}
</style>
const host = window.location.origin;
export const baseUrl = host.('localhost') ? 'http://www.gicdev.com' : host;
<template>
<li class="good-item">
<el-checkbox v-model="item.check"></el-checkbox>
<div class="good-info">
<img :src="item.img" />
<p>{{ item.name }}</p>
<p>{{ item.code }}</p>
</div>
<span class="price"> {{ item.price }} </span>
<span class="store"> {{ item.store }} </span>
</li>
</template>
<script>
export default {
name: 'GoodFilterItem',
props: {
goods: Object
},
data() {
return {
item: {}
};
},
watch: {
goods: {
immediate: true,
handler(newval) {
this.item = newval;
}
}
}
};
</script>
<template>
<div class="goods-ategory">
<div class="check-title">
<div class="ategory-lists">
<span class="ate-txt" v-if="!tags.length">下方选择品类</span>
<el-tag v-for="tag in tags" size="small" :key="tag.categoryId" closable @close="handleClose(tag)"> {{ tag.categoryName }} </el-tag>
<el-popover placement="top" width="320" trigger="hover" popper-class="selector-popper">
<el-tag class="dm-pop-tag" v-for="tag in tags" size="small" :key="tag.categoryId" closable @close="handleClose(tag)"> {{ tag.categoryName }} </el-tag>
<span class="pop-tips" slot="reference">{{ tags.length }}</span>
</el-popover>
</div>
</div>
<div class="ate-group">
<Cascader :data="ateData" :middle="middle"></Cascader>
</div>
<slot></slot>
</div>
</template>
<script>
import Cascader from './cascader';
import { baseUrl } from '@/config/index.js';
export default {
name: 'goods-ategory',
components: {
Cascader
},
props: {
tags: {
type: Array,
default() {
return [];
}
}
},
data() {
return {
ateData: [{}],
middle: [{}]
};
},
methods: {
getData() {
this.axios
.get(`${baseUrl}/api-mall/list-mall-goods-all-category?requestProject=mall`)
.then(res => {
if (res.data.errorCode == 0) {
const data = res.data.result;
if (data && data.length) {
this.ateData = data;
this.middle = data;
console.log(this.middle);
}
} else {
// 占位
}
})
.catch(err => {
console.log(err);
});
},
handleClose(tag) {
let index = this.tags.findIndex(t => {
return t.categoryId === tag.categoryId;
});
if (index != -1) {
this.tags.splice(index, 1);
}
}
},
created() {
this.getData();
}
};
</script>
<style lang="less" scoped>
.goods-ategory {
.check-title {
height: 48px;
line-height: 48px;
background-color: #ebeef5;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
overflow: hidden;
}
.ategory-lists {
position: relative;
overflow: hidden;
white-space: nowrap;
margin: 7px 20px;
padding: 2px 10px;
height: 32px;
line-height: 24px;
font-size: 0px;
border: 1px solid #dcdfe6;
border-radius: 5px;
box-sizing: border-box;
background-color: #fff;
.ate-txt {
font-size: 14px;
color: #c0c4cc;
}
.pop-tips {
position: absolute;
top: 0;
right: 0;
height: 32px;
line-height: 32px;
width: 70px;
text-align: center;
font-size: 14px;
color: #606266;
background-color: rgba(255, 255, 255, 1);
}
}
.ate-group {
padding: 10px 12px;
overflow-x: scroll;
}
}
.el-tag + .el-tag {
margin-left: 10px;
}
.dm-pop-tag {
margin-right: 10px;
margin-bottom: 5px;
}
.dm-pop-tag + .dm-pop-tag {
margin-left: 0px;
}
</style>
<template>
<div class="goods-brand">
<div class="check-title">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全部选择</el-checkbox>
</div>
<el-checkbox-group v-model="checkedBrandes" @change="handleCheckedBrandChange" class="brand-group">
<el-checkbox v-for="brand in brandes" :key="brand.brandId" :label="brand.brandId" class="brand-list">{{ brand.brandName }}</el-checkbox>
</el-checkbox-group>
<slot></slot>
</div>
</template>
<script>
import ElCollapseTransition from './collapse-transition';
import Emitter from './assist/emitter';
import { baseUrl } from '@/config/index.js';
// 品牌
export default {
name: 'goods-brand',
mixins: [Emitter],
components: {
ElCollapseTransition
},
props: {
goodsBrands: Array,
goodsIndex: Array
},
data() {
return {
isIndeterminate: false,
checkAll: false,
checkedBrandes: [],
brandes: []
};
},
methods: {
// 全选
handleCheckAllChange(val) {
this.checkedBrandes = val ? this.brandes : [];
this.isIndeterminate = false;
},
// 复选框多选
handleCheckedBrandChange(val) {
let checkCount = val.length;
this.checkAll = checkCount === this.brandes.length;
this.isIndeterminate = checkCount > 0 && checkCount < this.brandes.length;
},
getBrandList() {
const param = {
currentPage: 1,
pageSize: 20
};
this.axios
.get(`${baseUrl}/api-goods/brandlist?requestProject=goods`, {
params: param
})
.then(res => {
let data;
if (res.data.errorCode === 0) {
data = res.data.result;
this.brandes = data.result;
// 如果超过了20条 totalCount 是总数 根据总数来判断是否还要继续展示第二页的 并不适合全选
} else {
this.$message.error(res.data.message);
}
})
.catch(err => {
this.$message.error(err);
});
}
},
beforeMount() {
// 获取品牌列表
this.getBrandList();
},
watch: {
goodsBrands: {
immediate: true,
handler(newval) {
this.checkedBrandes = newval;
}
},
checkedBrandes(newval) {
this.dispatch('vue-gic-goods-selector', 'pass-checkbox', {
index: this.goodsIndex,
items: newval
});
}
}
};
</script>
<style lang="scss" scoped>
.goods-box {
.check-title {
height: 48px;
line-height: 48px;
padding-left: 20px;
background-color: #ebeef5;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
}
.brand-group {
padding: 10px 20px;
}
.brand-list {
line-height: 30px;
margin-left: 0;
margin-right: 10px;
}
}
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
</style>
<template>
<div class="collection">
<div class="coll-options" v-if="goodIndex[1] <= 3">
<el-radio-group v-model="bindCondition" @change="handleChange">
<el-radio :disabled="disabled" :label="0">并且</el-radio>
<el-radio :disabled="disabled" :label="1">或者</el-radio>
<el-radio :disabled="disabled" :label="2">剔除</el-radio>
</el-radio-group>
</div>
<div class="coll-options" v-else></div>
<div class="oper-btn">
<el-popover placement="top" width="150" trigger="click" v-model="visiable">
<el-radio-group v-model="goodOption" class="pop-options">
<el-radio :label="1" class="pop-goodlist">商品品牌</el-radio>
<el-radio :label="2" class="pop-goodlist">商品品类</el-radio>
<el-radio :label="3" class="pop-goodlist">商品规格</el-radio>
<el-radio :label="4" class="pop-goodlist">商品属性</el-radio>
<el-radio :label="5" class="pop-goodlist">部分商品</el-radio>
</el-radio-group>
<div class="insert-dir">
<el-button type="text" @click="insertUpward">上方插入</el-button>
<el-button type="text" @click="insertUpdown">下方插入</el-button>
</div>
<el-button type="text" class="button-txt" slot="reference" :disabled="length == 5">插入条件</el-button>
</el-popover>
<span class="cut-line">|</span>
<el-button type="text" class="button-txt" @click="deleteCondition">删除</el-button>
</div>
</div>
</template>
<script>
import Emitter from './assist/emitter';
// 集合条件 并且 或者 剔除
export default {
name: 'goods-collection',
props: {
disabled: Boolean,
goodIndex: Array,
length: Number,
condition: Number
},
mixins: [Emitter],
data() {
return {
bindCondition: '',
goodOption: 1, // 插入的商品
visiable: false
};
},
methods: {
deleteCondition() {
// 触发selector 组件去删除
this.dispatch('vue-gic-goods-selector', 'delete-gooditem', this.goodIndex);
},
handleChange(val) {
this.dispatch('vue-gic-goods-selector', 'pass-radioGroup', { index: this.goodIndex, val: this.bindCondition });
},
insertUpward() {
this.dispatch('vue-gic-goods-selector', 'insert-uselector', { index: this.goodIndex, type: parseInt(this.goodOption, 10) });
this.visiable = false;
},
insertUpdown() {
this.dispatch('vue-gic-goods-selector', 'insert-dselector', { index: this.goodIndex, type: parseInt(this.goodOption, 10) });
this.visiable = false;
}
},
watch: {
condition: {
immediate: true,
handler(val) {
this.bindCondition = val;
}
}
}
};
</script>
<style lang="less" scoped>
.collection {
margin-left: 20px;
margin-right: 20px;
padding-top: 10px;
border-top: 1px dashed #dcdfe6;
display: flex;
justify-content: space-between;
.coll-options {
display: inline-block;
}
.oper-btn {
display: inline-block;
text-align: right;
.cut-line {
color: #dcdfe6;
}
}
}
.pop-options {
text-align: center;
.pop-goodlist {
margin-left: 0;
line-height: 26px;
}
}
.insert-dir {
border-top: 1px solid #dcdfe6;
padding-top: 10px;
text-align: center;
}
.button-txt {
color: #a4a7aa;
&:hover {
color: #2F54EB;
}
}
</style>
import GoodsBrand from './goods-brand'; // 商品品牌
import GoodsAtegory from './goods-ategory'; // 商品品类
import GoodsSpecifications from './goods-specifications'; // 规格
import GoodsSome from './goods-some'; // 部分商品
import GoodsProperties from './goods-properties'; // 商品属性
import ElCollapseTransition from './collapse-transition';
export default {
name: 'gooditem',
components: {
GoodsBrand,
GoodsAtegory,
GoodsSpecifications,
GoodsSome,
GoodsProperties,
ElCollapseTransition
},
props: {
type: {
type: String,
validator: val => ['brand', 'ategory', 'specifications', 'properties', 'some'].indexOf(val) > -1
},
goodsIndex: Array,
tags: Array,
goodsBrands: Array
},
data() {
return {};
},
render(h) {
// 定义五种类型
const slotVal = this.$slots.default;
const type = this.type;
let FinalComponent;
// 扩展的属性
const goodsData = {
props: {
tags: this.tags,
'goods-brands': this.goodsBrands,
'goods-index': this.goodsIndex
}
};
if (type == 'brand') {
// 品牌
FinalComponent = <goods-brand {...goodsData}>{slotVal}</goods-brand>;
} else if (type == 'ategory') {
// 品类
FinalComponent = <goods-ategory {...goodsData}>{slotVal}</goods-ategory>;
} else if (type == 'specifications') {
// 规格
FinalComponent = <goods-specifications {...goodsData}>{slotVal}</goods-specifications>;
} else if (type == 'properties') {
// 属性
FinalComponent = <goods-properties {...goodsData}>{slotVal}</goods-properties>;
} else if (type == 'some') {
// 部分商品
FinalComponent = <goods-some {...goodsData}>{slotVal}</goods-some>;
}
return <el-collapse-transition>{FinalComponent}</el-collapse-transition>;
}
};
<template>
<div class="goods-properties">
<div class="check-title">
选择属性
<load-select v-model="propVal" @scrollload="loadMore" :load="load" @change-load="changeLoad">
<gic-load-item v-for="item in propOptions" :key="item.propertyId" :value="item.propertyId" :label="item.propertyName" @pass-item="resiver"> </gic-load-item>
</load-select>
<!-- 多选有 包含其一 和 包含所有-->
<!-- <el-select v-model="exclude" placeholder="请选择" style="width: 120px" v-if="propType === 'TYP_CHECK'">
<el-option
v-for="item in excludeOption"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select> -->
</div>
<div class="prop-content">
<!-- 单选 属性勾选 TYP_SINGLE -->
<!-- v-if="propType === 'TYP_SINGLE' || propType === 'TYP_CHECK'" -->
<div v-if="propType === 'TYP_SINGLE' || propType === 'TYP_CHECK'" class="prop-type">
<el-checkbox :indeterminate="isIndeterminate" v-model="propList.checkAll" @change="handleCheckAllChange">全选</el-checkbox>
<div class="box-group">
<el-checkbox-group v-model="checkedSpes" @change="handleCheckedSpesChange">
<el-checkbox v-for="spe in spes" class="dm-checkbox" :label="spe.propertyId" :key="spe.propertyId">
{{ spe.valueName }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
<!-- 文本 关键字搜索 -->
<!-- <div v-if="propType === 'TYP_TEXT'" class="prop-type">关键字搜索:<el-input v-model="propList.text" style="width: 200px;" maxlength="8" placeholder="关键字" clearable></el-input></div> -->
<!-- 整数 没有小数-->
<!-- <div v-if="propType === 'TYP_NUM'" class="prop-type">
<el-select v-model="interval" placeholder="请选择" style="width: 100px">
<el-option v-for="item in intervalOption" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
<el-input placeholder="请输入" maxlength="8" minlength="1" style="width: 150px" v-model="propList.number"></el-input>
</div> -->
<!-- 实数 有小数-->
<!-- <div v-if="propType === 'TYP_REAL_NUM'" class="prop-type">
<el-select v-model="interval" placeholder="请选择" style="width: 100px;">
<el-option v-for="item in intervalOption" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
<el-input placeholder="请输入" maxlength="8" minlength="1" style="width: 150px;" v-model="propList.rel_num"></el-input>
</div> -->
<!-- 时间 TYP_TIME -->
<!-- <div v-if="propType === 'TYP_TIME'" class="prop-type">
<el-date-picker v-model="propList.Time" type="daterange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间"> </el-date-picker>
</div> -->
</div>
<slot></slot>
</div>
</template>
<script>
import LoadSelect from './load-select';
import GicLoadItem from './load-item';
import Emitter from './assist/emitter';
import { baseUrl } from '@/config/index.js';
// 文本 单选 多选 勾选 整数 实数 货币 时间 百分比
const PROP_TYPE = [
'TYP_TEXT', // 文本
'TYP_SINGLE', // 单选
'TYP_CHECK', // 多选
'TYP_MULTI', // 勾选
'TYP_NUM', // 整数
'TYP_REAL_NUM', // 实数
'TYP_CURRENCY', // 货币
'TYP_TIME', // 时间
'TYP_PERCENT' // 百分比
];
export default {
name: 'goods-properties',
mixins: [Emitter],
props: {
goodsIndex: Array
},
components: {
GicLoadItem,
LoadSelect
},
data() {
return {
propOptions: [],
propVal: [],
checkedSpes: [],
load: false,
currentPage: 1,
spes: [],
interval: null,
isIndeterminate: false,
propType: '',
propList: {
Time: '',
checkAll: false,
number: null,
rel_num: null
}
// intervalOption: [{ label: '>=', value: 0 }, { label: '<=', value: 1 }, { label: '=', value: 2 }]
};
},
watch: {
checkedSpes(newval) {
this.dispatch('vue-gic-goods-selector', 'pass-property', {
index: this.goodsIndex,
items: {
propId: newval,
parentId: this.propertyId,
condition: this.exclude
}
});
},
},
methods: {
loadMore() {
if (this.propOptions.length == (this.currentPage - 1) * 20) {
this.getPropData('success');
} else {
this.load = true;
}
},
changeLoad() {
this.load = false;
},
handleCheckAllChange(val) {
this.checkedSpes = val ? this.spes : [];
this.isIndeterminate = false;
},
handleCheckedSpesChange(value) {
let checkedCount = value.length;
this.propList.checkAll = checkedCount === this.spes.length;
this.isIndeterminate = checkedCount > 0 && checkedCount < this.spes.length;
},
// 商品属性列表下拉数据
getPropData(suc) {
const param = {
currentPage: this.currentPage,
pageSize: 20
};
this.axios
.get(`${baseUrl}/api-goods/page-property?requestProject=goods`, {
params: param
})
.then(res => {
if (res.data.errorCode === 0) {
let data = res.data.result;
this.propOptions = this.propOptions.concat(data.result);
this.currentPage++;
if (suc == 'success') {
this.load = true;
}
} else {
// this.$message.error(res.data.message);
}
})
.catch(err => {
console.log(err);
// this.$message.error(error);
});
},
resiver(val) {
this.propVal = val;
const item = this.propOptions.find(el => el.propertyName === val);
this.propertyId = item.propertyId;
// propertyType 字段属性类型
const type = PROP_TYPE.find(type => type === item.propertyType);
// 属性类型
if (type) {
this.propType = type;
if (this.propType == 'TYP_SINGLE' || this.propType == 'TYP_CHECK') {
const param = {
currentPage: 1,
pageSize: 20,
propertyId: item.propertyId
};
this.axios
.get(`${baseUrl}/api-goods/page-property-value?requestProject=goods`, {
params: param
})
.then(res => {
if (res.data.errorCode == 0) {
const data = res.data.result;
if (data.result && data.result.length) {
this.spes = data.result;
} else {
this.spes = [];
}
}
})
.catch(err => {
console.log(err);
});
}
// 多选
}
}
},
beforeMount() {
this.getPropData();
},
mounted() {
this.$on('pass-item', this.resiver);
}
};
</script>
<style lang="less" scoped>
.goods-properties {
.check-title {
height: 48px;
line-height: 48px;
padding-left: 20px;
background-color: #ebeef5;
font-size: 14px;
color: #606266;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
}
.prop-content {
padding: 10px 20px;
.box-group {
margin-top: 10px;
padding-top: 10px;
border-top: 1px dashed #dcdfe6;
}
.prop-type {
color: #606266;
font-size: 14px;
}
}
}
</style>
<template>
<div class="goods-specifications">
<div class="check-title">
选择规格 &nbsp;
<load-select v-model="specvalue" @scrollload="loadMore" :load="load" @change-load="changeLoad">
<gic-load-item v-for="item in speOptions" :key="item.standardId" :value="item.standardId" :label="item.standardName" @pass-item="resiver"> </gic-load-item>
</load-select>
<!-- 规格类型筛选 -->
<div class="spe-type">
<el-radio v-model="speRadio" label="2">通过规格值筛选</el-radio>
<el-radio v-model="speRadio" label="1">通过规格值组筛选</el-radio>
</div>
</div>
<div class="spe-con">
<spes v-if="spesGroup" :list-spes="spesList" :goods-index="goodsIndex"></spes>
<spe-group v-if="spesVal" :list-group="groupList" :goods-index="goodsIndex" @spe-list="speList"></spe-group>
<!-- <spes v-if="spesGroup && speRadio == '1'" :list-spes="spesList" :goods-index="goodsIndex"></spes>
<spe-group v-if="spesVal && speRadio == '2'" :list-group="groupList" :goods-index="goodsIndex"></spe-group> -->
</div>
<slot></slot>
</div>
</template>
<script>
import Emitter from './assist/emitter';
import Spes from './spes';
import SpeGroup from './spe-group';
import LoadSelect from './load-select';
import GicLoadItem from './load-item';
import { baseUrl } from '@/config/index.js';
export default {
name: 'goods-specifications',
mixins: [Emitter],
components: {
Spes,
SpeGroup,
LoadSelect,
GicLoadItem
},
props: {
goodsIndex: Array
},
data() {
return {
spesGroup: false,
spesVal: false,
speOptions: [], // 规格
speRadio: '2',
currentPage: 1,
load: false,
specvalue: '',
spesList: [],
groupList: [] // 规格值 在规格值组里面
};
},
methods: {
speList(list) {
this.dispatch('vue-gic-goods-selector', 'pass-spe-group-list', {
index: this.goodsIndex,
item: list
});
},
loadMore() {
if (this.speOptions.length == (this.currentPage - 1) * 20) {
this.getOptionsData('success');
} else {
this.load = true;
}
},
// 规格查找
getOptionsData(suc) {
const param = {
type: 'TYP_NORMAL',
currentPage: this.currentPage,
pageSize: 20
};
this.axios
.get(`${baseUrl}/api-goods/page-standard?requestProject=goods`, {
params: param
})
.then(res => {
let data;
if (res.data.errorCode === 0) {
data = res.data.result;
this.speOptions = this.speOptions.concat(data.result);
this.currentPage++;
if (suc == 'success') {
this.load = true;
}
} else {
this.$message.error(res.data.message);
}
})
.catch(err => {
this.$message.error(err);
});
},
changeLoad() {
this.load = false;
},
resiver(val) {
// 选中的值
console.log(val);
this.specvalue = val;
this.specList = this.speOptions.find(val => val.standardName == this.specvalue);
if (this.specList && this.specList.standardId) {
this.validateGoods();
}
},
// 查询是规格值还是规格值组
validateGoods() {
this.axios.get(`${baseUrl}/api-goods/validate-standard-pull-data?requestProject=goods&standardId=${this.specList.standardId}`).then(res => {
const data = res.data;
// false是规格值组 true 是规格值
if (data.errorCode === 0) {
if (data.result) {
this.spesGroup = false;
this.spesVal = true;
// this.speRadio = '2';
this.getSpeData();
} else {
this.spesVal = false;
this.spesGroup = true;
// this.speRadio = '1';
this.getSpeGroupData();
}
}
});
},
// 规格值分组数据
getSpeGroupData() {
const param = {
currentPage: 1,
pageSize: 20,
parentId: this.specList.standardId,
type: 'TYP_GROUP',
categoryId: this.specList.gicStandardId
};
this.axios
.get(`${baseUrl}/api-goods/page-standard?requestProject=goods`, {
params: param
})
.then(res => {
if (res.data.errorCode === 0) {
const data = res.data.result;
if (data.result && data.result.length) {
this.spesList = data.result;
} else {
this.spesList = [];
}
}
})
.catch(err => {
console.log(err);
});
},
// 规格值数据
getSpeData() {
const param = {
currentPage: 1,
pageSize: 20,
standardId: this.specList.standardId
};
this.axios
.get(`${baseUrl}/api-goods/page-standard-values?requestProject=goods`, {
params: param
})
.then(res => {
if (res.data.errorCode === 0) {
const data = res.data.result;
if (data.result && data.result.length) {
const middleData = data.result;
this.groupList = middleData;
// this.groupList = middleData.map(el => {
// if (el.standardGroupNames && el.standardGroupNames.length) {
// el.standardGroup = [];
// for (let i = 0; i < el.standardGroupNames.length; i++) {
// el.standardGroup.push({
// valueName: el.standardGroupNames[i],
// valueId: el.standardGroupIds[i]
// });
// }
// }
// return el;
// });
} else {
this.groupList = [];
}
}
})
.catch(err => {
console.log(err);
});
}
},
mounted() {
// this.$on('pass-item', this.resiver);
},
beforeMount() {
this.getOptionsData();
}
};
</script>
<style lang="less" scoped>
.goods-box {
.check-title {
height: 48px;
line-height: 48px;
padding-left: 20px;
font-size: 14px;
background-color: #ebeef5;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
}
.spe-con {
max-height: 285px;
padding: 10px 20px;
overflow: hidden;
}
.spe-type {
float: right;
margin-right: 20px;
}
}
</style>
import vueGicSelector from './index.vue';
const gicSelector = {
install(Vue, options) {
Vue.component(vueGicSelector.name, vueGicSelector);
}
};
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(gicSelector);
}
export default gicSelector;
<template>
<li class="load-item" @click="handleClick">
<slot>
<span>{{ currentLabel }}</span>
</slot>
</li>
</template>
<script>
import Emitter from './assist/emitter';
export default {
name: 'gic-load-item',
mixins: [Emitter],
props: {
value: {
required: true
},
label: [String, Number]
},
computed: {
currentLabel() {
return this.label || this.value;
}
},
methods: {
handleClick() {
this.$emit('pass-item', this.currentLabel);
}
}
};
</script>
<style lang="less" scoped>
.load-item {
height: 24px;
line-height: 24px;
padding: 4px 10px;
cursor: pointer;
color: #606266;
&:hover {
background-color: #f5f7fa;
}
}
</style>
<template>
<el-popover placement="bottom" width="195" trigger="click" v-model="loadShow" popper-class="select-popper">
<ul class="load-ul" @scroll="handleScroll" ref="loadbox">
<slot></slot>
<p class="el-select-dropdown__empty no-data" v-if="isEmpty">
<i class="el-icon-loading"></i>
{{ emptyTxt }}
</p>
</ul>
<div class="load-select" slot="reference">
<el-input placeholder="请选择" v-model="selectLabel" readonly="readonly" :class="{ 'is-focus': visible }" ref="select">
<i slot="suffix" :class="['el-select__caret', 'el-input__icon', 'el-icon-arrow-up' + iconClass]" @click="handleIconClick"> </i>
</el-input>
</div>
</el-popover>
</template>
<script>
import LoadItem from './load-item'; // 加载的item选项
export default {
name: 'load-select',
components: {
LoadItem
},
props: {
value: {
required: true
},
load: {
type: Boolean,
default: false
},
loadover: {
type: Boolean,
default: false
}
},
computed: {
iconClass() {
if (this.visible) {
return ' is-reverse';
} else {
return '';
}
}
},
data() {
return {
readonly: false,
visible: false,
selectLabel: '',
isEmpty: false,
emptyTxt: '',
loadShow: false
};
},
watch: {
load: {
immediate: true,
handler(newval) {
if (newval) {
this.isEmpty = false;
this.$emit('change-load');
// 方案一 加载时候移动一下
// 方案二 价格loadover 标识
this.$refs.loadbox.scrollTop = this.$refs.loadbox.scrollHeight - 250;
}
}
},
value(newval) {
this.selectLabel = newval;
this.loadShow = false;
this.visible = false;
},
loadShow(newval) {
if (newval) {
this.visible = true;
} else {
this.visible = false;
}
}
},
methods: {
handleIconClick() {
this.visible = !this.visible;
},
// 滚动监听
handleScroll(e) {
const ele = e.target;
// scrollHeight 获取元素内容高度
// scrollTop 可以获取或者设置元素的偏移值
// 满足滚到底部和上次加载结束两个条件
if (ele.scrollHeight - ele.scrollTop == 220 && !this.isEmpty) {
// 滚到底部 先加载
this.emptyTxt = '加载中';
this.isEmpty = true;
setTimeout(_ => {
this.$emit('scrollload');
}, 500);
}
}
}
};
</script>
<style lang="less" scoped>
.load-select {
display: inline-block;
width: 200px;
cursor: pointer;
}
.load-ul {
position: relative;
max-height: 200px;
padding-bottom: 20px;
overflow: auto;
.no-data {
padding: 0;
text-align: center;
color: #ccc;
}
}
.el-select__caret {
color: #c0c4cc;
font-size: 14px;
transition: transform 0.3s;
transform: rotateZ(180deg);
cursor: pointer;
}
.el-select__caret.is-reverse {
transform: rotateZ(0deg);
}
</style>
<template>
<div class="sku-filter">
<div class="title">
<el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="handleCheckAllChange" v-if="!skuFlt"></el-checkbox>
<span class="arrow-bottom" v-if="skuFlt"></span>
<span class="good-info">
商品信息
</span>
<el-popover placement="bottom" width="280" trigger="click" v-model="showPopPrice">
<el-input placeholder="最低单价" :minlength="1" :maxlength="6" style="width: 90px;" v-model="lowPrice"></el-input>
<el-input placeholder="最高单价" :minlength="1" :maxlength="6" style="width: 90px;" v-model="mostPrice"></el-input>
&nbsp;
<el-button type="primary" @click="searchGoods">搜索</el-button>
<span class="price" :class="{ 'showpop-price': showPopPrice }" slot="reference" @click="showPopPrice = !showPopPrice">
单价
<i class="icon iconfont icon-shaixuan-shi icon-filter"></i>
</span>
</el-popover>
<el-popover placement="bottom" width="280" trigger="click" v-model="showPopNum">
<el-input placeholder="最低数量" :minlength="1" :maxlength="6" style="width: 90px;" v-model="lowStore"></el-input>
<el-input placeholder="最高数量" :minlength="1" :maxlength="6" style="width: 90px;" v-model="mostStore"></el-input>
&nbsp;
<el-button type="primary" @click="storeSearch">搜索</el-button>
<span class="price store" :class="{ 'showpop-num': showPopNum }" slot="reference" @click="showPopNum = !showPopNum">
库存
<i class="icon iconfont icon-shaixuan-shi icon-filter"></i>
</span>
</el-popover>
</div>
<ul class="goods-sku-lists">
<sku-left-item v-for="(item, i) in items" :key="i" :goods="item" :inx="i" :check="skuFlt" :checkbox.sync="item.check" @changeIndeterminate="handleIndeter"></sku-left-item>
<span class="el-table__empty-text no-data" v-if="!items || !items.length">暂无数据</span>
</ul>
</div>
</template>
<script>
import SkuLeftItem from './sku-left-item';
import { throttle } from './assist/util';
// 正则
const INTEGER_REG = /^[1-9]{1}[0-9]{0,5}$/; // 最小1 最大999999 的整数
export default {
name: 'SkuFilterTable',
components: {
SkuLeftItem
},
props: {
data: Array,
skufilter: Boolean // sku筛选
},
data() {
return {
skuFlt: null,
checkAll: false,
visiable: false,
items: [],
mostPrice: null,
lowPrice: null,
lowStore: null,
mostStore: null,
showPopPrice: false,
showPopNum: false,
isIndeterminate: false,
checkedGoods: [] // 选中的商品
};
},
methods: {
// 处理最低的库存
handleLowStore() {
// 占位
},
// 处理最高的库存
handleMostStore() {
// 占位
},
// item 是勾选的sku信息
resiverSku(val) {
// val里面有个check
if (val.checkAll !== void 0) {
this.$emit('resiverAllSku', {
skus: val.skus,
inx: val.inx,
})
} else {
this.$emit('resiverSku');
}
},
// 单价搜索
searchGoods() {
// 占位
},
// 库存搜索
storeSearch() {
// 占位
},
handleCheckAllChange(val) {
this.items = this.items.map(el => ({
...el,
check: val
}));
this.isIndeterminate = false;
this.$emit('resiverSku', this.items);
},
// 修改checkbox的状态
handleIndeter() {
this.checkedGoods = this.items.filter(el => el.check);
this.checkAll = this.checkedGoods.length === this.items.length;
this.isIndeterminate = this.checkedGoods.length > 0 && this.checkedGoods.length < this.items.length;
},
// 正则限制输入价格和库存
regInput(val) {
if (!INTEGER_REG.test(val)) {
this.$message.warning('单价必须大于0!');
}
}
},
mounted() {
this.$on('passku', this.resiverSku);
// 低价
this.$watch(
'lowPrice',
throttle(newval => {
this.regInput(newval);
}, 500)
);
// 高级
this.$watch(
'mostPrice',
throttle(newval => {
this.regInput(newval);
}, 500)
);
},
watch: {
skufilter: {
immediate: true,
handler(newval) {
this.skuFlt = newval;
}
},
data: {
immediate: true,
handler(newval) {
this.items = newval;
}
},
checkedGoods: {
immediate: true,
handler(newval) {
this.$emit('resiverSku');
}
}
}
};
</script>
<style lang="less" scoped>
.sku-filter {
height: 350px;
padding-bottom: 20px;
.title {
height: 44px;
line-height: 44px;
padding: 0 10px;
font-size: 14px;
background-color: #f5f7fa;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
color: #909399;
.arrow-bottom {
display: inline-block;
vertical-align: middle;
width: 14px;
}
span {
display: inline-block;
text-align: center;
height: 44px;
}
.good-info {
width: 160px;
text-align: left;
padding-left: 10px;
}
.price {
position: relative;
width: 60px;
outline: none;
border: none;
.icon-filter::before {
top: 10px;
}
}
.store {
position: relative;
width: 60px;
}
.showpop-price,
.showpop-num {
background-color: #e3e5eb;
}
}
.goods-sku-lists {
height: 303px;
overflow: auto;
list-style: none;
.no-data {
display: inline-block;
width: 100%;
text-align: center;
font-size: 14px;
}
}
}
</style>
<template>
<li class="sku-item" v-if="popShow">
<el-popover placement="bottom" :width="320" trigger="hover">
<div slot="reference">
<el-checkbox v-model="skuItem.check" @change="handleChange"></el-checkbox>
<div class="good-img">
<img :src="skuItem.img" />
</div>
<div class="good-info">
<p class="name" :title="skuItem.goodsName">{{ skuItem.goodsName }}</p>
<p class="code" :title="skuItem.goodsCode">{{ skuItem.goodsCode }}</p>
</div>
</div>
<table-checkbox :data="skuItem.skus" b-color="white"></table-checkbox>
</el-popover>
</li>
<li class="sku-item" v-else>
<el-checkbox v-model="skuItem.check" @change="handleChange"></el-checkbox>
<div class="good-img">
<img :src="skuItem.img" />
</div>
<div class="good-info">
<p class="name">{{ skuItem.goodsName }}</p>
<p class="code">{{ skuItem.goodsCode }}</p>
</div>
</li>
</template>
<script>
import TableCheckbox from './table-checkbox';
export default {
name: 'sku-item',
components: {
TableCheckbox
},
props: {
skuList: Object,
popShow: Boolean
},
data() {
return {
skuItem: {},
visiable: false
};
},
methods: {
handleChange(val) {
this.$emit('update:check', val);
this.$emit('pass-check');
}
},
watch: {
skuList: {
immediate: true,
handler(newval) {
this.skuItem = newval;
}
}
}
};
</script>
<style lang="less" scoped>
.sku-item {
height: 56px;
line-height: 56px;
padding: 0 10px;
box-sizing: border-box;
border-bottom: 1px solid #dcdfe6;
.good-img {
margin: 0 10px;
display: inline-block;
vertical-align: middle;
height: 35px;
width: 35px;
img {
height: 100%;
width: 100%;
}
}
.good-info {
display: inline-block;
vertical-align: middle;
p {
margin: 0;
font-size: 12px;
width: 73px;
height: 20px;
line-height: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
&:last-child {
border-bottom: none;
}
}
</style>
<template>
<li class="sku-left-item">
<div class="goods-box" :class="{ expands: expands }">
<div class="gic-icon">
<el-checkbox v-model="skuItem.check" @change="handleChange" v-if="!checked"></el-checkbox>
<i class="icon-trans el-icon-arrow-right" @click="expands = !expands" v-if="checked"></i>
</div>
<div class="good-img">
<img class="img" :src="skuItem.mainImageUrl" />
<div class="info">
<p class="name" :title="skuItem.goodsName">{{ skuItem.goodsName }}</p>
<p class="code" :titile="skuItem.goodsCode">{{ skuItem.goodsCode }}</p>
</div>
</div>
<div class="good-item good-price">
{{ skuItem.salePrice }}
</div>
<div class="good-item good-store">
{{ skuItem.spuStock }}
</div>
</div>
<!-- 如果勾选sku 展示sku show-checkbox 决定是左边的勾选 还是右边的pop显示 一个是展示 一个是待操作 -->
<el-collapse-transition>
<table-checkbox :data="skuItem.skus" show-checkbox v-if="expands" :inx="inx" @passku="resiverSku"></table-checkbox>
</el-collapse-transition>
</li>
</template>
<script>
import ElCollapseTransition from './collapse-transition';
import TableCheckbox from './table-checkbox';
import Emitter from './assist/emitter';
import { baseUrl } from '@/config/index.js';
export default {
name: 'sku-left-item',
mixins: [Emitter],
components: {
ElCollapseTransition,
TableCheckbox
},
props: {
check: Boolean,
goods: Object,
inx: Number
},
data() {
return {
checked: null, // 是显示el-box 还是显示 > ( 也就是sku的筛选 )
skuItem: null,
expands: false
};
},
methods: {
handleChange(val) {
this.$emit('update:checkbox', val);
this.$emit('changeIndeterminate');
},
// 接收 sku筛选的时候传过来的值
resiverSku(item) {
console.log(item);
this.dispatch('');
},
getSkuList() {
this.axios
.get(`${baseUrl}/api-goods/list-store-goods-select-sku?goodsId=${this.skuItem.goodsId}`)
.then(res => {
if (res.data.errorCode === 0) {
const data = res.data.result;
if (data && data.length) {
this.skuItem.skus = data.map(el => ({
...el,
color: this.parseAttr(el.skuAttributes).color,
size: this.parseAttr(el.skuAttributes).size
}));
// 当前商品id 跟左边的数据对比
const component = this.findComponentUpward(this, 'goods-some');
if (component.filterData.length) {
const data = component.filterData;
// 当前商品左边的商品
if (data.length) {
const currentGoods = data.find(ele => this.skuItem.goodsId === ele.goodsId);
// 找到存在的sku 然后切换状态
currentGoods.skus.forEach(sku => {
for (let i = 0; i < this.skuItem.skus.length; i++) {
if (this.skuItem.skus[i].skuId === sku.skuId) {
this.skuItem.skus[i].check = true;
break;
}
}
});
// 主动切换sku的状态
this.broadcast('table-checkbox', 'changeSkuStatus');
}
}
} else {
this.skuItem.skus = [];
}
}
})
.catch(err => {
console.log(err);
});
},
parseAttr(attr = '') {
if (!attr) return { color: '--', size: '--' };
let attrs = JSON.parse(attr);
return {
color: attrs[0].valueName,
size: attrs[1].valueName
};
}
},
watch: {
check: {
immediate: true,
handler(newval) {
this.checked = newval;
if (!newval) {
this.expands = false;
}
}
},
goods: {
immediate: true,
handler(newval) {
this.skuItem = newval;
}
},
expands(newval) {
// 请求商品的sku
if (newval) {
this.getSkuList();
}
}
}
};
</script>
<style lang="less" scoped>
.sku-left-item {
font-size: 12px;
color: #606266;
border-bottom: 1px solid #dcdfe6;
.expands {
border-bottom: 1px solid #dcdfe6;
}
.gic-icon {
display: inline-block;
vertical-align: middle;
width: 16px;
height: 56px;
line-height: 56px;
padding: 0 10px;
}
.good-img {
display: inline-block;
vertical-align: middle;
height: 56px;
width: 160px;
.img {
display: inline-block;
vertical-align: middle;
height: 40px;
width: 40px;
border-radius: 2px;
}
.info {
display: inline-block;
vertical-align: middle;
padding: 6px 0;
p {
width: 110px;
height: 16px;
line-height: 16px;
margin: 4px 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.good-info {
display: inline-block;
vertical-align: middle;
}
.good-item {
display: inline-block;
vertical-align: middle;
text-align: center;
width: 60px;
}
.goods-box {
.icon-trans {
padding: 4px;
transition: all 0.3s;
}
}
.expands .icon-trans {
transform: rotate(90deg);
}
&:last-child {
margin-bottom: -1px;
padding-bottom: 20px;
}
}
</style>
<template>
<!-- 商品规格 规格值筛选 -->
<div class="good-spes">
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
<div class="box-group">
<el-checkbox-group v-model="checkedSpes" @change="handleCheckedSpesChange">
<el-checkbox v-for="spe in spes" :label="spe" :key="spe.standardId">
{{ spe.standardName }}
</el-checkbox>
</el-checkbox-group>
</div>
</div>
</template>
<script>
import Emitter from './assist/emitter';
// 商品规格
export default {
name: 'good-spes',
mixins: [Emitter],
props: {
listSpes: {
type: Array,
default() {
return [];
}
},
goodsIndex: Array
},
data() {
return {
checkAll: false,
checkedSpes: [],
spes: [],
isIndeterminate: false
};
},
watch: {
listSpes: {
immediate: true,
handler(val) {
this.spes = val;
}
},
checkedSpes(newval) {
this.dispatch('vue-gic-goods-selector', 'pass-spes', {
index: this.goodsIndex,
items: newval
});
}
},
methods: {
handleCheckAllChange(val) {
this.checkedSpes = val ? this.spes : [];
this.isIndeterminate = false;
},
handleCheckedSpesChange(value) {
let checkedCount = value.length;
this.checkAll = checkedCount === this.spes.length;
this.isIndeterminate = checkedCount > 0 && checkedCount < this.spes.length;
}
}
};
</script>
<style lang="less" scoped>
.good-spes .box-group {
margin-top: 10px;
}
</style>
.goods-box {
.check-title {
height: 48px;
line-height: 48px;
padding-left: 20px;
border: 1px solid #dcdfe6;
border-bottom: none;
background-color: #f5f7fa;
}
.brand-group {
padding: 10px 20px;
border: 1px solid #dcdfe6;
border-top: none;
}
.brand-list {
min-width: 175px;
line-height: 30px;
margin-left: 0;
margin-right: 10px;
}
}
\ No newline at end of file
<template>
<!-- 表格内部sku筛选的组件 -->
<div class="sku-checkbox" :class="{ 'sku-white': bgColor }" v-if="skus.length">
<div class="sku-table">
<el-checkbox v-model="allSku" v-if="showCheckBox" :indeterminate="isIndeterminate" @change="handleCheckAllChange"></el-checkbox>
<span class="sku-attr sku-code">SKU码</span>
<span class="sku-attr sku-color">颜色</span>
<span class="sku-attr sku-size">大小</span>
</div>
<ul class="sku-lists">
<li v-for="(sku, i) in skus" :key="i" class="list">
<el-checkbox v-if="showCheckBox" v-model="sku.check" @change="handleCheckedSku"></el-checkbox>
<span class="sku-attr sku-code" :title="sku.skuCode">{{ sku.skuCode }}</span>
<span class="sku-color sku-attr">
{{ sku.color }}
</span>
<span class="sku-size sku-attr">
{{ sku.size }}
</span>
</li>
</ul>
</div>
<div class="no-sku-data" v-else>
<i class="icon iconfont icon-jibenxinxi"></i>
暂无数据
</div>
</template>
<script>
import Emitter from './assist/emitter';
export default {
name: 'table-checkbox',
mixins: [Emitter],
props: {
data: {
type: Array,
default() {
return [];
}
},
showCheckbox: Boolean,
bColor: String,
inx: Number
},
data() {
return {
skus: [],
allSku: false,
showCheckBox: false,
isIndeterminate: false,
checkedSku: []
};
},
methods: {
handleSkuStatus() {
this.checkedSku = this.skus.filter(el => el.check);
this.allSku = this.checkedSku.length === this.skus.length;
this.isIndeterminate = this.checkedSku.length > 0 && this.checkedSku.length < this.skus.length;
},
handleCheckAllChange(val) {
this.skus = this.skus.map(el => ({
...el,
check: val
}));
this.isIndeterminate = false;
this.dispatch('SkuFilterTable', 'passku', {
skus: this.skus,
inx: this.inx,
checkAll: val
});
},
handleCheckedSku() {
this.handleSkuStatus();
// 每次勾选sku的时候传到最外层的商品层
this.dispatch('SkuFilterTable', 'passku', {
skus: this.skus,
inx: this.inx
});
}
},
created() {
this.showCheckBox = this.showCheckbox;
this.bgColor = this.bColor ? this.bColor : '';
},
mounted() {
// 切换sku的状态 跟左边对应
this.$on('changeSkuStatus', this.handleSkuStatus);
},
watch: {
data: {
immediate: true,
handler(newval) {
this.skus = newval;
}
}
}
};
</script>
<style lang="less" scoped>
.sku-checkbox {
padding: 20px 10px 20px 30px;
.sku-attr {
display: inline-block;
vertical-align: middle;
margin: 0 5px;
line-height: 30px;
color: #909399;
}
.sku-code {
width: 140px;
}
.sku-color {
width: 50px;
text-align: center;
}
.sku-size {
width: 50px;
text-align: center;
}
.sku-lists {
.list {
height: 35px;
line-height: 35px;
}
}
}
.sku-white {
background-color: #fff;
.sku-table {
border-bottom: 1px solid #dcdfe6;
}
}
.no-sku-data {
margin: 15px 0;
text-align: center;
color: #8ab3d9;
.icon-jibenxinxi {
display: block;
margin-bottom: 10px;
color: #8ab3d9;
font-size: 18px;
}
}
</style>
<template> </template>
<script>
export default {
name: 'tree-node'
};
</script>
<template>
<div class="linktools">
<el-button type="primary" @click="open" @linkSelect="linkSelect">链接工具</el-button>
<linktools :showType="showType" :linkVisible.sync="linkToolsVisible" />
</div>
</template>
<script>
import Linktools from './linktools.vue';
export default {
name: 'linktool',
components: {
Linktools
},
data() {
return {
projectName: 'member', // 当前项目
linkToolsVisible: false,
showType: 0
};
},
methods: {
open() {
this.linkToolsVisible = true;
},
},
};
</script>
<template>
<div>
<div>
<vue-gic-group-people
:projectName="projectName"
:useId="useId"
:hasSearchData="hasSearchData"
:sceneValue="sceneValue"
ref="peopleFilter"
:isAdd="operateType"
@findFilter="findFilter"
@getBackData="getBackData"
@editHide="editHide"
@editShow="editShow"
@hideBtn="hideBtn"
></vue-gic-group-people>
<div class="people-button">
<el-button size="small" type="primary" @click="getData">确定</el-button>
<el-button size="small" @click="cancelFilter">取消</el-button>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'people',
data() {
return {
// 可传参数
projectName: "", // 当前项目名
sceneValue: "member", // 场景值
useId: "", // 模板id
hasSearchData: "", // 当前页回显的数据(接口返回)
operateType: true, // 编辑的时候是false 新增是true 例如列表筛选是开始true 编辑改成false
toggleTag: false, // 控制(确认取消)按钮显示的参数,仅供参考,可自行修改
saveTag: false // 控制(保存)按钮显示的参数,仅供参考,可自行修改
};
},
beforeMount() {
// (如果需要传递数据)请求的数据最好在这里写
},
methods: {
// 父组件调用子组件方法,触发父组件事件
getData() {
this.$refs.peopleFilter.confirmSet();
},
// 子组件触发父组件事件,返回过滤条件数据
findFilter(value) {
var that = this;
},
// 取消
cancelFilter() {
this.$refs.peopleFilter.cancelSet();
},
// 获取需要回显的数据, 供保存时候使用
getBackData(val) {
this.getSaveData = val;
},
// 显示编辑,保存按钮隐藏,确认按钮显示 (子组件会调用)
editShow() {
var that = this;
that.toggleTag = true;
that.saveTag = false;
},
// 显示保存按钮,隐藏确认按钮显示 (子组件会调用)
editHide() {
var that = this;
that.toggleTag = false;
that.saveTag = true;
},
// 隐藏保存按钮和确认按钮 (子组件会调用)
// 传个参数给父组件 来查数据
hideBtn(refresh) {
if (refresh === 0) {
this.memberSearchStr = -1;
this.toggleTag = false;
}
},
// 保存当前模板,对接保存接口
saveTempData() {
var that = this;
}
}
};
</script>
<template>
<div class="selector-router">
<vue-gic-goods-selector ref="selector"></vue-gic-goods-selector>
<div class="gic-button">
<el-button
type="primary"
@click="confirm"
v-if="expends"
>确认</el-button>
<el-button
@click="goback"
v-else
>返回</el-button>
</div>
<h1>一共有{{ total }}条数据</h1>
<!-- 展示数据 -->
<div>
<li v-for="(r, i) in ret" :key="i" class="good-list">{{r}}</li>
</div>
</div>
</template>
<script>
// import vueGicGoodsSelector from "./goods/index.vue";
import { doFetchqs } from "../components/axios/api";
import { baseUrl, ERR_OK } from "@/config/index.js";
export default {
name: "selector",
// components: {
// vueGicGoodsSelector
// },
data() {
return {
expends: true,
ret: [],
total: 0
};
},
methods: {
// 提交
confirm() {
// 占位
this.$refs.selector.collectConditions().then(res => {
this.expends = !res.filterAbbrInfo.length;
this.getGoodsList(res.conditions);
});
},
// reback 返回展示选的选项
goback() {
this.ret = [];
this.expends = !this.expends;
this.$refs.selector.removeConditions();
},
// 通过商品选择器获取商品列表
getGoodsList(queryList) {
const data = {
currentPage: 1,
pageSize: 40,
source: 1,
queryList: queryList
};
this.axios.post(`${baseUrl}/api-plug/store-goods-sku-filter`,data).then(res => {
if (res.data.errorCode === ERR_OK) {
const data = res.data.result;
this.ret = data.result;
this.total = data.total;
}
});
}
}
};
</script>
<style lang="scss" scoped>
.selector-router {
width: 650px;
margin: 40px auto;
.gic-button {
margin-top: 20px;
}
.good-list {
margin: 10px 0;
}
}
</style>
<template>
<div class="upload">
<vue-gic-space
id="dropzone"
ref="myDropzone"
:options="dropzoneOptions"
:action="folderUrl"
:parentId="parentId"
:useCustomSlot="true"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将图片或文件夹拖到此处上传,或点击<b>上传</b>图片</div>
<div class="upload-tips">仅支持5M以内的jpg、png、gif格式的图片</div>
</vue-gic-space>
</div>
</template>
<script>
export default {
name: "upload-space",
data() {
return {
dropzoneOptions: {
autoProcessQueue: false,
url: "http://gicdev.com/api-mall/gic-cloud-image-upload?requestProject=mall", //上传地址
headers: { "Gic-Header": "header value" }
},
parentId: "60404611a2a64502b0612b703f8c3b27",
folderUrl: "http://gicdev.com/api-mall/gic-cloud-image-createUploadFolder?requestProject=mall"
};
}
};
</script>
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -6,6 +6,167 @@
"description": "",
"glyphs": [
{
"icon_id": "28506829",
"name": "编辑",
"font_class": "bianji6",
"unicode": "ec81",
"unicode_decimal": 60545
},
{
"icon_id": "28506833",
"name": "删除",
"font_class": "delete",
"unicode": "ec82",
"unicode_decimal": 60546
},
{
"icon_id": "28687110",
"name": "more",
"font_class": "more",
"unicode": "ec97",
"unicode_decimal": 60567
},
{
"icon_id": "30105703",
"name": "升级",
"font_class": "shengji",
"unicode": "eca9",
"unicode_decimal": 60585
},
{
"icon_id": "11939784",
"name": "更多",
"font_class": "gengduo2",
"unicode": "e6aa",
"unicode_decimal": 59050
},
{
"icon_id": "7501395",
"name": "上传",
"font_class": "shangc",
"unicode": "e6ac",
"unicode_decimal": 59052
},
{
"icon_id": "19954052",
"name": "下载",
"font_class": "xiazai",
"unicode": "eb83",
"unicode_decimal": 60291
},
{
"icon_id": "20415179",
"name": "PlusOutlined",
"font_class": "PlusOutlined",
"unicode": "e6a9",
"unicode_decimal": 59049
},
{
"icon_id": "27876718",
"name": "配置为空",
"font_class": "peizhiweikong",
"unicode": "ec56",
"unicode_decimal": 60502
},
{
"icon_id": "8376401",
"name": "arrow-right",
"font_class": "arrow-right1",
"unicode": "e808",
"unicode_decimal": 59400
},
{
"icon_id": "23919509",
"name": "原因",
"font_class": "yuanyin",
"unicode": "e6a7",
"unicode_decimal": 59047
},
{
"icon_id": "19657697",
"name": "积分管理",
"font_class": "jifenguanli",
"unicode": "e6a8",
"unicode_decimal": 59048
},
{
"icon_id": "26925526",
"name": "角色列表",
"font_class": "jiaoseliebiao",
"unicode": "e6a1",
"unicode_decimal": 59041
},
{
"icon_id": "10235785",
"name": "用户列表",
"font_class": "yonghuliebiao1",
"unicode": "e6a0",
"unicode_decimal": 59040
},
{
"icon_id": "26804068",
"name": "停业整顿",
"font_class": "tingyezhengdun",
"unicode": "e69f",
"unicode_decimal": 59039
},
{
"icon_id": "26803980",
"name": "已上线",
"font_class": "yishangxian",
"unicode": "e689",
"unicode_decimal": 59017
},
{
"icon_id": "26803981",
"name": "未上线",
"font_class": "weishangxian",
"unicode": "e69d",
"unicode_decimal": 59037
},
{
"icon_id": "26803982",
"name": "待上线",
"font_class": "daishangxian",
"unicode": "e69e",
"unicode_decimal": 59038
},
{
"icon_id": "26701965",
"name": "活动列表",
"font_class": "huodongliebiao",
"unicode": "e698",
"unicode_decimal": 59032
},
{
"icon_id": "26701968",
"name": "活动统计",
"font_class": "huodongtongji",
"unicode": "e699",
"unicode_decimal": 59033
},
{
"icon_id": "26701969",
"name": "佣金管理",
"font_class": "yongjinguanli",
"unicode": "e69c",
"unicode_decimal": 59036
},
{
"icon_id": "24937766",
"name": "error_403",
"font_class": "error_403",
"unicode": "ebd0",
"unicode_decimal": 60368
},
{
"icon_id": "24838389",
"name": "no-access",
"font_class": "no-access",
"unicode": "ebc9",
"unicode_decimal": 60361
},
{
"icon_id": "20657659",
"name": "积分加倍",
"font_class": "jifenjiabei",
......@@ -48,6 +209,13 @@
"unicode_decimal": 58994
},
{
"icon_id": "26304073",
"name": "任务完成",
"font_class": "renwuwancheng",
"unicode": "ec13",
"unicode_decimal": 60435
},
{
"icon_id": "20893446",
"name": "QuestionCircleOutlined",
"font_class": "QuestionCircleOutlined",
......@@ -97,13 +265,6 @@
"unicode_decimal": 59020
},
{
"icon_id": "25698898",
"name": "积分",
"font_class": "jifen1",
"unicode": "e689",
"unicode_decimal": 59017
},
{
"icon_id": "672034",
"name": "收起",
"font_class": "shouqi1",
......@@ -1133,34 +1294,6 @@
"unicode_decimal": 59281
},
{
"icon_id": "6841622",
"name": "轨迹检索",
"font_class": "guijijiansuo",
"unicode": "e78c",
"unicode_decimal": 59276
},
{
"icon_id": "6841623",
"name": "消费",
"font_class": "xiaofei2",
"unicode": "e78d",
"unicode_decimal": 59277
},
{
"icon_id": "6841624",
"name": "基本信息",
"font_class": "jibenxinxi",
"unicode": "e78e",
"unicode_decimal": 59278
},
{
"icon_id": "6841625",
"name": "营销活动管理",
"font_class": "yingxiaohuodongguanli",
"unicode": "e78f",
"unicode_decimal": 59279
},
{
"icon_id": "3934054",
"name": "分隔符",
"font_class": "fengefu",
......@@ -1364,13 +1497,6 @@
"unicode_decimal": 59927
},
{
"icon_id": "327811",
"name": "双向呼叫",
"font_class": "shuangxianghujiao",
"unicode": "e617",
"unicode_decimal": 58903
},
{
"icon_id": "707983",
"name": "语音消息",
"font_class": "yuyinxiaoxi",
......@@ -1378,13 +1504,6 @@
"unicode_decimal": 58973
},
{
"icon_id": "1510339",
"name": "短信",
"font_class": "duanxin",
"unicode": "e61d",
"unicode_decimal": 58909
},
{
"icon_id": "2741961",
"name": "手机验证码",
"font_class": "shoujiyanzhengma",
......
No preview for this file type
import Vue from 'vue';
Vue.config.productionTip = false;
// require all test files (files that ends with .spec.js)
const testsContext = require.context('./specs', true, /\.spec$/);
testsContext.keys().forEach(testsContext);
// require all src files except main.js for coverage.
// you can also change this to match only the subset of files that
// you want coverage for.
const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/);
srcContext.keys().forEach(srcContext);
\ No newline at end of file
This is a karma config file. For more details see
http:karma-runner.github.io/0.13/config/configuration-file.html
we are also using it with karma-webpack
https:github.com/webpack/karma-webpack
var webpackConfig = require('../../build/webpack.base.test');
module.exports = function karmaConfig (config) {
config.set({
to run in additional browsers:
1. install corresponding karma launcher
http:karma-runner.github.io/0.13/config/browsers.html
2. add it to the `browsers` array below.
browsers: ['Chrome'],
frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'],
reporters: ['spec', 'coverage'],
files: ['./index.js'],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
coverageReporter: {
dir: './coverage',
reporters: [
{ type: 'lcov', subdir: '.' },
{ type: 'text-summary' }
]
}
});
};
\ No newline at end of file
import Vue from 'vue';
import TestCon from '@/test/TestCom';
describe('Test.vue', () => {
let vm;
it('测试TestCom组件值是否显示正常', done => {
vm = new Vue(TestCon).$mount();
console.log(vm.msg);
vm.msg = '测试';
Vue.nextTick(_ => {
expect(vm.msg).to.equal('测试');
});
});
});
\ No newline at end of file
import Vue from 'vue';
import Element from 'main/index.js';
Vue.use(Element);
let id = 0;
const createElm = function() {
const elm = document.createElement('div');
elm.id = 'app' + ++id;
document.body.appendChild(elm);
return elm;
};
/**
* 回收 vm
* @param {Object} vm
*/
exports.destroyVM = function(vm) {
vm.$destroy && vm.$destroy();
vm.$el &&
vm.$el.parentNode &&
vm.$el.parentNode.removeChild(vm.$el);
};
/**
* 创建一个 Vue 的实例对象
* @param {Object|String} Compo 组件配置,可直接传 template
* @param {Boolean=false} mounted 是否添加到 DOM 上
* @return {Object} vm
*/
exports.createVue = function(Compo, mounted = false) {
if (Object.prototype.toString.call(Compo) === '[object String]') {
Compo = { template: Compo };
}
return new Vue(Compo).$mount(mounted === false ? null : createElm());
};
/**
* 创建一个测试组件实例
* @link http:vuejs.org/guide/unit-testing.html#Writing-Testable-Components
* @param {Object} Compo - 组件对象
* @param {Object} propsData - props 数据
* @param {Boolean=false} mounted - 是否添加到 DOM 上
* @return {Object} vm
*/
exports.createTest = function(Compo, propsData = {}, mounted = false) {
if (propsData === true || propsData === false) {
mounted = propsData;
propsData = {};
}
const elm = createElm();
const Ctor = Vue.extend(Compo);
return new Ctor({ propsData }).$mount(mounted === false ? null : elm);
};
/**
* 触发一个事件
* mouseenter, mouseleave, mouseover, keyup, change, click 等
* @param {Element} elm
* @param {String} name
* @param {*} opts
*/
exports.triggerEvent = function(elm, name, ...opts) {
let eventName;
if (/^mouse|click/.test(name)) {
eventName = 'MouseEvents';
} else if (/^key/.test(name)) {
eventName = 'KeyboardEvent';
} else {
eventName = 'HTMLEvents';
}
const evt = document.createEvent(eventName);
evt.initEvent(name, ...opts);
elm.dispatchEvent
? elm.dispatchEvent(evt)
: elm.fireEvent('on' + name, evt);
return elm;
};
/**
* 触发 “mouseup” 和 “mousedown” 事件
* @param {Element} elm
* @param {*} opts
*/
exports.triggerClick = function(elm, ...opts) {
exports.triggerEvent(elm, 'mousedown', ...opts);
exports.triggerEvent(elm, 'mouseup', ...opts);
return elm;
};
/**
* 触发 keydown 事件
* @param {Element} elm
* @param {keyCode} int
*/
exports.triggerKeyDown = function(el, keyCode) {
const evt = document.createEvent('Events');
evt.initEvent('keydown', true, true);
evt.keyCode = keyCode;
el.dispatchEvent(evt);
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment