Commit c0221ff6 authored by smallwei's avatar smallwei

chmod(lib): update avue lib

parent 7489ff01
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
"test:e2e": "vue-cli-service test:e2e" "test:e2e": "vue-cli-service test:e2e"
}, },
"dependencies": { "dependencies": {
"@smallwei/avue": "^1.1.18", "@smallwei/avue": "^1.1.19",
"avue-plugin-transfer": "^0.0.2", "avue-plugin-transfer": "^0.0.2",
"avue-plugin-ueditor": "^0.0.1", "avue-plugin-ueditor": "^0.0.1",
"axios": "^0.18.0", "axios": "^0.18.0",
......
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,
cellBtnSize: 'small',
viewBtnSize: 'small',
delBtnSize: 'small',
editBtnSize: 'small',
addBtnSize: 'small',
searchBtnSize: 'small',
emptyBtnSize: 'small',
searchComponentSize: 'small',
columnBtnSize: 'small',
refreshBtnSize: 'small',
searchboxBtnSize: 'small',
menuBtnSize: 'small',
dateBtnSize: 'small',
//文字
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,
formWidth: '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="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"
@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"
: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"
: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"
: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="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="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" />
<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,
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
},
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.label.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]);
}
});
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 (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);
if (typeof this.nodeClick === 'function') this.nodeClick(data, callback);
else 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="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"
: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="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 ? '' : [],
fileList: [],
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';
},
imageUrl () {
return this.status ? this.text : '';
}
},
created () {
},
watch: {
text () {
this.fileList = this.text || [];
}
},
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.value, column: this.column });
this.loading = this.$loading({
lock: true,
text: this.loadText,
spinner: 'el-icon-loading',
});
const len = fileList.length;
this.fileList = this.fileList.splice(len, 1);
},
handleSuccess (file) {
{
this.fileList.push({
name: file.label,
url: file.value
});
this.$message.success('上传成功');
this.setVal();
}
},
handleRemove (file, fileList) {
this.fileList = fileList;
this.$message.success('删除成功');
this.setVal();
},
handleError () {
this.$message.error('上传失败');
},
show (res) {
const data = res.data;
this.loading.close();
this.handleSuccess({
label: data[this.labelKey],
value: data[this.valueKey]
});
},
hide () {
this.loading.close();
this.handleError();
},
httpRequest (config) {
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 () {
let value;
if (this.status) {
value = this.text;
} else {
value = this.fileList;
}
this.$emit('input', value);
this.$emit('change', value);
},
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-select @change="dateChange"
v-if="vaildData(tableOption.dateBtn,config.dateBtn)"
:default="vaildData(tableOption.dateDefault,config.dateDefault)"
:size="vaildData(tableOption.dateSize,config.dateBtnSize)">
</date-select>
</div>
<div :class="b('header')">
<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 :size="vaildData(tableOption.searchSize,config.searchComponentSize)"
:is="getSearchType(column.type)"
v-model="searchForm[column.prop]"
:type="getType(column)"
:props="column.props || tableOption.props"
:format="column.format"
:filterable="column.searchFilterable"
:filter-method="column.searchFilterMethod"
:value-format="column.valueFormat"
:multiple="config.searchMultiple.includes(column.type) && vaildData(column.searchMmultiple,false)"
clearable
:placeholder="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="vaildData(tableOption.searchSize,config.searchBtnSize)">{{config.searchBtnTitle}}</el-button>
<el-button @click="searchReset"
:icon="config.emptyBtnIcon"
:size="vaildData(tableOption.searchSize,config.emptyBtnSize)">{{config.emptyBtnTitle}}</el-button>
<slot name="searchMenu"></slot>
</el-form-item>
</el-form>
</el-collapse-transition>
</div>
<!-- 表格功能列 -->
<div :class="b('menu')">
<div :class="b('left')">
<el-button type="primary"
@click="rowAdd"
:icon="config.addBtnIcon"
:size="config.addBtnSize"
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="config.refreshBtnSize"
@click="refreshChange"
v-if="vaildData(tableOption.refreshBtn,config.refreshBtn)"></el-button>
<el-button :icon="config.columnBtnIcon"
circle
:size="config.columnBtnSize"
@click="columnBox=true"
v-if="vaildData(tableOption.columnBtn,config.columnBtn)"></el-button>
<el-button :icon="config.searchboxBtnIcon"
circle
:size="config.searchboxBtnSize"
@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"
:highlight-current-row="tableOption.highlightCurrentRow"
@current-change="currentRowChange"
: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">
<!-- 折叠面板 -->
<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 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>
<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 split-button
icon="el-icon-menu"
type="primary"
v-if="vaildData(tableOption.menuBtn,config.menuBtn)"
:size="config.menuBtnSize">
{{config.menuBtnTitle}}
<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="dropMenu"
:row="scope.row"
:dic="scope.dic"
:label="scope.label"
:index="scope.$index"></slot>
</el-dropdown-menu>
</el-dropdown>
<el-button type="primary"
:icon="scope.row.$cellEdit?config.cellSaveBtnIcon:config.cellEditBtnIcon"
:size="config.cellBtnSize"
@click.stop="rowCell(scope.row,scope.$index)"
v-if="vaildData(tableOption.cellBtn ,config.cellBtn)">{{scope.row.$cellEdit?config.cellSaveBtnTitle:config.cellEditBtnTitle}}</el-button>
<el-button type="success"
:icon="config.viewBtnIcon"
:size="config.viewBtnSize"
@click.stop="rowView(scope.row,scope.$index)"
v-if="vaildData(tableOption.viewBtn,tableOption.menuBtn?false:config.viewBtn)">{{config.viewBtnTitle}}</el-button>
<el-button type="primary"
:icon="config.editBtnIcon"
:size="config.editBtnSize"
@click.stop="rowEdit(scope.row,scope.$index)"
v-if="vaildData(tableOption.editBtn,tableOption.menuBtn?false:config.editBtn)">{{config.editBtnTitle}}</el-button>
<el-button type="danger"
:icon="config.delBtnIcon"
:size="config.delBtnSize"
@click.stop="rowDel(scope.row,scope.$index)"
v-if="vaildData(tableOption.delBtn,tableOption.menuBtn?false:config.delBtn)">{{config.delBtnTitle}}</el-button>
<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="page.currentPage"
:background="vaildData(tableOption.pageBackground,config.pageBackground)"
:page-size="page.pageSize"
:page-sizes="page.pageSizes"
@size-change="sizeChange"
@current-change="currentChange"
layout="total, sizes, prev, pager, next, jumper"
:total="page.total"></el-pagination>
</div>
</el-card>
<!-- 表单 -->
<el-dialog lock-scroll
:custom-class="vaildData(tableOption.customClass,config.customClass)"
:fullscreen="vaildData(tableOption.formFullscreen,config.formFullscreen)"
:modal-append-to-body="false"
:append-to-body="true"
:title="dialogTitle"
:visible.sync="boxVisible"
:width="vaildData(tableOption.formWidth,config.formWidth)"
@close="hide">
<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"
: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"
v-if="boxType=='edit'"
:loading="keyBtn">{{config.updateBtnTitle}}</el-button>
<el-button type="primary"
@click="rowSave"
:loading="keyBtn"
v-else-if="boxType=='add'">{{config.saveBtnTitle}}</el-button>
<el-button @click="closeDialog">{{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 dateSelect from '../../date-select'
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,
dateSelect
},
data () {
return {
clientHeight: document.documentElement.clientHeight,
defaultForm: {
tableForm: {},
searchForm: {}
},
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();
},
computed: {
dialogTitle () {
const key = `${this.boxType}Title`;
return this.tableOption[key] || this.config[key];
},
listLen () {
return this.list.length !== 0
},
columnOption () {
return this.tableOption.column || [];
},
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.emptytBtn = false;
return option;
}
},
watch: {
columnOption () {
this.columnInit();
},
data () {
this.dataInit();
}
},
mounted () { },
props: {
value: {
type: Object,
default: () => {
return {};
}
},
beforeClose: Function,
beforeOpen: Function,
rowClassName: Function,
uploadBefore: Function,
uploadAfter: Function,
page: {
type: Object,
default () {
return {
total: 0, // 总页数
currentPage: 0, // 当前页数
pageSize: 10, // 每页显示多少条
pageSizes: [10, 20, 30, 40, 50, 100],
background: true // 背景颜色
};
}
},
tableLoading: {
type: Boolean,
default: false
},
data: {
type: Array,
required: true,
default: () => {
return [];
}
}
},
methods: {
closeDialog () {
this.tableIndex = -1;
this.tableForm = {};
this.boxVisible = false;
this.keyBtn = false;
},
selectClear () {
this.$refs.table.clearSelection();
},
indexMethod (index) {
return (index + 1) + (((this.page.currentPage || 1) - 1) * (this.page.pageSize || 10));
},
refreshChange () {
this.$emit('refresh-change', {
page: this.page,
searchForm: this.searchForm
});
},
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.$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);
},
//设置多选选中
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.$nextTick(() => {
this.$refs['tableForm'].clearValidate();
this.$refs['tableForm'].cascadeInit();
});
this.boxVisible = true;
}
};
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);
}
}
});
</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">
<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>
</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">
<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>
</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}">
<h5 class="count">{{item.count}}</h5>
<span class="splitLine" />
<p class="title">{{item.title}}</p>
</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}]">
<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>
</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 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}">
<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>
</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 DateSelect from './src/main';
DateSelect.install = function(Vue) {
Vue.component(DateSelect.name, DateSelect);
};
export default DateSelect;
\ 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-select',
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 FormSteps from './src/main';
FormSteps.install = function(Vue) {
Vue.component(FormSteps.name, FormSteps);
};
export default FormSteps;
<template>
<div :class="b()">
<el-steps :active="formIndex"
:space="option.space"
:simple="option.simple"
:process-status="option.processStatus"
:align-center='vaildData(option.alignCenter,true)'
:direction="option.direction"
:class="b({'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>
<avue-form :option="formOption"
:class="b('form')"
:style="{width:vaildData(formOption.width,'40%')}"
@submit="submit"
v-model="text">
<template slot-scope="scope"
v-for="item in formOption.column"
: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"
v-if="formIndex!=1&&formIndex!=columnLen&&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 { formInitVal } from '../../utils/util';
export default create({
name: 'form-steps',
props: {
value: {
type: Object,
default: () => { }
},
option: {
type: Object,
required: true
}
},
computed: {
columnOption () {
return this.option.column || [];
},
columnLen () {
return this.columnOption.length;
},
formOption () {
return this.objectOption.option;
},
objectOption () {
return this.columnOption[this.formIndex - 1];
},
status () {
let status = [];
const leng = this.step - 1;
for (let i = 0; i < leng; i++) {
status.push(this.vaildData(this.option.finishStatus, '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();
},
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++;
}
this.formIndex++;
},
breaks () {
this.formIndex--;
},
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 FormTabs from './src/main';
FormTabs.install = function(Vue) {
Vue.component(FormTabs.name, FormTabs);
};
export default FormTabs;
<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-form :option="formOption"
@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">
<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';
export default create({
name: 'form-tabs',
props: {
value: {
type: Object,
default: () => { }
},
option: {
type: Object,
required: true
}
},
computed: {
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: {
formOption () {
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();
},
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
import Form from './src/main';
Form.install = function(Vue) {
Vue.component(Form.name, Form);
};
export default Form;
<template>
<div :class="b()">
<el-form ref="form"
:model="form"
:label-position="tableOption.labelPosition"
:size="tableOption.size"
:label-width="setPx(tableOption.labelWidth,80)"
:rules="formRules">
<el-row :gutter="20"
:span="24">
<draggable :list="columnOption"
:options="dragOptions"
:class="b('group')">
<div :class="b('row',{'block':column.row,'cursor':draggableStart})"
v-for="(column,index) in columnOption"
v-if="vaildVisdiplay(column)"
:key="index">
<el-col :md="column.span||12"
:xs="24"
@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"
v-model="form[column.prop]"
:change="column.change"
:click="column.click"
: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"
: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"
: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"
: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>
</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="submit"
:size="tableOption.submitSize"
icon="el-icon-check"
v-if="vaildData(tableOption.submitBtn,true)">{{vaildData(tableOption.submitText,'提 交')}}</el-button>
<el-button icon="el-icon-delete"
:size="tableOption.emptySize"
v-if="vaildData(tableOption.emptytBtn,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 { 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 () {
},
mounted () { },
computed: {
columnOption () {
return this.tableOption.column || [];
},
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.submitPostion === 'left') {
return '';
} else {
return '0';
}
},
menuPostion: function () {
if (this.tableOption.submitPostion) {
return this.tableOption.submitPostion;
} 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: {
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.$emit('input', this.form);
this.$emit('reset-change');
},
submit () {
this.$refs['form'].validate(valid => {
if (valid) {
this.$emit('submit', this.form);
}
});
}
}
});
</script>
import Crud from './crud/index.js';
import CrudCheckbox from './crud-checkbox/index.js';
import CrudDate from './crud-date/index.js';
import CrudTime from './crud-time/index.js';
import CrudInput from './crud-input/index.js';
import CrudRadio from './crud-radio/index.js';
import CrudSelect from './crud-select/index.js';
import CrudCascader from './crud-cascader/index.js';
import CrudNumberInput from './crud-input-number/index.js';
import CrudSwitch from './crud-switch/index.js';
import CrudRate from './crud-rate/index.js';
import CrudUpload from './crud-upload/index.js';
import CrudSilder from './crud-silder/index.js';
import DataDisplay from './data-display/index.js';
import DataCard from './data-card/index.js';
import DataTabs from './data-tabs/index.js';
import DataIcons from './data-icons/index.js';
import DataBox from './data-box/index.js';
import Form from './form/index.js';
import FormTabs from './form-tabs/index.js';
import FormSteps from './form-steps/index.js';
import FormDetail from './form-detail/index.js';
import TableTree from './table-tree/index.js';
import DateSelect from './date-select/index.js';
const components = [
Crud,
Form,
FormTabs,
FormSteps,
FormDetail,
CrudCheckbox,
CrudDate,
CrudTime,
CrudInput,
CrudRadio,
CrudSelect,
CrudCascader,
CrudNumberInput,
CrudSwitch,
CrudRate,
CrudUpload,
CrudSilder,
DataDisplay,
DataCard,
DataIcons,
DataTabs,
DataBox,
TableTree,
DateSelect
];
function install(Vue, axios) {
Vue.prototype.$http = axios;
const AVUE = {};
components.map(component => {
Vue.component(component.name, component);
});
Vue.prototype.$AVUE = AVUE;
}
if (window.Vue) {
install(window.Vue, window.axios);
}
export default install;
\ No newline at end of file
/**
* 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 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] || '';
if (column.type) {
if (['date', 'time', 'datetime'].includes(column.type) && column.format) {
const format = column.format
.replace('dd', 'DD')
.replace('yyyy', 'YYYY');
result = dayjs(result).format(format);
}
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'
}
return {
data() {
return {
text: undefined,
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
},
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
},
props: {
type: Object,
default: () => propsDefault
}
},
watch: {
value() {
this.text = this.value;
}
},
computed: {
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
},
value: {
handler() {
this.formVal();
},
deep: true
},
option: {
handler() {
this.init();
},
deep: true
}
},
data() {
return {
DIC: {},
dicCascaderList: []
};
},
created() {
this.init();
},
methods: {
init() {
// 初始化工具
this.initFun();
this.tableOption = this.deepClone(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
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>
'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-dialog{max-height:400px;overflow-y:auto}.avue-ghost{opacity:.5;background:#c8ebfb}.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:#fafafa}.avue-crud .el-table td{padding:8px 0}.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:500px;overflow:hidden;overflow-y:auto}
\ No newline at end of file
.data-box .item{display:-webkit-box;display:-ms-flexbox;display:flex;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-icon{width:100px;height:100%;color:#fff;text-align:center;line-height:100px}.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-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-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-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-tooltip__popper{max-width:60%}
\ 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__menu,.avue-form__row--block{width:100%}.avue-form__group,.avue-form__row--block{height:auto;overflow:hidden}.avue-form{padding:8px 10px}.avue-form__menu--center{text-align:center}.avue-form__menu--left{text-align:left}.avue-form__menu--right{text-align:right}.avue-form__group .el-col{position:relative}.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{-webkit-box-orient:vertical;-webkit-box-direction:normal}.avue-dialog{max-height:400px;overflow-y:auto}.avue-ghost{opacity:.5;background:#c8ebfb}.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}.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-tooltip__popper{max-width:60%}.avue-crud{margin:0 auto;width:99%}.avue-crud .el-table th{word-break:break-word;color:rgba(0,0,0,.85);background:#fafafa}.avue-crud .el-table td{padding:8px 0}.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:500px;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-form__group,.avue-form__row--block{height:auto;overflow:hidden}.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}}.avue-form{padding:8px 10px}.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 .el-col{position:relative}.avue-form__row--block{width:100%}.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}.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}.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--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)}.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-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,.data-box .item-info{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{display:flex;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-icon{width:100px;height:100%;color:#fff;text-align:center;line-height:100px}.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: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}.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-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-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
{
"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-ghost {
opacity: 0.5;
background: #c8ebfb;
}
.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: #fafafa;
}
.el-table td {
padding: 8px 0;
}
&__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 {
display: flex;
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;
}
}
.item-icon {
width: 100px;
height: 100%;
color: #fff;
text-align: center;
line-height: 100px;
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-tabs {
.item {
position: relative;
margin: 15px;
padding: 12px;
height: 160px;
border-radius: 4px;
box-sizing: border-box;
overflow: hidden;
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-select {
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-tooltip__popper {
max-width: 60%;
}
\ 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-steps {
&--vertical {
width: 100%;
display: flex;
}
&__steps {
width: 230px;
}
&__contail {
flex: 1;
}
&__form {
margin: 0 auto;
}
}
\ No newline at end of file
.avue-form {
padding: 8px 10px;
&__menu {
width: 100%;
&--center {
text-align: center;
}
&--left {
text-align: left;
}
&--right {
text-align: right;
}
}
&__group {
height: auto;
overflow: hidden;
.el-col {
position: relative;
}
}
&__row {
&--block {
width: 100%;
height: auto;
overflow: hidden;
}
&--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 './form-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 './date-select.scss';
\ 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
/**
* 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 {
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
*/
export const findByvalue = (dic, value, props) => {
props = props || {};
const labelKey = props.label || 'label';
const valueKey = props.value || 'value';
const childrenKey = props.children || 'children';
let result = '';
if (validatenull(dic)) return value;
if (typeof(value) === 'string' || typeof(value) === 'number' || typeof(value) === 'boolean') {
let index = 0;
index = findArray(dic, value, valueKey);
if (index !== -1) {
result = (dic[index][labelKey]);
} else {
result = value;
}
} else if (value instanceof Array && dic[0][childrenKey]) {
let index = 0;
let count = 0;
while (count < value.length) {
index = findArray(dic, value[count]);
if (!validatenull(dic[index])) {
result = result + dic[index][labelKey] + '/';
dic = dic[index][childrenKey];
}
count++;
}
if (result.length > 0) {
result = result.substr(0, result.length - 1);
}
} else if (value instanceof Array) {
result = [];
let index = 0;
value.forEach(ele => {
index = findArray(dic, ele);
if (index !== -1) {
result.push(dic[index][labelKey]);
} else {
result.push(ele);
}
});
result = result.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 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;
}
/*
* Copyright (c) 2018-2025, lengleng All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* Neither the name of the pig4cloud.com developer nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
* Author: lengleng (wangiegie@gmail.com)
*/
export const tableOption = {
border: true,
index: true,
indexLabel: '序号',
stripe: true,
menuAlign: 'center',
editBtn: false,
delBtn: false,
align: 'center',
addBtn: false,
column: [{
fixed: true,
label: 'id',
prop: 'userId',
span: 24,
editDisabled: true,
addVisdiplay: false,
}, {
fixed: true,
label: '用户名',
prop: 'username',
solt: true,
search: true,
span: 24,
}, {
label: '密码',
prop: 'password',
type: 'password',
hide: true,
span: 24,
}, {
label: '所属部门',
prop: 'deptId',
formsolt: true,
solt: true,
span: 24,
}, {
label: '角色',
prop: 'role',
formsolt: true,
solt: true,
span: 24,
}, {
label: '状态',
prop: 'delFlag',
type: "select",
solt: true,
span: 24,
dicData: [{
label: '有效',
value: '0'
}, {
label: '无效',
value: '1'
}, {
label: '锁定',
value: '9'
}]
}, {
width: 180,
label: '创建时间',
prop: 'createTime',
type: 'datetime',
format: 'yyyy-MM-dd HH:mm',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
editDisabled: true,
addVisdiplay: false,
span: 24,
}]
}
\ No newline at end of file
...@@ -25,9 +25,9 @@ import '@smallwei/avue/lib/index.js'; ...@@ -25,9 +25,9 @@ import '@smallwei/avue/lib/index.js';
// 引入avue的样式文件 // 引入avue的样式文件
import '@smallwei/avue/lib/theme-chalk/index.css'; import '@smallwei/avue/lib/theme-chalk/index.css';
// //源文件包 // // //源文件包
// import './packages/index.js'; // import '../packages/index.js';
// import './packages/theme-chalk/src/index.scss'; // import '../packages/theme-chalk/src/index.scss';
import basicContainer from './components/basic-container/main' import basicContainer from './components/basic-container/main'
import VueClipboard from 'vue-clipboard2' import VueClipboard from 'vue-clipboard2'
......
...@@ -18,304 +18,128 @@ ...@@ -18,304 +18,128 @@
<template> <template>
<div class="app-container calendar-list-container"> <div class="app-container calendar-list-container">
<basic-container> <basic-container>
<div class="filter-container"> <avue-crud :option="option"
<el-input @keyup.enter.native="handleFilter" ref="crud"
style="width: 200px;" v-model="form"
class="filter-item" :page="page"
placeholder="用户名" :table-loading="listLoading"
v-model="listQuery.username"> @current-change="handleCurrentChange"
</el-input> @size-change="handleSizeChange"
<el-button class="filter-item" @search-change="handleFilter"
type="primary" @refresh-change="handleRefreshChange"
icon="search" @row-update="update"
@click="handleFilter">搜索</el-button> @row-save="create"
:before-open="handleOpenBefore"
:data="list">
<template slot="menuLeft">
<el-button v-if="sys_user_add" <el-button v-if="sys_user_add"
class="filter-item" class="filter-item"
style="margin-left: 10px;"
@click="handleCreate" @click="handleCreate"
size="small"
type="primary" type="primary"
icon="edit">添加</el-button> icon="el-icon-edit">添加</el-button>
</div>
<el-table :key='tableKey'
:data="list"
v-loading="listLoading"
element-loading-text="给我一点时间"
border
fit
highlight-current-row
style="width: 99%">
<el-table-column align="center"
label="序号">
<template slot-scope="scope">
<span>{{scope.row.userId}}</span>
</template> </template>
</el-table-column> <template slot="username"
slot-scope="scope">
<el-table-column align="center"
label="用户名">
<template slot-scope="scope">
<span>
<img v-if="scope.row.avatar" <img v-if="scope.row.avatar"
class="user-avatar" class="user-avatar"
style="width: 20px; height: 20px; border-radius: 50%;" style="width: 20px; height: 20px; border-radius: 50%;"
:src="scope.row.avatar+'?imageView2/1/w/20/h/20'"> {{scope.row.username}} :src="scope.row.avatar+'?imageView2/1/w/20/h/20'" />
</span> <span>{{scope.row.username}}</span>
</template> </template>
</el-table-column> <template slot="role"
slot-scope="scope">
<el-table-column align="center"
label="所属部门"
show-overflow-tooltip>
<template slot-scope="scope">
<span>{{scope.row.deptName}} </span>
</template>
</el-table-column>
<el-table-column align="center"
label="角色">
<template slot-scope="scope">
<span v-for="(role,index) in scope.row.roleList" <span v-for="(role,index) in scope.row.roleList"
:key="index">{{role.roleDesc}} </span> :key="index">
<el-tag>{{role.roleDesc}} </el-tag>&nbsp;&nbsp;
</span>
</template> </template>
</el-table-column> <template slot="deptId"
slot-scope="scope">
<el-table-column align="center" {{scope.row.deptName}}
label="创建时间">
<template slot-scope="scope">
<span>{{scope.row.createTime | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template> </template>
</el-table-column> <template slot="delFlag"
slot-scope="scope">
<el-table-column align="center" <el-tag>{{scope.label}}</el-tag>
class-name="status-col"
label="状态">
<template slot-scope="scope">
<el-tag>{{scope.row.delFlag | statusFilter}}</el-tag>
</template> </template>
</el-table-column> <template slot="menu"
slot-scope="scope">
<el-table-column align="center"
label="操作"
width="200">
<template slot-scope="scope">
<el-button v-if="sys_user_edit" <el-button v-if="sys_user_edit"
size="small" size="small"
type="success" type="success"
@click="handleUpdate(scope.row)">编辑 @click="handleUpdate(scope.row,scope.id)">编辑
</el-button> </el-button>
<el-button v-if="sys_user_del" <el-button v-if="sys_user_del"
size="small" size="small"
type="danger" type="danger"
@click="deletes(scope.row)">删除 @click="deletes(scope.row,scope.id)">删除
</el-button> </el-button>
</template> </template>
</el-table-column> <template slot="deptIdForm"
slot-scope="scope">
</el-table> <avue-crud-input v-model="form.deptId"
type="tree"
<div v-show="!listLoading" :node-click="getNodeData"
class="pagination-container"> :dic="treeDeptData"
<el-pagination @size-change="handleSizeChange" :props="defaultProps"></avue-crud-input>
@current-change="handleCurrentChange" </template>
:current-page.sync="listQuery.page" <template slot="roleForm"
:page-sizes="[10,20,30, 50]" slot-scope="scope">
:page-size="listQuery.limit" <avue-crud-select v-model="role"
layout="total, sizes, prev, pager, next, jumper" multiple
:total="total"> :dic="rolesOptions"
</el-pagination> :props="roleProps"></avue-crud-select>
</div> </template>
</avue-crud>
</basic-container> </basic-container>
<el-dialog :title="textMap[dialogStatus]"
:visible.sync="dialogDeptVisible">
<el-tree class="filter-tree"
:data="treeDeptData"
:default-checked-keys="checkedKeys"
check-strictly
node-key="id"
highlight-current
ref="deptTree"
:props="defaultProps"
@node-click="getNodeData"
default-expand-all>
</el-tree>
</el-dialog>
<el-dialog :title="textMap[dialogStatus]"
:visible.sync="dialogFormVisible">
<el-form :model="form"
:rules="rules"
ref="form"
label-width="100px">
<el-form-item label="用户名"
prop="username">
<el-input v-model="form.username"
placeholder="请输用户名"></el-input>
</el-form-item>
<el-form-item v-if="dialogStatus == 'create'"
label="密码"
placeholder="请输入密码"
prop="newpassword1">
<el-input type="password"
v-model="form.newpassword1"></el-input>
</el-form-item>
<el-form-item label="所属部门"
prop="deptName">
<el-input v-model="form.deptName"
placeholder="选择部门"
@focus="handleDept()"
readonly></el-input>
<input type="hidden"
v-model="form.deptId" />
</el-form-item>
<el-form-item label="角色"
prop="role">
<el-select class="filter-item"
v-model="role"
placeholder="请选择"
multiple>
<el-option v-for="item in rolesOptions"
:key="item.roleId"
:label="item.roleDesc"
:value="item.roleId"
:disabled="isDisabled[item.delFlag]">
<span style="float: left">{{ item.roleDesc }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.roleCode }}</span>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="状态"
v-if="dialogStatus == 'update' && sys_user_del "
prop="delFlag">
<el-select class="filter-item"
v-model="form.delFlag"
placeholder="请选择">
<el-option v-for="item in statusOptions"
:key="item"
:label="item | statusFilter"
:value="item"> </el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer"
class="dialog-footer">
<el-button @click="cancel('form')"> </el-button>
<el-button v-if="dialogStatus=='create'"
type="primary"
@click="create('form')"> </el-button>
<el-button v-else
type="primary"
@click="update('form')"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { fetchList, getObj, addObj, putObj, delObj } from "@/api/user"; import { fetchList, getObj, addObj, putObj, delObj } from "@/api/user";
import { deptRoleList, fetchDeptTree } from "@/api/role"; import { deptRoleList, fetchDeptTree } from "@/api/role";
// import { parseTime } from '@/utils' import { tableOption } from '@/const/crud/user';
import { mapGetters } from "vuex"; import { mapGetters } from "vuex";
import ElRadioGroup from "element-ui/packages/radio/src/radio-group";
import ElOption from "element-ui/packages/select/src/option";
export default { export default {
components: {
ElOption,
ElRadioGroup
},
name: "table_user", name: "table_user",
data () { data () {
return { return {
option: tableOption,
treeDeptData: [], treeDeptData: [],
checkedKeys: [], checkedKeys: [],
roleProps: {
label: "roleDesc",
value: 'roleId'
},
defaultProps: { defaultProps: {
children: "children", label: "name",
label: "name" value: 'id',
},
page: {
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 20 // 每页显示多少条
}, },
list: null, list: [],
total: null,
listLoading: true, listLoading: true,
listQuery: { listQuery: {
page: 1, page: 1,
limit: 20 limit: 20
}, },
role: [], role: [],
form: { form: {},
username: undefined,
newpassword1: undefined,
delFlag: undefined,
deptId: undefined,
},
rules: {
username: [
{
required: true,
message: "请输入账户",
trigger: "blur"
},
{
min: 3,
max: 20,
message: "长度在 3 到 20 个字符",
trigger: "blur"
}
],
newpassword1: [
{
required: true,
message: "请输入密码",
trigger: "blur"
},
{
min: 6,
max: 20,
message: "长度在 6 到 20 个字符",
trigger: "blur"
}
],
deptId: [
{
required: true,
message: "请选择部门",
trigger: "blur"
}
],
role: [
{
required: true,
message: "请选择角色",
trigger: "blur"
}
]
},
statusOptions: ["0", "1"],
rolesOptions: [], rolesOptions: [],
dialogFormVisible: false,
dialogDeptVisible: false,
userAdd: false,
userUpd: false,
userDel: false,
dialogStatus: "",
textMap: {
update: "编辑",
create: "创建"
},
isDisabled: {
0: false,
1: true
},
tableKey: 0
}; };
}, },
computed: { computed: {
...mapGetters(["permissions"]) ...mapGetters(["permissions"])
}, },
watch: {
role () {
this.form.role = this.role
}
},
filters: { filters: {
statusFilter (status) { statusFilter (status) {
const statusMap = { const statusMap = {
...@@ -338,25 +162,23 @@ export default { ...@@ -338,25 +162,23 @@ export default {
this.listQuery.isAsc = false; this.listQuery.isAsc = false;
fetchList(this.listQuery).then(response => { fetchList(this.listQuery).then(response => {
this.list = response.data.records; this.list = response.data.records;
this.total = response.data.total; this.page.total = response.data.total
this.listLoading = false; this.listLoading = false;
}); });
}, },
getNodeData (data) { getNodeData (data, done) {
this.dialogDeptVisible = false; done();
this.form.deptId = data.id; deptRoleList(this.form.deptId).then(response => {
this.form.deptName = data.name;
deptRoleList(data.id).then(response => {
this.rolesOptions = response.data; this.rolesOptions = response.data;
}); });
}, },
handleDept () { handleDept () {
fetchDeptTree().then(response => { fetchDeptTree().then(response => {
this.treeDeptData = response.data; this.treeDeptData = response.data;
this.dialogDeptVisible = true;
}); });
}, },
handleFilter () { handleFilter (param) {
this.listQuery.username = param.username;
this.listQuery.page = 1; this.listQuery.page = 1;
this.getList(); this.getList();
}, },
...@@ -364,76 +186,66 @@ export default { ...@@ -364,76 +186,66 @@ export default {
this.listQuery.limit = val; this.listQuery.limit = val;
this.getList(); this.getList();
}, },
handleRefreshChange () {
this.getList()
},
handleCurrentChange (val) { handleCurrentChange (val) {
this.listQuery.page = val; this.listQuery.page = val;
this.getList(); this.getList();
}, },
handleCreate () { handleCreate () {
this.resetTemp(); this.$refs.crud.rowAdd();
this.dialogStatus = "create";
this.dialogFormVisible = true;
}, },
handleUpdate (row) { handleOpenBefore (show, type) {
getObj(row.userId).then(response => { this.handleDept();
this.form = response.data; if (['edit', 'views'].includes(type)) {
this.dialogFormVisible = true;
this.dialogStatus = "update";
this.role = []; this.role = [];
for (var i = 0; i < row.roleList.length; i++) { for (var i = 0; i < this.form.roleList.length; i++) {
this.role[i] = row.roleList[i].roleId; this.role[i] = this.form.roleList[i].roleId;
} }
deptRoleList(response.data.deptId).then(response => { deptRoleList(this.form.deptId).then(response => {
this.rolesOptions = response.data; this.rolesOptions = response.data;
}); });
}); } else if (type === 'add') {
this.role = [];
}
show();
}, },
create (formName) { handleUpdate (row, index) {
const set = this.$refs; this.$refs.crud.rowEdit(row, index);
this.form.role = this.role; },
set[formName].validate(valid => { create (row, done, loading) {
if (valid) {
addObj(this.form).then(() => { addObj(this.form).then(() => {
this.dialogFormVisible = false;
this.getList(); this.getList();
done();
this.$notify({ this.$notify({
title: "成功", title: "成功",
message: "创建成功", message: "创建成功",
type: "success", type: "success",
duration: 2000 duration: 2000
}); });
}); }).catch(() => {
} else { loading();
return false; });;
}
});
}, },
cancel (formName) { cancel (formName) {
this.dialogFormVisible = false;
this.$refs[formName].resetFields(); this.$refs[formName].resetFields();
}, },
update (formName) { update (row, index, done, loading) {
const set = this.$refs;
this.form.role = this.role;
set[formName].validate(valid => {
if (valid) {
this.dialogFormVisible = false;
this.form.password = undefined;
putObj(this.form).then(() => { putObj(this.form).then(() => {
this.dialogFormVisible = false;
this.getList(); this.getList();
done();
this.$notify({ this.$notify({
title: "成功", title: "成功",
message: "修改成功", message: "修改成功",
type: "success", type: "success",
duration: 2000 duration: 2000
}); });
}); }).catch(() => {
} else { loading();
return false;
}
}); });
}, },
deletes (row) { deletes (row, index) {
this.$confirm( this.$confirm(
"此操作将永久删除该用户(用户名:" + row.username + "), 是否继续?", "此操作将永久删除该用户(用户名:" + row.username + "), 是否继续?",
"提示", "提示",
...@@ -445,7 +257,7 @@ export default { ...@@ -445,7 +257,7 @@ export default {
).then(() => { ).then(() => {
delObj(row.userId) delObj(row.userId)
.then(() => { .then(() => {
this.getList(); this.list.splice(index, 1);
this.$notify({ this.$notify({
title: "成功", title: "成功",
message: "删除成功", message: "删除成功",
...@@ -462,16 +274,6 @@ export default { ...@@ -462,16 +274,6 @@ export default {
}); });
}); });
}); });
},
resetTemp () {
this.form = {
id: undefined,
username: "",
password: "",
role: [],
delFlag: "",
deptId: ""
};
} }
} }
}; };
......
This source diff could not be displayed because it is too large. You can view the blob instead.
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