Commit 1bd11330 by zhangmeng

init

parents
{
"presets": [
["env", { "modules": false }],
"stage-3"
]
}
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
# vue 插件—-门店选择联动
<<<<<<< HEAD
> A Vue.js store-linkage Plugin
![预览图1](http://115.159.76.241/vue-plugins/vue-gic-store-linkage/raw/master/preview/1.jpg)
![预览图2](http://115.159.76.241/vue-plugins/vue-gic-store-linkage/raw/master/preview/2.jpg)
## Install
```shell
npm install @gic-test/vue-gic-store-linkage -S
```
## how to use
```
// main.js
import vueGicStoreLinkage from '@gic-test/vue-gic-store-linkage'
Vue.use(vueGicStoreLinkage)
// 使用页面
<vue-gic-store-linkage :msg="sendChildData" @sendSelectGroupData="getSelectGroupData"></vue-gic-store-linkage>
data() {
return {
// 可传参数
sendChildData: {
storeType:0, //门店类型 0:全部门店 1:门店分组 (对应下面storeGroupIds)2:部分门店 (对应下面storeIds)
storeGroupIds:'', //门店分组 字符串数组,用逗号隔开
storeIds:[] //部分门店 数组对象 对象格式 {storeName:'门店1',storeId:'xxxxxxxxxxxxxx'} 传这种形式是为了回显
},
}
}
methods: {
//获得子元素传递的数据
getSelectGroupData() {
console.log(val)
}
},
```
This diff is collapsed. Click to expand it.
{"version":3,"file":"build.js","sources":["webpack:///build.js"],"mappings":"AAAA","sourceRoot":""}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<title>vue-gic-store</title>
</head>
<body>
<div id="app"></div>
<script src="/dist/build.js"></script>
<!-- <script src="/dist/vue-gic-store.js"></script> -->
</body>
</html>
{
"_from": "@gic-test/vue-gic-store-linkage",
"_id": "@gic-test/vue-gic-store-linkage@1.0.6",
"_inBundle": false,
"_integrity": "sha1-thiyJQQFMXVnC87YfqkPSCK7XzU=",
"_location": "/@gic-test/vue-gic-store-linkage",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "@gic-test/vue-gic-store-linkage",
"name": "@gic-test/vue-gic-store-linkage",
"escapedName": "@gic-test%2fvue-gic-store-linkage",
"scope": "@gic-test",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "http://www.gicdev.com:7001/@gic-test/vue-gic-store-linkage/download/@gic-test/vue-gic-store-linkage-1.0.6.tgz",
"_shasum": "b618b22504053175670bced87ea90f4822bb5f35",
"_spec": "@gic-test/vue-gic-store-linkage",
"_where": "C:\\Users\\Administrator\\Desktop\\private",
"bundleDependencies": false,
"dependencies": {
"axios": "^0.18.0",
"vue": "^2.5.11"
},
"deprecated": false,
"description": "vue-gic-store-linkage Plugin",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"element-ui": "^2.4.6",
"file-loader": "^1.1.4",
"less-loader": "^4.1.0",
"node-sass": "^4.5.3",
"sass-loader": "^6.0.6",
"url-loader": "^1.1.1",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.4.4",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1"
},
"license": "MIT",
"main": "dist/build.js",
"name": "@gic-test/vue-gic-store-linkage",
"private": false,
"scripts": {
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot"
},
"version": "1.0.6"
}
<template>
<div style="padding:20px;">
<vue-gic-store-linkage :model="storeGroupData" @commit-store="getStoreGroup" width="200"></vue-gic-store-linkage>
</div>
</template>
<script>
import vueGicStoreLinkage from './lib/component.vue'
export default {
name: 'app',
data () {
return {
storeGroupData:{"storeGroupId":"ff80808164c7266b0164cb9ee1550039","parentGroupId":"ff808081593917d90159398eca480016","groupLevel":2,"children":[],"storeGroupName":"给对方","label":"给对方","id":"ff80808164c7266b0164cb9ee1550039"}
}
},
components: {
vueGicStoreLinkage
},
methods: {
getStoreGroup(val) {
// console.log(JSON.stringify(val))
}
}
}
</script>
<style lang="scss">
* {
margin: 0;
padding: 0;
}
</style>
.fl {
float: left;
}
.fr {
float: right;
}
\ No newline at end of file
import axios from 'axios';
import qs from 'qs';
axios.defaults.timeout = 10000;
let base = "http://192.168.1.164:8282/gic/";
const timeout = 10000;
let token = ''//sessionStorage.getItem('user');
/*
*
* 统一 get 请求方法
* @url: 请求的 url
* @params: 请求带的参数
* @header: 带 token
*
*/
export const getRequest = (url, params) => {
return axios({
method: 'get',
url: `${base}${url}`,
data: {},
params: params,
headers: {'content-type': 'application/x-www-form-urlencoded'},// "token": token
});
}
<template>
<div class="select-shop" @click="hideTree" >
<el-select v-model="storeType" @change="selectShop" placeholder="请选择" class="select-shop__left" :disabled="disabled">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
<el-popover v-model="showShopTree" v-show="storeType=='1'" popper-class ="select-shop__popover" placement="top-start" trigger="click">
<div class="el-input__inner select-shop__right" slot="reference" @click.prevent.stop="toggleShopTree">{{shopGroupValue}}</div>
<div class="select-shop__tree">
<el-tree
ref="shopGroupTree"
:data="dataObj"
show-checkbox
default-expand-all
:default-checked-keys="checkedKeys"
node-key="storeGroupId"
highlight-current
:props="defaultProps">
</el-tree>
</div>
<div class="select-shop__btn--wrap">
<el-button @click.prevent.stop="hideTree" type="text" size="small" style="color:#303133">取消</el-button>
<el-button @click.prevent.stop="groupBtnSure" type="text" size="small">确定</el-button>
</div>
</el-popover>
<div v-show="storeType=='2'" class="select-shop__right">
<div class="el-input__inner select-shop__tag--input" @click.prevent.stop="toggleSearchShop">
<span v-for="(item,index) in storeIds" :key="index" class="select-shop__tag">{{item.storeName}}<i @click.prevent.stop="removeData(index)" class="dele-icon el-icon-error"></i></span>
<span class="select-shop__tag--tips" v-if="!storeIds.length">请选择门店</span>
</div>
<el-popover placement="top-start" popper-class="select-shop__popper" width="300" trigger="hover">
<el-tag class="select-shop__popper--tag" v-for="(tag,index) in storeIds" :key="tag.storeId" @close="removeData(index)" closable>
{{tag.storeName}}
</el-tag>
<span slot="reference" class="select-shop__right--total" v-show="storeIds.length>1">{{storeIds.length}}</span>
</el-popover>
<transition name="slide-fade">
<div class="select-shop__search" @mouseover="showSearchList = true" @mouseout="showSearchList = false" v-show="showSearchList" >
<div class="select-shop__search--input" @click.stop="">
<el-input @keydown.enter.native="getSearchData()" @keyup.native="getSearchData()" class="input-name" prefix-icon="el-icon-search" size="small" clearable v-model="searchValue" placeholder="输入搜索内容" ></el-input>
</div>
<div class="select-shop__search--list">
<ul v-if="selectList.length>0">
<li @click.prevent.stop="selectShopSuccess(item,index)" v-for="(item,index) in selectList" :key="index"><span>{{item.storeName}}</span></li>
</ul>
<p v-else class="no-data">无搜索内容</p>
<p class="select-shop__search--tip">最多显示5条数据</p>
</div>
</div>
</transition>
</div>
</div>
</template>
<script>
import qs from 'qs';
export default {
name: "vue-gic-store-linkage",
props:{
msg:{
type:Object
},
disabled:{
type:Boolean,
default:false
}
},
data(){
return {
options: [{value: '0',label: '所有门店'}, {value: '1',label: '门店分组'}, {value: '2',label: '部分门店'}],
defaultProps: {children: 'children',label: 'storeGroupName'},
dataObj:[],
showShopTree: false, // 显示门店的树级结构
showSearchList:false, // 显示部分门店的搜索结果
searchValue:'', // 部分门店的下拉框的搜索值
selecData:[],
selectListId:[], // 选中的门店的id
storeList:[], // 店员管理 -- 企业部门 -- 编辑企业成员
shopGroupValue:'已选择0个门店分组',
selectList:[],
storeIds:[],
checkedKeys:[], // 默认选中的门店分组
groupIds:'',
storeType: '0',
}
},
watch:{
msg(oldVal,newVal){
this.init(oldVal)
}
},
created(){
this.init(this.msg)
},
mounted(){
this.getGroupTreeData(); // 获得门店分组的数据
},
methods:{
init(dataObj){ // 初始化
if(dataObj.storeList){
if(dataObj && dataObj.storeList.length>0){ // 店员管理 -- 企业部门 -- 编辑企业成员
this.selecData = dataObj.storeList || []
}
}
if(dataObj.storeType){
this.storeType = dataObj.storeType.toString();
if(this.storeType == '1'){
this.groupIds = dataObj.storeGroupIds;
this.shopGroupValue = '已选择'+(dataObj.storeGroupIds.split(',').length)+'个门店分组';
this.checkedKeys = dataObj.storeGroupIds.split(',').filter(v => !!v);
} else if (this.storeType == '2') {
this.storeIds = Object.assign([],dataObj.storeIds)
}
this.getGroupTreeData();
}
},
getGroupTreeData(){
this.axios.get('/api-admin/store-group-list',{
params: {
requestProject:'gic-web'
}
}).then((res)=>{
var data = res.data;
if(data.errorCode==0){
this.dataObj = data.result;
}
})
},
getSearchData(){ // 部分门店的查询
this.axios.post('/api-plug/query-store-by-code-name',qs.stringify({
requestProject:'gic-web',
searchParam:this.searchValue,
selectedIds:this.selectListId.join(','),
flag:'1'
})).then((res)=>{
var data = res.data;
if(data.errorCode==0){
this.selectList = data.result;
}
})
},
selectShop(){ // 选择门店
this.emitObj();
},
toggleShopTree(){
if (this.disabled) return;
// 门店分组的树结构 1
this.showShopTree = !this.showShopTree
},
groupBtnSure(){ // 选择门店分组的确定按钮
this.showShopTree = false;
if (this.disabled) return;
var storeGroupList = this.$refs.shopGroupTree.getCheckedKeys();
var len = storeGroupList.length;
this.groupIds = storeGroupList.join(',');
this.shopGroupValue = '已选择'+len+'个门店分组';
this.emitObj();
},
toggleSearchShop(){ // 部分门店的树结构 -- 自定义 2
this.showSearchList = !this.showSearchList
},
showSearchTree(){ // 部分门店的搜索
this.showSearchList = true;
},
hideSearch(){ // 隐藏搜索结果框
this.showSearchList = false;
},
hideTree(){
this.showShopTree=false; // 门店分组
this.showSearchList = false; // 部分门店
},
selectShopSuccess(item,index){ // 成功选择部分门店
if (this.storeIds.map(v => v.storeId).indexOf(item.storeId) > -1 ) return;
this.storeIds.push(item);
this.emitObj();
},
removeData(index){ // 移出部分门店
if (this.disabled) return;
this.storeIds.splice(index,1);
this.emitObj();
},
emitObj() {
let obj = {
storeGroupIds:this.groupIds,
storeIds:this.storeIds,
storeType:parseInt(this.storeType)
}
this.$emit('sendSelectGroupData',obj);
}
}
}
</script>
<style lang="scss">
@import './style.scss';
</style>
import component from './component.vue'
const install = {
install(Vue, options) {
Vue.component(component.name, component)
}
}
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(install);
}
export default install;
\ No newline at end of file
.select-shop {
position: relative;
&__left {
width: 200px;
margin-right: 7px;
position: relative;
display: inline-block;
vertical-align: top;
}
&__popover {
width: 200px;
padding: 10px 0 0 0;
}
&__right {
width: 200px;
display: inline-block;
vertical-align: top;
font-size: 14px;
position: relative;
&--total {
position: absolute;
right: 1px;
top: 5px;
height: 30px;
line-height: 30px;
border-radius: 3px;
background: #fff;
opacity: 0.9;
padding: 0 5px;
font-size: 12px;
cursor: pointer;
}
}
&__tree {
padding: 0;
overflow-y: auto;
height: 260px;
box-sizing: border-box;
position: relative;
&::-webkit-scrollbar {
width: 0;
height: 0;
}
.el-tree-node__label {
text-overflow: ellipsis;
display: inline-block;
white-space: nowrap;
width: 100%;
overflow: hidden;
}
}
&__btn--wrap {
padding: 0px 15px;
border-top: 1px solid #ebeef5;
height: 36px;
line-height: 34px;
text-align: right;
}
&__tag--input {
padding: 0 4px;
line-height: 36px;
overflow: hidden;
white-space: nowrap;
}
&__tag--tips {
padding-left: 8px;
line-height: 36px;
}
&__search {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
&--input {
padding: 10px 10px 0 10px;
}
&--list {
.no-data {
height: 34px;
line-height: 34px;
text-align: center;
color: #606266;
}
ul {
padding: 0 10px;
li {
font-size: 14px;
position: relative;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: #606266;
height: 34px;
line-height: 34px;
box-sizing: border-box;
cursor: pointer;
&:hover {
background-color: #f5f7fa;
}
&.on {
color: #409eff;
background-color: #fff;
font-weight: 700;
&:after {
position: absolute;
right: 20px;
font-family: element-icons;
content: "\E611";
font-size: 12px;
font-weight: 700;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
}
}
}
&--tip {
font-size: 12px;
background-color: #f6f8f9;
height: 30px;
line-height: 30px;
padding-left: 10px;
color: #606266;
box-sizing: border-box;
}
}
&__tag {
box-sizing: border-box;
border-color: transparent;
margin: 2px 0 2px 6px;
background-color: #f0f2f5;
height: 24px;
padding: 2px 8px;
line-height: 22px;
color: #909399;
border-radius: 4px;
font-size: 12px;
display: inline-block;
.dele-icon {
padding-left: 5px;
cursor: pointer;
}
}
&__popper {
&--tag {
margin: 4px;
}
}
}
\ No newline at end of file
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import './assets/style.scss';
import axios from 'axios'
axios.defaults.baseURL = 'http://gicdev.demogic.com';
Vue.use(ElementUI);
axios.defaults.withCredentials = true
Vue.prototype.axios = axios
new Vue({
el: '#app',
render: h => h(App)
})
\ No newline at end of file
var path = require('path')
var webpack = require('webpack')
var isDev = process.env.NODE_ENV === 'development'
module.exports = {
entry: isDev ? './src/main.js' : './src/lib/index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js',
library: 'vue-gic-store-linkage',
libraryTarget: 'umd',
umdNamedDefine: true
},
module: {
rules: [{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
},
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
],
},
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this necessary.
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
],
'sass': [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
]
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
// options: {
// limit: 10000,
// name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
// }
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#cheap-module-source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}
\ No newline at end of file
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