Commit 3e0d0799 authored by smallwei's avatar smallwei

需要重新 install

parent fa73eccc
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -10,7 +10,7 @@
"test:e2e": "vue-cli-service test:e2e"
},
"dependencies": {
"@smallwei/avue": "^1.4.2",
"@smallwei/avue": "^1.4.3",
"avue-plugin-transfer": "^0.0.2",
"avue-plugin-ueditor": "^0.0.1",
"axios": "^0.18.0",
......
import Carousel from './src/main';
Carousel.install = function(Vue) {
Vue.component(Carousel.name, Carousel);
};
export default Carousel;
\ No newline at end of file
<template>
<div :class="b()">
<el-carousel :type="option.type"
:height="option.height+'px'"
:autoplay="option.autoplay"
:interval="option.interval"
indicator-position="outside">
<el-carousel-item v-for="(item,index) in data"
:key="index">
<div :class="b('item')">
<a :href="item.href?item.href:'javascript:void(0);'"
:target="item.target">
<div :class="b('img')"
:style="{backgroundImage:'url('+item.src+')'}"></div>
<div :class="b('title')"
v-if="item.title">{{ item.title }}</div>
</a>
</div>
</el-carousel-item>
</el-carousel>
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'carousel',
data () {
return {
};
},
props: {
option: {
type: Object,
default: () => { }
}
},
computed: {
data () {
return this.option.data || [];
},
},
created () { },
mounted () { },
watch: {},
methods: {}
});
</script>
\ No newline at end of file
import CrudCascader from '../crud/src/crud-cascader';
CrudCascader.install = function(Vue) {
Vue.component(CrudCascader.name, CrudCascader);
};
export default CrudCascader;
import CrudCheckBox from '../crud/src/crud-checkbox';
CrudCheckBox.install = function(Vue) {
Vue.component(CrudCheckBox.name, CrudCheckBox);
};
export default CrudCheckBox;
import CrudData from '../crud/src/crud-date';
CrudData.install = function(Vue) {
Vue.component(CrudData.name, CrudData);
};
export default CrudData;
import CrudInputNumber from '../crud/src/crud-input-number';
CrudInputNumber.install = function(Vue) {
Vue.component(CrudInputNumber.name, CrudInputNumber);
};
export default CrudInputNumber;
import CrudInput from '../crud/src/crud-input';
CrudInput.install = function(Vue) {
Vue.component(CrudInput.name, CrudInput);
};
export default CrudInput;
import CrudRadio from '../crud/src/crud-radio';
CrudRadio.install = function(Vue) {
Vue.component(CrudRadio.name, CrudRadio);
};
export default CrudRadio;
import CrudRate from '../crud/src/crud-rate';
CrudRate.install = function(Vue) {
Vue.component(CrudRate.name, CrudRate);
};
export default CrudRate;
import CrudSelect from '../crud/src/crud-select';
CrudSelect.install = function(Vue) {
Vue.component(CrudSelect.name, CrudSelect);
};
export default CrudSelect;
import CrudSilder from '../crud/src/crud-silder';
CrudSilder.install = function(Vue) {
Vue.component(CrudSilder.name, CrudSilder);
};
export default CrudSilder;
import CrudSwitch from '../crud/src/crud-switch';
CrudSwitch.install = function(Vue) {
Vue.component(CrudSwitch.name, CrudSwitch);
};
export default CrudSwitch;
import CrudTime from '../crud/src/crud-time';
CrudTime.install = function(Vue) {
Vue.component(CrudTime.name, CrudTime);
};
export default CrudTime;
import CrudUpload from '../crud/src/crud-upload.vue';
CrudUpload.install = function(Vue) {
Vue.component(CrudUpload.name, CrudUpload);
};
export default CrudUpload;
import Crud from './src/main';
Crud.install = function(Vue) {
Vue.component(Crud.name, Crud);
};
export default Crud;
//crud配置文件
export default {
//标题
editTitle: '编 辑',
addTitle: '新 增',
viewTitle: '查 看',
menuTitle: '操作',
tipStartTitle: '当前表格已选择',
tipEndTitle: '项',
//尺寸
menuWidth: 240,
//文字
viewBtnTitle: '查 看',
editBtnTitle: '编 辑',
addBtnTitle: '新 增',
delBtnTitle: '删 除',
updateBtnTitle: '修 改',
saveBtnTitle: '新 增',
cancelBtnTitle: '取 消',
columnBtnTitle: '多 选',
searchBtnTitle: '搜 索',
emptyBtnTitle: '清 空',
tipBtnTitle: '清空',
menuBtnTitle: '功 能',
cellEditBtnTitle: '修改',
cellSaveBtnTitle: '保存',
//图标
viewBtnIcon: 'el-icon-view',
editBtnIcon: 'el-icon-edit',
addBtnIcon: 'el-icon-plus',
delBtnIcon: 'el-icon-delete',
searchBtnIcon: 'el-icon-search',
emptyBtnIcon: 'el-icon-delete',
cellEditBtnIcon: 'el-icon-edit',
cellSaveBtnIcon: 'el-icon-check',
columnBtnIcon: 'el-icon-menu',
refreshBtnIcon: 'el-icon-refresh',
searchboxBtnIcon: 'el-icon-search',
//显隐
viewBtn: false,
editBtn: true,
addBtn: true,
delBtn: true,
cellBtn: false,
dateBtn: false,
refreshBtn: true,
columnBtn: true,
searchBtn: true,
menuBtn: false,
selectClearBtn: true,
searchShow: true,
tip: true,
dialogWidth: '50%',
formFullscreen: false,
customClass: '',
pageBackground: true,
page: true,
menu: true,
indexLabel: '#',
filterMultiple: true,
calcHeight: 300,
title: '表格标题',
width: '100%',
dateDefault: false,
//搜索参数
searchMultiple: ['checkbox', 'tree', 'select']
}
\ No newline at end of file
<template>
<el-cascader :options="dic"
v-model="text"
:placeholder="placeholder?placeholder:`请选择${label}`"
:props="props"
:readonly="readonly"
:change-on-select="changeoOnSelect"
:clearable="disabled?false:clearable"
:expand-trigger="expandTrigger"
:show-all-levels="showAllLevels"
:filterable="filterable"
:separator="separator"
:disabled="disabled"
@click.native="handleClick"
@change="handleChange">
</el-cascader>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-cascader',
mixins: [crudCompoents()],
props: {
value: {
type: Array,
default: () => []
},
changeoOnSelect: {
type: Boolean,
default: false
},
expandTrigger: {
type: String,
default: 'hover'
},
showAllLevels: {
type: Boolean,
default: true
},
filterable: {
type: Boolean,
default: false
},
separator: {
type: String,
default: '/'
}
},
data () {
return {};
},
watch: {},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
}
}
});
</script>
<template>
<el-checkbox-group v-model="text"
@change="handleChange"
:disabled="disabled"
@click.native="handleClick">
<el-checkbox v-for="(item,index) in dic"
:label="item[valueKey]"
:border="border"
:min="min"
:readonly="readonly"
:max="max"
:disabled="item[disabledKey]"
:key="index">{{item[labelKey]}}</el-checkbox>
</el-checkbox-group>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-checkbox',
mixins: [crudCompoents()],
data () {
return {};
},
props: {
value: {
type: Array,
default: () => []
}
},
watch: {},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
}
}
});
</script>
<template>
<div>
<el-table-column v-if="columnIndex.indexOf(column.prop)!=-1"
v-for="(column,index) in columnOption"
:prop="column.prop"
:key="index"
filter-placement="bottom-end"
:filters="column.filters"
:filter-method="column.filterMethod"
:filter-multiple="vaildData(column.filterMultiple,true)"
:show-overflow-tooltip="column.overHidden"
:min-width="column.minWidth"
:sortable="column.sortable"
:align="vaildData(column.align,tableOption.align)"
:header-align="vaildData(column.headerAlign,tableOption.headerAlign)"
:width="column.width"
:label="column.label"
:fixed="column.fixed">
<crud-components v-if="column.children"
:columnOption="column.children"
:tableOption="tableOption"
:tableForm="tableForm"
:columnIndex="columnIndex"
:DIC="DIC">
<template slot-scope="scope"
v-for="item in column.children"
:slot="item.prop">
<slot :row="scope.row"
:dic="scope.dic"
:label="scope.label"
:name="item.prop"
v-if="item.solt"></slot>
</template>
</crud-components>
<template slot-scope="scope">
<template v-if="cellEditFlag(scope.row,column)">
<component size="small"
:is="getSearchType(column.type)"
v-model="tableForm[column.prop]"
:type="getType(column)"
clearable
:placeholder="column.label"
:dic="setDic(column.dicData,DIC[column.dicData])"></component>
</template>
<slot :row="scope.row"
:dic="setDic(column.dicData,DIC[column.dicData])"
:label="detail(scope.row,column)"
:name="column.prop"
v-else-if="column.solt"></slot>
<template v-else>
<span v-html="detail(scope.row,column)"></span>
</template>
</template>
</el-table-column>
</div>
</template>
<script>
import column from '../../mixins/column'
import crudInput from './crud-input';
import crudSelect from './crud-select';
export default {
name: 'crud-components',
mixins: [column()],
props: [
'columnIndex',
'columnOption',
'tableOption',
'DIC',
'tableForm'
],
components: {
crudInput,
crudSelect,
},
created () {
this.initFun();
},
methods: {
}
}
</script>
<style>
</style>
<template>
<el-date-picker :type="type"
v-model="text"
:size="size"
:readonly="readonly"
range-separator="至"
:start-placeholder="startPlaceholder"
:end-placeholder="endPlaceholder"
:format="format"
:clearable="disabled?false:clearable"
:picker-options="pickerOptions"
:value-format="valueFormat"
:default-time="defaultTime"
:placeholder="placeholder?placeholder:`请输入${label}`"
@change="handleChange"
@click.native="handleClick"
:disabled="disabled"> </el-date-picker>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-date',
mixins: [crudCompoents()],
data () {
return {
text: ''
};
},
props: {
value: {
},
startPlaceholder: {
type: String,
default: '开始日期'
},
endPlaceholder: {
type: String,
default: '结束日期'
},
defaultTime: {
type: String
},
pickerOptions: {
type: Object,
default: () => { }
},
type: {
default: 'date'
},
valueFormat: {
},
format: {
}
},
watch: {},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
}
}
});
</script>
<template>
<el-input-number v-model="text"
class="avue-input-number"
@change="handleChange"
@click.native="handleClick"
:precision="precision"
:size="size"
:min="minRows"
:max="maxRows"
:clearable="disabled?false:clearable"
:readonly="readonly"
:controls-position="controlsPosition"
:label="placeholder?placeholder:`请输入${label}`"
:disabled="disabled"></el-input-number>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-input-number',
mixins: [crudCompoents()],
data () {
return {};
},
props: {
value: {
type: Number
},
step: {
type: Number,
default: 1
},
controlsPosition: {
type: String,
default: 'right'
},
precision: {
type: Number,
default: 0
},
minRows: {
type: Number,
default: -Infinity
},
maxRows: {
type: Number,
default: Infinity
}
},
watch: {},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
}
}
});
</script>
\ No newline at end of file
<template>
<div>
<el-input v-if="type==='tree'"
:size="size"
v-model="labelShow"
:type="typeParam"
:clearable="disabled?false:clearable"
:autosize="{ minRows: minRows, maxRows: maxRows}"
:prefix-icon="prefixIcon"
:suffix-icon="suffixIcon"
:placeholder="placeholder?placeholder:`请选择${label}`"
@change="handleChange"
:disabled="disabled"
:readonly="true"
@click.native="disabled?'':open()" />
<el-input v-else-if="type==='phone'"
:size="size"
:clearable="disabled?false:clearable"
v-model="text"
@click.native="handleClick"
:type="typeParam"
:maxlength="maxlength"
:autosize="{ minRows: minRows, maxRows: maxRows}"
:prefix-icon="prefixIcon"
:suffix-icon="suffixIcon"
:readonly="readonly"
:placeholder="placeholder?placeholder:`请输入${label}`"
@change="handleChange"
:disabled="disabled" />
<el-input v-else
:size="size"
:clearable="disabled?false:clearable"
v-model="text"
@click.native="handleClick"
:type="typeParam"
:maxlength="maxlength"
:minlength="minlength"
:autosize="{ minRows: minRows, maxRows: maxRows}"
:prefix-icon="prefixIcon"
:suffix-icon="suffixIcon"
:readonly="readonly"
:placeholder="placeholder?placeholder:`请输入${label}`"
@change="handleChange"
:disabled="disabled">
<template slot="prepend"
v-if="prepend">{{prepend}}</template>
<template slot="append"
v-if="append">{{append}}</template>
</el-input>
<el-dialog :visible.sync="box"
append-to-body
:title="`请选择${label}`"
width="50%">
<el-input style="margin-bottom:15px;"
placeholder="输入关键字进行过滤"
v-model="filterText"
v-if="filter">
</el-input>
<div class="avue-dialog">
<el-tree :data="dic"
:node-key="valueKey"
:show-checkbox="multiple"
:props="props"
ref="tree"
@check="checkChange"
:filter-node-method="filterNode"
:default-expanded-keys="multiple?text:[]"
:default-checked-keys="multiple?text:[]"
:default-expand-all="defaultExpandAll"
@node-click="handleNodeClick"></el-tree>
</div>
</el-dialog>
</div>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
import { validatenull } from '../../utils/validate';
export default create({
name: 'crud-input',
mixins: [crudCompoents()],
data () {
return {
filterText: '',
box: false,
labelText: this.multiple ? [] : ''
};
},
props: {
nodeClick: Function,
checked: Function,
value: {
},
filter: {
type: Boolean,
default: true
},
multiple: {
type: Boolean,
default: false
},
parent: {
type: Boolean,
default: true
},
defaultExpandAll: {
type: Boolean,
default: true
},
prefixIcon: {
type: String
},
suffixIcon: {
type: String
},
prepend: {
type: String
},
append: {
type: String
},
minlength: {
type: Number
},
maxlength: {
type: Number,
default: function () {
if (this.type === 'phone') return 11;
}
},
minRows: {
type: Number,
default: 3
},
maxRows: {
type: Number,
default: 4
}
},
watch: {
value () {
this.init();
},
filterText (val) {
this.$refs.tree.filter(val);
}
},
computed: {
labelShow () {
return this.multiple ? this.labelText.join('/').toString() : this.labelText;
},
textShow () {
if (this.textLen === 11) return `${this.text.substr(0, 3)} ${this.text.substr(3, 4)} ${this.text.substr(7, 4)}`
return this.text;
},
textLen () {
return this.text.length;
},
typeParam: function () {
if (this.type === 'textarea') {
return 'textarea';
} else if (this.type === 'password') {
return 'password';
} else {
return 'text';
}
}
},
created () { },
mounted () {
this.init();
},
methods: {
filterNode (value, data) {
if (!value) return true;
return data[this.labelKey].indexOf(value) !== -1;
},
checkChange (checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys) {
console.log(checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys);
this.text = [];
this.labelText = [];
checkedKeys.checkedNodes.forEach(node => {
if (validatenull(node[this.childrenKey])) {
this.text.push(node[this.valueKey]);
this.labelText.push(node[this.labelKey]);
}
});
if (typeof this.checked === 'function') this.checked(checkedNodes);
this.$emit('input', this.text);
this.$emit('change', this.text);
},
open () {
this.box = true;
this.handleClick();
},
init () {
if (this.type === 'tree') {
if (this.multiple) {
this.labelText = ['获取字典中...'];
} else {
this.labelText = '获取字典中...';
}
const check = setInterval(() => {
if (!validatenull(this.dic)) {
if (this.multiple) {
this.labelText = [];
this.text.forEach(ele => {
this.findLabelNode(this.dic, ele, this.props);
});
} else {
this.labelText = this.text;
this.findLabelNode(this.dic, this.text, this.props);
}
if (!this.parent) this.disabledParentNode(this.dic);
clearInterval(check);
} else {
this.labelText = '';
}
}, 500);
} else if (this.type === 'phone') {
if (!validatenull(this.text) && this.textLen == 11) {
this.text = this.textShow;
}
}
},
findLabelNode (dic, value, props) {
const labelKey = props.label || 'label';
const valueKey = props.value || 'value';
const childrenKey = props.children || 'children';
dic.forEach(ele => {
const children = ele[childrenKey];
if (ele[valueKey] === value) {
const label = ele[labelKey];
this.multiple ? this.labelText.push(label) : this.labelText = label;
} else if (!validatenull(children)) {
this.findLabelNode(children, value, props);
}
});
},
disabledParentNode (dic) {
dic.forEach(ele => {
const children = ele[this.childrenKey];
if (!validatenull(children)) {
ele.disabled = true;
this.disabledParentNode(children);
}
});
},
handleNodeClick (data) {
const callback = () => {
this.box = false;
}
if (typeof this.nodeClick === 'function') this.nodeClick(data);
if (this.multiple) return;
if (validatenull(data[this.childrenKey]) && !this.multiple || this.parent) {
const value = data[this.valueKey];
const label = data[this.labelKey];
this.text = value;
this.labelText = label;
this.$emit('input', value);
this.$emit('change', value);
callback();
}
},
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
let text = this.text;
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
if (this.type === 'phone') {
this.text = text.replace(/[^0-9.]/g, '');
this.text = this.textShow;
text = this.text.replace(/\s/g, "");
}
this.$emit('input', text);
this.$emit('change', text);
}
}
});
</script>
<template>
<el-radio-group v-model="text"
@change="handleChange"
@click.native="handleClick"
:disabled="disabled">
<el-radio v-for="(item,index) in dic"
:label="item[valueKey]"
:border="border"
:readonly="readonly"
:disabled="item[disabledKey]"
:key="index">{{item[labelKey]}}</el-radio>
</el-radio-group>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-radio',
mixins: [crudCompoents()],
data () {
return {};
},
props: {
value: {}
},
watch: {},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
}
}
});
</script>
\ No newline at end of file
<template>
<el-rate v-model="text"
style="margin-top:10px"
@change="handleChange"
@click.native="handleClick"
:max="max"
:readonly="readonly"
:show-text="showText"
:icon-classes="iconClasses"
:void-icon-class="voidIconClass"
:disabled="disabled"
:colors="colors"></el-rate>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-rate',
mixins: [crudCompoents()],
props: {
value: {
type: Number,
default: 0
},
colors: {
type: Array
},
max: {
type: Number,
default: 5
},
iconClasses: {
type: Array
},
texts: {
type: Array
},
showText: {
type: Boolean,
default: false
},
voidIconClass: {
type: String
}
},
data () {
return {};
},
watch: {},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
}
}
});
</script>
<template>
<el-select v-model="text"
:size="size"
:multiple="multiple"
:filterable="filterable"
:readonly="readonly"
:clearable="disabled?false:clearable"
:placeholder="placeholder?placeholder:`请选择${label}`"
@change="handleChange"
@click.native="handleClick"
:disabled="disabled">
<el-option v-for="(item,index) in dic"
:key="index"
:disabled="item[disabledKey]"
:label="item[labelKey]"
:value="item[valueKey]">
</el-option>
</el-select>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-select',
mixins: [crudCompoents()],
data () {
return {};
},
props: {
value: {
},
multiple: {
type: Boolean,
default: false
},
filterable: {
type: Boolean,
default: false
},
},
watch: {
},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
}
}
});
</script>
\ No newline at end of file
<template>
<el-slider v-model="text"
:disabled="disabled"
:step="step"
:min="min"
:max="max"
:range="range"
:show-stops="showStops"
:show-input="showInput"
:format-tooltip="formatTooltip"
@click.native="handleClick"
@change="handleChange"></el-slider>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-silder',
mixins: [crudCompoents()],
props: {
value: {
},
step: {
type: Number
},
min: {
type: Number
},
max: {
type: Number
},
range: {
type: Boolean,
default: false
},
showInput: {
type: Boolean,
default: false
},
showStops: {
type: Boolean,
default: false
},
formatTooltip: Function
},
data () {
return {};
},
watch: {},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
},
getDic (index) {
return this.dic[index] ? this.dic[index] : {};
}
}
});
</script>
<template>
<div>
<el-switch v-model="text"
@change="handleChange"
@click.native="handleClick"
:active-text="getDic(0)[labelKey]"
:active-value="getDic(0)[valueKey]"
:inactive-value="getDic(1)[valueKey]"
:inactive-text="getDic(1)[labelKey]"
:disabled="disabled"
:readonly="readonly"
:size="size">
</el-switch>
</div>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-switch',
mixins: [crudCompoents()],
props: {
value: {
}
},
data () {
return {};
},
watch: {},
created () { },
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
},
getDic (index) {
return this.dic[index] ? this.dic[index] : {};
}
}
});
</script>
<template>
<el-time-picker v-model="text"
:is-range="isRange"
:size="size"
range-separator="至"
:start-placeholder="startPlaceholder"
:end-placeholder="endPlaceholder"
:format="format"
:readonly="readonly"
:clearable="disabled?false:clearable"
:value-format="valueFormat"
:placeholder="placeholder?placeholder:`请输入${label}`"
@change="handleChange"
@click.native="handleClick"
:disabled="disabled"> </el-time-picker>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-time',
mixins: [crudCompoents()],
data () {
return {};
},
props: {
startPlaceholder: {
type: String,
default: '开始时间'
},
endPlaceholder: {
type: String,
default: '结束时间'
},
value: {
required: true
},
valueFormat: {
default: ''
},
type: {
default: ''
},
format: {
default: ''
}
},
watch: {},
created () { },
mounted () { },
computed: {
isRange () {
return this.type === 'timerange'
}
},
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (value) {
if (typeof this.change === 'function') this.change({ value: value, column: this.column });
this.$emit('input', value);
this.$emit('change', value);
}
}
});
</script>
<template>
<div :class="b()">
<el-upload :class="b({'list':listType=='picture-img'})"
@click.native="handleClick"
:action="action"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:multiple="multiple"
:on-preview="handlePictureCardPreview"
:limit="status?99:limit"
:http-request="httpRequest"
:drag="drag"
:readonly="readonly"
:show-file-list="showFileList"
:list-type="listType"
:on-change="handleChange"
:on-exceed="handleExceed"
:disabled="disabled"
:file-list="fileList">
<template v-if="listType=='picture-card'">
<i class="el-icon-plus"></i>
</template>
<template v-else-if="listType=='picture-img'">
<img v-if="imageUrl"
:src="imageUrl"
:class="b('avatar')">
<i v-else
class="el-icon-plus"
:class="b('icon')"></i>
</template>
<template v-else-if="drag">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或
<em>点击上传</em>
</div>
</template>
<template v-else>
<el-button size="small"
type="primary">点击上传</el-button>
</template>
<div slot="tip"
class="el-upload__tip">{{tip}}</div>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<div class="avue-dialog">
<img width="100%"
:src="dialogImageUrl"
alt="">
</div>
</el-dialog>
</div>
</template>
<script>
import create from '../../utils/create';
import crudCompoents from '../../mixins/crud-compoents.js';
export default create({
name: 'crud-upload',
mixins: [crudCompoents()],
data () {
return {
loading: false,
dialogImageUrl: '',
dialogVisible: false,
text: this.status ? '' : [],
file: {}
};
},
props: {
value: {
},
showFileList: {
type: Boolean,
default: true
},
limit: {
type: Number,
default: 3
},
listType: {
type: String
},
drag: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: true
},
loadText: {
type: String,
default: '文件上传中,请稍等'
},
action: {
type: String,
default: ''
},
uploadBefore: Function,
uploadAfter: Function
},
computed: {
status () {
return this.listType === 'picture-img';
},
isArray () {
return this.dataType === 'array';
},
imageUrl () {
return this.status ? this.text : '';
},
fileList () {
let list = [];
if (!Array.isArray(this.text) && !this.status) this.text = (this.text || '').split(',');
if (!this.status) {
this.text.forEach((ele, index) => {
let obj;
if (this.isArray) {
obj = {
name: index,
url: ele,
}
} else {
obj = {
name: ele[this.labelKey],
url: ele[this.valueKey],
}
}
list.push(obj)
})
}
return list;
}
},
created () {
},
watch: {
},
mounted () { },
methods: {
handleClick () {
if (typeof this.click === 'function') this.click({ value: this.text, column: this.column });
},
handleChange (file, fileList) {
if (typeof this.change === 'function') this.change({ value: this.text, column: this.column });
},
handleSuccess (file) {
if (!this.status) {
if (this.isArray) {
this.text.push(file[this.nameKey]);
} else {
let obj = {};
obj[this.labelKey] = file[this.nameKey];
obj[this.valueKey] = file[this.urlKey];
this.text.push(obj);
}
} else {
this.text = file[this.urlKey];
}
this.$message.success('上传成功');
this.setVal();
},
handleRemove (file, fileList) {
this.delete(file);
this.$message.success('删除成功');
this.setVal();
},
handleError () {
this.$message.error('上传失败');
},
delete (file) {
this.text.forEach((ele, index) => {
if (ele[this.valueKey] === file.url) this.text.splice(index, 1);
})
},
show (res) {
this.loading.close();
this.handleSuccess(res.data);
},
hide () {
this.loading.close();
this.handleError();
},
httpRequest (config) {
this.loading = this.$loading({
lock: true,
text: this.loadText,
spinner: 'el-icon-loading',
});
const file = config.file;
this.file = config.file;
const headers = { 'Content-Type': 'multipart/form-data' }
let param = new FormData()
param.append('file', file, file.name)
const callack = () => {
this.$http.post(this.action, param, { headers }).then(res => {
if (typeof this.uploadAfter === 'function') this.uploadAfter(res, () => {
this.show(res)
})
else this.show(res);
}).catch((error) => {
if (typeof this.uploadAfter === 'function') this.uploadAfter(error, this.hide);
else this.hide(error);
});
};
if (typeof this.uploadBefore === 'function') this.uploadBefore(this.file, callack);
else callack();
},
setVal () {
this.$emit('input', this.text);
this.$emit('change', this.text);
},
handleExceed (files, fileList) {
this.$message.warning(`当前限制选择 ${this.limit} 个文件,本次选择了 ${files.length} 个文件,共上传了 ${files.length + fileList.length} 个文件`);
},
handlePictureCardPreview (file) {
this.dialogImageUrl = file.url;
this.dialogVisible = true;
},
beforeRemove (file) {
return this.$confirm(`确定移除 ${file.name}?`);
}
}
});
</script>
\ No newline at end of file
<template>
<div :class="b()">
<el-card :class="b('box')">
<div slot="header"
:class="b('title')"
v-if="vaildData(tableOption.title,false) || vaildData(tableOption.dateBtn,config.dateBtn)">
<span>{{tableOption.title}}</span>
<date-group @change="dateChange"
v-if="vaildData(tableOption.dateBtn,config.dateBtn)"
:default="vaildData(tableOption.dateDefault,config.dateDefault)"
:size="isMediumSize">
</date-group>
</div>
<div :class="b('header')"
v-if="vaildData(tableOption.header,true)">
<el-collapse-transition>
<el-form :model="searchForm"
:inline="true"
ref="searchForm"
v-if="searchShow && searchFlag">
<!-- 循环列搜索框 -->
<el-form-item :prop="column.prop"
:label="column.label"
v-for="(column,index) in columnOption"
:key="index"
v-if="column.search">
<component :is="getSearchType(column.type)"
:size="isMediumSize"
v-model="searchForm[column.prop]"
:type="getType(column)"
:props="column.props || tableOption.props"
:format="column.format"
:parent="column.parent"
:defaultExpandAll="column.defaultExpandAll"
:filterable="column.searchFilterable"
:filter-method="column.searchFilterMethod"
:value-format="column.valueFormat"
:multiple="config.searchMultiple.includes(column.type) && vaildData(column.searchMmultiple,false)"
:clearable="column.searchClearable"
:placeholder="column.searchPlaceholder || column.label"
:dic="setDic(column.dicData,DIC[column.dicData])"></component>
</el-form-item>
<slot name="search"></slot>
<el-form-item>
<el-button type="primary"
@click="searchChange"
:icon="config.searchBtnIcon"
:size="isMediumSize">{{config.searchBtnTitle}}</el-button>
<el-button @click="searchReset"
:icon="config.emptyBtnIcon"
:size="isMediumSize">{{config.emptyBtnTitle}}</el-button>
<slot name="searchMenu"></slot>
</el-form-item>
</el-form>
</el-collapse-transition>
</div>
<!-- 表格功能列 -->
<div :class="b('menu')"
v-if="vaildData(tableOption.header,true)">
<div :class="b('left')">
<el-button type="primary"
@click="rowAdd"
:icon="config.addBtnIcon"
:size="isMediumSize"
v-if="vaildData(tableOption.addBtn,config.addBtn)">{{config.addBtnTitle}}</el-button>
<slot name="menuLeft"></slot>
</div>
<div :class="b('right')">
<slot name="menuRight"></slot>
<el-button :icon="config.refreshBtnIcon"
circle
:size="isMediumSize"
@click="refreshChange"
v-if="vaildData(tableOption.refreshBtn,config.refreshBtn)"></el-button>
<el-button :icon="config.columnBtnIcon"
circle
:size="isMediumSize"
@click="columnBox=true"
v-if="vaildData(tableOption.columnBtn,config.columnBtn)"></el-button>
<el-button :icon="config.searchboxBtnIcon"
circle
:size="isMediumSize"
@click="searchShow=!searchShow"
v-if="searchFlag && vaildData(tableOption.searchBtn,config.searchBtn)"></el-button>
</div>
</div>
<el-tag class="avue-tip"
v-if="vaildData(tableOption.tip,config.tip) && tableOption.selection">
<i class="el-icon-info avue-tip__icon">&nbsp;</i>
<span class="avue-tip__name">
{{config.tipStartTitle}}
<span class="avue-tip__name--bold">{{selectLen}}</span> {{config.tipEndTitle}}
</span>
<span class="avue-tip__btn"
@click="selectClear"
v-if="vaildData(tableOption.selectClearBtn,config.selectClearBtn) && tableOption.selection">
{{config.tipBtnTitle}}
</span>
</el-tag>
<el-table :data="list"
:size="controlSize"
:highlight-current-row="tableOption.highlightCurrentRow"
@current-change="currentRowChange"
:show-summary="tableOption.showSummary"
:summary-method="tableSummaryMethod"
:sum-text="tableOption.sumText"
:empty-text="tableOption.emptyText"
:span-method="tableSpanMethod"
:stripe="tableOption.stripe"
:show-header="tableOption.showHeader"
:default-sort="tableOption.defaultSort"
@row-click="rowClick"
@row-dblclick="rowDblclick"
:row-class-name="rowClassName"
:max-height="tableOption.maxHeight"
:height="tableOption.height=='auto'?(clientHeight - vaildData(tableOption.calcHeight,config.calcHeight)):tableOption.height"
ref="table"
:width="setPx(tableOption.width,config.width)"
:border="tableOption.border"
v-loading="tableLoading"
@selection-change="selectionChange"
@sort-change="sortChange">
<!-- 暂无数据提醒 -->
<template slot="empty">
<slot name="empty"
v-if="$slots.empty"></slot>
<span @click="refreshChange"
v-else
style="cursor:pointer">暂无数据,点击刷新</span>
</template>
<!-- 折叠面板 -->
<el-table-column type="expand"
width="50"
fixed="left"
align="center"
v-if="tableOption.expand">
<template slot-scope="props">
<slot :row="props.row"
name="expand"></slot>
</template>
</el-table-column>
<!-- 选择框 -->
<el-table-column v-if="tableOption.selection"
type="selection"
width="50"
fixed="left"
align="center">
</el-table-column>
<!-- 序号 -->
<el-table-column v-if="tableOption.index"
:label="vaildData(tableOption.indexLabel,config.indexLabel)"
type="index"
width="50"
:index="indexMethod"
fixed="left"
align="center">
</el-table-column>
<!-- 循环列 -->
<el-table-column v-if="columnIndex.indexOf(column.prop)!=-1"
v-for="(column,index) in columnOption"
:prop="column.prop"
:key="index"
filter-placement="bottom-end"
:filters="column.filters"
:filter-method="column.filterMethod"
:filter-multiple="vaildData(column.filterMultiple,config.filterMultiple)"
:show-overflow-tooltip="column.overHidden"
:min-width="column.minWidth"
:sortable="column.sortable"
:align="vaildData(column.align,tableOption.align)"
:header-align="vaildData(column.headerAlign,tableOption.headerAlign)"
:width="column.width"
:label="column.label"
:fixed="column.fixed">
<crud-components v-if="column.children"
:columnOption="column.children"
:tableOption="tableOption"
:tableForm="tableForm"
:columnIndex="columnIndex"
:DIC="DIC">
<template slot-scope="scope"
v-for="item in column.children"
:slot="item.prop">
<slot :row="scope.row"
:dic="scope.dic"
:label="scope.label"
:name="item.prop"
v-if="item.solt"></slot>
</template>
</crud-components>
<template slot-scope="scope">
<template v-if="cellEditFlag(scope.row,column)">
<component :is="getSearchType(column.type)"
v-model="tableForm[column.prop]"
:type="getType(column)"
:clearable="column.clearable"
:size="isMediumSize"
:placeholder="column.label"
:dic="setDic(column.dicData,DIC[column.dicData])"></component>
</template>
<slot :row="scope.row"
:dic="setDic(column.dicData,DIC[column.dicData])"
:label="detail(scope.row,column)"
:name="column.prop"
v-else-if="column.solt"></slot>
<template v-else>
<span v-html="detail(scope.row,column)"></span>
</template>
</template>
</el-table-column>
<el-table-column fixed="right"
v-if="vaildData(tableOption.menu,config.menu)"
:label="config.menuTitle"
:align="tableOption.menuAlign"
:header-align="tableOption.menuHeaderAlign"
:width="vaildData(tableOption.menuWidth,config.menuWidth)">
<template slot-scope="scope">
<el-dropdown v-if="menuType==='menu'"
style="margin-right:9px;">
<el-button type="primary"
:size="isMediumSize">
{{config.menuBtnTitle}}<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-if="vaildData(tableOption.viewBtn,true)"
@click.native="rowView(scope.row,scope.$index)">{{config.viewBtnTitle}}</el-dropdown-item>
<el-dropdown-item divided
v-if="vaildData(tableOption.editBtn,true)"
@click.native="rowEdit(scope.row,scope.$index)">{{config.editBtnTitle}}</el-dropdown-item>
<el-dropdown-item divided
v-if="vaildData(tableOption.delBtn,true)"
@click.native="rowDel(scope.row,scope.$index)">{{config.delBtnTitle}}</el-dropdown-item>
<slot name="menuBtn"
:row="scope.row"
:dic="scope.dic"
:label="scope.label"
:index="scope.$index"></slot>
</el-dropdown-menu>
</el-dropdown>
<template v-else-if="['button','text','icon'].includes(menuType)">
<el-button :type="menuText('primary')"
:icon="scope.row.$cellEdit?config.cellSaveBtnIcon:config.cellEditBtnIcon"
:size="isMediumSize"
@click.stop="rowCell(scope.row,scope.$index)"
v-if="vaildData(tableOption.cellBtn ,config.cellBtn)">{{menuIcon(scope.row.$cellEdit?config.cellSaveBtnTitle:config.cellEditBtnTitle)}}</el-button>
<el-button :type="menuText('success')"
:icon="config.viewBtnIcon"
:size="isMediumSize"
@click.stop="rowView(scope.row,scope.$index)"
v-if="vaildData(tableOption.viewBtn,config.viewBtn)">{{menuIcon(config.viewBtnTitle)}}</el-button>
<el-button :type="menuText('primary')"
:icon="config.editBtnIcon"
:size="isMediumSize"
@click.stop="rowEdit(scope.row,scope.$index)"
v-if="vaildData(tableOption.editBtn,config.editBtn)">{{menuIcon(config.editBtnTitle)}}</el-button>
<el-button :type="menuText('danger')"
:icon="config.delBtnIcon"
:size="isMediumSize"
@click.stop="rowDel(scope.row,scope.$index)"
v-if="vaildData(tableOption.delBtn,config.delBtn)">{{menuIcon(config.delBtnTitle)}}</el-button>
</template>
<slot name="menu"
:row="scope.row"
:dic="scope.dic"
:label="scope.label"
:index="scope.$index"></slot>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<div :class="b('pagination')"
v-if="vaildData(tableOption.page,config.page) && listLen">
<el-pagination :current-page.sync="defaultPage.currentPage"
:background="vaildData(defaultPage.pageBackground,config.pageBackground)"
:page-size="defaultPage.pageSize"
:page-sizes="defaultPage.pageSizes"
@size-change="sizeChange"
@current-change="currentChange"
layout="total, sizes, prev, pager, next, jumper"
:total="defaultPage.total"></el-pagination>
</div>
</el-card>
<!-- 表单 -->
<el-dialog lock-scroll
:custom-class="vaildData(tableOption.customClass,config.customClass)"
:fullscreen="tableOption.dialogFullscreen"
:modal-append-to-body="false"
:append-to-body="true"
:title="dialogTitle"
:close-on-press-escape="tableOption.dialogEscape"
:close-on-click-modal="tableOption.dialogClickModal"
:modal="tableOption.dialogModal"
:show-close="tableOption.dialogCloseBtn"
:visible.sync="boxVisible"
:width="vaildData(tableOption.dialogWidth,config.dialogWidth)"
@close="closeDialog">
<div :class="b('dialog', ['overflow'])">
<avue-form v-model="tableForm"
ref="tableForm"
:disabled="keyBtn"
:uploadBefore="uploadBefore"
:uploadAfter="uploadAfter"
:option="formOption">
<template slot-scope="scope"
v-for="item in columnOption"
:slot="item.prop">
<slot :value="scope.value"
:column="scope.column"
:dic="scope.dic"
:row="tableForm"
:index="tableIndex"
:name="item.prop+'Form'"
v-if="item.formsolt"></slot>
</template>
</avue-form>
</div>
<span slot="footer"
class="dialog-footer">
<!-- 弹出框按钮组 -->
<slot name="menuForm"
:row="tableForm"
:type="boxType"></slot>
<el-button type="primary"
@click="rowUpdate"
:size="controlSize"
v-if="boxType=='edit'"
:loading="keyBtn">{{vaildData(tableOption.updateBtnTitle,config.updateBtnTitle)}}</el-button>
<el-button type="primary"
@click="rowSave"
:size="controlSize"
:loading="keyBtn"
v-else-if="boxType=='add'">{{vaildData(tableOption.saveBtnTitle,config.saveBtnTitle)}}</el-button>
<el-button :size="controlSize"
@click="closeDialog">{{vaildData(tableOption.cancelBtnTitle,config.cancelBtnTitle)}}</el-button>
</span>
</el-dialog>
<!-- 动态列 -->
<el-dialog lock-scroll
:modal-append-to-body="false"
:append-to-body="true"
:title="config.columnBtnTitle"
:visible.sync="columnBox">
<el-checkbox-group v-model="columnIndex">
<el-row :span="24">
<el-col :span="6"
v-for="(item,index) in columnList"
:key="index">
<el-checkbox :label="item.prop">{{item.label}}</el-checkbox>
</el-col>
</el-row>
</el-checkbox-group>
</el-dialog>
</div>
</template>
<script>
import dateGroup from '../../date-group'
import create from '../../utils/create';
import crud from '../../mixins/crud.js';
import column from '../../mixins/column.js';
import crudComponents from './crud-components';
import config from './config.js';
import {
validatenull
} from '../../utils/validate.js';
import {
setTimeout
} from 'timers';
export default create({
name: 'crud',
mixins: [crud(), column()],
components: {
crudComponents,
dateGroup
},
data () {
return {
clientHeight: document.documentElement.clientHeight,
defaultForm: {
tableForm: {},
searchForm: {}
},
defaultPage: {
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 10, // 每页显示多少条
pageSizes: [10, 20, 30, 40, 50, 100],
background: true // 背景颜色
},
defaultParam: ['$index'],
keyBtn: false,
config: config,
list: [],
searchShow: true,
searchForm: {},
boxVisible: false,
boxType: 'add',
columnIndex: [],
columnBox: false,
columnList: [],
tableForm: {},
tableOption: {},
tableFormRules: {},
tableIndex: -1,
tableSelect: [],
};
},
created () {
// 初始化数据
this.dataInit();
// 初始化列
this.columnInit();
//初始化分页
this.$emit('on-load', this.defaultPage);
this.pageInit();
},
computed: {
dialogTitle () {
const key = `${this.boxType}Title`;
return this.tableOption[key] || this.config[key];
},
menuType () {
return this.tableOption.menuType || 'button'
},
listLen () {
return this.list.length !== 0
},
columnOption () {
return this.tableOption.column || [];
},
sumColumnList () {
return this.tableOption.sumColumnList || [];
},
selectLen () {
return this.tableSelect ? this.tableSelect.length : 0;
},
searchSolt () {
return this.vaildData(this.tableOption.searchsolt, false);
},
searchFlag () {
if (this.searchSolt) return true;
else return !validatenull(this.searchForm);
},
formOption () {
let option = this.deepClone(this.tableOption);
option.submitBtn = false;
option.submitPostion = 'right';
option.boxType = this.boxType;
option.dicFlag = false;
option.dicData = this.DIC;
option.emptyBtn = false;
return option;
}
},
watch: {
value: {
handler () {
this.formVal();
},
deep: true
},
page: {
handler () {
this.pageInit();
},
deep: true
},
columnOption () {
this.columnInit();
},
data () {
this.dataInit();
}
},
mounted () { },
props: {
value: {
type: Object,
default: () => {
return {};
}
},
spanMethod: Function,
summaryMethod: Function,
beforeClose: Function,
beforeOpen: Function,
rowClassName: Function,
uploadBefore: Function,
uploadAfter: Function,
page: {
type: Object,
default () {
return {};
}
},
tableLoading: {
type: Boolean,
default: false
},
data: {
type: Array,
required: true,
default: () => {
return [];
}
}
},
methods: {
menuIcon (value) {
return this.menuType === 'icon' ? '' : value
},
menuText (value) {
return this.menuType === 'text' ? 'text' : value
},
closeDialog () {
this.tableIndex = -1;
this.tableForm = {};
this.boxVisible = false;
this.keyBtn = false;
this.hide();
},
selectClear () {
this.$refs.table.clearSelection();
},
indexMethod (index) {
return (index + 1) + (((this.defaultPage.currentPage || 1) - 1) * (this.defaultPage.pageSize || 10));
},
refreshChange () {
this.$emit('refresh-change', {
page: this.defaultPage,
searchForm: this.searchForm
});
},
pageInit (onload) {
this.page.total ? this.defaultPage.total = this.page.total : '';
this.page.currentPage ? this.defaultPage.currentPage = this.page.currentPage : ''
this.page.pageSize ? this.defaultPage.pageSize = this.page.pageSize : ''
this.page.pageSizes ? this.defaultPage.pageSizes = this.page.pageSizes : ''
this.page.background ? this.defaultPage.background = this.page.background : ''
},
rulesInit () {
this.tableFormRules = {};
this.columnOption.forEach(ele => {
if (ele.rules) this.tableFormRules[ele.prop] = ele.rules;
});
},
columnInit: function () {
const safe = this;
this.columnIndex = [];
this.columnList = [];
function addChild (list) {
list.forEach((ele, index) => {
const children = ele.children;
if (!validatenull(children)) {
safe.tableOption.columnBtn = false;
addChild(children);
}
if (validatenull(ele.hide)) safe.columnIndex.push(ele.prop);
if (ele.showClomnu !== false) {
let obj = {
label: ele.label,
prop: ele.prop,
index: index
};
safe.columnList.push(safe.deepClone(obj));
}
});
}
addChild(this.columnOption)
},
formVal () {
Object.keys(this.value).forEach(ele => {
this.tableForm[ele] = this.value[ele];
})
this.$emit('input', this.tableForm);
},
dataInit () {
this.list = [].concat(this.data);
//初始化序号
this.list.forEach((ele, index) => {
ele.$index = index;
})
},
formInit () {
this.defaultForm = this.formInitVal(this.columnOption);
this.tableForm = this.deepClone(this.defaultForm.tableForm);
this.searchForm = this.deepClone(this.defaultForm.searchForm);
this.searchShow = this.vaildData(this.tableOption.searchShow, this.config.searchShow);
this.formVal();
},
// 搜索清空
searchReset () {
this.$refs['searchForm'].resetFields();
this.$emit('search-reset');
},
// 页大小回调
sizeChange (val) {
this.defaultPage.currentPage = 1;
this.defaultPage.pageSize = val
this.$emit('on-load', this.defaultPage);
this.$emit('size-change', val);
},
//日期组件回调
dateChange (val) {
this.$emit('date-change', val);
},
// 页码回调
currentChange (val) {
this.$emit('on-load', this.defaultPage);
this.$emit('current-change', val);
},
//设置单选
currentRowChange (currentRow, oldCurrentRow) {
this.$emit('current-row-change', currentRow, oldCurrentRow);
},
//设置多选选中
setCurrentRow (row) {
this.$refs.table.setCurrentRow(row);
},
// 选中实例
toggleSelection (rows) {
if (rows) {
rows.forEach(row => {
this.$refs.table.toggleRowSelection(row);
});
} else {
this.$refs.table.clearSelection();
}
},
// 选择回调
selectionChange (val) {
this.tableSelect = val;
this.$emit('selection-change', this.tableSelect);
},
// 排序回调
sortChange (val) {
this.$emit('sort-change', val);
},
// 搜索回调
searchChange () {
this.$emit('search-change', this.searchForm);
},
// 行双击
rowDblclick (row, event) {
this.$emit('row-dblclick', row, event);
},
// 行单机
rowClick (row, event, column) {
this.$emit('row-click', row, event, column);
},
// 新增
rowAdd () {
this.boxType = 'add';
this.tableForm = this.deepClone(this.defaultForm.tableForm);
this.clearDefaultParam();
this.$emit('input', this.tableForm);
this.show();
},
rowCell (row, index) {
if (row.$cellEdit) this.rowCellUpdate(row, index)
else this.rowCellEdit(row, index)
},
// 单元格编辑
rowCellEdit (row, index) {
if (this.tableIndex != -1) {
this.$message.error('先保存当前编辑的数据');
return;
}
this.tableIndex = index;
this.tableForm = this.deepClone(row);
this.$emit('input', this.tableForm);
row.$cellEdit = !row.$cellEdit;
this.$set(this.list, index, row);
},
// 编辑
rowEdit (row, index) {
this.tableForm = this.deepClone(row);
this.clearDefaultParam();
this.$emit('input', this.tableForm);
this.tableIndex = index;
this.boxType = 'edit';
this.show();
},
//查看
rowView (row, index) {
this.tableForm = this.deepClone(row);
this.clearDefaultParam();
this.$emit('input', this.tableForm);
this.tableIndex = index;
this.boxType = 'view';
this.keyBtn = true;
this.show();
},
rowCellUpdate (row, index) {
const form = this.deepClone(this.tableForm);
this.$emit('input', form);
this.$emit(
'row-update',
form,
index,
() => {
row.$cellEdit = !row.$cellEdit;
this.tableForm = {};
this.tableIndex = -1;
this.$set(this.list, index, form);
}
);
},
// 删除
rowDel (row, index) {
this.$emit('row-del', row, index);
},
// 保存
rowSave () {
this.$refs['tableForm'].validate().then(() => {
this.keyBtn = true;
this.$emit('row-save', this.deepClone(this.tableForm), this.closeDialog,
() => {
this.keyBtn = false;
});
});
},
// 更新
rowUpdate () {
this.$refs['tableForm'].validate().then(() => {
this.keyBtn = true;
const index = this.tableIndex;
this.$emit(
'row-update',
this.deepClone(this.tableForm),
index,
this.closeDialog,
() => {
this.keyBtn = false;
}
);
});
},
// 显示表单
show (cancel) {
const callack = () => {
if (cancel !== true) {
this.boxVisible = true;
this.$nextTick(() => {
this.$refs['tableForm'].clearValidate();
this.$refs['tableForm'].cascadeInit();
});
}
};
if (typeof this.beforeOpen === 'function') this.beforeOpen(callack, this.boxType);
else callack();
},
// 隐藏表单
hide (cancel) {
const callack = () => {
if (cancel !== false) {
this.$refs['tableForm'].resetForm();
this.$refs['tableForm'].clearValidate();
}
};
if (typeof this.beforeClose === 'function') this.beforeClose(callack, this.boxType);
else callack();
},
//清空多余字段
clearDefaultParam () {
this.defaultParam.forEach(ele => {
delete this.tableForm[ele];
})
},
//清空表单
resetForm () {
this.$refs['tableForm'].resetForm();
this.$emit('input', this.tableForm);
},
//合并行
tableSpanMethod (param) {
if (typeof this.spanMethod === 'function') return this.spanMethod(param);
},
//合集统计逻辑
tableSummaryMethod (param) {
//如果自己写逻辑则调用summaryMethod方法
if (typeof this.summaryMethod === 'function') return this.summaryMethod(param);
const {
columns,
data
} = param;
const sums = [];
if (columns.length > 0) {
columns.forEach((column, index) => {
let currItem = this.sumColumnList.find((item => item.name === column.property));
if (currItem) {
switch (currItem.type) {
case "count":
sums[index] = '计数:' + data.length;
break;
case "avg":
let avgValues = data.map(item => Number(item[column.property]));
let nowindex = 1;
sums[index] = avgValues.reduce((perv, curr) => {
let value = Number(curr);
if (!isNaN(value)) {
return (perv + curr) / nowindex++;
} else {
return perv;
}
}, 0);
sums[index] = '平均:' + sums[index];
break;
case "sum":
let values = data.map(item => Number(item[column.property]));
sums[index] = values.reduce((perv, curr) => {
let value = Number(curr);
if (!isNaN(value)) {
return perv + curr;
} else {
return perv;
}
}, 0);
sums[index] = '合计:' + sums[index];
break;
}
}
})
}
return sums;
}
}
});
</script>
import DataBox from './src/data-box.vue';
DataBox.install = function(Vue) {
Vue.component(DataBox.name, DataBox);
};
export default DataBox;
<template>
<div class="data-box">
<el-row :span="24">
<el-col :md="span"
:xs="24"
:sm="12"
v-for="(item,index) in data"
:key="index">
<div class="item">
<a :href="item.href?item.href:'javascript:void(0);'"
:target="item.target">
<div class="item-icon"
:style="{backgroundColor:item.color}">
<i :class="item.icon"></i>
</div>
<div class="item-info">
<div :style="{color:item.color}"
class="title">{{item.count}}</div>
<div class="info">{{item.title}}</div>
</div>
</a>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'data-box',
data () {
return {
};
},
props: {
option: {
type: Object,
default: () => { }
}
},
computed: {
span () { return this.option.span || 8; },
data () { return this.option.data || []; }
},
created () { },
mounted () { },
watch: {},
methods: {}
});
</script>
\ No newline at end of file
import DataCard from './src/data-card.vue';
DataCard.install = function(Vue) {
Vue.component(DataCard.name, DataCard);
};
export default DataCard;
<template>
<div class="data-card">
<el-row :span="24">
<el-col :md="span"
:xs="24"
:sm="12"
v-for="(item,index) in data"
:key="index">
<div class="item">
<a :href="item.href?item.href:'javascript:void(0);'"
:target="item.target">
<img :src="item.src"
class="item-img" />
<div class="item-text"
:style="{backgroundColor:bgText}">
<h3 :style="{color:colorText}">{{item.name}}</h3>
<p :style="{color:colorText}">{{item.text}}</p>
</div>
</a>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'data-card',
data () {
return {
};
},
props: {
option: {
type: Object,
default: () => { }
}
},
computed: {
span () {
return this.option.span || 6;
},
data () {
return this.option.data || [];
},
colorText () {
return this.option.colorText || '#fff';
},
bgText () {
return this.option.bgText || '#2e323f';
},
borderColor () {
return this.option.borderColor || '#2e323f';
}
},
created () { },
mounted () { },
watch: {},
methods: {}
});
</script>
\ No newline at end of file
import DataDisplay from './src/data-display.vue';
DataDisplay.install = function(Vue) {
Vue.component(DataDisplay.name, DataDisplay);
};
export default DataDisplay;
<template>
<div class="avue-data-display">
<el-row :span="24">
<el-col v-for="(item,index) in data"
:key="index"
:md="span"
:xs="12"
:sm="12">
<div class="item"
:style="{color:color}">
<a :href="item.href?item.href:'javascript:void(0);'"
:target="item.target">
<h5 class="count">{{item.count}}</h5>
<span class="splitLine" />
<p class="title">{{item.title}}</p>
</a>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'data-display',
data () {
return {
};
},
computed: {
span () {
return this.option.span || 6;
},
data () {
return this.option.data || [];
},
color () {
return this.option.color || 'rgb(63, 161, 255)';
}
},
props: {
option: {
type: Object,
default: () => { }
}
},
created () { },
methods: {}
});
</script>
import DataIcons from './src/data-icons.vue';
DataIcons.install = function(Vue) {
Vue.component(DataIcons.name, DataIcons);
};
export default DataIcons;
<template>
<div class="data-icons">
<el-row :span="24">
<template v-for="(item,index) in data">
<el-col :xs="12"
:sm="6"
:md="span"
:key="index">
<div class="item"
:class="[{'item--easy':discount}]">
<a :href="item.href?item.href:'javascript:void(0);'"
:target="item.target">
<div class="item-icon"
:style="{color:color}">
<i :class="item.icon"></i>
</div>
<div class="item-info">
<span>{{item.title}}</span>
<div class="count"
:style="{color:color}">{{item.count}}</div>
</div>
</a>
</div>
</el-col>
</template>
</el-row>
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'data-icons',
data () {
return {
};
},
computed: {
span () { return this.option.span || 4; },
data () { return this.option.data; },
color () { return this.option.color || 'rgb(63, 161, 255)'; },
discount () { return this.option.discount || false; }
},
props: {
option: {
type: Object,
default: () => { }
}
}
});
</script>
\ No newline at end of file
import DataProgress from './src/data-progress.vue';
DataProgress.install = function(Vue) {
Vue.component(DataProgress.name, DataProgress);
};
export default DataProgress;
\ No newline at end of file
<template>
<div class="data-progress">
<el-row :span="24">
<el-col :md="span"
:xs="24"
:sm="12"
v-for="(item,index) in data"
:key="index">
<div class="item">
<a :href="item.href?item.href:'javascript:void(0);'"
:target="item.target">
<div class="item-header">
<div class="item-count"
v-text="item.count+'%'"></div>
<div class="item-title"
v-text="item.title"></div>
</div>
<el-progress :stroke-width="15"
:percentage="item.count"
:color="item.color"
:show-text="false"></el-progress>
</a>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'data-progress',
data () {
return {
};
},
props: {
option: {
type: Object,
default: () => { }
}
},
computed: {
span () { return this.option.span || 8; },
data () { return this.option.data || []; }
},
created () { },
mounted () { },
watch: {},
methods: {}
});
</script>
\ No newline at end of file
import DataTabs from './src/data-tabs.vue';
DataTabs.install = function(Vue) {
Vue.component(DataTabs.name, DataTabs);
};
export default DataTabs;
<template>
<div class="data-tabs">
<el-row :span="24">
<el-col :md="span"
:xs="24"
:sm="12"
v-for="(item,index) in data"
:key="index">
<div class="item"
:style="{background:item.color}">
<a :href="item.href?item.href:'javascript:void(0);'"
:target="item.target">
<div class="item-header">
<p>{{item.title}}</p>
<span>{{item.subtitle}}</span>
</div>
<div class="item-body">
<h2>{{item.count}}</h2>
</div>
<div class="item-footer">
<span>{{item.allcount}}</span>
<p>{{item.text}}</p>
</div>
<p class="item-tip">{{item.key}}</p>
</a>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import create from '../../utils/create';
export default create({
name: 'data-tabs',
data () {
return {
};
},
computed: {
span () {
return this.option.span || 8;
},
data () {
return this.option.data || [];
}
},
props: {
option: {
type: Object,
default: () => { }
}
}
});
</script>
import DateGroup from './src/main';
DateGroup.install = function(Vue) {
Vue.component(DateGroup.name, DateGroup);
};
export default DateGroup;
\ No newline at end of file
<template>
<div :class="b()">
<div :class="b('radio')">
<el-radio-group :size="size"
@change="handleChange"
v-model="text">
<el-radio-button :label="item.value"
v-for="(item,index) in menu"
:key="index">{{item.label}}</el-radio-button>
</el-radio-group>
</div>
<div :class="b('date')">
<el-date-picker v-model="datetime"
type="daterange"
:size="size"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</div>
</div>
</template>
<script>
import create from '../../utils/create';
import { GetDateStr } from '../../utils/dateUtil.js';
export default create({
name: 'date-group',
data () {
return {
menu: [],
text: '',
datetime: [GetDateStr(0), GetDateStr(30)]
};
},
watch: {
datetime () {
this.text = '';
this.setCurrent(this.datetime.join(','));
},
},
computed: {
},
props: {
default: {
type: Boolean,
default: false
},
size: {
type: String,
default: 'medium'
}
},
created () {
this.init();
},
methods: {
handleChange (val) {
this.setCurrent(val);
},
setCurrent (val) {
this.$emit('input', val);
this.$emit('change', val);
},
init () {
this.menu = [
{
label: '今天',
value: GetDateStr(0)
}, {
label: '昨天',
value: GetDateStr(-1)
}, {
label: '近7天',
value: GetDateStr(-7)
}, {
label: '全部',
value: '-1'
}
];
if (this.default) {
this.text = GetDateStr(0);
this.setCurrent(this.text);
}
}
}
});
</script>
\ No newline at end of file
import FormDetail from './src/main';
FormDetail.install = function(Vue) {
Vue.component(FormDetail.name, FormDetail);
};
export default FormDetail;
<template>
<div :class="b()">
<el-row span="24"
:class="b('item')"
v-for="(item,index) in columnOption"
:key="index">
<div :class="b('header')">
<i :class="[item.icon,b('icon')]"></i>
<h1 :class="b('title')">{{item.label}}</h1>
</div>
<slot :name="item.prop"
:form="form"
:column="item"
v-if="item.slot"></slot>
<el-col :md="column.span||8"
:xs="24"
v-else
v-for="(column,cindex) in item.column"
:key="cindex">
<div :class="b('box')">
<span :class="b('label',[labelPostion])"
:style="{width:`${item.labelWidth}px`}">{{column.label}}:</span>
<slot :name="column.prop+'Form'"
:column="column"
:form="form"
v-if="column.slot"></slot>
<span v-else
:class="b('content')">{{detail(form,column)}}</span>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import create from '../../utils/create';
import crud from '../../mixins/crud.js';
import column from '../../mixins/column.js';
import { validatenull } from '../../utils/validate.js';
export default create({
name: 'form-detail',
mixins: [crud(), column()],
props: {
option: {
type: Object,
default: () => { }
},
value: {}
},
computed: {
labelPostion: function () {
if (this.option.labelPostion) {
return this.option.labelPostion;
}
return 'left';
},
columnOption () {
return this.option.option || [];
}
},
watch: {
value: {
handler (n) {
this.form = n;
},
deep: true
}
},
data () {
return {
tableOption: {},
form: {}
};
},
created () {
this.formInit();
},
methods: {
dicInit () {
let locaDic = this.tableOption.dicData || {};
this.columnOption.forEach(child => {
child.column.forEach(ele => {
if (this.vaildData(ele.dicFlag, true)) {
if (!validatenull(ele.dicUrl)) {
this.dicCascaderList.push({
dicUrl: ele.dicUrl,
dicData: ele.dicData
});
} else if (!validatenull(this.tableOption.dicUrl) && typeof ele.dicData === 'string') {
this.dicCascaderList.push({
dicUrl: this.tableOption.dicUrl,
dicData: ele.dicData
});
}
}
})
});
this.GetDic().then(data => {
this.DIC = Object.assign({}, locaDic, data);
});
},
rulesInit () {
},
formInit () {
this.form = this.value;
}
}
});
</script>
\ No newline at end of file
import Form from './src/main';
Form.install = function(Vue) {
Vue.component(Form.name, Form);
};
export default Form;
<template>
<div :class="b()"
:style="{width:setPx(tableOption.formWidth,'100%')}">
<el-form ref="form"
:model="form"
:label-position="tableOption.labelPosition"
:size="controlSize"
:label-width="setPx(tableOption.labelWidth,80)"
:rules="formRules">
<el-row :gutter="20"
:span="24">
<draggable :list="columnOption"
:options="dragOptions"
:class="b('group')">
<template v-if="vaildVisdiplay(column)"
v-for="(column,index) in columnOption">
<el-col :key="index"
:md="column.span||12"
:xs="24"
:class="b('row',{'cursor':draggableStart})"
@mouseover.native="draggableMenu?mouseover(index):''"
@mouseout.native="draggableMenu?mouseout(index):''">
<div :class="b('option')"
v-if="optionIndex[index]">
<i class="el-icon-menu"
@click="optionMenu(column,index)"></i>
<i class="el-icon-delete"
@click="optionDelete(column,index)"></i>
</div>
<el-form-item :label="column.label"
:prop="column.prop"
:label-width="setPx(column.labelWidth,tableOption.labelWidth || 80)">
<slot :value="form[column.prop]"
:column="column"
:dic="setDic(column.dicData,DIC[column.dicData])"
:name="column.prop"
v-if="column.formsolt"></slot>
<component :is="getComponent({type:column.type,component:column.component})"
v-else
:props="column.props || tableOption.props"
:propsHttp="column.propsHttp || tableOption.propsHttp"
v-model="form[column.prop]"
:change="column.change"
:click="column.click"
:nodeClick="column.nodeClick"
:checked="column.checked"
:prepend="column.prepend"
:append="column.append"
:column="column"
:filter="column.filter"
:precision="column.precision"
:multiple="column.multiple"
:readonly="vaildData(draggableStart,column.readonly)"
:placeholder="column.placeholder"
:step="column.step"
:range="column.range"
:showStops="column.showStops"
:showInput="column.showInput"
:controls-position="column.controlsPosition"
:expand-trigger="column.expandTrigger"
:size="column.size || controlSize"
:parent="column.parent"
:colors="column.colors"
:action="column.action"
:limit="column.limit"
:tip="column.tip"
:loadText="column.loadText"
:listType="column.listType"
:drag="column.drag"
:showFileList="column.showFileList"
:iconClasses="column.iconClasses"
:voidIconClass="column.voidIconClass"
:showText="column.showText"
:texts="column.texts"
:filterable="column.filterable"
:separator="column.separator"
:border="column.border"
:minlength="column.minlength"
:maxlength="column.maxlength"
:prefixIcon="column.prefixIcon"
:suffixIcon="column.suffixIcon"
:defaultExpandAll="column.defaultExpandAll"
:options="column.options"
:pickerOptions="column.pickerOptions"
:defaultTime="column.defaultTime"
:min="column.min"
:max="column.max"
:changeoOnSelect="column.changeoOnSelect"
:label="column.label"
:clearable="column.clearable"
:startPlaceholder="column.startPlaceholder"
:dataType="column.dataType"
:endPlaceholder="column.endPlaceholder"
:type="column.type"
:minRows="column.minRows"
:maxRows="column.maxRows"
:format="column.format"
:formatTooltip="column.formatTooltip"
:value-format="column.valueFormat"
:dic="setDic(column.dicData,DIC[column.dicData])"
:disabled="vaildDisabled(column)"
:upload-before="uploadBefore"
:upload-after="uploadAfter"
@change="column.cascader?change(index):''"></component>
<!-- <p class="avue-tip">{{column.tip}}</p> -->
</el-form-item>
</el-col>
<div :class="b('line')"
:key="index"
:style="{width:(column.count/24*100)+'%'}"
v-if="column.row && column.span!==24">
</div>
</template>
</draggable>
<el-col :span="24"
v-if="vaildData(tableOption.menuBtn,true)">
<el-form-item :label-width="menuWidth">
<!-- 菜单按钮组 -->
<div :class="b('menu',[menuPostion])">
<el-button type="primary"
@click="handleMock"
:size="controlSize"
icon="el-icon-edit-outline"
v-if="vaildData(tableOption.mock,false)">一键填充数据</el-button>
<el-button type="primary"
@click="submit"
:size="controlSize"
icon="el-icon-check"
v-if="vaildData(tableOption.submitBtn,true)">{{vaildData(tableOption.submitText,'提 交')}}</el-button>
<el-button icon="el-icon-delete"
:size="controlSize"
v-if="vaildData(tableOption.emptyBtn,true)"
@click="resetForm">{{vaildData(tableOption.emptyText,'清 空')}}</el-button>
<slot name="menuForm"></slot>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script>
import create from '../../utils/create';
import draggable from "vuedraggable";
import crud from '../../mixins/crud';
import { deepClone } from '../../utils/util';
import mock from '../../utils/mock';
import { validatenull } from '../../utils/validate.js';
export default create({
name: 'form',
mixins: [crud()],
components: {
draggable
},
data () {
return {
first: true,
optionIndex: [],
optionBox: false,
tableOption: {},
form: {},
formDefault: {},
formRules: {}
};
},
created () {
},
watch: {
value: {
handler () {
this.formVal();
},
deep: true
}
},
mounted () { },
computed: {
columnOption () {
let list = this.tableOption.column || [];
let count = 0;
list.forEach(ele => {
count = count + (ele.span || 12);
if (count >= 24) {
count = 0 + (ele.span || 12);
} else if (ele.row && count !== 24) {
ele.count = 24 - count;
count = 0
}
})
return list;
},
draggable () {
return this.tableOption.draggable || {};
},
draggableMenu () {
return this.draggable.menu || false;
},
draggableStart () {
return this.draggable.start;
},
draggableFlag () {
return this.vaildData(this.draggable.clone, true)
},
dragOptions () {
if (!this.draggableStart) {
return {
disabled: true,
}
}
let pull = (() => {
if (this.draggableFlag) {
return {
pull: 'clone',
revertClone: false
}
}
return {
}
})();
return {
animation: 0,
ghostClass: "avue-ghost",
group: (function () {
return Object.assign({ name: "avue" }, pull);
})(),
sort: this.vaildData(this.draggable.sort, false),
};
},
menuWidth: function () {
if (this.tableOption.menuPostion === 'left') {
return '';
} else {
return '0';
}
},
menuPostion: function () {
if (this.tableOption.menuPostion) {
return this.tableOption.menuPostion;
} else {
return 'center';
}
},
boxType: function () {
return this.tableOption.boxType;
}
},
props: {
disabled: {
type: Boolean,
default: false
},
uploadBefore: Function,
uploadAfter: Function,
value: {
type: Object,
required: true,
default: () => {
return {};
}
}
},
methods: {
handleMock () {
const form = mock(this.columnOption, this.DIC);
Object.keys(form).forEach(ele => {
this.form[ele] = form[ele];
})
this.clearValidate();
this.$message.success('模拟数据填充成功');
},
optionDelete (column, index) {
this.$emit('option-delete', { column, index })
},
optionMenu (column, index) {
this.$emit('option-menu', { column, index })
},
mouseover (index) {
this.optionIndex[index] = true;
this.optionIndex.splice(0, 0);
},
mouseout (index) {
this.optionIndex[index] = false;
this.optionIndex.splice(0, 0);
},
// 验证表单是否禁止
vaildDisabled (column) {
if (this.disabled) return true;
if (!validatenull(column.disabled)) {
return this.vaildData(column.disabled, false);
} else if (this.boxType === 'add') {
return this.vaildData(column.addDisabled, false);
} else if (this.boxType === 'edit') {
return this.vaildData(column.editDisabled, false);
} else if (this.boxType === 'view') {
return true;
} else {
return false;
}
},
// 验证表单是否显隐
vaildVisdiplay (column) {
if (!validatenull(column.visdiplay)) {
return this.vaildData(column.visdiplay, true);
} else if (this.boxType === 'add') {
return this.vaildData(column.addVisdiplay, true);
} else if (this.boxType === 'edit') {
return this.vaildData(column.editVisdiplay, true);
} else if (this.boxType === 'view') {
return this.vaildData(column.viewVisdiplay, true);
} else {
return true;
}
},
rulesInit () {
this.formRules = {};
this.columnOption.forEach(ele => {
if (ele.rules) this.formRules[ele.prop] = ele.rules;
});
},
change (index) {
const column = this.columnOption;
const list = column[index].cascader;
const prop = column[index].prop;
const url = column[index + 1].dicUrl;
const type = column[index + 1].dicData;
if (!this.first) {
list.forEach((ele) => {
this.form[ele] = '';
this.DIC[ele] = [];
this.DIC = Object.assign({}, this.DIC);
});
}
this.GetDicByType(url.replace('{{key}}', this.form[prop])).then(res => {
let data = res;
this.DIC[type] = data;
this.DIC = Object.assign({}, this.DIC);
});
},
formInit () {
this.formDefault = this.formInitVal(this.columnOption);
this.form = this.deepClone(this.formDefault.tableForm);
this.formVal();
const dicFlag = this.vaildData(this.tableOption.dicFlag, true);
//初始化联动
if (dicFlag) this.cascadeInit();
},
cascadeInit () {
this.first = true;
for (let i = 0; i < this.columnOption.length; i++) {
const ele = this.columnOption[i];
if (ele.cascaderFirst) {
const cascader = [].concat(ele.cascader);
const cascaderLen = ele.cascader.length - 1;
cascader.forEach((ele) => {
this.DIC[ele] = [];
this.DIC = Object.assign({}, this.DIC);
});
if (!validatenull(this.form[ele.prop])) this.change(i);
for (let j = 0; j < cascaderLen; j++) {
const cindex = i + (j + 1);
const cele = this.columnOption[cindex];
cele.cascader = cascader.slice(cindex);
if (!validatenull(this.form[cele.prop])) this.change(cindex);
}
}
}
this.first = false;
},
formVal () {
Object.keys(this.value).forEach(ele => {
this.form[ele] = this.value[ele];
})
this.$emit('input', this.form);
},
clearValidate () {
this.$refs['form'].clearValidate();
},
validate () {
return new Promise((resolve, reject) => {
this.$refs.form.validate(valid => {
if (valid) {
resolve();
} else {
reject();
}
});
});
},
resetForm () {
this.form = this.deepClone(this.formDefault.tableForm);
this.clearValidate();
this.$emit('input', this.form);
this.$emit('reset-change');
},
submit () {
this.$refs['form'].validate(valid => {
if (valid) {
this.$emit('submit', this.form);
}
});
}
}
});
</script>
import Carousel from './carousel/';
import Json from './json/'
import Crud from './crud/';
import CrudCheckbox from './crud-checkbox/';
import CrudDate from './crud-date/';
import CrudTime from './crud-time/';
import CrudInput from './crud-input/';
import CrudRadio from './crud-radio/';
import CrudSelect from './crud-select/';
import CrudCascader from './crud-cascader/';
import CrudNumberInput from './crud-input-number/';
import CrudSwitch from './crud-switch/';
import CrudRate from './crud-rate/';
import CrudUpload from './crud-upload/';
import CrudSilder from './crud-silder/';
import DataDisplay from './data-display/';
import DataCard from './data-card/';
import DataTabs from './data-tabs/';
import DataProgress from './data-progress/';
import DataIcons from './data-icons/';
import DataBox from './data-box/';
import Form from './form/';
import Tabs from './tabs/';
import Steps from './steps/';
import Tree from './tree/';
import FormDetail from './form-detail/';
import TableTree from './table-tree/';
import DateGroup from './date-group/';
import axios from 'axios';
const components = [
Json,
Crud,
Form,
Tabs,
Tree,
Carousel,
Steps,
FormDetail,
CrudCheckbox,
CrudDate,
CrudTime,
CrudInput,
CrudRadio,
CrudSelect,
CrudCascader,
CrudNumberInput,
CrudSwitch,
CrudRate,
CrudUpload,
CrudSilder,
DataProgress,
DataDisplay,
DataCard,
DataIcons,
DataTabs,
DataBox,
TableTree,
DateGroup
];
function install(Vue, opts = {}) {
if (axios || window.axios) Vue.prototype.$http = axios || window.axios;
components.map(component => {
Vue.component(component.name, component);
});
Vue.prototype.$AVUE = {
size: opts.size || 'medium',
};
}
if (window.Vue) {
install(window.Vue, window.axios);
}
export default {
install,
Json,
Crud,
Form,
Tabs,
Tree,
Carousel,
Steps,
FormDetail,
CrudCheckbox,
CrudDate,
CrudTime,
CrudInput,
CrudRadio,
CrudSelect,
CrudCascader,
CrudNumberInput,
CrudSwitch,
CrudRate,
CrudUpload,
CrudSilder,
DataProgress,
DataDisplay,
DataCard,
DataIcons,
DataTabs,
DataBox,
TableTree,
DateGroup
};
\ No newline at end of file
import Json from './src/main';
Json.install = function(Vue) {
Vue.component(Json.name, Json);
};
export default Json;
\ No newline at end of file
<template>
<span class="json-tree"
:class="{'json-tree-root': parsed.depth === 0}">
<span class="json-tree-row"
v-if="parsed.primitive"
@mouseover="hovered = true"
@mouseout="hovered = false">
<span class="json-tree-indent"
v-for="n in (parsed.depth * 2 + 3)"
:key="n">&nbsp;</span>
<span class="json-tree-key"
v-if="parsed.key">{{ parsed.key }}</span>
<span class="json-tree-colon"
v-if="parsed.key">:&nbsp;</span>
<span class="json-tree-value"
:class="'json-tree-value-' + parsed.type"
:title="`${parsed.value}`">{{ `${parsed.value}` }}</span>
<span class="json-tree-comma"
v-if="!parsed.last">,</span>
<span class="json-tree-indent">&nbsp;</span>
</span>
<span class="json-tree-deep"
v-if="!parsed.primitive">
<span class="json-tree-row json-tree-expando"
@mouseover="hovered = true"
@mouseout="hovered = false">
<span class="json-tree-indent">&nbsp;</span>
<span class="json-tree-sign"
@click="expanded = !expanded">{{ expanded ? '-' : '+' }}</span>
<span class="json-tree-indent"
v-for="n in (parsed.depth * 2 + 1)"
:key="n">&nbsp;</span>
<span class="json-tree-key"
v-if="parsed.key">{{ parsed.key }}</span>
<span class="json-tree-colon"
v-if="parsed.key">:&nbsp;</span>
<span class="json-tree-open">{{ parsed.type === 'array' ? '[' : '{' }}</span>
<span class="json-tree-collapsed"
v-show="!expanded">&nbsp;/*&nbsp;{{ format(parsed.value.length) }}&nbsp;*/&nbsp;</span>
<span class="json-tree-close"
v-show="!expanded">{{ parsed.type === 'array' ? ']' : '}' }}</span>
<span class="json-tree-comma"
v-show="!expanded && !parsed.last">,</span>
<span class="json-tree-indent">&nbsp;</span>
</span>
<span class="json-tree-deeper"
v-show="expanded">
<avue-json-tree v-for="(item, index) in parsed.value"
:key="index"
:data="data"
:kv="item"
:level="level"></avue-json-tree>
</span>
<span class="json-tree-row"
v-show="expanded">
<span class="json-tree-ending"
:class="{'json-tree-paired': hovered}">
<span class="json-tree-indent"
v-for="n in (parsed.depth * 2 + 3)"
:key="n">&nbsp;</span>
<span class="json-tree-close">{{ parsed.type === 'array' ? ']' : '}' }}</span>
<span class="json-tree-comma"
v-if="!parsed.last">,</span>
<span class="json-tree-indent">&nbsp;</span>
</span>
</span>
</span>
</span>
</template>
<script>
function parse (data, depth = 0, last = true, key = undefined, parent = [], isArray = false, index = -1) {
let kv = { depth, last, primitive: true, key: JSON.stringify(key), parent, isArray, index }
if (typeof data !== 'object') {
return Object.assign(kv, { type: typeof data, value: JSON.stringify(data) })
} else if (data === null) {
return Object.assign(kv, { type: 'null', value: 'null' })
} else if (Array.isArray(data)) {
let value = data.map((item, index) => {
key ? parent.push(key) : ''
parent.push(index);
return parse(item, depth + 1, index === data.length - 1, undefined, [...parent], true, index)
})
return Object.assign(kv, { primitive: false, type: 'array', value })
} else {
let keys = Object.keys(data)
key ? parent.push(key) : ''
let value = keys.map((item, index) => {
return parse(data[item], depth + 1, index === keys.length - 1, item, [...parent], isArray, index)
})
return Object.assign(kv, { primitive: false, type: 'object', value })
}
}
import create from '../../utils/create';
export default create({
name: 'json-tree',
props: {
level: {
type: Number,
default: Infinity
},
kv: {
type: Object
},
raw: {
type: Object
},
data: {}
},
data () {
return {
expanded: true,
hovered: false,
list: {},
}
},
computed: {
parsed () {
if (this.kv) {
return this.kv
}
let result
try {
if (this.raw) {
result = JSON.parse(this.raw);
} else if (typeof this.data !== 'undefined') {
result = this.data
} else {
result = '[Vue JSON Tree] No data passed.'
console.warn(result)
}
} catch (e) {
result = '[Vue JSON Tree] Invalid raw JSON.'
console.warn(result)
} finally {
return parse(result)
}
}
},
methods: {
format (n) {
if (n > 1) return `${n} items`
return n ? '1 item' : 'no items'
}
},
created () {
this.list = this.data;
this.expanded = this.parsed.depth < this.level
}
})
</script>
/**
* bem helper
* b() // 'button'
* b('text') // 'button__text'
* b({ disabled }) // 'button button--disabled'
* b('text', { disabled }) // 'button__text button__text--disabled'
* b(['disabled', 'primary']) // 'button button--disabled button--primary'
*/
const ELEMENT = '__';
const MODS = '--';
const join = (name, el, symbol) => el ? name + symbol + el : name;
const prefix = (name, mods) => {
if (typeof mods === 'string') {
return join(name, mods, MODS);
}
if (Array.isArray(mods)) {
return mods.map(item => prefix(name, item));
}
const ret = {};
Object.keys(mods).forEach(key => {
ret[name + MODS + key] = mods[key];
});
return ret;
};
export default {
methods: {
b(el, mods) {
const { name } = this.$options;
if (el && typeof el !== 'string') {
mods = el;
el = '';
}
el = join(name, el, ELEMENT);
return mods ? [el, prefix(el, mods)] : el;
}
}
};
\ No newline at end of file
import * as utils from '../utils/util.js';
import { validatenull } from '../utils/validate.js';
import dayjs from 'dayjs';
export default function() {
return {
methods: {
initFun() {
Object.keys(utils).forEach(key => {
this[key] = utils[key];
});
},
cellEditFlag(row, column) {
return row.$cellEdit && [undefined, 'select', 'input'].includes(column.type) && column.solt !== true && column.cell;
},
// 处理数据
detail(row, column) {
let result = row[column.prop || column.value],
type = column.type;
if (validatenull(result)) result = '';
if (type) {
//日期处理
if (['date', 'time', 'datetime'].includes(type) && column.format && !validatenull(result)) {
const format = column.format
.replace('dd', 'DD')
.replace('yyyy', 'YYYY');
result = dayjs(result).format(format);
}
// 密码处理
if (['password'].includes(type)) {
return this.getPasswordChar(result.toString().length, '*');
}
//字典处理
if (column.dicData) {
result = this.findByvalue(
(typeof column.dicData === 'string' ? this.DIC[column.dicData] : column.dicData) || [],
result,
(column.props || this.tableOption.props)
);
}
}
if (column.formatter && typeof column.formatter === 'function') {
result = column.formatter(row, row[column.prop], result, column);
}
return result;
},
}
}
}
\ No newline at end of file
export default function() {
//props配置
const propsDefault = {
id: 'id',
label: 'label',
value: 'value',
children: 'children',
disabled: 'disabled'
}
//httpProps配置
const propsHttpDefault = {
name: 'name',
url: 'url',
}
return {
data() {
return {
text: undefined,
propsHttpDefault: propsHttpDefault,
propsDefault: propsDefault
}
},
props: {
change: Function,
click: Function,
column: {
type: Object,
default: () => {}
},
label: {
type: String,
default: ''
},
readonly: {
type: Boolean,
default: false
},
size: {
type: String,
default: ''
},
tip: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
dataType: {
type: String
},
clearable: {
type: Boolean,
default: true
},
type: {
type: String,
default: ''
},
dic: {
type: Array,
default: () => []
},
placeholder: {
type: String,
default: ''
},
min: {
type: Number
},
max: {
type: Number
},
border: {
type: Boolean,
default: false
},
propsHttp: {
type: Object,
default: () => propsHttpDefault
},
props: {
type: Object,
default: () => propsDefault
}
},
watch: {
value() {
this.text = this.value;
}
},
computed: {
nameKey: function() {
return this.propsHttp.name || this.propsHttpDefault.name;
},
urlKey: function() {
return this.propsHttp.url || this.propsHttpDefault.url;
},
valueKey: function() {
return this.props.value || this.propsDefault.value;
},
labelKey: function() {
return this.props.label || this.propsDefault.label;
},
childrenKey: function() {
return this.props.children || this.propsDefault.children;
},
disabledKey: function() {
return this.props.disabled || this.propsDefault.disabled;
},
idKey: function() {
return this.props.id || this.propsDefault.id;
}
},
created() {
this.text = this.value;
}
};
}
\ No newline at end of file
import * as utils from '../utils/util.js';
import { validatenull } from '../utils/validate.js';
import crudInput from '../crud/src/crud-input';
import crudSelect from '../crud/src/crud-select';
import crudRadio from '../crud/src/crud-radio';
import crudCheckbox from '../crud/src/crud-checkbox';
import crudCascader from '../crud/src/crud-cascader';
import crudDate from '../crud/src/crud-date';
import crudTime from '../crud/src/crud-time';
import crudInputNumber from '../crud/src/crud-input-number';
import crudSwitch from '../crud/src/crud-switch';
import crudRate from '../crud/src/crud-rate';
import crudUpload from '../crud/src/crud-upload';
import crudSilder from '../crud/src/crud-silder';
export default function() {
return {
props: {
option: {
type: Object,
required: true,
default: () => {
return {};
}
}
},
components: {
crudInput,
crudSelect,
crudRadio,
crudCheckbox,
crudDate,
crudTime,
crudCascader,
crudInputNumber,
crudSwitch,
crudRate,
crudUpload,
crudSilder
},
watch: {
tableForm: {
handler() {
this.$emit('input', this.tableForm);
},
deep: true
},
form: {
handler() {
this.$emit('input', this.form);
},
deep: true
},
option: {
handler() {
this.init();
},
deep: true
}
},
data() {
return {
DIC: {},
dicCascaderList: []
};
},
created() {
this.init();
},
computed: {
isMediumSize() {
return this.controlSize === 'medium' ? 'small' : this.controlSize;
},
controlSize() {
return this.tableOption.size || (this.$AVUE || {}).size || 'medium';
}
},
methods: {
init() {
// 初始化工具
this.initFun();
this.tableOption = this.option;
const dicFlag = this.vaildData(this.tableOption.dicFlag, true);
// 规则初始化
this.rulesInit();
// 初始化字典
if (dicFlag) this.dicInit();
else this.DIC = this.tableOption.dicData;
// 初始化表单formInitVal
this.formInit();
},
dicInit() {
let locaDic = this.tableOption.dicData || {};
this.columnOption.forEach(ele => {
if (this.vaildData(ele.dicFlag, true)) {
if (!validatenull(ele.dicUrl)) {
this.dicCascaderList.push({
dicUrl: ele.dicUrl,
dicData: ele.dicData
});
} else if (!validatenull(this.tableOption.dicUrl) && typeof ele.dicData === 'string') {
this.dicCascaderList.push({
dicUrl: this.tableOption.dicUrl,
dicData: ele.dicData
});
}
}
});
this.GetDic().then(data => {
this.DIC = Object.assign({}, locaDic, data);
});
},
vaildData(val, dafult) {
if (typeof val === 'boolean') {
return val;
}
return !validatenull(val) ? val : dafult;
},
GetDicByType(href) {
return new Promise((resolve) => {
this.$http.get(href).then(function(res) {
// 降级处理
const list = res.data;
if (!validatenull(list.data)) {
resolve(list.data instanceof Array ? list.data : []);
} else if (!validatenull(list)) {
resolve(list instanceof Array ? list : []);
} else {
resolve([]);
}
});
});
},
GetDic() {
return new Promise((resolve) => {
let result = [];
let dicData = {};
let cascaderList = Object.assign([], this.dicCascaderList);
if (validatenull(cascaderList)) resolve({});
cascaderList.forEach(ele => {
result.push(new Promise((resolve) => {
this.GetDicByType(`${ele.dicUrl.replace('{{key}}', ele.dicData)}`).then(function(res) {
resolve(res);
});
}));
});
Promise.all(result).then(data => {
cascaderList.forEach((ele, index) => {
dicData[ele.dicData] = data[index];
});
resolve(dicData);
});
});
},
initFun() {
Object.keys(utils).forEach(key => {
this[key] = utils[key];
});
}
}
};
}
\ No newline at end of file
export default function() {
return {
props: {
tableLoading: {
type: Boolean,
default: false,
},
beforeOpen: Function,
beforeClose: Function,
uploadBefore: Function,
uploadAfter: Function,
rowClassName: Function,
spanMethod: Function,
summaryMethod: Function,
data: {
type: Array,
default: () => []
},
},
methods: {
refreshChange(params) {
this.$emit('refresh-change', params);
},
searchReset() {
this.$emit('search-reset');
},
sizeChange(val) {
this.$emit('size-change', val);
},
dateChange(val) {
this.$emit('date-change', val);
},
currentChange(val) {
this.$emit('current-change', val);
},
currentRowChange(currentRow, oldCurrentRow) {
this.$emit('current-row-change', currentRow, oldCurrentRow);
},
selectionChange(val) {
this.$emit('selection-change', val);
},
sortChange(val) {
this.$emit('sort-change', val);
},
searchChange(val) {
this.$emit('search-change', val);
},
rowDblclick(row, event) {
this.$emit('row-dblclick', row, event);
},
rowClick(row, event, column) {
this.$emit('row-click', row, event, column);
},
rowDel(row, index) {
this.$emit('row-del', row, index);
},
rowSave(row, done, loading) {
this.$emit('row-save', row, done, loading);
},
rowUpdate(row, index, done, loading) {
this.$emit('row-update', row, index, done, loading);
},
rowAdd() {
this.$refs.crud.rowAdd();
},
rowEdit(row, index) {
this.$refs.crud.rowEdit(row, index);
}
}
}
}
\ No newline at end of file
import Steps from './src/main';
Steps.install = function(Vue) {
Vue.component(Steps.name, Steps);
};
export default Steps;
\ No newline at end of file
<template>
<div :class="b()">
<el-steps :active="formIndex"
:space="option.space"
:simple="option.simple"
finish-status="process"
process-status="wait"
:align-center='vaildData(option.simple?false:option.alignCenter,true)'
:direction="option.direction"
:class="b('tabs',{'steps':option.direction})">
<el-step :title="item.label"
:icon="item.icon"
:status="vaildData(item.status,status[index])"
:description="item.description"
v-for="(item,index) in columnOption"
:key="index"
@click.native="option.switchBtn?switchs(index):''"></el-step>
</el-steps>
<div :class="b('contail')">
<slot name="before"></slot>
<div v-if="crudFlag">
<avue-crud ref="crud"
:option="formOption"
:data="data"
:table-loading="tableLoading"
:before-open="beforeOpen"
:before-close="beforeClose"
:upload-before="uploadBefore"
:upload-after="uploadAfter"
:row-class-name="rowClassName"
:span-method="spanMethod"
:summary-method="summaryMethod"
@refresh-change="refreshChange"
@search-reset="searchReset"
@size-change="size-change"
@date-change="date-change"
@current-change="currentChange"
@current-row-change="currentRowChange"
@selection-change="selectionChange"
@sort-change="sortChange"
@search-change="searchChange"
@row-dblclick="rowDblclick"
@row-click="rowClick"
@row-del="rowDel"
@row-save="rowSave"
@row-update="rowUpdate"
v-model="text">
<!-- 自定义搜索 -->
<template slot="search">
<slot name="search"></slot>
</template>
<!-- 自定义搜索按钮 -->
<template slot="searchMenu">
<slot name="searchMenu"></slot>
</template>
<!-- 自定义表单列 -->
<template slot-scope="scope"
v-for="item in formColumnOption"
:slot="item.prop">
<slot :value="scope.value"
:column="scope.column"
:dic="scope.dic"
:name="item.prop+'Form'"
v-if="item.formsolt"></slot>
</template>
<!-- 自定义表格列 -->
<template slot-scope="scope"
v-for="item in formColumnOption"
:slot="item.prop">
<slot :value="scope.value"
:column="scope.column"
:dic="scope.dic"
:name="item.prop"
v-if="item.solt"></slot>
</template>
<!-- 表格左侧卡槽 -->
<template slot="menuLeft">
<slot name="menuLeft"></slot>
</template>
<!-- 表格右测卡槽 -->
<template slot="menuRight">
<slot name="menuRight"></slot>
</template>
<!-- 清空卡槽 -->
<template slot="empty">
<slot name="empty"
v-if="$slots.empty"></slot>
</template>
<!-- 折叠面板卡槽 -->
<template slot-scope="props"
slot="expand">
<slot :row="props.row"
name="expand"></slot>
</template>
<!-- 菜单栏按钮卡槽 -->
<template slot-scope="scope"
slot="menuBtn">
<slot name="menuBtn"
:row="scope.row"
:dic="scope.dic"
:label="scope.label"
:index="scope.$index"></slot>
</template>
<!-- 菜单栏 -->
<template slot-scope="scope"
slot="menu">
<slot name="menu"
:value="scope.value"
:column="scope.column"
:dic="scope.dic"></slot>
</template>
<!-- 弹出框按钮 -->
<template slot="menuForm">
<slot name="menuForm"></slot>
</template>
</avue-crud>
<div :class="b('menu')">
<el-button @click="submit"
icon="el-icon-back"
type="primary">{{lastFlag?'提交':'下一步'}}</el-button>
<el-button @click="breaks"
icon="el-icon-back"
v-if="formIndex!=1&&vaildData(option.breakBtn,true)">返 回</el-button>
</div>
</div>
<avue-form v-else
:option="formOption"
:class="b('form')"
@submit="submit"
v-model="text">
<template slot-scope="scope"
v-for="item in formColumnOption"
:slot="item.prop">
<slot :value="scope.value"
:column="scope.column"
:dic="scope.dic"
:name="item.prop"
v-if="item.formsolt"></slot>
</template>
<template slot="menuForm">
<el-button @click="breaks"
icon="el-icon-back"
v-if="formIndex!=1&&vaildData(option.breakBtn,true)">返 回</el-button>
<slot name="menuForm"></slot>
</template>
</avue-form>
<slot name="after"></slot>
</div>
</div>
</template>
<script>
import create from '../../utils/create';
import { deepClone } from '../../utils/util';
import fun from '../../mixins/fun'
import { formInitVal, vaildData } from '../../utils/util';
export default create({
name: 'steps',
mixins: [fun()],
props: {
value: {
type: Object,
default: () => { }
},
option: {
type: Object,
required: true
}
},
computed: {
lastFlag () {
return this.formIndex === this.columnLen;
},
crudFlag () {
return this.objectOption.type === 'crud'
},
columnOption () {
return this.option.column || [];
},
columnLen () {
return this.columnOption.length;
},
formOption () {
return this.objectOption.option;
},
formColumnOption () {
return this.formOption.column || [];
},
objectOption () {
let formobj = deepClone(this.columnOption[this.formIndex - 1]);
let submitText = formobj.option.submitText;
if (!submitText && this.formIndex !== this.columnLen) formobj.option.submitText = '下一步';
return formobj;
},
status () {
let status = [];
const leng = this.step - 1;
for (let i = 0; i < leng; i++) {
status.push('success');
}
return status;
}
},
watch: {
formOption () {
this.formInit();
this.$emit('change', this.objectOption);
},
text: {
handler () {
for (let o in this.tableForm) {
this.tableForm[o] = this.text[o];
}
},
deep: true
},
value: {
handler () {
this.formVal();
},
deep: true
}
},
data () {
return {
step: 1,
tableForm: {},
text: {},
formIndex: 1
};
},
created () {
this.formInit();
this.$emit('change', this.columnOption[this.formIndex - 1]);
},
methods: {
reset () {
this.formIndex = 1;
this.step = 1;
},
switchs (index) {
if (index < this.step) { this.formIndex = index + 1; }
},
next () {
if (this.step <= this.formIndex) {
this.step++;
}
if (!this.lastFlag) {
this.formIndex++;
}
},
breaks () {
this.formIndex--;
},
vaildData (val, dafult) {
return vaildData(val, dafult)
},
formInit () {
const column = this.formOption.column;
this.tableForm = formInitVal(column).tableForm;
this.formVal();
},
formVal () {
for (let o in this.value) {
this.text[o] = this.value[o];
}
for (let o in this.tableForm) {
this.tableForm[o] = this.text[o];
}
this.$emit('input', this.tableForm);
},
submit () {
this.$emit('submit', this.tableForm, this.next);
}
}
});
</script>
import TableTree from './src/main';
TableTree.install = function(Vue) {
Vue.component(TableTree.name, TableTree);
};
export default TableTree;
'use strict';
import Vue from 'vue';
export default function treeToArray(data, expandAll, parent = null, level = null) {
let tmp = [];
Array.from(data).forEach(function(record) {
if (record._expanded === undefined) {
Vue.set(record, '_expanded', expandAll);
}
let _level = 1;
if (level !== undefined && level !== null) {
_level = level + 1;
}
Vue.set(record, '_level', _level);
// 如果有父元素
if (parent) {
Vue.set(record, 'parent', parent);
}
tmp.push(record);
if (record.children && record.children.length > 0) {
const children = treeToArray(record.children, expandAll, record, _level);
tmp = tmp.concat(children);
}
});
return tmp;
}
<template>
<el-table :data="formatData"
:class="b()"
:stripe="option.stripe"
:row-style="showRow"
:row-class-name="rowClassName"
v-bind="$attrs"
:border="border">
<el-table-column v-if="columns.length===0"
width="150">
<template slot-scope="scope">
<span v-for="space in scope.row._level"
class="ms-tree-space"
:key="space"></span>
<span class="tree-ctrl"
v-if="iconShow(0,scope.row)"
@click="toggleExpanded(scope.$index)">
<i v-if="!scope.row._expanded"
class="el-icon-plus"></i>
<i v-else
class="el-icon-minus"></i>
</span>
{{scope.$index}}
</template>
</el-table-column>
<el-table-column v-else
v-for="(column, index) in columns"
:key="column.value"
:label="column.text"
:width="column.width">
<template slot-scope="scope">
<span v-if="index === 0"
v-for="space in scope.row._level"
class="ms-tree-space"
:key="space"></span>
<span class="tree-ctrl"
v-if="iconShow(index,scope.row)"
@click="toggleExpanded(scope.$index)">
<i v-if="!scope.row._expanded"
class="el-icon-plus"></i>
<i v-else
class="el-icon-minus"></i>
</span>
{{detail(scope.row,column)}}
</template>
</el-table-column>
<slot></slot>
</el-table>
</template>
<script>
import create from '../../utils/create';
import treeToArray from './eval';
import crud from '../../mixins/crud.js';
import column from '../../mixins/column.js';
export default create({
name: 'tree-table',
mixins: [crud(), column()],
props: {
option: {
type: Object,
required: true
},
rowClassName: Function,
evalFunc: Function,
evalArgs: Array
},
data () {
return {};
},
created () { },
computed: {
columnOption () {
return this.option.columns || [];
},
data: function () {
return this.option.data || [];
},
columns: function () {
return this.option.columns || [];
},
expandAll: function () {
return this.option.expandAll;
},
border: function () {
return this.option.border || true;
},
// 格式化数据源
formatData: function () {
let tmp;
if (!Array.isArray(this.data)) {
tmp = [this.data];
} else {
tmp = this.data;
}
const func = this.evalFunc || treeToArray;
const args = this.evalArgs
? Array.concat([tmp, this.expandAll], this.evalArgs)
: [tmp, this.expandAll];
return func.apply(null, args);
}
},
methods: {
rulesInit () {
},
formInit () {
},
showRow: function (row) {
const show = row.row.parent
? row.row.parent._expanded && row.row.parent._show
: true;
row.row._show = show;
return show
? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;'
: 'display:none;';
},
// 切换下级是否展开
toggleExpanded: function (trIndex) {
const record = this.formatData[trIndex];
record._expanded = !record._expanded;
},
// 图标显示
iconShow (index, record) {
return index === 0 && record.children && record.children.length > 0;
}
}
});
</script>
import Tabs from './src/main';
Tabs.install = function(Vue) {
Vue.component(Tabs.name, Tabs);
};
export default Tabs;
\ No newline at end of file
<template>
<div class="b()">
<el-tabs v-model="formIndex"
:type="option.type"
:tab-position="option.tabPosition">
<el-tab-pane v-for="(item,index) in columnOption"
:key="index"
:disabled="item.disabled"
:name="index+''">
<span slot="label">
<i :class="item.icon"></i> {{item.label}}</span>
</el-tab-pane>
</el-tabs>
<div>
<slot name="before"></slot>
<avue-crud v-if="crudFlag"
ref="crud"
:option="formOption"
:data="data"
:table-loading="tableLoading"
:before-open="beforeOpen"
:before-close="beforeClose"
:upload-before="uploadBefore"
:upload-after="uploadAfter"
:row-class-name="rowClassName"
:span-method="spanMethod"
:summary-method="summaryMethod"
@refresh-change="refreshChange"
@search-reset="searchReset"
@size-change="size-change"
@date-change="date-change"
@current-change="currentChange"
@current-row-change="currentRowChange"
@selection-change="selectionChange"
@sort-change="sortChange"
@search-change="searchChange"
@row-dblclick="rowDblclick"
@row-click="rowClick"
@row-del="rowDel"
@row-save="rowSave"
@row-update="rowUpdate"
v-model="text">
<!-- 自定义搜索 -->
<template slot="search">
<slot name="search"></slot>
</template>
<!-- 自定义搜索按钮 -->
<template slot="searchMenu">
<slot name="searchMenu"></slot>
</template>
<!-- 自定义表单列 -->
<template slot-scope="scope"
v-for="item in formColumnOption"
:slot="item.prop">
<slot :value="scope.value"
:column="scope.column"
:dic="scope.dic"
:name="item.prop+'Form'"
v-if="item.formsolt"></slot>
</template>
<!-- 自定义表格列 -->
<template slot-scope="scope"
v-for="item in formColumnOption"
:slot="item.prop">
<slot :value="scope.value"
:column="scope.column"
:dic="scope.dic"
:name="item.prop"
v-if="item.solt"></slot>
</template>
<!-- 表格左侧卡槽 -->
<template slot="menuLeft">
<slot name="menuLeft"></slot>
</template>
<!-- 表格右测卡槽 -->
<template slot="menuRight">
<slot name="menuRight"></slot>
</template>
<!-- 清空卡槽 -->
<template slot="empty">
<slot name="empty"
v-if="$slots.empty"></slot>
</template>
<!-- 折叠面板卡槽 -->
<template slot-scope="props"
slot="expand">
<slot :row="props.row"
name="expand"></slot>
</template>
<!-- 菜单栏按钮卡槽 -->
<template slot-scope="scope"
slot="menuBtn">
<slot name="menuBtn"
:row="scope.row"
:dic="scope.dic"
:label="scope.label"
:index="scope.$index"></slot>
</template>
<!-- 菜单栏 -->
<template slot-scope="scope"
slot="menu">
<slot name="menu"
:value="scope.value"
:column="scope.column"
:dic="scope.dic"></slot>
</template>
<!-- 弹出框按钮 -->
<template slot="menuForm">
<slot name="menuForm"></slot>
</template>
</avue-crud>
<avue-form v-else
:option="formOption"
:upload-before="uploadBefore"
:upload-after="uploadAfter"
@submit="submit"
ref="form"
v-model="text">
<template slot-scope="scope"
v-for="item in formColumnOption"
:slot="item.prop">
<slot :value="scope.value"
:column="scope.column"
:dic="scope.dic"
:name="item.prop"
v-if="item.formsolt"></slot>
</template>
<template slot="menuForm">
<slot name="menuForm"></slot>
</template>
</avue-form>
<slot name="after"></slot>
</div>
</div>
</template>
<script>
import create from '../../utils/create';
import { formInitVal } from '../../utils/util';
import fun from '../../mixins/fun'
import { setTimeout } from 'timers';
export default create({
name: 'tabs',
mixins: [fun()],
props: {
value: {
type: Object,
default: () => { }
},
option: {
type: Object,
required: true
}
},
computed: {
crudFlag () {
return this.objectOption.type === 'crud'
},
columnOption () {
return this.option.column || [];
},
columnLen () {
return this.columnOption.length;
},
formOption () {
return this.objectOption.option;
},
formColumnOption () {
return this.formOption.column || [];
},
objectOption () {
return this.columnOption[this.formIndex];
}
},
watch: {
formIndex () {
if (!this.crudFlag) {
setTimeout(() => {
this.$refs.form.clearValidate();
}, 0)
}
this.formInit();
this.$emit('change', this.columnOption[this.formIndex]);
},
text: {
handler () {
for (let o in this.tableForm) {
this.tableForm[o] = this.text[o];
}
},
deep: true
},
value: {
handler () {
this.formVal();
},
deep: true
}
},
data () {
return {
tableForm: {},
text: {},
formIndex: '0'
};
},
created () {
this.formInit();
this.$emit('change', this.columnOption[this.formIndex]);
},
methods: {
formInit () {
const column = this.formOption.column;
this.tableForm = formInitVal(column).tableForm;
this.formVal();
},
formVal () {
for (let o in this.value) {
this.text[o] = this.value[o];
}
for (let o in this.tableForm) {
this.tableForm[o] = this.text[o];
}
this.$emit('input', this.tableForm);
},
submit () {
this.$emit('submit', this.tableForm);
},
}
});
</script>
\ No newline at end of file
'use strict';
var gulp = require('gulp');
var sass = require('gulp-sass');
var autoprefixer = require('gulp-autoprefixer');
var cssmin = require('gulp-cssmin');
gulp.task('compile', function() {
return gulp.src('./src/**')
.pipe(sass.sync())
.pipe(autoprefixer({
browsers: ['ie > 9', 'last 2 versions'],
cascade: false
}))
.pipe(cssmin())
.pipe(gulp.dest('./lib'));
});
gulp.task('copyfont', function() {
return gulp.src('./src/fonts/**')
.pipe(cssmin())
.pipe(gulp.dest('./lib/fonts'));
});
gulp.task('build', ['compile', 'copyfont']);
.avue-carousel__item{position:relative;width:100%;height:100%}.avue-carousel__item a{width:100%;height:100%;display:block}.avue-carousel__img{height:100%;background-size:cover;background-position:center center}.avue-carousel__title{z-index:1024;position:absolute;left:0;bottom:0;width:100%;height:50px;line-height:50px;font-size:16px;text-align:center;color:#fff;background-color:rgba(0,0,0,.6)}
\ No newline at end of file
.avue-ghost{opacity:.5;background:#c8ebfb}.avue-dialog{max-height:500px;overflow:hidden;overflow-y:auto}.avue-tip{position:relative;margin-bottom:12px;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-tip__icon{margin-top:3px;margin-right:5px;font-size:14px}.avue-tip__name{font-size:12px;margin-right:15px;color:#515a6e}.avue-tip__name--bold{padding:0 6px;color:#409eff;font-weight:700;font-size:18px}.avue-tip__btn{margin-top:3px;cursor:pointer}
\ No newline at end of file
.avue-crud-upload--list .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avue-crud-upload--list .el-upload:hover{border-color:#409eff}.avue-crud-upload__icon{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avue-crud-upload__avatar{width:178px;height:178px;display:block}
\ No newline at end of file
.avue-crud{margin:0 auto;width:99%}.avue-crud .el-table th{word-break:break-word;color:rgba(0,0,0,.85);background-color:#fafafa}.avue-crud__pagination{position:relative;height:25px;margin-top:15px;margin-bottom:10px;padding:10px 20px}.avue-crud__pagination .el-pagination{position:absolute;right:0}.avue-crud__form{padding:0 8px}.avue-crud__header{margin-bottom:10px}.avue-crud__header>.el-button{padding:12px 25px}.avue-crud__box{-webkit-box-shadow:none!important;box-shadow:none!important;border:none}.avue-crud__box .el-card__body,.avue-crud__box .el-card__header{padding:18px 0}.avue-crud__title{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.avue-crud__menu{position:relative;width:100%;min-height:40px;height:auto;overflow:hidden;margin-bottom:12px}.avue-crud__left,.avue-crud__right{position:absolute;height:auto;overflow:hidden}.avue-crud__left{left:0}.avue-crud__left .el-button{margin-right:5px}.avue-crud__right{right:0}.avue-crud__right .el-button{margin-left:5px}.avue-crud__dialog .el-dialog__header{border-top-left-radius:5px;border-top-right-radius:5px;padding:12px 20px;background-color:#409eff}.avue-crud__dialog .el-dialog__close{color:#fff;font-size:18px}.avue-crud__dialog .el-dialog__close:hover{color:#fdf}.avue-crud__dialog .el-dialog__title{color:#fff;font-size:18px}.avue-crud__dialog .el-dialog__headerbtn{top:18px}.avue-crud__dialog--overflow{max-height:400px;overflow:hidden;overflow-y:auto}
\ No newline at end of file
.data-box .item a,.data-box .item-icon{display:-webkit-box;display:-ms-flexbox}.data-box .item{position:relative;margin:0 auto 10px;width:96%;height:100px;overflow:hidden;border-radius:5px;-webkit-box-sizing:border-box;box-sizing:border-box}.data-box .item:hover .item-text{top:0}.data-box .item a{display:flex}.data-box .item-icon{width:100px;height:100px;color:#fff;text-align:center;line-height:100px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;display:flex}.data-box .item-icon i{font-size:48px!important}.data-box .item-info{border:1px solid #eee;border-left:none;background-color:#fff;-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.data-box .item-info .title{font-size:30px;line-height:40px;text-align:center}.data-box .item-info .info{color:#999;font-size:14px;text-align:center}
\ No newline at end of file
.data-card .item{position:relative;margin:0 auto 50px;width:230px;height:340px;overflow:hidden;border-radius:5px;border-color:#fff;border-width:1px;border-style:solid}.data-card .item:hover .item-text{top:0}.data-card .item-img{width:100%;background:red;border-radius:5px 5px 0 0}.data-card .item-text{position:absolute;top:150px;padding:20px 15px;width:100%;height:340px;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:0 0 5px 5px;opacity:.9;-webkit-transition:top .4s;transition:top .4s}.data-card .item-text>p{font-size:12px;line-height:25px;text-indent:2em}
\ No newline at end of file
.avue-data-display .item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:5px 0;text-align:center}.avue-data-display .count{margin:8px 0;font-weight:700;font-size:32px;color:#15A0FF}.avue-data-display .title{color:#999}.avue-data-display .splitLine{display:block;margin:0 auto;width:24px;height:1px;background:#9B9B9B}
\ No newline at end of file
.data-icons .item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:90%;margin:0 auto}.data-icons .item-icon{margin-top:3px;margin-right:8px}.data-icons .item-icon>i{font-size:46px!important}.data-icons .item-info{text-align:center}.data-icons .item-info>span{display:block;color:#999;font-size:12px}.data-icons .item-info .count{font-size:20px;line-height:25px}.data-icons .item--easy{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.data-icons .item--easy>.item-icon{margin:0}.data-icons .item--easy>.item-info{margin-top:-15px}.data-icons .item--easy>.item-info>span{font-size:14px}
\ No newline at end of file
.data-progress .item{margin:10px}.data-progress .item-header{margin-bottom:10px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.data-progress .item-count{line-height:26px;font-size:26px;color:#666}.data-progress .item-title{color:#999;font-size:14px}
\ No newline at end of file
.data-tabs .item,.data-tabs .item-header{position:relative}.data-tabs .item{margin:15px;padding:12px;height:160px;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;color:#fff}.data-tabs .item a{color:#fff}.data-tabs .item-header>p{color:#fff;margin:0;font-size:14px}.data-tabs .item-header>span{position:absolute;right:0;top:0;padding:2px 8px;border-radius:4px;font-size:12px;background:rgba(255,255,255,.3)}.data-tabs .item-body>h2{color:#fff;margin:0;font-size:32px;line-height:60px}.data-tabs .item-footer{padding-top:8px;line-height:20px}.data-tabs .item-footer>span{font-size:10px}.data-tabs .item-footer>p{color:#fff;margin:0;font-size:12px}.data-tabs .item-tip{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:absolute;width:80px;height:80px;bottom:10px;right:10px;border:2px solid #fff;border-radius:100%;font-size:48px;-webkit-transform:rotate(-40deg);transform:rotate(-40deg);opacity:.1}
\ No newline at end of file
.avue-date-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-date-group__radio .el-radio-button:last-child .el-radio-button__inner{border-radius:0;border-right:0}.avue-date-group__date{width:300px}.avue-date-group__date .el-date-editor{border-top-left-radius:0;border-bottom-left-radius:0}
\ No newline at end of file
.avue-date-select{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-date-select__radio .el-radio-button:last-child .el-radio-button__inner{border-radius:0;border-right:0}.avue-date-select__date{width:300px}.avue-date-select__date .el-date-editor{border-top-left-radius:0;border-bottom-left-radius:0}
\ No newline at end of file
.avue-input-number,.el-cascader,.el-date-editor.el-input,.el-date-editor.el-input__inner,.el-select{width:100%!important}.el-input__inner{height:38px;line-height:38px}.el-input--small input{height:32px!important;line-height:32px!important}.el-input--mini input{height:28px!important;line-height:28px!important}.el-table--medium td{padding:7px 0!important}.el-tooltip__popper{max-width:60%}.el-dropdown-menu__item{line-height:25px}
\ No newline at end of file
.avue-form-detail__item{padding:20px 0;border-bottom:1px solid #eee}.avue-form-detail__item:last-child{border-bottom:none}.avue-form-detail__icon{margin-right:10px;font-size:20px}.avue-form-detail__header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:15px}.avue-form-detail__title{font-size:16px;font-weight:500;color:rgba(0,0,0,.85)}.avue-form-detail__box{margin-bottom:20px;font-size:14px}.avue-form-detail__label{margin-right:10px;line-height:20px;color:rgba(0,0,0,.85)}.avue-form-detail__label--center{text-align:center}.avue-form-detail__label--left{text-align:left}.avue-form-detail__label--right{text-align:right}.avue-form-detail__content{line-height:22px;width:100%;color:rgba(0,0,0,.65)}
\ No newline at end of file
.avue-form-steps--vertical{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex}.avue-form-steps__steps{width:230px}.avue-form-steps__contail{-webkit-box-flex:1;-ms-flex:1;flex:1}.avue-form-steps__form{margin:0 auto}
\ No newline at end of file
.avue-form,.avue-form__group .el-col{position:relative}.avue-form{margin:0 auto;-webkit-box-sizing:border-box;box-sizing:border-box;padding-right:20px}.avue-form__menu{width:100%}.avue-form__menu--center{text-align:center}.avue-form__menu--left{text-align:left}.avue-form__menu--right{text-align:right}.avue-form__group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-ms-flex-wrap:wrap;flex-wrap:wrap;height:auto;overflow:hidden}.avue-form__line{height:30px}.avue-form__row--block{width:100%;display:block}.avue-form__row--cursor{cursor:pointer}.avue-form__option{position:absolute;right:0;top:-10px;z-index:999}.avue-form__option i{color:#666}.avue-form__option i+i{margin-left:10px}
\ No newline at end of file
.avue-data-display .item,.data-box .item-info,.data-icons .item--easy,.json-tree{-webkit-box-orient:vertical;-webkit-box-direction:normal}.avue-form__row--cursor,.avue-steps__tabs,.avue-tip__btn,.avue-tree-table .tree-ctrl,.json-tree-expando{cursor:pointer}.avue-ghost{opacity:.5;background:#c8ebfb}.avue-dialog{max-height:500px;overflow:hidden;overflow-y:auto}.avue-tip{position:relative;margin-bottom:12px;width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-tip__icon{margin-top:3px;margin-right:5px;font-size:14px}.avue-tip__name{font-size:12px;margin-right:15px;color:#515a6e}.avue-tip__name--bold{padding:0 6px;color:#409eff;font-weight:700;font-size:18px}.avue-tip__btn{margin-top:3px}.avue-input-number,.el-cascader,.el-date-editor.el-input,.el-date-editor.el-input__inner,.el-select{width:100%!important}.el-input__inner{height:38px;line-height:38px}.el-input--small input{height:32px!important;line-height:32px!important}.el-input--mini input{height:28px!important;line-height:28px!important}.el-table--medium td{padding:7px 0!important}.el-tooltip__popper{max-width:60%}.el-dropdown-menu__item{line-height:25px}.avue-crud{margin:0 auto;width:99%}.avue-crud .el-table th{word-break:break-word;color:rgba(0,0,0,.85);background-color:#fafafa}.avue-crud__pagination{position:relative;height:25px;margin-top:15px;margin-bottom:10px;padding:10px 20px}.avue-crud__pagination .el-pagination{position:absolute;right:0}.avue-crud__form{padding:0 8px}.avue-crud__header{margin-bottom:10px}.avue-crud__header>.el-button{padding:12px 25px}.avue-crud__box{-webkit-box-shadow:none!important;box-shadow:none!important;border:none}.avue-crud__box .el-card__body,.avue-crud__box .el-card__header{padding:18px 0}.avue-crud__title{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.avue-crud__menu{position:relative;width:100%;min-height:40px;height:auto;overflow:hidden;margin-bottom:12px}.avue-crud__left,.avue-crud__right{position:absolute;height:auto;overflow:hidden}.avue-crud__left{left:0}.avue-crud__left .el-button{margin-right:5px}.avue-crud__right{right:0}.avue-crud__right .el-button{margin-left:5px}.avue-crud__dialog .el-dialog__header{border-top-left-radius:5px;border-top-right-radius:5px;padding:12px 20px;background-color:#409eff}.avue-crud__dialog .el-dialog__close{color:#fff;font-size:18px}.avue-crud__dialog .el-dialog__close:hover{color:#fdf}.avue-crud__dialog .el-dialog__title{color:#fff;font-size:18px}.avue-crud__dialog .el-dialog__headerbtn{top:18px}.avue-crud__dialog--overflow{max-height:400px;overflow:hidden;overflow-y:auto}.avue-crud-upload--list .el-upload{border:1px dashed #d9d9d9;border-radius:6px;cursor:pointer;position:relative;overflow:hidden}.avue-crud-upload--list .el-upload:hover{border-color:#409eff}.avue-crud-upload__icon{font-size:28px;color:#8c939d;width:178px;height:178px;line-height:178px;text-align:center}.avue-crud-upload__avatar{width:178px;height:178px;display:block}.avue-tree-table .ms-tree-space{position:relative;top:1px;display:inline-block;font-style:normal;font-weight:400;line-height:1;width:18px;height:14px}.avue-tree-table .ms-tree-space::before{content:""}.avue-tree-table .processContainer{width:100%;height:100%}.avue-tree-table table td{line-height:26px}.avue-tree-table .tree-ctrl{position:relative;color:#2196f3;margin-left:-18px}@keyframes treeTableShow{from{opacity:0}to{opacity:1}}@-webkit-keyframes treeTableShow{from{opacity:0}to{opacity:1}}.avue-form{position:relative;margin:0 auto;-webkit-box-sizing:border-box;box-sizing:border-box;padding-right:20px}.avue-form__menu{width:100%}.avue-form__menu--center{text-align:center}.avue-form__menu--left{text-align:left}.avue-form__menu--right{text-align:right}.avue-form-detail__label--center,.avue-steps__menu{text-align:center}.avue-form__group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-ms-flex-wrap:wrap;flex-wrap:wrap;height:auto;overflow:hidden}.avue-form__group .el-col{position:relative}.avue-form__line{height:30px}.avue-form__row--block{width:100%;display:block}.avue-form__option{position:absolute;right:0;top:-10px;z-index:999}.avue-form__option i{color:#666}.avue-form__option i+i{margin-left:10px}.avue-steps--vertical{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex}.avue-steps__steps{width:230px}.avue-steps__contail{padding:20px 0;-webkit-box-flex:1;-ms-flex:1;flex:1}.avue-steps__form{margin:0 auto}.avue-form-detail__item{padding:20px 0;border-bottom:1px solid #eee}.avue-form-detail__item:last-child{border-bottom:none}.avue-form-detail__icon{margin-right:10px;font-size:20px}.avue-form-detail__header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-bottom:15px}.avue-data-display .item,.data-tabs .item-tip{display:-webkit-box;display:-ms-flexbox;-webkit-box-align:center}.avue-form-detail__title{font-size:16px;font-weight:500;color:rgba(0,0,0,.85)}.avue-form-detail__box{margin-bottom:20px;font-size:14px}.avue-form-detail__label{margin-right:10px;line-height:20px;color:rgba(0,0,0,.85)}.avue-form-detail__label--left{text-align:left}.avue-form-detail__label--right{text-align:right}.avue-form-detail__content{line-height:22px;width:100%;color:rgba(0,0,0,.65)}.avue-data-display .item{display:flex;-ms-flex-align:center;align-items:center;-ms-flex-direction:column;flex-direction:column;margin:5px 0;text-align:center}.avue-data-display .count{margin:8px 0;font-weight:700;font-size:32px;color:#15A0FF}.avue-data-display .title{color:#999}.avue-data-display .splitLine{display:block;margin:0 auto;width:24px;height:1px;background:#9B9B9B}.data-card .item{position:relative;margin:0 auto 50px;width:230px;height:340px;overflow:hidden;border-radius:5px;border-color:#fff;border-width:1px;border-style:solid}.data-card .item:hover .item-text{top:0}.data-card .item-img{width:100%;background:red;border-radius:5px 5px 0 0}.data-card .item-text{position:absolute;top:150px;padding:20px 15px;width:100%;height:340px;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:0 0 5px 5px;opacity:.9;-webkit-transition:top .4s;transition:top .4s}.data-tabs .item,.data-tabs .item-header{position:relative}.data-card .item-text>p{font-size:12px;line-height:25px;text-indent:2em}.data-tabs .item{margin:15px;padding:12px;height:160px;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;color:#fff}.data-tabs .item a{color:#fff}.data-tabs .item-header>p{color:#fff;margin:0;font-size:14px}.data-tabs .item-header>span{position:absolute;right:0;top:0;padding:2px 8px;border-radius:4px;font-size:12px;background:rgba(255,255,255,.3)}.data-tabs .item-body>h2{color:#fff;margin:0;font-size:32px;line-height:60px}.data-tabs .item-footer{padding-top:8px;line-height:20px}.data-tabs .item-footer>span{font-size:10px}.data-tabs .item-footer>p{color:#fff;margin:0;font-size:12px}.data-tabs .item-tip{display:flex;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:absolute;width:80px;height:80px;bottom:10px;right:10px;border:2px solid #fff;border-radius:100%;font-size:48px;-webkit-transform:rotate(-40deg);transform:rotate(-40deg);opacity:.1}.data-icons .item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:90%;margin:0 auto}.data-icons .item-icon{margin-top:3px;margin-right:8px}.data-icons .item-icon>i{font-size:46px!important}.data-icons .item-info{text-align:center}.data-icons .item-info>span{display:block;color:#999;font-size:12px}.data-box .item a,.data-box .item-icon{display:-webkit-box;display:-ms-flexbox}.data-icons .item-info .count{font-size:20px;line-height:25px}.data-icons .item--easy{-ms-flex-direction:column;flex-direction:column}.data-icons .item--easy>.item-icon{margin:0}.data-icons .item--easy>.item-info{margin-top:-15px}.data-icons .item--easy>.item-info>span{font-size:14px}.data-box .item{position:relative;margin:0 auto 10px;width:96%;height:100px;overflow:hidden;border-radius:5px;-webkit-box-sizing:border-box;box-sizing:border-box}.data-box .item:hover .item-text{top:0}.data-box .item a{display:flex}.data-box .item-icon{width:100px;height:100px;color:#fff;text-align:center;line-height:100px;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;display:flex}.data-box .item-icon i{font-size:48px!important}.data-box .item-info{border:1px solid #eee;border-left:none;background-color:#fff;-webkit-box-flex:1;-ms-flex:1;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-ms-flex-direction:column;flex-direction:column}.data-box .item-info .title{font-size:30px;line-height:40px;text-align:center}.data-box .item-info .info{color:#999;font-size:14px;text-align:center}.data-progress .item{margin:10px}.data-progress .item-header{margin-bottom:10px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.data-progress .item-count{line-height:26px;font-size:26px;color:#666}.data-progress .item-title{color:#999;font-size:14px}.avue-date-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-date-group__radio .el-radio-button:last-child .el-radio-button__inner{border-radius:0;border-right:0}.avue-date-group__date{width:300px}.avue-date-group__date .el-date-editor{border-top-left-radius:0;border-bottom-left-radius:0}.avue-carousel__item{position:relative;width:100%;height:100%}.avue-carousel__item a{width:100%;height:100%;display:block}.avue-carousel__img{height:100%;background-size:cover;background-position:center center}.avue-carousel__title{z-index:1024;position:absolute;left:0;bottom:0;width:100%;height:50px;line-height:50px;font-size:16px;text-align:center;color:#fff;background-color:rgba(0,0,0,.6)}.json-tree{color:#394359;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px;line-height:20px}.json-tree-root{background-color:#f7f8f9;border-radius:3px;margin:2px 0;min-width:560px;padding:10px}.json-tree-input,.json-tree-menu span{margin-right:5px}.json-tree-ending,.json-tree-row{position:relative;border-radius:2px;display:-webkit-box;display:-ms-flexbox;display:flex}.json-tree-paired,.json-tree-row:hover{background-color:#bce2ff}.json-tree-menu{position:absolute;right:0}.json-tree-input{padding:3px 0;height:12px;border:1px solid #eee;outline:0}.json-tree-submit{height:10px}.json-tree-sign{font-weight:700}.json-tree-collapsed{color:gray;font-style:italic}.json-tree-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.json-tree-value-string{color:#9aab3a}.json-tree-value-boolean{color:#ff0080}.json-tree-value-number{color:#4f7096}.json-tree-value-null{color:#c7444a}.avue-tree__item{position:relative;width:100%}.avue-tree__title{font-size:14px}.avue-tree__icon{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.avue-tree__menu{position:absolute;top:2px;right:2px;z-index:1024}.avue-tree__filter{margin-bottom:15px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}
\ No newline at end of file
.json-tree{color:#394359;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;font-family:Menlo,Monaco,Consolas,monospace;font-size:12px;line-height:20px}.json-tree-root{background-color:#f7f8f9;border-radius:3px;margin:2px 0;min-width:560px;padding:10px}.json-tree-input,.json-tree-menu span{margin-right:5px}.json-tree-ending,.json-tree-row{position:relative;border-radius:2px;display:-webkit-box;display:-ms-flexbox;display:flex}.json-tree-paired,.json-tree-row:hover{background-color:#bce2ff}.json-tree-expando{cursor:pointer}.json-tree-menu{position:absolute;right:0}.json-tree-input{padding:3px 0;height:12px;border:1px solid #eee;outline:0}.json-tree-submit{height:10px}.json-tree-sign{font-weight:700}.json-tree-collapsed{color:gray;font-style:italic}.json-tree-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.json-tree-value-string{color:#9aab3a}.json-tree-value-boolean{color:#ff0080}.json-tree-value-number{color:#4f7096}.json-tree-value-null{color:#c7444a}
\ No newline at end of file
.avue-select-date{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.avue-select-date__radio .el-radio-button:last-child .el-radio-button__inner{border-radius:0;border-right:0}.avue-select-date__date{width:300px}.avue-select-date__date .el-date-editor{padding:0 10px;height:36px;border-top-left-radius:0;border-bottom-left-radius:0}
\ No newline at end of file
.avue-steps__menu{text-align:center}.avue-steps--vertical{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex}.avue-steps__tabs{cursor:pointer}.avue-steps__steps{width:230px}.avue-steps__contail{padding:20px 0;-webkit-box-flex:1;-ms-flex:1;flex:1}.avue-steps__form{margin:0 auto}
\ No newline at end of file
.avue-tree-table .ms-tree-space{position:relative;top:1px;display:inline-block;font-style:normal;font-weight:400;line-height:1;width:18px;height:14px}.avue-tree-table .ms-tree-space::before{content:""}.avue-tree-table .processContainer{width:100%;height:100%}.avue-tree-table table td{line-height:26px}.avue-tree-table .tree-ctrl{position:relative;cursor:pointer;color:#2196f3;margin-left:-18px}@keyframes treeTableShow{from{opacity:0}to{opacity:1}}@-webkit-keyframes treeTableShow{from{opacity:0}to{opacity:1}}
\ No newline at end of file
.avue-tree__item{position:relative;width:100%}.avue-tree__title{font-size:14px}.avue-tree__icon{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.avue-tree__menu{position:absolute;top:2px;right:2px;z-index:1024}.avue-tree__filter{margin-bottom:15px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}
\ No newline at end of file
{
"name": "avue-theme-chalk",
"version": "2.0.0",
"main": "lib/index.css",
"style": "lib/index.css",
"files": [
"lib",
"src"
],
"scripts": {
"build": "gulp build"
},
"keywords": [],
"license": "MIT",
"bugs": {
"devDependencies": {
"gulp": "^3.9.1",
"gulp-cssmin": "^0.1.7",
"gulp-sass": "^3.1.0",
"gulp-autoprefixer": "^4.0.0"
},
"dependencies": {}
}
}
\ No newline at end of file
.avue-carousel {
&__item {
position: relative;
width: 100%;
height: 100%;
a {
width: 100%;
height: 100%;
display: block;
}
}
&__img {
height: 100%;
background-size: cover;
background-position: center center;
}
&__title {
z-index: 1024;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 50px;
line-height: 50px;
font-size: 16px;
text-align: center;
color: #fff;
background-color: rgba(0, 0, 0, .6);
}
}
\ No newline at end of file
.avue-ghost {
opacity: 0.5;
background: #c8ebfb;
}
.avue-dialog {
max-height: 500px;
overflow: hidden;
overflow-y: auto;
}
.avue-tip {
position: relative;
margin-bottom: 12px;
width: 100%;
display: flex;
align-items: center;
&__icon {
margin-top: 3px;
margin-right: 5px;
font-size: 14px;
}
&__name {
font-size: 12px;
margin-right: 15px;
color: #515a6e;
&--bold {
padding: 0 6px;
color: #409eff;
font-weight: bold;
font-size: 18px;
}
}
&__btn {
margin-top: 3px;
cursor: pointer;
}
}
\ No newline at end of file
.avue-crud-upload {
&--list {
.el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.el-upload:hover {
border-color: #409eff;
}
}
&__icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
&__avatar {
width: 178px;
height: 178px;
display: block;
}
}
\ No newline at end of file
.avue-crud {
margin: 0 auto;
width: 99%;
.el-table th {
word-break: break-word;
color: rgba(0, 0, 0, 0.85);
background-color: #fafafa;
}
&__pagination {
position: relative;
height: 25px;
margin-top: 15px;
margin-bottom: 10px;
padding: 10px 20px;
.el-pagination {
position: absolute;
right: 0;
}
}
&__form {
padding: 0 8px;
}
&__header {
margin-bottom: 10px;
&>.el-button {
padding: 12px 25px;
}
}
&__box {
box-shadow: none !important;
border: none;
.el-card__body,
.el-card__header {
padding: 18px 0;
}
}
&__title {
display: flex;
align-items: center;
justify-content: space-between;
}
&__menu {
position: relative;
width: 100%;
min-height: 40px;
height: auto;
overflow: hidden;
margin-bottom: 12px;
}
&__left,
&__right {
position: absolute;
height: auto;
overflow: hidden;
}
&__left {
left: 0;
.el-button {
margin-right: 5px;
}
}
&__right {
right: 0;
.el-button {
margin-left: 5px;
}
}
&__dialog {
.el-dialog__header {
border-top-left-radius: 5px;
border-top-right-radius: 5px;
padding: 12px 20px;
background-color: #409eff;
}
.el-dialog__close {
color: #fff;
font-size: 18px;
&:hover {
color: #ffddff;
}
}
.el-dialog__title {
color: #fff;
font-size: 18px;
}
.el-dialog__headerbtn {
top: 18px;
}
&--overflow {
max-height: 400px;
overflow: hidden;
overflow-y: auto;
}
}
}
\ No newline at end of file
.data-box {
$height: 100px;
$radius: 5px;
.item {
position: relative;
margin: 0 auto 10px auto;
width: 96%;
height: $height;
overflow: hidden;
border-radius: $radius;
box-sizing: border-box;
&:hover .item-text {
top: 0;
}
a {
display: flex;
}
}
.item-icon {
width: 100px;
height: $height;
color: #fff;
text-align: center;
line-height: $height;
align-items: center;
justify-content: center;
display: flex;
i {
font-size: 48px !important;
}
}
.item-info {
border: 1px solid #eee;
border-left: none;
background-color: #fff;
flex: 1;
display: flex;
justify-content: center;
flex-direction: column;
.title {
font-size: 30px;
line-height: 40px;
text-align: center;
}
.info {
color: #999;
font-size: 14px;
text-align: center;
}
}
}
\ No newline at end of file
.data-card {
$height: 340px;
.item {
position: relative;
margin: 0 auto;
margin-bottom: 50px;
width: 230px;
height: $height;
overflow: hidden;
border-radius: 5px;
border-color: #fff;
border-width: 1px;
border-style: solid;
&:hover .item-text {
top: 0;
}
}
.item-img {
width: 100%;
background: red;
border-radius: 5px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.item-text {
position: absolute;
top: 150px;
padding: 20px 15px;
width: 100%;
height: $height;
overflow: auto;
box-sizing: border-box;
border-radius: 5px;
border-top-left-radius: 0;
border-top-right-radius: 0;
opacity: 0.9;
transition: top 0.4s;
&>p {
font-size: 12px;
line-height: 25px;
text-indent: 2em;
}
}
}
\ No newline at end of file
.avue-data-display {
.item {
display: flex;
align-items: center;
flex-direction: column;
margin: 5px 0;
text-align: center;
}
.count {
margin: 8px 0;
font-weight: bold;
font-size: 32px;
color: #15A0FF;
}
.title {
color: #999;
}
.splitLine {
display: block;
margin: 0 auto;
width: 24px;
height: 1px;
background: #9B9B9B;
}
}
\ No newline at end of file
.data-icons {
.item {
display: flex;
align-items: center;
justify-content: center;
width: 90%;
margin: 0 auto;
}
.item-icon {
margin-top: 3px;
margin-right: 8px;
&>i {
font-size: 46px !important;
}
}
.item-info {
text-align: center;
&>span {
display: block;
color: #999;
font-size: 12px;
}
.count {
font-size: 20px;
line-height: 25px;
}
}
.item--easy {
flex-direction: column;
&>.item-icon {
margin: 0;
}
&>.item-info {
margin-top: -15px;
&>span {
font-size: 14px;
}
}
}
}
\ No newline at end of file
.data-progress {
.item {
margin: 10px;
&-header {
margin-bottom: 10px;
display: flex;
align-items: center;
justify-content: space-between;
}
&-count {
line-height: 26px;
font-size: 26px;
color: #666;
}
&-title {
color: #999;
font-size: 14px;
}
}
}
\ No newline at end of file
.data-tabs {
.item {
position: relative;
margin: 15px;
padding: 12px;
height: 160px;
border-radius: 4px;
box-sizing: border-box;
overflow: hidden;
color: #fff;
a {
color: #fff;
}
}
.item-header {
position: relative;
&>p {
color: #fff;
margin: 0px;
font-size: 14px;
}
&>span {
position: absolute;
right: 0px;
top: 0px;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
background: rgba(255, 255, 255, 0.3);
}
}
.item-body {
&>h2 {
color: #fff;
margin: 0;
font-size: 32px;
line-height: 60px;
}
}
.item-footer {
padding-top: 8px;
line-height: 20px;
&>span {
font-size: 10px;
}
&>p {
color: #fff;
margin: 0px;
font-size: 12px;
}
}
.item-tip {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
width: 80px;
height: 80px;
bottom: 10px;
right: 10px;
border: 2px solid #fff;
border-radius: 100%;
font-size: 48px;
transform: rotate(-40deg);
opacity: 0.1;
}
}
\ No newline at end of file
.avue-date-group {
display: flex;
align-items: center;
&__radio {
.el-radio-button:last-child .el-radio-button__inner {
border-radius: 0;
border-right: 0;
}
}
&__date {
width: 300px;
.el-date-editor {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
}
}
}
\ No newline at end of file
.el-select,
.el-date-editor.el-input,
.el-date-editor.el-input__inner,
.el-cascader,
.avue-input-number {
width: 100% !important;
}
.el-input__inner {
height: 38px;
line-height: 38px;
}
.el-input--small {
input {
height: 32px !important;
line-height: 32px !important;
}
}
.el-input--mini {
input {
height: 28px !important;
line-height: 28px !important;
}
}
.el-table--medium td {
padding: 7px 0 !important;
}
.el-tooltip__popper {
max-width: 60%;
}
.el-dropdown-menu__item {
line-height: 25px;
}
\ No newline at end of file
.avue-form-detail {
&__item {
padding: 20px 0 20px 0;
border-bottom: 1px solid #eee;
&:last-child {
border-bottom: none;
}
}
&__icon {
margin-right: 10px;
font-size: 20px;
}
&__header {
display: flex;
align-items: center;
margin-bottom: 15px;
}
&__title {
font-size: 16px;
font-weight: 500;
color: rgba(0, 0, 0, 0.85);
}
&__box {
margin-bottom: 20px;
font-size: 14px;
}
&__label {
margin-right: 10px;
line-height: 20px;
color: rgba(0, 0, 0, 0.85);
&--center {
text-align: center;
}
&--left {
text-align: left;
}
&--right {
text-align: right;
}
}
&__content {
line-height: 22px;
width: 100%;
color: rgba(0, 0, 0, 0.65);
}
}
\ No newline at end of file
.avue-form {
position: relative;
margin: 0 auto;
box-sizing: border-box;
padding-right: 20px;
&__menu {
width: 100%;
&--center {
text-align: center;
}
&--left {
text-align: left;
}
&--right {
text-align: right;
}
}
&__group {
display: flex;
align-items: flex-start;
flex-wrap: wrap;
height: auto;
overflow: hidden;
.el-col {
position: relative;
}
}
&__line {
height: 30px;
}
&__row {
&--block {
width: 100%;
display: block;
}
&--cursor {
cursor: pointer;
}
}
&__option {
position: absolute;
right: 0;
top: -10px;
z-index: 999;
i {
color: #666;
}
i+i {
margin-left: 10px;
}
}
}
\ No newline at end of file
@import './common.scss';
@import './element-ui.scss';
@import './crud.scss';
@import './crud-upload.scss';
@import './table-tree.scss';
@import './form.scss';
@import './steps.scss';
@import './form-detail.scss';
@import './data-display.scss';
@import './data-card.scss';
@import './data-tabs.scss';
@import './data-icons.scss';
@import './data-box.scss';
@import './data-progress.scss';
@import './date-group.scss';
@import './carousel.scss';
@import './json.scss';
@import './tree.scss';
\ No newline at end of file
.json-tree {
color: #394359;
display: flex;
flex-direction: column;
font-family: Menlo, Monaco, Consolas, monospace;
font-size: 12px;
line-height: 20px;
}
.json-tree-root {
background-color: #f7f8f9;
border-radius: 3px;
margin: 2px 0;
min-width: 560px;
padding: 10px;
}
.json-tree-ending,
.json-tree-row {
position: relative;
border-radius: 2px;
display: flex;
}
.json-tree-paired,
.json-tree-row:hover {
background-color: #bce2ff;
}
.json-tree-expando {
cursor: pointer;
}
.json-tree-menu {
position: absolute;
right: 0;
span {
margin-right: 5px;
}
}
.json-tree-input {
padding: 3px 0;
margin-right: 5px;
height: 12px;
border: 1px solid #eee;
outline: none;
}
.json-tree-submit {
height: 10px;
}
.json-tree-sign {
font-weight: 700;
}
.json-tree-collapsed {
color: gray;
font-style: italic;
}
.json-tree-value {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.json-tree-value-string {
color: #9aab3a;
}
.json-tree-value-boolean {
color: #ff0080;
}
.json-tree-value-number {
color: #4f7096;
}
.json-tree-value-null {
color: #c7444a;
}
\ No newline at end of file
.avue-steps {
&__menu {
text-align: center;
}
&--vertical {
width: 100%;
display: flex;
}
&__tabs {
cursor: pointer;
}
&__steps {
width: 230px;
}
&__contail {
padding: 20px 0;
flex: 1;
}
&__form {
margin: 0 auto;
}
}
\ No newline at end of file
$color-blue: #2196f3;
$space-width: 18px;
.avue-tree-table {
.ms-tree-space {
position: relative;
top: 1px;
display: inline-block;
font-style: normal;
font-weight: 400;
line-height: 1;
width: $space-width;
height: 14px;
&::before {
content: "";
}
}
.processContainer {
width: 100%;
height: 100%;
}
table td {
line-height: 26px;
}
.tree-ctrl {
position: relative;
cursor: pointer;
color: $color-blue;
margin-left: -$space-width;
}
@keyframes treeTableShow {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@-webkit-keyframes treeTableShow {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
\ No newline at end of file
.avue-tree {
&__item {
position: relative;
width: 100%;
}
&__title {
font-size: 14px;
}
&__icon {
transform: rotate(90deg);
}
&__menu {
position: absolute;
top: 2px;
right: 2px;
z-index: 1024;
}
&__filter {
margin-bottom: 15px;
display: flex;
align-items: center;
}
}
\ No newline at end of file
import Tree from './src/main';
Tree.install = function(Vue) {
Vue.component(Tree.name, Tree);
};
export default Tree;
\ No newline at end of file
<template>
<div :class="b()">
<div :class="b('filter')">
<el-input placeholder="输入关键字进行过滤"
size="small"
v-model="filterText">
<el-button slot="append"
size="small"
@click="parentAdd"
icon="el-icon-plus"
v-if="vaildData(option.addBtn,true)"></el-button>
<template slot="append">
<slot name="addBtn"></slot>
</template>
</el-input>
</div>
<el-tree ref="tree"
:data="list"
:node-key="nodeKey"
:filter-node-method="filterNode"
:expand-on-click-node="false"
:default-expand-all="defaultExpandAll">
<div slot-scope="{ node,data }"
:class="b('item')">
<div :class="b('title')"
@click.stop="nodeClick(data)"
@mouseenter="data.is_show=true"
@mouseleave="data.is_show=false">{{ data[labelKey]}}
<div :class="b('menu')"
v-show="data.is_show && vaildData(option.menu,true)">
<el-dropdown>
<i class="el-icon-more"
:class="b('icon')"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-if="vaildData(option.addBtn,true)"
@click.native="append(node,data)">新增</el-dropdown-item>
<el-dropdown-item v-if="vaildData(option.editBtn,true)"
@click.native="edit(node,data)">修改</el-dropdown-item>
<el-dropdown-item v-if="vaildData(option.delBtn,true)"
@click.native="remove(node,data)">删除</el-dropdown-item>
<slot name="menuBtn"
:node="node"
:data="data"></slot>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
</el-tree>
<el-dialog :title="obj[labelKey]"
:visible.sync="box"
@close="hide"
:width="vaildData(option.dialogWidth,'50%')">
<avue-form v-model="form"
:option="formOption"
ref="form"
@submit="addFlag?save():update()"></avue-form>
</el-dialog>
</div>
</template>
<script>
const propsDefault = {
nodeKey: 'id',
label: 'label',
value: 'value',
children: 'children',
labelText: '名称'
}
import { deepClone, vaildData } from '../../utils/util';
import create from '../../utils/create'
export default create({
name: 'tree',
props: {
option: {
type: Object,
default: () => {
return {};
}
},
data: {
type: Array,
default: () => {
return [];
}
},
value: {
type: Object,
default: () => {
return {};
}
}
},
computed: {
addText () {
return this.addFlag ? '新增' : '修改';
},
addFlag () {
return this.type === 'add' || this.type === 'parentAdd'
},
props () {
return this.option.props || {}
},
valueKey () {
return this.props.value || propsDefault.value;
},
labelText () {
return this.props.labelText || propsDefault.labelText;
},
labelKey () {
return this.props.label || propsDefault.label;
},
childrenKey () {
return this.props.children || propsDefault.children;
},
defaultExpandAll () {
return this.option.defaultExpandAll || true;
},
nodeKey () {
return this.option.nodeKey || propsDefault.nodeKey;
},
columnOption () {
return this.appednKey(deepClone(this.data || []));
},
formColumnOption () {
return (this.option.formOption || {}).column || [];
},
formOption () {
return Object.assign({
submitText: this.addText,
column: [
{
label: this.labelText,
prop: this.labelKey,
rules: [{
required: true,
message: "请输入" + this.labelText,
trigger: "blur"
}]
}, ...this.formColumnOption]
}, (() => {
let option = this.option.formOption || {};
delete option.column;
return option
})())
}
},
data () {
return {
filterText: '',
box: false,
type: '',
node: {},
obj: {},
form: {},
list: [],
}
},
created () {
this.vaildData = vaildData;
this.list = deepClone(this.columnOption);
},
watch: {
columnOption () {
this.list = deepClone(this.columnOption);
},
option () {
this.init();
},
filterText (val) {
this.$refs.tree.filter(val);
},
value (val) {
this.form = val;
},
form (val) {
this.$emit('input', val);
}
},
methods: {
appednKey (list) {
list.forEach(ele => {
ele.is_show = false;
if (ele[this.childrenKey]) {
this.appednKey(ele[this.childrenKey]);
}
})
return list;
},
nodeClick (data) {
this.$emit('node-click', data);
},
filterNode (value, data) {
if (!value) return true;
return data[this.labelKey].indexOf(value) !== -1;
},
hide () {
this.$refs.form.clearValidate();
this.$refs.form.resetForm();
this.box = false;
this.node = {};
this.obj = {};
},
save () {
const callback = () => {
const form = deepClone(Object.assign(this.form, { is_show: false }));
if (this.type === 'add') {
if (!this.obj[this.childrenKey]) {
this.$set(this.obj, 'children', []);
}
this.obj.children.push(form);
}
else if (this.type === 'parentAdd') this.obj.push(form);
this.hide();
}
this.$emit('save', this.obj, this.node, callback);
},
update () {
const callback = () => {
const parent = this.node.parent;
const children = parent.data[this.childrenKey] || parent.data;
const index = children.findIndex(item => item[this.nodeKey] === this.form[this.nodeKey]);
children.splice(index, 1, this.form);
this.hide();
}
this.$emit('update', this.obj, this.node, callback);
},
edit (node, data) {
this.type = 'edit';
this.node = node;
this.obj = data;
this.form = deepClone(this.obj);
this.box = true;
},
parentAdd (data) {
this.type = 'parentAdd';
this.obj = this.list;
this.box = true;
},
append (node, data) {
this.type = 'add';
this.obj = data;
this.node = node;
this.box = true;
},
remove (node, data) {
this.obj = data;
this.node = node;
const callback = () => {
const parent = node.parent;
const children = parent.data.children || parent.data;
const index = children.findIndex(d => d.id === data.id);
children.splice(index, 1);
}
this.$confirm('是否删除改节点?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$emit('del', this.obj, this.node, callback);
}).catch(() => {
});
}
}
})
</script>
<style>
</style>
/**
* Create a basic component with common options
*/
import bem from '../mixins/bem';
const install = function(Vue) {
Vue.component(this.name, this);
};
export default function(sfc) {
sfc.name = 'avue-' + sfc.name;
sfc.install = sfc.install || install;
sfc.mixins = sfc.mixins || [];
sfc.mixins.push(bem);
return sfc;
}
\ No newline at end of file
/**
* Create a component with common options
*/
import createBasic from './create-basic';
export default function(sfc) {
return createBasic(sfc);
}
\ No newline at end of file
export const dateFtt = (fmt, date) => { // author: meizz
var o = {
'M+': date.getMonth() + 1, // 月份
'd+': date.getDate(), // 日
'h+': date.getHours(), // 小时
'm+': date.getMinutes(), // 分
's+': date.getSeconds(), // 秒
'q+': Math.floor((date.getMonth() + 3) / 3), // 季度
'S': date.getMilliseconds() // 毫秒
};
if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); }
for (var k in o) {
if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))); }
}
return fmt;
};
export const GetDateStr = (AddDayCount) => {
var dd = new Date();
dd.setDate(dd.getDate() + AddDayCount); // 获取AddDayCount天后的日期
var y = dd.getFullYear();
var m = (dd.getMonth() + 1) < 10 ? '0' + (dd.getMonth() + 1) : (dd.getMonth() + 1); // 获取当前月份的日期,不足10补0
var d = dd.getDate() < 10 ? '0' + dd.getDate() : dd.getDate(); // 获取当前几号,不足10补0
return y + '-' + m + '-' + d;
};
import mockjs from 'mockjs';
const Random = mockjs.Random;
export default (column, dic) => {
let form = {};
function createName({ en }) {
if (en) {
return Random.name(true);
}
return Random.cname();
}
function createNumber({ max, min, precision }) {
if (precision) {
const number = Random.float(min, max, precision) + '';
const index = number.indexOf('.') + 1;
return Number(number.substring(0, index + precision));
} else {
return Random.integer(min, max)
}
}
function createUrl({ header, footer }) {
let url = Random.url();
const index = url.indexOf('://');
if (header === false) {
url = url.substring(index + 3);
} else {
url = 'http://' + url.substring(index + 3);
}
return url;
}
function createDatetime({ format, now }) {
if (now) {
return Random.now(format)
}
return Random.datetime(format)
}
function createText({ min, max }) {
return Random.csentence(min, max)
}
function createCounty() {
return Random.county(true);
}
function createDic({ dic, props, columnType, multiple }) {
const value = props.value || 'value';
const len = dic.length;
if (['checkbox'].includes(columnType) || multiple) {
const number = createNumber({
min: 1,
max: len
});
let result = [];
for (let i = 0; i < number; i++) {
let flag = true;
while (flag) {
const numbers = createNumber({
min: 0,
max: len - 1
});
const values = dic[numbers][value];
if (!result.includes(values)) {
result.push(values);
flag = false;
}
}
}
return result;
} else {
const number = createNumber({
min: 0,
max: len - 1
});
return dic[number][value];
}
}
function create() {
Object.keys(column).forEach(index => {
const ele = column[index];
if (ele.mock && typeof ele.mock === 'object') {
let params = ele.mock;
params.dic = typeof ele.dicData === 'string' ? dic[ele.dicData] : (ele.dicData || []);
params.props = ele.props || {};
params.columnType = ele.type;
params.multiple = ele.multiple;
switch (params.type) {
case 'name':
form[ele.prop] = createName(params);
break;
case 'number':
form[ele.prop] = createNumber(params);
break;
case 'datetime':
form[ele.prop] = createDatetime(params);
break;
case 'word':
form[ele.prop] = createText(params);
break;
case 'url':
form[ele.prop] = createUrl(params);
break;
case 'county':
form[ele.prop] = createCounty(params);
break;
case 'dic':
form[ele.prop] = createDic(params);
break;
}
}
})
}
create();
return form;
}
\ No newline at end of file
import {
validatenull
} from './validate';
export const getObjType = obj => {
var toString = Object.prototype.toString;
var map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
};
if (obj instanceof Element) {
return 'element';
}
return map[toString.call(obj)];
};
/**
* 对象深拷贝
*/
export const deepClone = data => {
var type = getObjType(data);
var obj;
if (type === 'array') {
obj = [];
} else if (type === 'object') {
obj = {};
} else {
//不再具有下一层次
return data;
}
if (type === 'array') {
for (var i = 0, len = data.length; i < len; i++) {
obj.push(deepClone(data[i]));
}
} else if (type === 'object') {
for (var key in data) {
obj[key] = deepClone(data[key]);
}
}
return obj;
};
/**
* 根据字典的value显示label
*/
let result = '';
export const findByvalue = (dic, value, props, first) => {
props = props || {};
const labelKey = props.label || 'label';
const valueKey = props.value || 'value';
const childrenKey = props.children || 'children';
if (validatenull(first)) result = value;
if (validatenull(dic)) return result;
//正常字典
if (typeof(value) === 'string' || typeof(value) === 'number' || typeof(value) === 'boolean') {
for (let i = 0; i < dic.length; i++) {
if (dic[i][valueKey] === value) {
result = dic[i][labelKey];
break;
} else {
findByvalue(dic[i][childrenKey], value, props, true);
}
}
//父子集字典
} else if (value instanceof Array && dic[0][childrenKey]) {
let index = 0;
let count = 0;
result = [];
while (count < value.length) {
index = findArray(dic, value[count], valueKey);
if (index !== -1) {
result.push(dic[index][labelKey]);
} else {
result.push(value[count]);
}
if (!validatenull(dic[index][childrenKey])) {
dic = dic[index][childrenKey] || [];
}
count++;
}
result = result.join('/').toString();
//多选字典
} else if (value instanceof Array) {
let index = 0;
let count = 0;
result = [];
while (count < value.length) {
index = findArray(dic, value[count], valueKey);
if (index !== -1) {
result.push(dic[index][labelKey]);
} else {
result.push(value[count]);
}
count++;
}
result = result.join(',').toString();
}
return result;
};
/**
* 根据字典的value查找对应的index
*/
export const findArray = (dic, value, valueKey) => {
valueKey = valueKey || 'value';
for (let i = 0; i < dic.length; i++) {
if (dic[i][valueKey] === value) {
return i;
}
}
return -1;
};
/**
* 获取字典
*/
export const setDic = (dicData, DIC) => {
return (typeof(dicData) === 'string') ? DIC : dicData;
};
/**
* 设置px
*/
export const setPx = (val, defval) => {
if (validatenull(val)) {
val = defval;
}
val = val + '';
if (val.indexOf('%') === -1) {
val = val + 'px';
}
return val;
};
/**
* 表格初始化值
*/
export const formInitVal = (list) => {
let tableForm = {};
let searchForm = {};
list.forEach(ele => {
if (
ele.type === 'checkbox' ||
ele.type === 'cascader' ||
ele.type === 'dates' ||
(ele.type === 'upload' && ele.listType !== 'picture-img') ||
ele.multiple ||
ele.range || ele.dataType === 'array'
) {
tableForm[ele.prop] = [];
if (ele.search) searchForm[ele.prop] = [];
} else if (['number', 'rate', 'silder'].includes(ele.type) || ele.dataType === 'number') {
tableForm[ele.prop] = 0;
if (ele.search) {
searchForm[ele.prop] = 0;
}
} else {
tableForm[ele.prop] = '';
if (ele.search) {
searchForm[ele.prop] = '';
}
}
//表单默认值设置
if (!validatenull(ele.valueDefault)) tableForm[ele.prop] = ele.valueDefault;
//搜索表单默认值设置
if (!validatenull(ele.searchDefault)) searchForm[ele.prop] = ele.searchDefault;
});
return {
tableForm,
searchForm
};
};
export const getType = (column) => {
const type = column.type
const more = column.more || false;
if (more) {
if (type === 'date') {
return 'daterange';
} else if (type === 'datetime') {
return 'datetimerange';
} else if (type === 'time') {
return 'timerange';
} else {
return type;
}
}
return type;
};
/**
* 搜索框获取动态组件
*/
export const getSearchType = (type) => {
if (['select', 'radio', 'checkbox'].includes(type)) {
return 'crudSelect';
} else if (['time', 'timerange'].includes(type)) {
return 'crudTime';
} else if (['dates', 'date', 'datetime', 'datetimerange', 'daterange', 'week', 'month', 'year'].includes(type)) {
return 'crudDate';
} else if (['cascader'].includes(type)) {
return 'crudCascader';
} else if (['number'].includes(type)) {
return 'crudInputNumber';
} else {
return 'crudInput';
}
};
/**
* 动态获取组件
*/
export const getComponent = ({ type, component }) => {
if (!validatenull(component)) {
return component;
} else if (type === 'select') {
return 'crudSelect';
} else if (type === 'radio') {
return 'crudRadio';
} else if (type === 'checkbox') {
return 'crudCheckbox';
} else if (['time', 'timerange'].includes(type)) {
return 'crudTime';
} else if (['dates', 'date', 'datetime', 'datetimerange', 'daterange', 'week', 'month', 'year'].includes(type)) {
return 'crudDate';
} else if (type === 'cascader') {
return 'crudCascader';
} else if (type === 'number') {
return 'crudInputNumber';
} else if (type === 'password') {
return 'crudInput';
} else if (type === 'switch') {
return 'crudSwitch';
} else if (type === 'rate') {
return 'crudRate';
} else if (type === 'upload') {
return 'crudUpload';
} else if (type === 'silder') {
return 'crudSilder';
} else {
return 'crudInput';
}
};
export const getPasswordChar = (len, char) => {
let result = '';
for (let i = 0; i < len; i++) {
result = result + char;
}
return result;
}
export const vaildData = (val, dafult) => {
if (typeof val === 'boolean') {
return val;
}
return !validatenull(val) ? val : dafult;
};
\ No newline at end of file
/**
* 判断是否为空
*/
export function validatenull(val) {
if (typeof val === 'boolean') {
return false;
}
if (typeof val === 'number') {
return false;
}
if (val instanceof Array) {
if (val.length === 0) return true;
} else if (val instanceof Object) {
if (JSON.stringify(val) === '{}') return true;
} else {
if (val === 'null' || val == null || val === 'undefined' || val === undefined || val === '') return true;
return false;
}
return false;
}
......@@ -21,13 +21,13 @@ import {
import * as filters from './filters' // 全局filter
import './styles/common.scss';
// // 引入avue的包
// import '@smallwei/avue/lib/index.js';
import '@smallwei/avue/lib/index.js';
// // 引入avue的样式文件
// import '@smallwei/avue/lib/theme-chalk/index.css';
import '@smallwei/avue/lib/theme-chalk/index.css';
// //源文件包
import '../packages/index.js';
import '../packages/theme-chalk/src/index.scss';
// import '../packages/index.js';
// import '../packages/theme-chalk/src/index.scss';
import basicContainer from './components/basic-container/main'
import VueClipboard from 'vue-clipboard2'
......
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