Compare commits
59 Commits
Author | SHA1 | Date |
---|---|---|
liunan | 0859519fea | |
ln1778 | 58b2d52adf | |
ln1778 | 7a08110f8b | |
ln1778 | 146a02cdd9 | |
ln1778 | 57ef27b43d | |
ln1778 | 8565ddb5a3 | |
ln1778 | 578004cdb7 | |
ln1778 | 829d0a2b63 | |
ln1778 | 0d1f9fc845 | |
ln1778 | c99120819f | |
ln1778 | c2278fb3cb | |
ln1778 | bd2b674dc6 | |
ln1778 | 1d6e67d6ed | |
ln1778 | f91a8c0c7a | |
ln1778 | 3bbf8a51dc | |
ln1778 | b631f64cbb | |
ln1778 | 083a5bf7d6 | |
ln1778 | 1390f95d96 | |
ln1778 | 0684ac1f09 | |
ln1778 | 9675750d73 | |
ln1778 | 29d5c8d26b | |
ln1778 | d14d425a29 | |
ln1778 | 756f3307f3 | |
ln1778 | ef3a38f1a7 | |
ln1778 | 089e1a7c20 | |
ln1778 | 007853d66e | |
ln1778 | bf0006367b | |
ln1778 | 9e3d766d80 | |
ln1778 | 0bee153304 | |
ln1778 | baa8568ea8 | |
ln1778 | e2c28f3bf2 | |
ln1778 | b74f0ca3fc | |
ln1778 | 2f9ddc22c0 | |
ln1778 | 703d815339 | |
ln1778 | 5653581b8c | |
ln1778 | 11f09906cb | |
ln1778 | 96690a1063 | |
ln1778 | 401608de32 | |
ln1778 | ba97fbca46 | |
ln1778 | fb6bba617a | |
ln1778 | 3f5e264a37 | |
ln1778 | ab371f676a | |
ln1778 | 9675c4f2d5 | |
ln1778 | 5fe305aa80 | |
ln1778 | b1b9b7ee1a | |
ln1778 | b378f846a8 | |
ln1778 | 9c3de1ec85 | |
ln1778 | 7606e5c3eb | |
liunan | 297e10d70c | |
ln1778 | c542ebecd0 | |
ln1778 | 4845378029 | |
qiaopengfei | 6eff4461ca | |
qiaopengfei | 9b525b9077 | |
qiaopengfei | e5e98d54ab | |
qiaopengfei | d1ac7cd359 | |
qiaopengfei | bc47718607 | |
qiaopengfei | ecc128e51a | |
qiaopengfei | b6cd1c207b | |
houhaobing | e07b7df8da |
|
@ -3,7 +3,7 @@ import App from '../src/App.vue'
|
||||||
|
|
||||||
|
|
||||||
//基于element组件封装,引入element组件库
|
//基于element组件封装,引入element组件库
|
||||||
import { Input, Select, Option, OptionGroup, DatePicker, Tabs, TabPane, Pagination, Dialog, Button } from 'element-ui';
|
import { Input, Select, Option, OptionGroup, DatePicker, Tabs, TabPane, Pagination, Dialog, Button, Form, FormItem, Popover } from 'element-ui';
|
||||||
import 'element-ui/lib/theme-chalk/index.css';
|
import 'element-ui/lib/theme-chalk/index.css';
|
||||||
import '../src/styles/element-variables.scss'//element 组件样式文件
|
import '../src/styles/element-variables.scss'//element 组件样式文件
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@ Vue.use(TabPane);
|
||||||
Vue.use(Pagination)
|
Vue.use(Pagination)
|
||||||
Vue.use(Dialog)
|
Vue.use(Dialog)
|
||||||
Vue.use(Button)
|
Vue.use(Button)
|
||||||
|
Vue.use(Form)
|
||||||
|
Vue.use(FormItem)
|
||||||
|
Vue.use(Popover)
|
||||||
|
|
||||||
// 导入组件库
|
// 导入组件库
|
||||||
import erp_element_ui from '../packages'
|
import erp_element_ui from '../packages'
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,15 @@
|
||||||
{
|
{
|
||||||
"name": "ag-element-ui",
|
"name": "ag-element-ui",
|
||||||
"version": "0.1.0",
|
"version": "0.1.20",
|
||||||
"private": true,
|
"main": "packages/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vue-cli-service serve",
|
"dev": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
"lib": "vue-cli-service build --target lib --dest lib packages/index.js"
|
"lib": "vue-cli-service build --target lib --dest lib packages/index.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.8.3"
|
"core-js": "^3.8.3",
|
||||||
|
"vuedraggable": "^2.24.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-babel": "~5.0.0",
|
"@vue/cli-plugin-babel": "~5.0.0",
|
||||||
|
@ -19,9 +20,9 @@
|
||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
"sass": "^1.32.7",
|
"sass": "^1.32.7",
|
||||||
"sass-loader": "^12.0.0",
|
"sass-loader": "^12.0.0",
|
||||||
"vue-template-compiler": "^2.6.14",
|
|
||||||
"vue": "^2.6.14",
|
"vue": "^2.6.14",
|
||||||
"vue-router": "^3.5.1",
|
"vue-router": "^3.5.1",
|
||||||
|
"vue-template-compiler": "^2.6.14",
|
||||||
"vuex": "^3.6.2"
|
"vuex": "^3.6.2"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
// import pedestal from './src'
|
|
||||||
|
|
||||||
// // 为组件提供 install 安装方法,供按需引入
|
|
||||||
// pedestal.install = function (Vue) {
|
|
||||||
// Vue.component(pedestal.name, pedestal)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 导出组件
|
|
||||||
// export default pedestal
|
|
|
@ -1,18 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<h1>主组件</h1>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
components: {},
|
|
||||||
data() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
methods: {},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang='scss'>
|
|
||||||
</style>
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agCascadeOptional from './src'
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agCascadeOptional.install = function (Vue) {
|
||||||
|
Vue.component(agCascadeOptional.name, agCascadeOptional)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agCascadeOptional
|
|
@ -0,0 +1,163 @@
|
||||||
|
<template>
|
||||||
|
<div class="ag-CascadeOptional">
|
||||||
|
<ag-input
|
||||||
|
class="ag_input_group"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
:value="value[1]"
|
||||||
|
v-bind="config.input"
|
||||||
|
v-on="Listeners.input"
|
||||||
|
|
||||||
|
>
|
||||||
|
<ag-select
|
||||||
|
slot="prepend"
|
||||||
|
:clearable="false"
|
||||||
|
placeholder="请选择"
|
||||||
|
:value="value[0]"
|
||||||
|
v-bind="config.select"
|
||||||
|
v-on="Listeners.select"
|
||||||
|
class="ag_select_group"
|
||||||
|
>
|
||||||
|
|
||||||
|
</ag-select>
|
||||||
|
<template slot="suffix">
|
||||||
|
<el-button>提交</el-button>
|
||||||
|
</template>
|
||||||
|
</ag-input>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import agSelect from "../../agSelect/src/index.vue";
|
||||||
|
import agInput from "../../agInput/src/index.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "agCascadeOptional",
|
||||||
|
components: {
|
||||||
|
agSelect,
|
||||||
|
agInput,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [null, null];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
values: [null, null],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
config() {
|
||||||
|
const input_config = this.getAfterAgo(this.$attrs, "after_");
|
||||||
|
const input = {
|
||||||
|
...this.$attrs,
|
||||||
|
...input_config,
|
||||||
|
};
|
||||||
|
const select_configs = this.getAfterAgo(this.$attrs, "ago_");
|
||||||
|
const select = {
|
||||||
|
...this.$attrs,
|
||||||
|
...select_configs,
|
||||||
|
};
|
||||||
|
console.log(input, select);
|
||||||
|
return {
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
Listeners() {
|
||||||
|
const new_listeners = Object.assign({}, this.$listeners, {
|
||||||
|
after_input: (value) => {
|
||||||
|
this.$emit("change", [value, this.value[1] ? this.value[1] : ""]);
|
||||||
|
},
|
||||||
|
ago_input: (value) => {
|
||||||
|
this.$emit("change", [this.value[0] ? this.value[0] : "", value]);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const select = this.getAfterAgo(new_listeners, "after_");
|
||||||
|
const input = this.getAfterAgo(new_listeners, "ago_");
|
||||||
|
return {
|
||||||
|
select,
|
||||||
|
input,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (!Array.isArray(newVal)) {
|
||||||
|
throw new Error("agDatePicker data请传入数组");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getAfterAgo(attr, prefix) {
|
||||||
|
const config = {};
|
||||||
|
for (const key in attr) {
|
||||||
|
if (attr.hasOwnProperty(key) && key.startsWith(prefix)) {
|
||||||
|
const newKey = key.substring(prefix.length);
|
||||||
|
config[newKey] = attr[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
::v-deep {
|
||||||
|
.el-input-group__prepend {
|
||||||
|
background-color: #fff;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.el-input__suffix {
|
||||||
|
z-index: 99;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
.el-input__inner {
|
||||||
|
position: relative;
|
||||||
|
left: 0;
|
||||||
|
border: 1px solid #dcdfe6 !important;
|
||||||
|
padding: 0 5px 0 15px !important;
|
||||||
|
&:hover {
|
||||||
|
position: relative;
|
||||||
|
z-index: 20 !important;
|
||||||
|
border: 1px solid #c0c4cc !important;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
position: relative;
|
||||||
|
z-index: 20 !important;
|
||||||
|
border: 1px solid #1890ff !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .ag_select_group {
|
||||||
|
min-width: 45px;
|
||||||
|
max-width: 165px;
|
||||||
|
color: #606266;
|
||||||
|
text-align: start;
|
||||||
|
.el-input__prefix {
|
||||||
|
position: relative;
|
||||||
|
left: 0;
|
||||||
|
padding: 0 5px 0 15px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: #606266;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__inner {
|
||||||
|
border-radius: 4px 0 0 4px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep .el-select {
|
||||||
|
margin: 0 -21px !important;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agCol from './src'
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agCol.install = function (Vue) {
|
||||||
|
Vue.component(agCol.name, agCol);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agCol;
|
|
@ -0,0 +1,33 @@
|
||||||
|
<template>
|
||||||
|
<div class="agColbox" :style="{flex:`0 0 ${Number(span)/24*100}%`,marginLeft:`${Number(offset)/24*100}%`}">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'AgCol',
|
||||||
|
props: {
|
||||||
|
span:{
|
||||||
|
type:Number|String,
|
||||||
|
default:24
|
||||||
|
},
|
||||||
|
offset:{
|
||||||
|
type:Number|String,
|
||||||
|
default:0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.agColbox{
|
||||||
|
flex:0 0 100%;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agColorPicker from './src'
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agColorPicker.install = function (Vue) {
|
||||||
|
Vue.component(agColorPicker.name, agColorPicker)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agColorPicker
|
|
@ -0,0 +1,317 @@
|
||||||
|
const hsv2hsl = function(hue, sat, val) {
|
||||||
|
return [
|
||||||
|
hue,
|
||||||
|
(sat * val / ((hue = (2 - sat) * val) < 1 ? hue : 2 - hue)) || 0,
|
||||||
|
hue / 2
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
|
||||||
|
// <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
|
||||||
|
const isOnePointZero = function(n) {
|
||||||
|
return typeof n === 'string' && n.indexOf('.') !== -1 && parseFloat(n) === 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isPercentage = function(n) {
|
||||||
|
return typeof n === 'string' && n.indexOf('%') !== -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Take input from [0, n] and return it as [0, 1]
|
||||||
|
const bound01 = function(value, max) {
|
||||||
|
if (isOnePointZero(value)) value = '100%';
|
||||||
|
|
||||||
|
const processPercent = isPercentage(value);
|
||||||
|
value = Math.min(max, Math.max(0, parseFloat(value)));
|
||||||
|
|
||||||
|
// Automatically convert percentage into number
|
||||||
|
if (processPercent) {
|
||||||
|
value = parseInt(value * max, 10) / 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle floating point rounding errors
|
||||||
|
if ((Math.abs(value - max) < 0.000001)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert into [0, 1] range if it isn't already
|
||||||
|
return (value % max) / parseFloat(max);
|
||||||
|
};
|
||||||
|
|
||||||
|
const INT_HEX_MAP = { 10: 'A', 11: 'B', 12: 'C', 13: 'D', 14: 'E', 15: 'F' };
|
||||||
|
|
||||||
|
const toHex = function({ r, g, b }) {
|
||||||
|
const hexOne = function(value) {
|
||||||
|
value = Math.min(Math.round(value), 255);
|
||||||
|
const high = Math.floor(value / 16);
|
||||||
|
const low = value % 16;
|
||||||
|
return '' + (INT_HEX_MAP[high] || high) + (INT_HEX_MAP[low] || low);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isNaN(r) || isNaN(g) || isNaN(b)) return '';
|
||||||
|
|
||||||
|
return '#' + hexOne(r) + hexOne(g) + hexOne(b);
|
||||||
|
};
|
||||||
|
|
||||||
|
const HEX_INT_MAP = { A: 10, B: 11, C: 12, D: 13, E: 14, F: 15 };
|
||||||
|
|
||||||
|
const parseHexChannel = function(hex) {
|
||||||
|
if (hex.length === 2) {
|
||||||
|
return (HEX_INT_MAP[hex[0].toUpperCase()] || +hex[0]) * 16 + (HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return HEX_INT_MAP[hex[1].toUpperCase()] || +hex[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
const hsl2hsv = function(hue, sat, light) {
|
||||||
|
sat = sat / 100;
|
||||||
|
light = light / 100;
|
||||||
|
let smin = sat;
|
||||||
|
const lmin = Math.max(light, 0.01);
|
||||||
|
let sv;
|
||||||
|
let v;
|
||||||
|
|
||||||
|
light *= 2;
|
||||||
|
sat *= (light <= 1) ? light : 2 - light;
|
||||||
|
smin *= lmin <= 1 ? lmin : 2 - lmin;
|
||||||
|
v = (light + sat) / 2;
|
||||||
|
sv = light === 0 ? (2 * smin) / (lmin + smin) : (2 * sat) / (light + sat);
|
||||||
|
|
||||||
|
return {
|
||||||
|
h: hue,
|
||||||
|
s: sv * 100,
|
||||||
|
v: v * 100
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// `rgbToHsv`
|
||||||
|
// Converts an RGB color value to HSV
|
||||||
|
// *Assumes:* r, g, and b are contained in the set [0, 255] or [0, 1]
|
||||||
|
// *Returns:* { h, s, v } in [0,1]
|
||||||
|
const rgb2hsv = function(r, g, b) {
|
||||||
|
r = bound01(r, 255);
|
||||||
|
g = bound01(g, 255);
|
||||||
|
b = bound01(b, 255);
|
||||||
|
|
||||||
|
const max = Math.max(r, g, b);
|
||||||
|
const min = Math.min(r, g, b);
|
||||||
|
let h, s;
|
||||||
|
let v = max;
|
||||||
|
|
||||||
|
const d = max - min;
|
||||||
|
s = max === 0 ? 0 : d / max;
|
||||||
|
|
||||||
|
if (max === min) {
|
||||||
|
h = 0; // achromatic
|
||||||
|
} else {
|
||||||
|
switch (max) {
|
||||||
|
case r:
|
||||||
|
h = (g - b) / d + (g < b ? 6 : 0);
|
||||||
|
break;
|
||||||
|
case g:
|
||||||
|
h = (b - r) / d + 2;
|
||||||
|
break;
|
||||||
|
case b:
|
||||||
|
h = (r - g) / d + 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
h /= 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { h: h * 360, s: s * 100, v: v * 100 };
|
||||||
|
};
|
||||||
|
|
||||||
|
// `hsvToRgb`
|
||||||
|
// Converts an HSV color value to RGB.
|
||||||
|
// *Assumes:* h is contained in [0, 1] or [0, 360] and s and v are contained in [0, 1] or [0, 100]
|
||||||
|
// *Returns:* { r, g, b } in the set [0, 255]
|
||||||
|
const hsv2rgb = function(h, s, v) {
|
||||||
|
h = bound01(h, 360) * 6;
|
||||||
|
s = bound01(s, 100);
|
||||||
|
v = bound01(v, 100);
|
||||||
|
|
||||||
|
const i = Math.floor(h);
|
||||||
|
const f = h - i;
|
||||||
|
const p = v * (1 - s);
|
||||||
|
const q = v * (1 - f * s);
|
||||||
|
const t = v * (1 - (1 - f) * s);
|
||||||
|
const mod = i % 6;
|
||||||
|
const r = [v, q, p, p, t, v][mod];
|
||||||
|
const g = [t, v, v, q, p, p][mod];
|
||||||
|
const b = [p, p, t, v, v, q][mod];
|
||||||
|
|
||||||
|
return {
|
||||||
|
r: Math.round(r * 255),
|
||||||
|
g: Math.round(g * 255),
|
||||||
|
b: Math.round(b * 255)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default class Color {
|
||||||
|
constructor(options) {
|
||||||
|
this._hue = 0;
|
||||||
|
this._saturation = 100;
|
||||||
|
this._value = 100;
|
||||||
|
this._alpha = 100;
|
||||||
|
|
||||||
|
this.enableAlpha = false;
|
||||||
|
this.format = 'hex';
|
||||||
|
this.value = '';
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
for (let option in options) {
|
||||||
|
if (options.hasOwnProperty(option)) {
|
||||||
|
this[option] = options[option];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.doOnChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
set(prop, value) {
|
||||||
|
if (arguments.length === 1 && typeof prop === 'object') {
|
||||||
|
for (let p in prop) {
|
||||||
|
if (prop.hasOwnProperty(p)) {
|
||||||
|
this.set(p, prop[p]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this['_' + prop] = value;
|
||||||
|
this.doOnChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
get(prop) {
|
||||||
|
return this['_' + prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
toRgb() {
|
||||||
|
return hsv2rgb(this._hue, this._saturation, this._value);
|
||||||
|
}
|
||||||
|
|
||||||
|
fromString(value) {
|
||||||
|
if (!value) {
|
||||||
|
this._hue = 0;
|
||||||
|
this._saturation = 100;
|
||||||
|
this._value = 100;
|
||||||
|
|
||||||
|
this.doOnChange();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fromHSV = (h, s, v) => {
|
||||||
|
this._hue = Math.max(0, Math.min(360, h));
|
||||||
|
this._saturation = Math.max(0, Math.min(100, s));
|
||||||
|
this._value = Math.max(0, Math.min(100, v));
|
||||||
|
|
||||||
|
this.doOnChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (value.indexOf('hsl') !== -1) {
|
||||||
|
const parts = value.replace(/hsla|hsl|\(|\)/gm, '')
|
||||||
|
.split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||||
|
|
||||||
|
if (parts.length === 4) {
|
||||||
|
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||||
|
} else if (parts.length === 3) {
|
||||||
|
this._alpha = 100;
|
||||||
|
}
|
||||||
|
if (parts.length >= 3) {
|
||||||
|
const { h, s, v } = hsl2hsv(parts[0], parts[1], parts[2]);
|
||||||
|
fromHSV(h, s, v);
|
||||||
|
}
|
||||||
|
} else if (value.indexOf('hsv') !== -1) {
|
||||||
|
const parts = value.replace(/hsva|hsv|\(|\)/gm, '')
|
||||||
|
.split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||||
|
|
||||||
|
if (parts.length === 4) {
|
||||||
|
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||||
|
} else if (parts.length === 3) {
|
||||||
|
this._alpha = 100;
|
||||||
|
}
|
||||||
|
if (parts.length >= 3) {
|
||||||
|
fromHSV(parts[0], parts[1], parts[2]);
|
||||||
|
}
|
||||||
|
} else if (value.indexOf('rgb') !== -1) {
|
||||||
|
const parts = value.replace(/rgba|rgb|\(|\)/gm, '')
|
||||||
|
.split(/\s|,/g).filter((val) => val !== '').map((val, index) => index > 2 ? parseFloat(val) : parseInt(val, 10));
|
||||||
|
|
||||||
|
if (parts.length === 4) {
|
||||||
|
this._alpha = Math.floor(parseFloat(parts[3]) * 100);
|
||||||
|
} else if (parts.length === 3) {
|
||||||
|
this._alpha = 100;
|
||||||
|
}
|
||||||
|
if (parts.length >= 3) {
|
||||||
|
const { h, s, v } = rgb2hsv(parts[0], parts[1], parts[2]);
|
||||||
|
fromHSV(h, s, v);
|
||||||
|
}
|
||||||
|
} else if (value.indexOf('#') !== -1) {
|
||||||
|
const hex = value.replace('#', '').trim();
|
||||||
|
if (!/^(?:[0-9a-fA-F]{3}){1,2}|[0-9a-fA-F]{8}$/.test(hex)) return;
|
||||||
|
let r, g, b;
|
||||||
|
|
||||||
|
if (hex.length === 3) {
|
||||||
|
r = parseHexChannel(hex[0] + hex[0]);
|
||||||
|
g = parseHexChannel(hex[1] + hex[1]);
|
||||||
|
b = parseHexChannel(hex[2] + hex[2]);
|
||||||
|
} else if (hex.length === 6 || hex.length === 8) {
|
||||||
|
r = parseHexChannel(hex.substring(0, 2));
|
||||||
|
g = parseHexChannel(hex.substring(2, 4));
|
||||||
|
b = parseHexChannel(hex.substring(4, 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hex.length === 8) {
|
||||||
|
this._alpha = Math.floor(parseHexChannel(hex.substring(6)) / 255 * 100);
|
||||||
|
} else if (hex.length === 3 || hex.length === 6) {
|
||||||
|
this._alpha = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { h, s, v } = rgb2hsv(r, g, b);
|
||||||
|
fromHSV(h, s, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(color) {
|
||||||
|
return Math.abs(color._hue - this._hue) < 2 &&
|
||||||
|
Math.abs(color._saturation - this._saturation) < 1 &&
|
||||||
|
Math.abs(color._value - this._value) < 1 &&
|
||||||
|
Math.abs(color._alpha - this._alpha) < 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
doOnChange() {
|
||||||
|
const { _hue, _saturation, _value, _alpha, format } = this;
|
||||||
|
|
||||||
|
if (this.enableAlpha) {
|
||||||
|
switch (format) {
|
||||||
|
case 'hsl':
|
||||||
|
const hsl = hsv2hsl(_hue, _saturation / 100, _value / 100);
|
||||||
|
this.value = `hsla(${ _hue }, ${ Math.round(hsl[1] * 100) }%, ${ Math.round(hsl[2] * 100) }%, ${ _alpha / 100})`;
|
||||||
|
break;
|
||||||
|
case 'hsv':
|
||||||
|
this.value = `hsva(${ _hue }, ${ Math.round(_saturation) }%, ${ Math.round(_value) }%, ${ _alpha / 100})`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
const { r, g, b } = hsv2rgb(_hue, _saturation, _value);
|
||||||
|
this.value = `rgba(${r}, ${g}, ${b}, ${ _alpha / 100 })`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (format) {
|
||||||
|
case 'hsl':
|
||||||
|
const hsl = hsv2hsl(_hue, _saturation / 100, _value / 100);
|
||||||
|
this.value = `hsl(${ _hue }, ${ Math.round(hsl[1] * 100) }%, ${ Math.round(hsl[2] * 100) }%)`;
|
||||||
|
break;
|
||||||
|
case 'hsv':
|
||||||
|
this.value = `hsv(${ _hue }, ${ Math.round(_saturation) }%, ${ Math.round(_value) }%)`;
|
||||||
|
break;
|
||||||
|
case 'rgb':
|
||||||
|
const { r, g, b } = hsv2rgb(_hue, _saturation, _value);
|
||||||
|
this.value = `rgb(${r}, ${g}, ${b})`;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.value = toHex(hsv2rgb(_hue, _saturation, _value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,132 @@
|
||||||
|
<template>
|
||||||
|
<div class="el-color-alpha-slider" :class="{ 'is-vertical': vertical }">
|
||||||
|
<div class="el-color-alpha-slider__bar"
|
||||||
|
@click="handleClick"
|
||||||
|
ref="bar"
|
||||||
|
:style="{
|
||||||
|
background: background
|
||||||
|
}">
|
||||||
|
</div>
|
||||||
|
<div class="el-color-alpha-slider__thumb"
|
||||||
|
ref="thumb"
|
||||||
|
:style="{
|
||||||
|
left: thumbLeft + 'px',
|
||||||
|
top: thumbTop + 'px'
|
||||||
|
}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import draggable from '../draggable';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'el-color-alpha-slider',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
color: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
vertical: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
'color._alpha'() {
|
||||||
|
this.update();
|
||||||
|
},
|
||||||
|
|
||||||
|
'color.value'() {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleClick(event) {
|
||||||
|
const thumb = this.$refs.thumb;
|
||||||
|
const target = event.target;
|
||||||
|
|
||||||
|
if (target !== thumb) {
|
||||||
|
this.handleDrag(event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDrag(event) {
|
||||||
|
const rect = this.$el.getBoundingClientRect();
|
||||||
|
const { thumb } = this.$refs;
|
||||||
|
|
||||||
|
if (!this.vertical) {
|
||||||
|
let left = event.clientX - rect.left;
|
||||||
|
left = Math.max(thumb.offsetWidth / 2, left);
|
||||||
|
left = Math.min(left, rect.width - thumb.offsetWidth / 2);
|
||||||
|
|
||||||
|
this.color.set('alpha', Math.round((left - thumb.offsetWidth / 2) / (rect.width - thumb.offsetWidth) * 100));
|
||||||
|
} else {
|
||||||
|
let top = event.clientY - rect.top;
|
||||||
|
top = Math.max(thumb.offsetHeight / 2, top);
|
||||||
|
top = Math.min(top, rect.height - thumb.offsetHeight / 2);
|
||||||
|
|
||||||
|
this.color.set('alpha', Math.round((top - thumb.offsetHeight / 2) / (rect.height - thumb.offsetHeight) * 100));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
getThumbLeft() {
|
||||||
|
if (this.vertical) return 0;
|
||||||
|
const el = this.$el;
|
||||||
|
const alpha = this.color._alpha;
|
||||||
|
|
||||||
|
if (!el) return 0;
|
||||||
|
const thumb = this.$refs.thumb;
|
||||||
|
return Math.round(alpha * (el.offsetWidth - thumb.offsetWidth / 2) / 100);
|
||||||
|
},
|
||||||
|
|
||||||
|
getThumbTop() {
|
||||||
|
if (!this.vertical) return 0;
|
||||||
|
const el = this.$el;
|
||||||
|
const alpha = this.color._alpha;
|
||||||
|
|
||||||
|
if (!el) return 0;
|
||||||
|
const thumb = this.$refs.thumb;
|
||||||
|
return Math.round(alpha * (el.offsetHeight - thumb.offsetHeight / 2) / 100);
|
||||||
|
},
|
||||||
|
|
||||||
|
getBackground() {
|
||||||
|
if (this.color && this.color.value) {
|
||||||
|
const { r, g, b } = this.color.toRgb();
|
||||||
|
return `linear-gradient(to right, rgba(${r}, ${g}, ${b}, 0) 0%, rgba(${r}, ${g}, ${b}, 1) 100%)`;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.thumbLeft = this.getThumbLeft();
|
||||||
|
this.thumbTop = this.getThumbTop();
|
||||||
|
this.background = this.getBackground();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
thumbLeft: 0,
|
||||||
|
thumbTop: 0,
|
||||||
|
background: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
const { bar, thumb } = this.$refs;
|
||||||
|
|
||||||
|
const dragConfig = {
|
||||||
|
drag: (event) => {
|
||||||
|
this.handleDrag(event);
|
||||||
|
},
|
||||||
|
end: (event) => {
|
||||||
|
this.handleDrag(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
draggable(bar, dragConfig);
|
||||||
|
draggable(thumb, dragConfig);
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<div class="el-color-hue-slider" :class="{ 'is-vertical': vertical }">
|
||||||
|
<div class="el-color-hue-slider__bar" @click="handleClick" ref="bar"></div>
|
||||||
|
<div class="el-color-hue-slider__thumb"
|
||||||
|
:style="{
|
||||||
|
left: thumbLeft + 'px',
|
||||||
|
top: thumbTop + 'px'
|
||||||
|
}"
|
||||||
|
ref="thumb">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import draggable from '../draggable';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'el-color-hue-slider',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
color: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
vertical: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
thumbLeft: 0,
|
||||||
|
thumbTop: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
hueValue() {
|
||||||
|
const hue = this.color.get('hue');
|
||||||
|
return hue;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
hueValue() {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleClick(event) {
|
||||||
|
const thumb = this.$refs.thumb;
|
||||||
|
const target = event.target;
|
||||||
|
|
||||||
|
if (target !== thumb) {
|
||||||
|
this.handleDrag(event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDrag(event) {
|
||||||
|
const rect = this.$el.getBoundingClientRect();
|
||||||
|
const { thumb } = this.$refs;
|
||||||
|
let hue;
|
||||||
|
|
||||||
|
if (!this.vertical) {
|
||||||
|
let left = event.clientX - rect.left;
|
||||||
|
left = Math.min(left, rect.width - thumb.offsetWidth / 2);
|
||||||
|
left = Math.max(thumb.offsetWidth / 2, left);
|
||||||
|
|
||||||
|
hue = Math.round((left - thumb.offsetWidth / 2) / (rect.width - thumb.offsetWidth) * 360);
|
||||||
|
} else {
|
||||||
|
let top = event.clientY - rect.top;
|
||||||
|
top = Math.min(top, rect.height - thumb.offsetHeight / 2);
|
||||||
|
top = Math.max(thumb.offsetHeight / 2, top);
|
||||||
|
|
||||||
|
hue = Math.round((top - thumb.offsetHeight / 2) / (rect.height - thumb.offsetHeight) * 360);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.color.set('hue', hue);
|
||||||
|
},
|
||||||
|
|
||||||
|
getThumbLeft() {
|
||||||
|
if (this.vertical) return 0;
|
||||||
|
const el = this.$el;
|
||||||
|
const hue = this.color.get('hue');
|
||||||
|
|
||||||
|
if (!el) return 0;
|
||||||
|
const thumb = this.$refs.thumb;
|
||||||
|
return Math.round(hue * (el.offsetWidth - thumb.offsetWidth / 2) / 360);
|
||||||
|
},
|
||||||
|
|
||||||
|
getThumbTop() {
|
||||||
|
if (!this.vertical) return 0;
|
||||||
|
const el = this.$el;
|
||||||
|
const hue = this.color.get('hue');
|
||||||
|
|
||||||
|
if (!el) return 0;
|
||||||
|
const thumb = this.$refs.thumb;
|
||||||
|
return Math.round(hue * (el.offsetHeight - thumb.offsetHeight / 2) / 360);
|
||||||
|
},
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.thumbLeft = this.getThumbLeft();
|
||||||
|
this.thumbTop = this.getThumbTop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
const { bar, thumb } = this.$refs;
|
||||||
|
|
||||||
|
const dragConfig = {
|
||||||
|
drag: (event) => {
|
||||||
|
this.handleDrag(event);
|
||||||
|
},
|
||||||
|
end: (event) => {
|
||||||
|
this.handleDrag(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
draggable(bar, dragConfig);
|
||||||
|
draggable(thumb, dragConfig);
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,128 @@
|
||||||
|
<template>
|
||||||
|
<transition name="el-zoom-in-top" @after-leave="doDestroy">
|
||||||
|
<div
|
||||||
|
class="el-color-dropdown"
|
||||||
|
v-show="showPopper">
|
||||||
|
<div class="el-color-dropdown__main-wrapper">
|
||||||
|
<hue-slider ref="hue" :color="color" vertical style="float: right;"></hue-slider>
|
||||||
|
<sv-panel ref="sl" :color="color"></sv-panel>
|
||||||
|
</div>
|
||||||
|
<alpha-slider v-if="showAlpha" ref="alpha" :color="color"></alpha-slider>
|
||||||
|
<predefine v-if="predefine" :color="color" :colors="predefine"></predefine>
|
||||||
|
<div class="el-color-dropdown__btns">
|
||||||
|
<span class="el-color-dropdown__value">
|
||||||
|
<el-input
|
||||||
|
v-model="customInput"
|
||||||
|
@keyup.native.enter="handleConfirm"
|
||||||
|
@blur="handleConfirm"
|
||||||
|
:validate-event="false"
|
||||||
|
size="mini">
|
||||||
|
</el-input>
|
||||||
|
</span>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
class="el-color-dropdown__link-btn"
|
||||||
|
@click="$emit('eyedropper')">
|
||||||
|
<i class="el-icon-magic-stick"></i>
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="text"
|
||||||
|
class="el-color-dropdown__link-btn"
|
||||||
|
@click="$emit('clear')">
|
||||||
|
{{ t('el.colorpicker.clear') }}
|
||||||
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
plain
|
||||||
|
size="mini"
|
||||||
|
class="el-color-dropdown__btn"
|
||||||
|
@click="confirmValue">
|
||||||
|
{{ t('el.colorpicker.confirm') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SvPanel from './sv-panel';
|
||||||
|
import HueSlider from './hue-slider';
|
||||||
|
import AlphaSlider from './alpha-slider';
|
||||||
|
import Predefine from './predefine';
|
||||||
|
import Popper from 'element-ui/src/utils/vue-popper';
|
||||||
|
import Locale from 'element-ui/src/mixins/locale';
|
||||||
|
import ElInput from 'element-ui/packages/input';
|
||||||
|
import ElButton from 'element-ui/packages/button';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'el-color-picker-dropdown',
|
||||||
|
|
||||||
|
mixins: [Popper, Locale],
|
||||||
|
|
||||||
|
components: {
|
||||||
|
SvPanel,
|
||||||
|
HueSlider,
|
||||||
|
AlphaSlider,
|
||||||
|
ElInput,
|
||||||
|
ElButton,
|
||||||
|
Predefine
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
color: {
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
showAlpha: Boolean,
|
||||||
|
predefine: Array
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
customInput: ''
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
currentColor() {
|
||||||
|
const parent = this.$parent;
|
||||||
|
return !parent.value && !parent.showPanelColor ? '' : parent.color.value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
confirmValue() {
|
||||||
|
this.$emit('pick');
|
||||||
|
},
|
||||||
|
|
||||||
|
handleConfirm() {
|
||||||
|
this.color.fromString(this.customInput);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$parent.popperElm = this.popperElm = this.$el;
|
||||||
|
this.referenceElm = this.$parent.$el;
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
showPopper(val) {
|
||||||
|
if (val === true) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const { sl, hue, alpha } = this.$refs;
|
||||||
|
sl && sl.update();
|
||||||
|
hue && hue.update();
|
||||||
|
alpha && alpha.update();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
currentColor: {
|
||||||
|
immediate: true,
|
||||||
|
handler(val) {
|
||||||
|
this.customInput = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,61 @@
|
||||||
|
<template>
|
||||||
|
<div class="el-color-predefine">
|
||||||
|
<div class="el-color-predefine__colors">
|
||||||
|
<div class="el-color-predefine__color-selector"
|
||||||
|
:class="{selected: item.selected, 'is-alpha': item._alpha < 100}"
|
||||||
|
v-for="(item, index) in rgbaColors"
|
||||||
|
:key="colors[index]"
|
||||||
|
@click="handleSelect(index)">
|
||||||
|
<div :style="{'background-color': item.value}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Color from '../color';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
colors: { type: Array, required: true },
|
||||||
|
color: { required: true }
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
rgbaColors: this.parseColors(this.colors, this.color)
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSelect(index) {
|
||||||
|
this.color.fromString(this.colors[index]);
|
||||||
|
},
|
||||||
|
parseColors(colors, color) {
|
||||||
|
return colors.map(value => {
|
||||||
|
const c = new Color();
|
||||||
|
c.enableAlpha = true;
|
||||||
|
c.format = 'rgba';
|
||||||
|
c.fromString(value);
|
||||||
|
c.selected = c.value === color.value;
|
||||||
|
return c;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'$parent.currentColor'(val) {
|
||||||
|
const color = new Color();
|
||||||
|
color.fromString(val);
|
||||||
|
|
||||||
|
this.rgbaColors.forEach(item => {
|
||||||
|
item.selected = color.compare(item);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
colors(newVal) {
|
||||||
|
this.rgbaColors = this.parseColors(newVal, this.color);
|
||||||
|
},
|
||||||
|
color(newVal) {
|
||||||
|
this.rgbaColors = this.parseColors(this.colors, newVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,100 @@
|
||||||
|
<template>
|
||||||
|
<div class="el-color-svpanel"
|
||||||
|
:style="{
|
||||||
|
backgroundColor: background
|
||||||
|
}">
|
||||||
|
<div class="el-color-svpanel__white"></div>
|
||||||
|
<div class="el-color-svpanel__black"></div>
|
||||||
|
<div class="el-color-svpanel__cursor"
|
||||||
|
:style="{
|
||||||
|
top: cursorTop + 'px',
|
||||||
|
left: cursorLeft + 'px'
|
||||||
|
}">
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import draggable from '../draggable';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'el-sl-panel',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
color: {
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
colorValue() {
|
||||||
|
const hue = this.color.get('hue');
|
||||||
|
const value = this.color.get('value');
|
||||||
|
return { hue, value };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
colorValue() {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
update() {
|
||||||
|
const saturation = this.color.get('saturation');
|
||||||
|
const value = this.color.get('value');
|
||||||
|
|
||||||
|
const el = this.$el;
|
||||||
|
let { clientWidth: width, clientHeight: height } = el;
|
||||||
|
|
||||||
|
this.cursorLeft = saturation * width / 100;
|
||||||
|
this.cursorTop = (100 - value) * height / 100;
|
||||||
|
|
||||||
|
this.background = 'hsl(' + this.color.get('hue') + ', 100%, 50%)';
|
||||||
|
},
|
||||||
|
|
||||||
|
handleDrag(event) {
|
||||||
|
const el = this.$el;
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
|
||||||
|
let left = event.clientX - rect.left;
|
||||||
|
let top = event.clientY - rect.top;
|
||||||
|
left = Math.max(0, left);
|
||||||
|
left = Math.min(left, rect.width);
|
||||||
|
|
||||||
|
top = Math.max(0, top);
|
||||||
|
top = Math.min(top, rect.height);
|
||||||
|
|
||||||
|
this.cursorLeft = left;
|
||||||
|
this.cursorTop = top;
|
||||||
|
this.color.set({
|
||||||
|
saturation: left / rect.width * 100,
|
||||||
|
value: 100 - top / rect.height * 100
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
draggable(this.$el, {
|
||||||
|
drag: (event) => {
|
||||||
|
this.handleDrag(event);
|
||||||
|
},
|
||||||
|
end: (event) => {
|
||||||
|
this.handleDrag(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cursorTop: 0,
|
||||||
|
cursorLeft: 0,
|
||||||
|
background: 'hsl(0, 100%, 50%)'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -0,0 +1,36 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
let isDragging = false;
|
||||||
|
|
||||||
|
export default function(element, options) {
|
||||||
|
if (Vue.prototype.$isServer) return;
|
||||||
|
const moveFn = function(event) {
|
||||||
|
if (options.drag) {
|
||||||
|
options.drag(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const upFn = function(event) {
|
||||||
|
document.removeEventListener('mousemove', moveFn);
|
||||||
|
document.removeEventListener('mouseup', upFn);
|
||||||
|
document.onselectstart = null;
|
||||||
|
document.ondragstart = null;
|
||||||
|
|
||||||
|
isDragging = false;
|
||||||
|
|
||||||
|
if (options.end) {
|
||||||
|
options.end(event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
element.addEventListener('mousedown', function(event) {
|
||||||
|
if (isDragging) return;
|
||||||
|
document.onselectstart = function() { return false; };
|
||||||
|
document.ondragstart = function() { return false; };
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', moveFn);
|
||||||
|
document.addEventListener('mouseup', upFn);
|
||||||
|
isDragging = true;
|
||||||
|
|
||||||
|
if (options.start) {
|
||||||
|
options.start(event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,201 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
:class="[
|
||||||
|
'el-color-picker',
|
||||||
|
colorDisabled ? 'is-disabled' : '',
|
||||||
|
colorSize ? `el-color-picker--${ colorSize }` : ''
|
||||||
|
]"
|
||||||
|
v-clickoutside="hide">
|
||||||
|
<div class="el-color-picker__mask" v-if="colorDisabled"></div>
|
||||||
|
<div class="el-color-picker__trigger" @click="handleTrigger">
|
||||||
|
<span class="el-color-picker__color" :class="{ 'is-alpha': showAlpha }">
|
||||||
|
<span class="el-color-picker__color-inner"
|
||||||
|
:style="{
|
||||||
|
backgroundColor: displayedColor
|
||||||
|
}"></span>
|
||||||
|
<span class="el-color-picker__empty el-icon-close" v-if="!value && !showPanelColor"></span>
|
||||||
|
</span>
|
||||||
|
<span class="el-color-picker__icon el-icon-arrow-down" v-show="value || showPanelColor"></span>
|
||||||
|
</div>
|
||||||
|
<picker-dropdown
|
||||||
|
ref="dropdown"
|
||||||
|
:class="['el-color-picker__panel', popperClass || '']"
|
||||||
|
v-model="showPicker"
|
||||||
|
@pick="confirmValue"
|
||||||
|
@clear="clearValue"
|
||||||
|
@eyedropper="eyedropper"
|
||||||
|
:color="color"
|
||||||
|
:show-alpha="showAlpha"
|
||||||
|
:predefine="predefine">
|
||||||
|
</picker-dropdown>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Color from './color';
|
||||||
|
import PickerDropdown from './components/picker-dropdown.vue';
|
||||||
|
import Clickoutside from 'element-ui/src/utils/clickoutside';
|
||||||
|
import Emitter from 'element-ui/src/mixins/emitter';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AgColorPicker',
|
||||||
|
|
||||||
|
mixins: [Emitter],
|
||||||
|
|
||||||
|
props: {
|
||||||
|
value: String,
|
||||||
|
showAlpha: Boolean,
|
||||||
|
colorFormat: String,
|
||||||
|
disabled: Boolean,
|
||||||
|
size: String,
|
||||||
|
popperClass: String,
|
||||||
|
predefine: Array
|
||||||
|
},
|
||||||
|
|
||||||
|
inject: {
|
||||||
|
elForm: {
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
elFormItem: {
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
directives: { Clickoutside },
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
displayedColor() {
|
||||||
|
if (!this.value && !this.showPanelColor) {
|
||||||
|
return 'transparent';
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.displayedRgb(this.color, this.showAlpha);
|
||||||
|
},
|
||||||
|
|
||||||
|
_elFormItemSize() {
|
||||||
|
return (this.elFormItem || {}).elFormItemSize;
|
||||||
|
},
|
||||||
|
|
||||||
|
colorSize() {
|
||||||
|
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
|
||||||
|
},
|
||||||
|
|
||||||
|
colorDisabled() {
|
||||||
|
return this.disabled || (this.elForm || {}).disabled;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
value(val) {
|
||||||
|
if (!val) {
|
||||||
|
this.showPanelColor = false;
|
||||||
|
} else if (val && val !== this.color.value) {
|
||||||
|
this.color.fromString(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
deep: true,
|
||||||
|
handler() {
|
||||||
|
this.showPanelColor = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
displayedColor(val) {
|
||||||
|
if (!this.showPicker) return;
|
||||||
|
const currentValueColor = new Color({
|
||||||
|
enableAlpha: this.showAlpha,
|
||||||
|
format: this.colorFormat
|
||||||
|
});
|
||||||
|
currentValueColor.fromString(this.value);
|
||||||
|
|
||||||
|
const currentValueColorRgb = this.displayedRgb(currentValueColor, this.showAlpha);
|
||||||
|
if (val !== currentValueColorRgb) {
|
||||||
|
this.$emit('active-change', val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
handleTrigger() {
|
||||||
|
if (this.colorDisabled) return;
|
||||||
|
this.showPicker = !this.showPicker;
|
||||||
|
},
|
||||||
|
confirmValue() {
|
||||||
|
const value = this.color.value;
|
||||||
|
this.$emit('input', value);
|
||||||
|
this.$emit('change', value);
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', value);
|
||||||
|
this.showPicker = false;
|
||||||
|
},
|
||||||
|
clearValue() {
|
||||||
|
this.$emit('input', null);
|
||||||
|
this.$emit('change', null);
|
||||||
|
if (this.value !== null) {
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', null);
|
||||||
|
}
|
||||||
|
this.showPanelColor = false;
|
||||||
|
this.showPicker = false;
|
||||||
|
this.resetColor();
|
||||||
|
},
|
||||||
|
async eyedropper(){
|
||||||
|
const dropper=new EyeDropper();
|
||||||
|
try{
|
||||||
|
const result=await dropper.open();
|
||||||
|
const value = result.sRGBHex;
|
||||||
|
this.$emit('input', value);
|
||||||
|
this.$emit('change', value);
|
||||||
|
this.dispatch('ElFormItem', 'el.form.change', value);
|
||||||
|
}catch(e){
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hide() {
|
||||||
|
this.showPicker = false;
|
||||||
|
this.resetColor();
|
||||||
|
},
|
||||||
|
resetColor() {
|
||||||
|
this.$nextTick(_ => {
|
||||||
|
if (this.value) {
|
||||||
|
this.color.fromString(this.value);
|
||||||
|
} else {
|
||||||
|
this.showPanelColor = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
displayedRgb(color, showAlpha) {
|
||||||
|
if (!(color instanceof Color)) {
|
||||||
|
throw Error('color should be instance of Color Class');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { r, g, b } = color.toRgb();
|
||||||
|
return showAlpha
|
||||||
|
? `rgba(${ r }, ${ g }, ${ b }, ${ color.get('alpha') / 100 })`
|
||||||
|
: `rgb(${ r }, ${ g }, ${ b })`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
const value = this.value;
|
||||||
|
if (value) {
|
||||||
|
this.color.fromString(value);
|
||||||
|
}
|
||||||
|
this.popperElm = this.$refs.dropdown.$el;
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
const color = new Color({
|
||||||
|
enableAlpha: this.showAlpha,
|
||||||
|
format: this.colorFormat
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
showPicker: false,
|
||||||
|
showPanelColor: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
components: {
|
||||||
|
PickerDropdown
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
|
@ -6,4 +6,4 @@ agDatePicker.install = function (Vue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出组件
|
// 导出组件
|
||||||
export default agDatePicker
|
export default agDatePicker;
|
||||||
|
|
|
@ -1,148 +1,248 @@
|
||||||
<template>
|
<template>
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
:style="{ width }"
|
:style="{ width }"
|
||||||
class="ag-date-picker"
|
:prefix-icon="iconClass"
|
||||||
|
clear-icon="ag-icon-clear"
|
||||||
|
ref="datepickerref"
|
||||||
v-model="dateArr"
|
v-model="dateArr"
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
v-on="inputListeners"
|
v-on="Listeners"
|
||||||
|
:size="$attrs.size||'small'"
|
||||||
|
:value="value"
|
||||||
|
:type="datetype"
|
||||||
|
@mouseenter.native="mousetrue = true"
|
||||||
|
@mouseleave.native="mousetrue = false"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/**
|
|
||||||
* agDatePicker 时间选择器
|
|
||||||
*/
|
|
||||||
import isEmpty from "../../../src/utils/isEmpty";
|
import isEmpty from "../../../src/utils/isEmpty";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "agDatePicker",
|
name: "AgDatePicker",
|
||||||
props: {
|
props: {
|
||||||
|
range:false,
|
||||||
|
showTime:false,
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: "date",
|
||||||
|
},
|
||||||
value: {
|
value: {
|
||||||
type: Array,
|
default:()=>{
|
||||||
default: () => [null, null],
|
return null||[]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
width: "160px",
|
width: "160px",
|
||||||
dateArr: [null, null],
|
dateArr: null||[],
|
||||||
|
date_picker: false,
|
||||||
|
mousetrue: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
datetype(){
|
||||||
|
if(this.range){
|
||||||
|
if(this.showTime){
|
||||||
|
return "datetimerange"
|
||||||
|
}else{
|
||||||
|
return "daterange";
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(this.showTime){
|
||||||
|
return "datetime";
|
||||||
|
}else{
|
||||||
|
return "date";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
attrs() {
|
attrs() {
|
||||||
|
let config = {};
|
||||||
|
if (this.range) {
|
||||||
|
config = {
|
||||||
|
"start-placeholder":this.$attrs.startPlaceholder||"开始日期",
|
||||||
|
"end-placeholder":this.$attrs.endPlaceholder|| "结束日期",
|
||||||
|
"range-separator":this.$attrs.rangeSeparator||"-",
|
||||||
|
"picker-options": {
|
||||||
|
disabledDate(time) {
|
||||||
|
return (
|
||||||
|
time.getTime() >
|
||||||
|
new Date(new Date().toLocaleDateString()).getTime() +
|
||||||
|
24 * 60 * 60 * 1000 -
|
||||||
|
1
|
||||||
|
);
|
||||||
|
},
|
||||||
|
shortcuts: [
|
||||||
|
{
|
||||||
|
text: "本月",
|
||||||
|
onClick(picker) {
|
||||||
|
const end =
|
||||||
|
new Date(new Date().toLocaleDateString()).getTime() +
|
||||||
|
24 * 60 * 60 * 1000 -
|
||||||
|
1;
|
||||||
|
const time = new Date();
|
||||||
|
time.setDate(1);
|
||||||
|
time.setHours(0);
|
||||||
|
time.setSeconds(0);
|
||||||
|
time.setMinutes(0);
|
||||||
|
var start = time.getTime();
|
||||||
|
picker.$emit("pick", [start, end]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "近一个月",
|
||||||
|
onClick(picker) {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
||||||
|
picker.$emit("pick", [start, end]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "近三个月",
|
||||||
|
onClick(picker) {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
|
||||||
|
picker.$emit("pick", [start, end]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "近六个月",
|
||||||
|
onClick(picker) {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180);
|
||||||
|
picker.$emit("pick", [start, end]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "最近一年",
|
||||||
|
onClick(picker) {
|
||||||
|
const end = new Date();
|
||||||
|
const start = new Date();
|
||||||
|
start.setTime(start.getTime() - 3600 * 1000 * 24 * 360);
|
||||||
|
picker.$emit("pick", [start, end]);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}, //多选日期
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
config = {
|
||||||
|
align: "right",
|
||||||
|
placeholder: this.$attrs.placeholder||"选择日期",
|
||||||
|
"picker-options": {
|
||||||
|
disabledDate(time) {
|
||||||
|
return time.getTime() > Date.now();
|
||||||
|
},
|
||||||
|
shortcuts: [
|
||||||
|
{
|
||||||
|
text: "今天",
|
||||||
|
onClick(picker) {
|
||||||
|
const date = new Date();
|
||||||
|
date.setTime(date.getTime());
|
||||||
|
picker.$emit("pick", date);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "昨天",
|
||||||
|
onClick(picker) {
|
||||||
|
const date = new Date();
|
||||||
|
date.setTime(date.getTime() - 1* 24 * 60 * 60 * 1000);
|
||||||
|
picker.$emit("pick", date);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: "一周前",
|
||||||
|
onClick(picker) {
|
||||||
|
const date = new Date();
|
||||||
|
date.setTime(date.getTime() - 7 * 24 * 60 * 60 * 1000);
|
||||||
|
picker.$emit("pick", date);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
size: "small",
|
size: "small",
|
||||||
type: "daterange",
|
type: "daterange",
|
||||||
format: "yyyy/MM/dd",
|
format: this.showTime?"yyyy-MM-dd hh:mm:ss":"yyyy-MM-dd",
|
||||||
"value-format": "yyyy-MM-dd",
|
"value-format":this.showTime?"yyyy-MM-dd hh:mm:ss": "yyyy-MM-dd",
|
||||||
"start-placeholder": "开始日期",
|
...config,
|
||||||
"end-placeholder": "结束日期",
|
|
||||||
"range-separator": "-",
|
|
||||||
"prefix-icon": " ag-el-icon-prefix",
|
|
||||||
"picker-options": {
|
|
||||||
disabledDate(time) {
|
|
||||||
return (
|
|
||||||
time.getTime() >
|
|
||||||
new Date(new Date().toLocaleDateString()).getTime() +
|
|
||||||
24 * 60 * 60 * 1000 -
|
|
||||||
1
|
|
||||||
);
|
|
||||||
},
|
|
||||||
shortcuts: [
|
|
||||||
{
|
|
||||||
text: "本月",
|
|
||||||
onClick(picker) {
|
|
||||||
const end =
|
|
||||||
new Date(new Date().toLocaleDateString()).getTime() +
|
|
||||||
24 * 60 * 60 * 1000 -
|
|
||||||
1;
|
|
||||||
const time = new Date();
|
|
||||||
time.setDate(1);
|
|
||||||
time.setHours(0);
|
|
||||||
time.setSeconds(0);
|
|
||||||
time.setMinutes(0);
|
|
||||||
var start = time.getTime();
|
|
||||||
picker.$emit("pick", [start, end]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "近一个月",
|
|
||||||
onClick(picker) {
|
|
||||||
const end = new Date();
|
|
||||||
const start = new Date();
|
|
||||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
|
||||||
picker.$emit("pick", [start, end]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "近三个月",
|
|
||||||
onClick(picker) {
|
|
||||||
const end = new Date();
|
|
||||||
const start = new Date();
|
|
||||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
|
|
||||||
picker.$emit("pick", [start, end]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "近六个月",
|
|
||||||
onClick(picker) {
|
|
||||||
const end = new Date();
|
|
||||||
const start = new Date();
|
|
||||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 180);
|
|
||||||
picker.$emit("pick", [start, end]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "最近一年",
|
|
||||||
onClick(picker) {
|
|
||||||
const end = new Date();
|
|
||||||
const start = new Date();
|
|
||||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 360);
|
|
||||||
picker.$emit("pick", [start, end]);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}, //多选日期
|
|
||||||
...this.$attrs,
|
...this.$attrs,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
// 所有父级事件
|
// 所有父级事件
|
||||||
inputListeners() {
|
Listeners() {
|
||||||
return Object.assign({}, this.$listeners, {
|
return Object.assign({}, this.$listeners, {
|
||||||
input: (value) => {
|
input: (value) => {
|
||||||
let date1 = "";
|
if (this.range) {
|
||||||
let date2 = "";
|
if (!isEmpty(value) && value.length === 2 && value[0] && value[1]) {
|
||||||
|
if(this.showTime){
|
||||||
if (!isEmpty(value) && value.length === 2 && value[0] && value[1]) {
|
if(this.$listeners.change){
|
||||||
date1 = `${value[0]} 00:00:00`;
|
this.$emit("change", value);
|
||||||
date2 = `${value[1]} 23:59:59`;
|
}
|
||||||
|
}else{
|
||||||
|
if(this.$listeners.change){
|
||||||
|
this.$emit("change", [
|
||||||
|
`${value[0]} 00:00:00`,
|
||||||
|
`${value[1]} 23:59:59`,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if(this.$listeners.change){
|
||||||
|
this.$emit("change", []);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(this.$listeners.change){
|
||||||
|
this.$emit("change", value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.$emit("input", [date1, date2]);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
iconClass() {
|
||||||
|
return this.mousetrue
|
||||||
|
? "ag-icon-prefix-hide"
|
||||||
|
: "ag-icon-prefix-show";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
mounted() {
|
||||||
|
if (Array.isArray(this.value)&&this.range){
|
||||||
|
this.dateArr = [this.value[0] || "", this.value[1] || ""];
|
||||||
|
} else {
|
||||||
|
this.dateArr = this.value;
|
||||||
|
}
|
||||||
|
for(const key in this.$refs.datepickerref){
|
||||||
|
if(!this[key]&&key!='value'){
|
||||||
|
this[key]=this.$refs.datepickerref[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
value: {
|
value: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (Array.isArray(newVal)&&this.range){
|
||||||
|
this.dateArr = [newVal[0] || "", newVal[1] || ""];
|
||||||
|
} else {
|
||||||
|
this.dateArr = newVal;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
dateArr: {
|
||||||
handler(newVal) {
|
handler(newVal) {
|
||||||
if (!Array.isArray(newVal)) {
|
if(!newVal){
|
||||||
throw new Error("agDatePicker date请传入数组");
|
return
|
||||||
}
|
}
|
||||||
console.log(newVal,'newVal');
|
let defaultWidth = this.range ?this.showTime?"330px":"200px" : this.showTime?"190px":"150px";
|
||||||
|
this.width = defaultWidth;
|
||||||
newVal.length > 0 &&
|
|
||||||
newVal.some(
|
|
||||||
(item) => item !== null && item !== undefined && item !== ""
|
|
||||||
)
|
|
||||||
? (this.width = "205px")
|
|
||||||
: (this.width = "160px");
|
|
||||||
let [date1, date2] = newVal;
|
|
||||||
if (!this.dateArr) {
|
|
||||||
this.dateArr = [date1 || "", date2 || ""];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.$set(this.dateArr, 0, date1 || "");
|
|
||||||
this.$set(this.dateArr, 1, date2 || "");
|
|
||||||
},
|
},
|
||||||
immediate: true,
|
immediate: true,
|
||||||
deep: true,
|
deep: true,
|
||||||
|
@ -154,7 +254,7 @@ export default {
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
::v-deep {
|
::v-deep {
|
||||||
[class*="el-icon-"] {
|
[class*="ag-icon-"] {
|
||||||
font-family: element-icons !important;
|
font-family: element-icons !important;
|
||||||
speak: none;
|
speak: none;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
|
@ -167,38 +267,35 @@ export default {
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
.el-range-editor.is-active:hover{
|
.el-input__icon,
|
||||||
border: #8a1818;
|
.ag-icon-prefix-show,
|
||||||
}
|
.ag-iconfont,
|
||||||
.el-input__icon.el-range__close-icon {
|
.ag-icon-clear {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
font-size: 12px;
|
width: 16px !important;
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
right: 5px;
|
|
||||||
&:hover {
|
|
||||||
border-radius: 50%;
|
|
||||||
color: #c0c4cc;
|
|
||||||
background: #ecedee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.ag-el-icon-prefix {
|
|
||||||
width: 16px;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
margin-left: -5px;
|
margin-left: -5px;
|
||||||
line-height: 38px;
|
line-height: 1 !important;
|
||||||
|
right: 6px;
|
||||||
|
top: 1px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.el-input__prefix {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 8px;
|
left: 98%;
|
||||||
top: 0;
|
}
|
||||||
|
.ag-icon-clear {
|
||||||
|
&:before {
|
||||||
|
content: "\e6db";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ag-icon-prefix-show {
|
||||||
&:before {
|
&:before {
|
||||||
content: "\e78e";
|
content: "\e78e";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ag-icon-prefix-hide {
|
||||||
.el-icon-circle-close:before {
|
display: none;
|
||||||
content: "\e6db";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agForm from './src'
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agForm.install = function (Vue) {
|
||||||
|
Vue.component(agForm.name, agForm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agForm;
|
|
@ -0,0 +1,191 @@
|
||||||
|
<template>
|
||||||
|
<el-form v-bind="$attrs" v-on="$listeners" :model="formValue" ref="formref">
|
||||||
|
<ag-row>
|
||||||
|
<ag-col v-for="item,index in data" :key="index" :span="item.span||24">
|
||||||
|
<el-form-item v-bind="item" :prop="item.enName" >
|
||||||
|
<slot :name="item.soltName" v-if="item.soltName" :row="item"/>
|
||||||
|
<div class="contentbox" v-else>
|
||||||
|
<ag-input v-model="formValue[item.enName]" type="textarea" v-bind="item" v-if="item.type=='ag-textarea'" size="small" clearable></ag-input>
|
||||||
|
<ag-input v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-input'" size="small" clearable></ag-input>
|
||||||
|
<ag-date-picker v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-date-picker'" size="small" clearable/>
|
||||||
|
<ag-select v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-select'" size="small" clearable/>
|
||||||
|
<el-radio-group v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-radio'&&formValue[item.enName]" size="small" clearable>
|
||||||
|
<el-radio :label="it.value" v-for="it,index in item.options" :key="index">{{it.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<el-checkbox-group v-bind="item" v-if="item.type=='ag-checkbox'&&formValue[item.enName]" v-model="formValue[item.enName]" size="small" clearable>
|
||||||
|
<el-checkbox v-for="it,index in item.options" :label="it.value" :key="index">{{it.label}}</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
<el-input-number v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-input-number'" clearable></el-input-number>
|
||||||
|
<el-cascader v-model="formValue[item.enName]" v-bind="item" size="small" v-if="item.type=='ag-cascader'" clearable :style="{width:'100%'}"></el-cascader>
|
||||||
|
<el-switch
|
||||||
|
v-model="formValue[item.enName]"
|
||||||
|
v-bind="item" size="small" v-if="item.type=='ag-switch'&&formValue[item.enName]" >
|
||||||
|
</el-switch>
|
||||||
|
<el-slider v-model="formValue[item.enName]"
|
||||||
|
v-bind="item" size="small" v-if="item.type=='ag-slider'"></el-slider>
|
||||||
|
<el-time-select
|
||||||
|
:style="{width:'100%'}"
|
||||||
|
clearable
|
||||||
|
v-model="formValue[item.enName]"
|
||||||
|
v-bind="item" size="small"
|
||||||
|
v-if="item.type=='ag-time-select'"
|
||||||
|
:picker-options="item.options">
|
||||||
|
</el-time-select>
|
||||||
|
<ag-upload v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-upload'" clear isPre></ag-upload>
|
||||||
|
<el-rate v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-rate'" size="small"></el-rate>
|
||||||
|
<agColorPicker v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-color-picker'" size="small">
|
||||||
|
</agColorPicker>
|
||||||
|
<el-transfer :data="item.data" v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-transfer'" size="small"></el-transfer>
|
||||||
|
<agNumberRange v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-numberRange'" size="small" clearable/>
|
||||||
|
<ag-multion-input v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-multion-input'" size="small" clearable/>
|
||||||
|
<agQuery v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-query'" size="small" clearable/>
|
||||||
|
<ag-mution-checkbox :datas="item.datas" v-bind="item" :placeholder="item.placeholder" v-model="formValue[item.enName]" v-if="item.type=='ag-mution-checkbox'" size="small"> </ag-mution-checkbox>
|
||||||
|
<ag-multion-date-picker v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-multion-datte-picker'" size="small"/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</ag-col>
|
||||||
|
</ag-row>
|
||||||
|
<div class="footerbox" v-if="$listeners.onSubmit">
|
||||||
|
<slot name="button" :value="formValue">
|
||||||
|
<el-button @click="onSubmit" type="primary" size="small" class="submitbtn">
|
||||||
|
{{submittitle||'提交'}}
|
||||||
|
</el-button>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
import agInput from './../../agInput/src/index.vue';
|
||||||
|
import agDatePicker from './../../agDatePicker/src/index.vue';
|
||||||
|
import agSelect from './../../agSelect/src/index.vue';
|
||||||
|
import agRow from './../../agRow/src/index.vue';
|
||||||
|
import agCol from './../../agCol/src/index.vue';
|
||||||
|
import agUpload from './../../agUpload/src/index.vue';
|
||||||
|
import agColorPicker from './../../agColorPicker/src/index.vue';
|
||||||
|
import agNumberRange from './../../agNumberRange/src/index.vue';
|
||||||
|
import agMultionInput from './../../agMultionInput/src/index.vue';
|
||||||
|
import agQuery from './../../agQuery/src/index.vue';
|
||||||
|
import agMultionDatePicker from '../../agMultionDatePicker';
|
||||||
|
|
||||||
|
|
||||||
|
export default{
|
||||||
|
name:"agForm",
|
||||||
|
components:{
|
||||||
|
agMultionDatePicker,
|
||||||
|
agInput:agInput,
|
||||||
|
agDatePicker,
|
||||||
|
agSelect,
|
||||||
|
agRow,
|
||||||
|
agCol,
|
||||||
|
agUpload:agUpload,
|
||||||
|
agColorPicker,
|
||||||
|
agNumberRange,
|
||||||
|
agMultionInput,
|
||||||
|
agQuery
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
submittitle:{
|
||||||
|
type:String,
|
||||||
|
default:'提交'
|
||||||
|
},
|
||||||
|
data:{
|
||||||
|
type:Array,
|
||||||
|
default(){
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
span:{
|
||||||
|
type:Number,
|
||||||
|
default:24
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return{
|
||||||
|
formValue:{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
this.formValue=this.$attrs.value;
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.$refs.formref.clearValidate();
|
||||||
|
},1);
|
||||||
|
if(this.$refs.formref){
|
||||||
|
for(const key in this.$refs.formref){
|
||||||
|
if(!this[key]&&key!='value'){
|
||||||
|
this[key]=this.$refs.formref[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
value(val){
|
||||||
|
this.formValue = val;
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.$refs.formref.clearValidate();
|
||||||
|
},1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
onSubmit(){
|
||||||
|
this.$emit('onSubmit',this.formValue)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.footerbox{
|
||||||
|
margin-top:12px;
|
||||||
|
display:flex;
|
||||||
|
justify-content:center;
|
||||||
|
.submitbtn{
|
||||||
|
width:200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-form--inline{
|
||||||
|
.el-form-item{
|
||||||
|
display:flex;
|
||||||
|
}
|
||||||
|
.el-form-item__content{
|
||||||
|
flex:1;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.contentbox{
|
||||||
|
width:100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
.flexcenter{
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
::v-deep{
|
||||||
|
.el-form--inline{
|
||||||
|
.el-form-item{
|
||||||
|
display:flex;
|
||||||
|
}
|
||||||
|
.el-form-item__content{
|
||||||
|
display:flex;
|
||||||
|
flex:1;
|
||||||
|
width:100%;
|
||||||
|
margin-left:0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-form-item{
|
||||||
|
width:100%;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.el-form-item__content{
|
||||||
|
flex:1;
|
||||||
|
display:flex;
|
||||||
|
width:100%;
|
||||||
|
margin-left:0!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,22 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<el-input
|
<el-input
|
||||||
class="ag_input"
|
class="ag_input"
|
||||||
:style="{ width }"
|
:size="$attrs.size||'small'"
|
||||||
v-on="inputListeners"
|
ref="apinputref"
|
||||||
v-bind="attrs"
|
:style="{ width }"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="$listeners"
|
||||||
>
|
>
|
||||||
<slot name="append" slot="append" />
|
<slot v-for="(_,name) in $slots" :name="name" :slot="name"> </slot>
|
||||||
<slot name="prefix" slot="prefix" />
|
|
||||||
<slot name="suffix" slot="suffix" />
|
|
||||||
<slot name="prepend" slot="prepend" />
|
|
||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
/**
|
|
||||||
* WInput
|
|
||||||
* @desc 处理输入的输入框(转大写,不能有中文空格等)
|
|
||||||
*/
|
|
||||||
export default {
|
export default {
|
||||||
name: "agInput",
|
name: "agInput",
|
||||||
props: {
|
props: {
|
||||||
|
@ -26,67 +21,25 @@ export default {
|
||||||
},
|
},
|
||||||
toUpperCase: {
|
toUpperCase: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true,
|
default: false,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
if(this.$refs.apinputref){
|
||||||
|
for(const key in this.$refs.apinputref){
|
||||||
|
if(!this[key]&&key!='value'){
|
||||||
|
this[key]=this.$refs.apinputref[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
attrs() {
|
|
||||||
return {
|
|
||||||
size: "small",
|
|
||||||
clearable: true, // 默认清空
|
|
||||||
...this.$attrs,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
// 所有父级事件
|
|
||||||
inputListeners() {
|
|
||||||
return Object.assign(
|
|
||||||
{},
|
|
||||||
// 我们从父级添加所有的监听器
|
|
||||||
this.$listeners,
|
|
||||||
// 然后我们添加自定义监听器,
|
|
||||||
// 或覆写一些监听器的行为
|
|
||||||
{
|
|
||||||
// 这里确保组件配合 `v-model` 的工作
|
|
||||||
input: (value) => {
|
|
||||||
this.$emit("input", this.toUpperCase ? value.toUpperCase() : value);
|
|
||||||
},
|
|
||||||
blur: (e) => {
|
|
||||||
let value = e.target.value
|
|
||||||
.trim()
|
|
||||||
.replace(/\s/g, (match) =>
|
|
||||||
match.charCodeAt(0) === 12288 ? String.fromCharCode(32) : match
|
|
||||||
);
|
|
||||||
|
|
||||||
// 失去焦点自动首位去空格
|
|
||||||
this.$emit("input", value);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
::v-deep {
|
::v-deep {
|
||||||
.el-input__suffix {
|
.el-input__icon {
|
||||||
// @include sjf;
|
font-size: 16px !important;
|
||||||
.el-input__suffix-inner {
|
|
||||||
.el-input__icon {
|
|
||||||
font-size: 12px;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
// @include cj1;
|
|
||||||
right: 5px;
|
|
||||||
&:hover {
|
|
||||||
border-radius: 50%;
|
|
||||||
color: #c0c4cc;
|
|
||||||
background: #ecedee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.el-icon-circle-close:before {
|
.el-icon-circle-close:before {
|
||||||
content: "\e6db";
|
content: "\e6db";
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agMultionDatePicker from './src';
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agMultionDatePicker.install = function (Vue) {
|
||||||
|
Vue.component(agMultionDatePicker.name, agMultionDatePicker)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agMultionDatePicker;
|
|
@ -0,0 +1,238 @@
|
||||||
|
<template>
|
||||||
|
<div class="ag-MultifunctionSearch">
|
||||||
|
<ag-select
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="listeners"
|
||||||
|
:options="$attrs.options||[]"
|
||||||
|
:value="value&&value[0]"
|
||||||
|
@change="onSelect"
|
||||||
|
class="ag_select_group"
|
||||||
|
:style="{ width: `${swidth}px` }"
|
||||||
|
>
|
||||||
|
</ag-select>
|
||||||
|
|
||||||
|
<ag-date-picker
|
||||||
|
class="ag_input_group"
|
||||||
|
:placeholder="$attrs.placeholder||'请选择时间'"
|
||||||
|
:disabled="$attrs.disabled"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="listeners"
|
||||||
|
:value="value[1]"
|
||||||
|
@change="onInputChange"
|
||||||
|
>
|
||||||
|
</ag-date-picker>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import agSelect from "../../agSelect/src/index.vue";
|
||||||
|
import agDatePicker from "../../agDatePicker/src/index.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "agMultionDatePicker",
|
||||||
|
components: {
|
||||||
|
agSelect,
|
||||||
|
agDatePicker,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
default: () => {
|
||||||
|
return [null, []];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
values: [null, []],
|
||||||
|
swidth:100,
|
||||||
|
inputValue:"",
|
||||||
|
selectvalue:"",
|
||||||
|
imeipopover:false,
|
||||||
|
listeners:{}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'value', // 明确指定 prop 为 'value'
|
||||||
|
event: 'change' // 自定义事件名,用于更新 value
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (!Array.isArray(newVal)) {
|
||||||
|
throw new Error("请传入数组");
|
||||||
|
}
|
||||||
|
let newselectValue=newVal[0];
|
||||||
|
const find=this.$attrs.options&&this.$attrs.options.find((f)=>f.value==newselectValue);
|
||||||
|
if(find){
|
||||||
|
let fontwidth=this.getStringWidth(find.label);
|
||||||
|
this.swidth=fontwidth>165?165:fontwidth;
|
||||||
|
}else{
|
||||||
|
this.swidth=100;
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
let newlist=Object.assign({},this.$listeners);
|
||||||
|
delete newlist.change;
|
||||||
|
delete newlist.input;
|
||||||
|
this.listeners=newlist;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSelect(value){
|
||||||
|
if(this.$listeners.change){
|
||||||
|
this.$emit("change", [value, this.value[1]||[]]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onInputChange(val){
|
||||||
|
if(this.$listeners.change){
|
||||||
|
this.$emit("change", [this.value[0] ||"",val]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getStringWidth(text) {
|
||||||
|
let font = "13px";
|
||||||
|
// 创建一个隐藏的元素
|
||||||
|
let element = document.createElement('span');
|
||||||
|
element.style.visibility = 'hidden';
|
||||||
|
element.style.whiteSpace = 'nowrap';
|
||||||
|
element.style.font = font; // 设置字体样式
|
||||||
|
element.textContent = text;
|
||||||
|
// 将元素添加到文档中
|
||||||
|
document.body.appendChild(element);
|
||||||
|
// 获取元素的宽度
|
||||||
|
let width = element.offsetWidth;
|
||||||
|
// 移除元素
|
||||||
|
document.body.removeChild(element);
|
||||||
|
return width+50;
|
||||||
|
},
|
||||||
|
imeiiconClick(){
|
||||||
|
this.imeipopover=!this.imeipopover;
|
||||||
|
},
|
||||||
|
|
||||||
|
imeiclose(){
|
||||||
|
this.imeipopover=false;
|
||||||
|
},
|
||||||
|
cleartext(){
|
||||||
|
this.value[1]=[];
|
||||||
|
this.$set(this.value,1,[]);
|
||||||
|
},
|
||||||
|
search(){
|
||||||
|
this.imeipopover=false;
|
||||||
|
if(this.$listeners.onSrarch){
|
||||||
|
this.$emit("onSrarch", this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
getAfterAgo(attr, prefix) {
|
||||||
|
const config = {};
|
||||||
|
for (const key in attr) {
|
||||||
|
if (attr.hasOwnProperty(key) && key.startsWith(prefix)) {
|
||||||
|
const newKey = key.substring(prefix.length);
|
||||||
|
config[newKey] = attr[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.popperOptions {
|
||||||
|
min-width: 200px !important;
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.ag-MultifunctionSearch {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imeiicondefault {
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #f0f2f5;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.imeiiconActive {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #409eff;
|
||||||
|
background: #e9f1fc;
|
||||||
|
}
|
||||||
|
.divider {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btnbox {
|
||||||
|
padding: 5px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep{
|
||||||
|
.ag_select_group{
|
||||||
|
.el-input__inner{
|
||||||
|
border:1px solid #e5e5e5;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
outline:none;
|
||||||
|
&:focus{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-range-editor.is-active, .el-range-editor.is-active:hover, .el-select .el-input.is-focus .el-input__inner{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
.el-range-editor.el-input__inner{
|
||||||
|
border:1px solid #e5e5e5;
|
||||||
|
border-left:0px;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-left:none;
|
||||||
|
outline:none;
|
||||||
|
&:focus{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ag_input_group{
|
||||||
|
.el-input__inner{
|
||||||
|
border:1px solid #e5e5e5;
|
||||||
|
border-left:0px;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-left:none;
|
||||||
|
outline:none;
|
||||||
|
&:focus{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-select{
|
||||||
|
.el-input{
|
||||||
|
&.is-focus{
|
||||||
|
.el-input__inner{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
.el-input__inner{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-textarea__inner{
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
.el-input__suffix-inner{
|
||||||
|
height:100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agMultionInput from './src'
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agMultionInput.install = function (Vue) {
|
||||||
|
Vue.component(agMultionInput.name, agMultionInput)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agMultionInput
|
|
@ -0,0 +1,294 @@
|
||||||
|
<template>
|
||||||
|
<div class="ag-MultifunctionSearch">
|
||||||
|
<ag-select
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="listeners"
|
||||||
|
:options="$attrs.options||[]"
|
||||||
|
:value="value&&value[0]"
|
||||||
|
@change="onSelect"
|
||||||
|
class="ag_select_group"
|
||||||
|
:style="{ width: `${swidth+20}px` }"
|
||||||
|
>
|
||||||
|
</ag-select>
|
||||||
|
<ag-input
|
||||||
|
v-if="!showExtra"
|
||||||
|
class="ag_input_group"
|
||||||
|
:placeholder="$attrs.placeholder||'请输入内容'"
|
||||||
|
:disabled="$attrs.disabled||imeipopover"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="listeners"
|
||||||
|
:value="value[1]"
|
||||||
|
@input="onInputChange"
|
||||||
|
|
||||||
|
>
|
||||||
|
<template slot="prefix" >
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</ag-input>
|
||||||
|
<el-popover
|
||||||
|
v-if="showExtra"
|
||||||
|
placement="bottom"
|
||||||
|
trigger="manual"
|
||||||
|
ref="popover"
|
||||||
|
popper-class="popperOptions"
|
||||||
|
v-model="imeipopover"
|
||||||
|
>
|
||||||
|
<template slot="reference">
|
||||||
|
<ag-input
|
||||||
|
class="ag_input_group"
|
||||||
|
:placeholder="$attrs.placeholder||'请输入内容'"
|
||||||
|
:disabled="$attrs.disabled||imeipopover"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="listeners"
|
||||||
|
:value="value&&value[1]"
|
||||||
|
@input="onInputChange"
|
||||||
|
>
|
||||||
|
<template slot="suffix" v-if="showExtra">
|
||||||
|
<i
|
||||||
|
class="iconfont icon-icon-piliangcaozuo imeiicondefault"
|
||||||
|
:class="imeipopover && 'imeiiconActive'"
|
||||||
|
style="font-size: 12px;"
|
||||||
|
@click.prevent="imeiiconClick"
|
||||||
|
></i>
|
||||||
|
</template>
|
||||||
|
</ag-input>
|
||||||
|
</template>
|
||||||
|
<el-input
|
||||||
|
type="textarea"
|
||||||
|
:rows="12"
|
||||||
|
:value="value&&value[1]"
|
||||||
|
placeholder="一行一项,最多支持200行"
|
||||||
|
resize="none"
|
||||||
|
border="none"
|
||||||
|
class="textareainput"
|
||||||
|
@input="onInputChange"
|
||||||
|
/>
|
||||||
|
<divider class="divider"></divider>
|
||||||
|
<div class="btnbox">
|
||||||
|
<div>
|
||||||
|
<el-button size="mini" @click="imeiclose"
|
||||||
|
>关闭</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<el-button size="mini" @click="cleartext"
|
||||||
|
>清空</el-button
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
size="mini"
|
||||||
|
type="primary"
|
||||||
|
plain
|
||||||
|
@click="search"
|
||||||
|
>查询</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import agSelect from "../../agSelect/src/index.vue";
|
||||||
|
import agInput from "../../agInput/src/index.vue";
|
||||||
|
import {Divider} from "element-ui";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "agMultionInput",
|
||||||
|
components: {
|
||||||
|
agSelect,
|
||||||
|
agInput,
|
||||||
|
Divider
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [null, ''];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
showExtra: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
values: [null, ""],
|
||||||
|
swidth:120,
|
||||||
|
inputValue:"",
|
||||||
|
selectvalue:"",
|
||||||
|
imeipopover:false,
|
||||||
|
listeners:{}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'value', // 明确指定 prop 为 'value'
|
||||||
|
event: 'change' // 自定义事件名,用于更新 value
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value: {
|
||||||
|
handler(newVal) {
|
||||||
|
if (!Array.isArray(newVal)) {
|
||||||
|
throw new Error("请传入数组");
|
||||||
|
}
|
||||||
|
let newselectValue=newVal[0];
|
||||||
|
const find=newselectValue&&newselectValue!=""&&this.$attrs.options&&this.$attrs.options.find((f)=>f.value==newselectValue);
|
||||||
|
if(find){
|
||||||
|
let fontwidth=this.getStringWidth(find.label);
|
||||||
|
this.swidth=fontwidth>165?165:fontwidth;
|
||||||
|
}else{
|
||||||
|
this.swidth=120;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
let newlist=Object.assign({},this.$listeners);
|
||||||
|
delete newlist.change;
|
||||||
|
delete newlist.input;
|
||||||
|
this.listeners=newlist;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onSelect(value){
|
||||||
|
if(this.$listeners.change){
|
||||||
|
this.$emit("change", [value||"", this.value[1]||""]);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
onInputChange(val){
|
||||||
|
if(this.$listeners.change){
|
||||||
|
this.$emit("change", [this.value[0]||"",val]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getStringWidth(text) {
|
||||||
|
let font = "13px";
|
||||||
|
// 创建一个隐藏的元素
|
||||||
|
let element = document.createElement('span');
|
||||||
|
element.style.visibility = 'hidden';
|
||||||
|
element.style.whiteSpace = 'nowrap';
|
||||||
|
element.style.font = font; // 设置字体样式
|
||||||
|
element.textContent = text;
|
||||||
|
// 将元素添加到文档中
|
||||||
|
document.body.appendChild(element);
|
||||||
|
// 获取元素的宽度
|
||||||
|
let width = element.offsetWidth;
|
||||||
|
// 移除元素
|
||||||
|
document.body.removeChild(element);
|
||||||
|
return width+50;
|
||||||
|
},
|
||||||
|
imeiiconClick(){
|
||||||
|
this.imeipopover=!this.imeipopover;
|
||||||
|
},
|
||||||
|
|
||||||
|
imeiclose(){
|
||||||
|
this.imeipopover=false;
|
||||||
|
},
|
||||||
|
cleartext(){
|
||||||
|
this.value[1]="";
|
||||||
|
this.$set(this.value,1,"");
|
||||||
|
},
|
||||||
|
search(){
|
||||||
|
this.imeipopover=false;
|
||||||
|
if(this.$listeners.onSrarch){
|
||||||
|
this.$emit("onSrarch", this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
getAfterAgo(attr, prefix) {
|
||||||
|
const config = {};
|
||||||
|
for (const key in attr) {
|
||||||
|
if (attr.hasOwnProperty(key) && key.startsWith(prefix)) {
|
||||||
|
const newKey = key.substring(prefix.length);
|
||||||
|
config[newKey] = attr[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.popperOptions {
|
||||||
|
min-width: 200px !important;
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.ag-MultifunctionSearch {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imeiicondefault {
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #f0f2f5;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.imeiiconActive {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #409eff;
|
||||||
|
background: #e9f1fc;
|
||||||
|
}
|
||||||
|
.divider {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btnbox {
|
||||||
|
padding: 5px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep{
|
||||||
|
|
||||||
|
.ag_select_group{
|
||||||
|
.el-input__inner{
|
||||||
|
border:1px solid #e5e5e5;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
outline:none;
|
||||||
|
&:focus{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ag_input_group{
|
||||||
|
.el-input__inner{
|
||||||
|
border:1px solid #e5e5e5;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-left:none;
|
||||||
|
outline:none;
|
||||||
|
&:focus{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-select{
|
||||||
|
.el-input{
|
||||||
|
&.is-focus{
|
||||||
|
.el-input__inner{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
.el-input__inner{
|
||||||
|
border-color:#e5e5e5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-textarea__inner{
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
.el-input__suffix-inner{
|
||||||
|
height:100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agMutionCheckbox from './src';
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agMutionCheckbox.install = function (Vue) {
|
||||||
|
Vue.component(agMutionCheckbox.name, agMutionCheckbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agMutionCheckbox;
|
|
@ -0,0 +1,430 @@
|
||||||
|
<template>
|
||||||
|
<div class="ag-multion-checkbox">
|
||||||
|
<el-dropdown
|
||||||
|
size="small"
|
||||||
|
trigger="click"
|
||||||
|
ref="multioncheckref"
|
||||||
|
@click.native="checkeddown"
|
||||||
|
:class="{ 'el-dropdown_active': !down }"
|
||||||
|
@visible-change="dropdownchange"
|
||||||
|
>
|
||||||
|
<span class="el-dropdown-link">
|
||||||
|
<span>
|
||||||
|
<span :class="{ color: checkedList.length }">{{ checkedList.length==0?placeholder||'请选择':dropdownvalue }}</span
|
||||||
|
><span class="list-length" v-if="valuelength >= 1"
|
||||||
|
>+ {{ valuelength }}</span
|
||||||
|
></span
|
||||||
|
><i
|
||||||
|
v-if="dropdownvalue == ''"
|
||||||
|
class="el-icon-arrow-up el-icon--right"
|
||||||
|
:class="{ 'rotate-arrow': down }"
|
||||||
|
></i>
|
||||||
|
<i v-else class="el-icon-close el-icon--right" @click.stop.prevent="clear"></i>
|
||||||
|
</span>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-input
|
||||||
|
placeholder="请输入内容"
|
||||||
|
v-model="seek"
|
||||||
|
size="small"
|
||||||
|
class="el_input"
|
||||||
|
@input="inputblur"
|
||||||
|
@keydown.enter.prevent="confirm()"
|
||||||
|
>
|
||||||
|
<i slot="prefix" class="el-input__icon el-icon-search"></i>
|
||||||
|
</el-input>
|
||||||
|
<div v-if="dataList && dataList.length" class="checkbox-group">
|
||||||
|
<div v-if="dataList && dataList.length > 1" class="all-checked">
|
||||||
|
<el-checkbox
|
||||||
|
:indeterminate="isIndeterminate"
|
||||||
|
v-model="checkAll"
|
||||||
|
@change="handleCheckAllChange"
|
||||||
|
>全选</el-checkbox
|
||||||
|
>
|
||||||
|
/
|
||||||
|
<span class="invertstatus" @click="handleCheckAllChange(!checkAll)">反选</span>
|
||||||
|
</div>
|
||||||
|
<el-checkbox-group
|
||||||
|
class="checked-list"
|
||||||
|
:class="{ 'top-height': dataList && dataList.length <= 1 }"
|
||||||
|
v-model="checkedList"
|
||||||
|
@change="handleCheckedCitiesChange"
|
||||||
|
>
|
||||||
|
<div v-for="(el, id) in dataList" :key="id" class="setScore">
|
||||||
|
<el-checkbox :label="el.value">{{ el.label }}</el-checkbox>
|
||||||
|
<span @click="confirm(el, 'only')">仅筛选此项</span>
|
||||||
|
</div>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</div>
|
||||||
|
<div v-else class="nothing">暂无数据</div>
|
||||||
|
<div class="btnbox">
|
||||||
|
<div>
|
||||||
|
<el-button size="mini" @click="cancel">取消</el-button>
|
||||||
|
<el-button size="mini" type="primary" plain @click="confirm()"
|
||||||
|
>确定</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { nextTick } from 'vue';
|
||||||
|
export default {
|
||||||
|
props: ["datas", "placeholder", "value"],
|
||||||
|
name: "AgMutionCheckbox",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
seek: "",
|
||||||
|
dropdownvalue:"",
|
||||||
|
valuelength: 0,
|
||||||
|
down: true,
|
||||||
|
checkAll: false,
|
||||||
|
checkedList: [],
|
||||||
|
dataList: [
|
||||||
|
|
||||||
|
], //渲染数据
|
||||||
|
isIndeterminate: false,
|
||||||
|
retract: false,
|
||||||
|
olddatas:[
|
||||||
|
],
|
||||||
|
oldvalue:[]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'value', // 明确指定 prop 为 'value'
|
||||||
|
event: 'onSearch' // 自定义事件名,用于更新 value
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if(this.datas&&Array.isArray(this.datas)){
|
||||||
|
this.dataList = this.datas;
|
||||||
|
this.olddatas=Object.assign([],this.datas);
|
||||||
|
this.checkedList = []; //清空旧值-解决出现累加问题
|
||||||
|
if (this.checkAll && this.dataList) {
|
||||||
|
this.checkedList=this.dataList.map((e) =>e.value);
|
||||||
|
this.confirm();
|
||||||
|
}
|
||||||
|
if(this.value){
|
||||||
|
this.checkedList=this.value;
|
||||||
|
const filters=this.olddatas.filter((f)=>{
|
||||||
|
return this.checkedList.find((c)=>c==f.value);
|
||||||
|
});
|
||||||
|
if(filters.length>0){
|
||||||
|
const [onedatas,...otherdatas]=filters;
|
||||||
|
this.valuelength=otherdatas.length;
|
||||||
|
this.dropdownvalue=onedatas.label;
|
||||||
|
if(filters.length==this.olddatas.length){
|
||||||
|
this.checkAll=true;
|
||||||
|
this.isIndeterminate=false;
|
||||||
|
}else{
|
||||||
|
this.checkAll=false;
|
||||||
|
this.isIndeterminate=true;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.valuelength=0;
|
||||||
|
this.dropdownvalue="";
|
||||||
|
this.checkAll=false;
|
||||||
|
this.isIndeterminate=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.olddatas=Object.assign([],this.dataList);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
datas: {
|
||||||
|
handler(val) {
|
||||||
|
if(val&&Array.isArray(val)){
|
||||||
|
this.dataList = val;
|
||||||
|
this.olddatas=Object.assign([],val);
|
||||||
|
this.checkedList = []; //清空旧值-解决出现累加问题
|
||||||
|
if (this.checkAll&&this.dataList) {
|
||||||
|
this.checkedList=this.dataList.map((e) =>e.value);
|
||||||
|
this.confirm();
|
||||||
|
}
|
||||||
|
if(this.value){
|
||||||
|
this.checkedList=this.value;
|
||||||
|
const filters=this.olddatas.filter((f)=>{
|
||||||
|
return this.checkedList.find((c)=>c==f.value);
|
||||||
|
});
|
||||||
|
if(filters.length>0){
|
||||||
|
const [onedatas,...otherdatas]=filters;
|
||||||
|
this.valuelength=otherdatas.length;
|
||||||
|
this.dropdownvalue=onedatas.label;
|
||||||
|
if(filters.length==this.olddatas.length){
|
||||||
|
this.checkAll=true;
|
||||||
|
this.isIndeterminate=false;
|
||||||
|
}else{
|
||||||
|
this.checkAll=false;
|
||||||
|
this.isIndeterminate=true;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.valuelength=0;
|
||||||
|
this.dropdownvalue="";
|
||||||
|
this.checkAll=false;
|
||||||
|
this.isIndeterminate=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else{
|
||||||
|
this.olddatas=Object.assign([],this.dataList);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
clear(){
|
||||||
|
this.checkedList = [];
|
||||||
|
this.valuelength=0;
|
||||||
|
this.dropdownvalue="";
|
||||||
|
this.isIndeterminate = false;
|
||||||
|
this.checkAll=false;
|
||||||
|
this.nextTick(()=>{
|
||||||
|
this.$refs.multioncheckref.hide();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
checkeddown(val){
|
||||||
|
this.oldvalue={list:this.checkedList,checkAll:this.checkAll,isIndeterminate:this.isIndeterminate};
|
||||||
|
},
|
||||||
|
dropdownchange(){
|
||||||
|
this.down = !this.down;
|
||||||
|
},
|
||||||
|
inputblur(val){
|
||||||
|
this.dataList=this.olddatas.filter((f)=>f.label.indexOf(val)>-1);
|
||||||
|
|
||||||
|
},
|
||||||
|
handleCheckAllChange(val){
|
||||||
|
this.checkedList = val ? this.olddatas.map((h)=>h.value) : [];
|
||||||
|
this.isIndeterminate = false;
|
||||||
|
this.checkAll=val;
|
||||||
|
},
|
||||||
|
confirm(e,type){
|
||||||
|
if(e&&type=="only"){
|
||||||
|
this.checkedList=[e.value];
|
||||||
|
if(this.olddatas.length!=1){
|
||||||
|
this.isIndeterminate=true;
|
||||||
|
this.checkAll=false;
|
||||||
|
}else{
|
||||||
|
this.isIndeterminate=false;
|
||||||
|
this.checkAll=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filters=this.olddatas.filter((f)=>{
|
||||||
|
return f.value==e.value
|
||||||
|
});
|
||||||
|
if(this.$listeners.onSearch){
|
||||||
|
this.$emit("onSearch",[e.value]);
|
||||||
|
}
|
||||||
|
if(filters.length==0){
|
||||||
|
this.valuelength=0;
|
||||||
|
this.dropdownvalue="";
|
||||||
|
this.$refs.multioncheckref.hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const [onedatas,...otherdatas]=filters;
|
||||||
|
this.valuelength=otherdatas.length;
|
||||||
|
this.dropdownvalue=onedatas.label;
|
||||||
|
}else{
|
||||||
|
if(this.checkedList.length==0){
|
||||||
|
this.valuelength=0;
|
||||||
|
this.dropdownvalue="";
|
||||||
|
if(this.$listeners.onSearch){
|
||||||
|
this.$emit("onSearch",this.checkedList);
|
||||||
|
}
|
||||||
|
this.$refs.multioncheckref.hide();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const filters=this.olddatas.filter((f)=>{
|
||||||
|
return this.checkedList.find((c)=>c==f.value);
|
||||||
|
});
|
||||||
|
const [onedatas,...otherdatas]=filters;
|
||||||
|
this.valuelength=otherdatas.length;
|
||||||
|
this.dropdownvalue=onedatas.label;
|
||||||
|
if(this.$listeners.onSearch){
|
||||||
|
this.$emit("onSearch",this.checkedList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$refs.multioncheckref.hide();
|
||||||
|
},
|
||||||
|
handleCheckedCitiesChange(val){
|
||||||
|
if(val.length>0){
|
||||||
|
if(val.length==this.olddatas.length){
|
||||||
|
this.isIndeterminate = false;
|
||||||
|
this.checkAll=true;
|
||||||
|
}else{
|
||||||
|
this.isIndeterminate = true;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.isIndeterminate = false;
|
||||||
|
this.checkAll=false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cancel(){
|
||||||
|
this.checkedList=this.oldvalue.list;
|
||||||
|
this.isIndeterminate=this.oldvalue.isIndeterminate;
|
||||||
|
this.checkAll=this.oldvalue.checkAll;
|
||||||
|
|
||||||
|
this.$refs.multioncheckref.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
::v-deep .el_input {
|
||||||
|
padding: 0 10px;
|
||||||
|
.el-input__inner {
|
||||||
|
border-radius: 0px;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
}
|
||||||
|
.el-input__inner:hover {
|
||||||
|
border-bottom: 1px solid #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-dropdown {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border: 1px solid #dcdfe6;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dropdown:hover {
|
||||||
|
border: 1px solid #c0c4cc;
|
||||||
|
}
|
||||||
|
.el-dropdown_active {
|
||||||
|
border: 1px solid #409eff;
|
||||||
|
}
|
||||||
|
.el-dropdown_active:hover {
|
||||||
|
border: 1px solid #409eff;
|
||||||
|
}
|
||||||
|
.el-icon-arrow-up {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
.rotate-arrow {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dropdown-menu {
|
||||||
|
min-width: 400px;
|
||||||
|
padding: 10px 0 0 0;
|
||||||
|
}
|
||||||
|
.checkbox-group {
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 5px 0px 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.all-checked {
|
||||||
|
span {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.invertstatus:hover {
|
||||||
|
color: #409eff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.checked-list {
|
||||||
|
max-height: 180px;
|
||||||
|
margin-top:5px;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 5px 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.top-height {
|
||||||
|
margin-top: 0px;
|
||||||
|
}
|
||||||
|
.el-checkbox-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.el-checkbox {
|
||||||
|
margin-right: 0px !important;
|
||||||
|
padding: 5px 0px 5px 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.btnbox {
|
||||||
|
padding: 5px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: right;
|
||||||
|
border-top: 1px solid #dcdfe6;
|
||||||
|
}
|
||||||
|
.el-dropdown-link {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
height:100%;
|
||||||
|
min-width: 180px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #c0c4cc;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.list-length {
|
||||||
|
padding: 3px 7px;
|
||||||
|
margin-left: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #33333379;
|
||||||
|
background-color: #dcdfe6;
|
||||||
|
}
|
||||||
|
.color {
|
||||||
|
color: #333;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
:focus-visible {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.nothing {
|
||||||
|
min-height: 80px;
|
||||||
|
line-height: 80px;
|
||||||
|
text-align: center;
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
|
.el-icon-close {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.el-icon-close:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
.setScore {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
span {
|
||||||
|
display: none;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
padding: 0 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
::v-deep .el-checkbox {
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setScore:hover {
|
||||||
|
background-color: rgba(192, 196, 204, 0.267);
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
color: #409eff;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,4 +1,4 @@
|
||||||
import agNumberRange from './src'
|
import agNumberRange from './src';
|
||||||
|
|
||||||
// 为组件提供 install 安装方法,供按需引入
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
agNumberRange.install = function (Vue) {
|
agNumberRange.install = function (Vue) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
@input="handleStartInput"
|
@input="handleStartInput"
|
||||||
@blur="handleInputBlur"
|
@blur="handleInputBlur"
|
||||||
></el-input>
|
></el-input>
|
||||||
<span class="separator">{{ rangeSeparator }}</span>
|
<span class="separator">{{ rangeSeparator||'-'}}</span>
|
||||||
<el-input
|
<el-input
|
||||||
:style="{ width: width + 'px' }"
|
:style="{ width: width + 'px' }"
|
||||||
:size="size"
|
:size="size"
|
||||||
|
@ -49,7 +49,7 @@ export default {
|
||||||
// 输入框宽度
|
// 输入框宽度
|
||||||
width: {
|
width: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
default: "50",
|
default: "60",
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -64,8 +64,8 @@ export default {
|
||||||
endValue: "",
|
endValue: "",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
comments: {
|
mounted() {
|
||||||
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(newValue) {
|
value(newValue) {
|
||||||
|
@ -115,4 +115,8 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.separator {
|
||||||
|
margin: 0 5px;
|
||||||
|
color: #c0c4cc;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agQuery from './src'
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agQuery.install = function (Vue) {
|
||||||
|
Vue.component(agQuery.name, agQuery)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agQuery;
|
|
@ -0,0 +1,163 @@
|
||||||
|
<template>
|
||||||
|
<div class="ag-querybox">
|
||||||
|
<el-popover
|
||||||
|
placement="bottom"
|
||||||
|
:width="width"
|
||||||
|
v-model="popState"
|
||||||
|
trigger="click">
|
||||||
|
<ag-input slot="reference" size="small" class="queryplacetext" :style="{width:labelWidth}" :clearable="false" :value="placeholderValue" :placeholder="placeholder"></ag-input>
|
||||||
|
<el-form label-position="left" size="small" :model="values" :inline="false" v-if="inputs.length>0" ref="queryformref">
|
||||||
|
<ag-row>
|
||||||
|
<ag-col :span="12" v-for="(item,index) in inputs" :key="index">
|
||||||
|
<el-form-item :label="item.label" :rules="item.rules" :prop="item.name">
|
||||||
|
<ag-select :placeholder="item.placeholder" :value="item.value||''" closeable :options="item.options" style="width:100%" @change="onSelect($event,item,index)"/>
|
||||||
|
</el-form-item>
|
||||||
|
</ag-col>
|
||||||
|
</ag-row>
|
||||||
|
<div class="footerbox">
|
||||||
|
<el-button size="small" @click="onCancel">取消</el-button>
|
||||||
|
<el-button size="small" type="primary" @click="onQuery">查询</el-button>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</el-popover>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import agSelect from "../../agSelect/src/index.vue";
|
||||||
|
import agInput from "../../agInput/src/index.vue";
|
||||||
|
import agRow from "./../../agRow/src/index.vue";
|
||||||
|
import AgCol from "./../../agCol/src/index.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "agQuery",
|
||||||
|
components: {
|
||||||
|
agSelect,
|
||||||
|
agInput,
|
||||||
|
AgCol,
|
||||||
|
agRow
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
width:{
|
||||||
|
type: Number,
|
||||||
|
default: 450,
|
||||||
|
},
|
||||||
|
labelWidth:{
|
||||||
|
type: Number,
|
||||||
|
default: 200,
|
||||||
|
},
|
||||||
|
inputs:{
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {
|
||||||
|
lazyLoad (node, resolve) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'values', // 明确指定 prop 为 'value'
|
||||||
|
event: 'onSearch' // 自定义事件名,用于更新 value
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
let newinput=this.inputs.map((g)=>g.label);
|
||||||
|
this.placeholder="请选择"+newinput.join("/");
|
||||||
|
if(this.props.lazyLoad){
|
||||||
|
this.props.lazyLoad({level:0,pathLabels:this.values,value:""},(datas)=>{
|
||||||
|
this.inputs[index+1].options=datas;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
values: {},
|
||||||
|
placeholderValue:"",
|
||||||
|
placeholder:"请选择",
|
||||||
|
popState:false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onReset(){
|
||||||
|
this.values={};
|
||||||
|
this.$emit('onSearch',this.values);
|
||||||
|
},
|
||||||
|
onSelect(value,item,index){
|
||||||
|
item.value=value;
|
||||||
|
this.$set(this.inputs,index,item);
|
||||||
|
let newvalues={};
|
||||||
|
|
||||||
|
let newplaceholderValue=[];
|
||||||
|
this.inputs.map((g)=>{
|
||||||
|
if(g.value&&g.name){
|
||||||
|
newvalues[g.name]=g.value;
|
||||||
|
g.options.find((f)=>f.value==g.value).label&&(newplaceholderValue.push(g.options.find((f)=>f.value==g.value).label));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.values=newvalues;
|
||||||
|
if(this.$listeners.change){
|
||||||
|
this.$emit('change',newvalues);
|
||||||
|
}
|
||||||
|
if(this.props.lazyLoad){
|
||||||
|
this.props.lazyLoad({level:index+1,pathLabels:newvalues,value},(datas)=>{
|
||||||
|
this.inputs[index+1].options=datas;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.placeholderValue=newplaceholderValue.join("/")
|
||||||
|
},
|
||||||
|
onCancel(){
|
||||||
|
this.popState=false;
|
||||||
|
if(this.$listeners.onCancel){
|
||||||
|
this.$emit('onCancel');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onQuery(){
|
||||||
|
if(this.$refs.queryformref){
|
||||||
|
this.$refs.queryformref.validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
this.$emit('onSearch',this.values);
|
||||||
|
this.popState=false;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang='scss'>
|
||||||
|
.ag-querybox {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.queryplacetext{
|
||||||
|
color:#333;
|
||||||
|
max-width:200px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
caret-color: transparent; /* 隐藏光标 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.footerbox{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top:5px;
|
||||||
|
}
|
||||||
|
::v-deep {
|
||||||
|
.el-form-item--small .el-form-item__label{
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
.el-form-item--small.el-form-item{
|
||||||
|
margin-bottom:5px;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agRow from './src'
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agRow.install = function (Vue) {
|
||||||
|
Vue.component(agRow.name, agRow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agRow;
|
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<div class="agRowbox">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'agRow',
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.agRowbox{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agSearch from './src';
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agSearch.install = function (Vue) {
|
||||||
|
Vue.component(agSearch.name, agSearch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agSearch;
|
|
@ -0,0 +1,229 @@
|
||||||
|
<template>
|
||||||
|
<el-form v-bind="$attrs" v-on="$listeners" :model="formValue" ref="formref">
|
||||||
|
<ag-row class="searchbox">
|
||||||
|
<ag-col v-for="item,index in data" :key="index" :span="item.span||24">
|
||||||
|
<el-form-item :prop="item.enName" >
|
||||||
|
<slot :name="item.soltName" v-if="item.soltName" :row="item"/>
|
||||||
|
<div class="contentbox" v-else>
|
||||||
|
<ag-input v-model="formValue[item.enName]" type="textarea" v-bind="item" v-if="item.type=='ag-textarea'" size="small" clearable></ag-input>
|
||||||
|
<ag-input v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-input'" size="small" clearable></ag-input>
|
||||||
|
<ag-date-picker v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-date-picker'" size="small" clearable/>
|
||||||
|
<ag-select v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-select'" size="small" clearable/>
|
||||||
|
<el-radio-group v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-radio'&&formValue[item.enName]" size="small" clearable>
|
||||||
|
<el-radio :label="it.value" v-for="it,index in item.options" :key="index">{{it.label}}</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
<el-checkbox-group v-bind="item" v-if="item.type=='ag-checkbox'&&formValue[item.enName]" v-model="formValue[item.enName]" size="small" clearable>
|
||||||
|
<el-checkbox v-for="it,index in item.options" :label="it.value" :key="index">{{it.label}}</el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
<el-input-number v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-input-number'" clearable></el-input-number>
|
||||||
|
<el-cascader v-model="formValue[item.enName]" v-bind="item" size="small" v-if="item.type=='ag-cascader'" clearable :style="{width:'100%'}"></el-cascader>
|
||||||
|
<el-switch
|
||||||
|
v-model="formValue[item.enName]"
|
||||||
|
v-bind="item" size="small" v-if="item.type=='ag-switch'&&formValue[item.enName]" >
|
||||||
|
</el-switch>
|
||||||
|
<el-slider v-model="formValue[item.enName]"
|
||||||
|
v-bind="item" size="small" v-if="item.type=='ag-slider'"></el-slider>
|
||||||
|
<el-time-select
|
||||||
|
:style="{width:'100%'}"
|
||||||
|
clearable
|
||||||
|
v-model="formValue[item.enName]"
|
||||||
|
v-bind="item" size="small"
|
||||||
|
v-if="item.type=='ag-time-select'"
|
||||||
|
:picker-options="item.options">
|
||||||
|
</el-time-select>
|
||||||
|
<ag-upload v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-upload'" clear isPre></ag-upload>
|
||||||
|
<el-rate v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-rate'" size="small"></el-rate>
|
||||||
|
<agColorPicker v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-color-picker'" size="small">
|
||||||
|
</agColorPicker>
|
||||||
|
<el-transfer :data="item.data" v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-transfer'" size="small"></el-transfer>
|
||||||
|
<agNumberRange v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-numberRange'" size="small" clearable/>
|
||||||
|
<ag-multion-input v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-multion-input'" size="small" clearable/>
|
||||||
|
<agQuery v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-query'" size="small" clearable/>
|
||||||
|
<ag-mution-checkbox :datas="item.datas" v-bind="item" :placeholder="item.placeholder" v-model="formValue[item.enName]" v-if="item.type=='ag-mution-checkbox'" size="small"> </ag-mution-checkbox>
|
||||||
|
<ag-multion-date-picker v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-multion-datte-picker'" size="small"/>
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
|
</ag-col>
|
||||||
|
<ag-col :span="4">
|
||||||
|
<el-button @click="onSubmit" type="primary" size="small" class="submitbtn">
|
||||||
|
{{submittitle||'查询'}}
|
||||||
|
</el-button>
|
||||||
|
<el-button @click="onRest" size="small" class="submitbtn">
|
||||||
|
重置
|
||||||
|
</el-button>
|
||||||
|
</ag-col>
|
||||||
|
</ag-row>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
|
||||||
|
import agInput from './../../agInput/src/index.vue';
|
||||||
|
import agDatePicker from './../../agDatePicker/src/index.vue';
|
||||||
|
import agSelect from './../../agSelect/src/index.vue';
|
||||||
|
import agRow from './../../agRow/src/index.vue';
|
||||||
|
import agCol from './../../agCol/src/index.vue';
|
||||||
|
import agUpload from './../../agUpload/src/index.vue';
|
||||||
|
import agColorPicker from './../../agColorPicker/src/index.vue';
|
||||||
|
import agNumberRange from './../../agNumberRange/src/index.vue';
|
||||||
|
import agMultionInput from './../../agMultionInput/src/index.vue';
|
||||||
|
import agQuery from './../../agQuery/src/index.vue';
|
||||||
|
import agMultionDatePicker from '../../agMultionDatePicker';
|
||||||
|
|
||||||
|
|
||||||
|
export default{
|
||||||
|
name:"agSearch",
|
||||||
|
components:{
|
||||||
|
agMultionDatePicker,
|
||||||
|
agInput:agInput,
|
||||||
|
agDatePicker,
|
||||||
|
agSelect,
|
||||||
|
agRow,
|
||||||
|
agCol,
|
||||||
|
agUpload:agUpload,
|
||||||
|
agColorPicker,
|
||||||
|
agNumberRange,
|
||||||
|
agMultionInput,
|
||||||
|
agQuery
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
submittitle:{
|
||||||
|
type:String,
|
||||||
|
default:'查询'
|
||||||
|
},
|
||||||
|
data:{
|
||||||
|
type:Array,
|
||||||
|
default(){
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
span:{
|
||||||
|
type:Number,
|
||||||
|
default:24
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return{
|
||||||
|
formValue:{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
model:{
|
||||||
|
prop:'value',
|
||||||
|
event:{
|
||||||
|
'onSubmit':'submit',
|
||||||
|
'onRest':'rest'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted(){
|
||||||
|
this.formValue=this.$attrs.value;
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.$refs.formref.clearValidate();
|
||||||
|
},1);
|
||||||
|
if(this.$refs.formref){
|
||||||
|
for(const key in this.$refs.formref){
|
||||||
|
if(!this[key]&&key!='value'){
|
||||||
|
this[key]=this.$refs.formref[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
value(val){
|
||||||
|
this.formValue = val;
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.$refs.formref.clearValidate();
|
||||||
|
},1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
onSubmit(){
|
||||||
|
if(this.$listeners.onSearch){
|
||||||
|
this.$emit('onSearch',this.formValue);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onRest(){
|
||||||
|
Object.keys(this.formValue).map((key,index)=>{
|
||||||
|
let itemvalue=Object.values(this.formValue)[index];
|
||||||
|
if(typeof(itemvalue)=="string"||typeof(itemvalue)=="number"){
|
||||||
|
this.formValue[key]=null;
|
||||||
|
}else{
|
||||||
|
this.formValue[key]=[];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setTimeout(()=>{
|
||||||
|
this.$refs.formref.clearValidate();
|
||||||
|
},1);
|
||||||
|
if(this.$listeners.onRest){
|
||||||
|
this.$emit('onRest',this.formValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.searchbox{
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.footerbox{
|
||||||
|
margin-top:12px;
|
||||||
|
display:flex;
|
||||||
|
justify-content:center;
|
||||||
|
.submitbtn{
|
||||||
|
width:200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-form--inline{
|
||||||
|
.el-form-item{
|
||||||
|
display:flex;
|
||||||
|
}
|
||||||
|
.el-form-item__content{
|
||||||
|
flex:1;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.contentbox{
|
||||||
|
width:100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
.flexcenter{
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
::v-deep{
|
||||||
|
.el-form--inline{
|
||||||
|
.el-form-item{
|
||||||
|
display:flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
.el-form-item__content{
|
||||||
|
display:flex;
|
||||||
|
flex:1;
|
||||||
|
width:100%;
|
||||||
|
margin-left:0;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-form-item{
|
||||||
|
width:100%;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
line-height:1;
|
||||||
|
}
|
||||||
|
.el-form-item__content{
|
||||||
|
flex:1;
|
||||||
|
display:flex;
|
||||||
|
width:100%;
|
||||||
|
align-items: center;
|
||||||
|
margin-left:0!important;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
line-height:1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,20 +1,21 @@
|
||||||
<template>
|
<template>
|
||||||
<el-select
|
<el-select
|
||||||
class="ag_select"
|
class="ag_select"
|
||||||
:style="{ width }"
|
:style="{ width: `100%` }"
|
||||||
v-bind="attrs"
|
:value="selectValue"
|
||||||
v-on="inputListeners"
|
ref="apselectref"
|
||||||
>
|
:size="$attrs.size||'small'"
|
||||||
<slot />
|
v-bind="$attrs"
|
||||||
<slot name="prefix" slot="prefix" />
|
v-on="$listeners"
|
||||||
<slot name="empty" slot="empty" />
|
>
|
||||||
<el-option
|
<slot v-for="(_,name) in $slots" :name="name" :slot="name"> </slot>
|
||||||
v-for="item in options"
|
<el-option
|
||||||
:key="item.value"
|
v-for="item in options"
|
||||||
:label="item.label"
|
:key="item.value"
|
||||||
:value="item.value"
|
:label="item.label"
|
||||||
></el-option>
|
:value="item.value"
|
||||||
</el-select>
|
></el-option>
|
||||||
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -22,79 +23,60 @@ export default {
|
||||||
name: "agSelect",
|
name: "agSelect",
|
||||||
props: {
|
props: {
|
||||||
width: {
|
width: {
|
||||||
type: String,
|
type: Number,
|
||||||
default: "",
|
default:0,
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => {
|
default: () => {
|
||||||
return [];
|
return [];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
value:{
|
||||||
|
default: () =>'',
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {};
|
return {
|
||||||
|
selectValue:""
|
||||||
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
mounted(){
|
||||||
attrs() {
|
if(this.$refs.apselectref){
|
||||||
return {
|
for(const key in this.$refs.apselectref){
|
||||||
size: "small",
|
if(!this[key]&&key!='value'){
|
||||||
remote: true,
|
this[key]=this.$refs.apselectref[key];
|
||||||
clearable: true,
|
}
|
||||||
filterable: true,
|
}
|
||||||
...this.$attrs,
|
}
|
||||||
};
|
},
|
||||||
},
|
watch: {
|
||||||
// 所有父级事件
|
value: {
|
||||||
inputListeners() {
|
handler(newVal) {
|
||||||
return Object.assign(
|
let newselectValue=newVal;
|
||||||
{},
|
const find=this.options.find((f)=>f.value==newselectValue);
|
||||||
// 我们从父级添加所有的监听器
|
if(find){
|
||||||
this.$listeners,
|
this.selectValue=newselectValue;
|
||||||
// 然后我们添加自定义监听器,
|
}else{
|
||||||
// 或覆写一些监听器的行为
|
this.selectValue="";
|
||||||
{
|
}
|
||||||
// 这里确保组件配合 `v-model` 的工作
|
},
|
||||||
input: (value) => {
|
immediate: true,
|
||||||
this.$emit("input", this.toUpperCase ? value.toUpperCase() : value);
|
},
|
||||||
},
|
},
|
||||||
blur: (e) => {
|
methods: {
|
||||||
let value = e.target.value
|
|
||||||
.trim()
|
|
||||||
.replace(/\s/g, (match) =>
|
|
||||||
match.charCodeAt(0) === 12288 ? String.fromCharCode(32) : match
|
|
||||||
);
|
|
||||||
// 失去焦点自动首位去空格
|
|
||||||
this.$emit("input", value);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
::v-deep {
|
::v-deep {
|
||||||
.el-input__inner {
|
.ag_select{
|
||||||
width: none;
|
min-width: 90px;
|
||||||
|
width:100%;
|
||||||
}
|
}
|
||||||
.el-input__suffix {
|
.el-input__icon {
|
||||||
.el-input__suffix-inner {
|
font-size: 16px !important;
|
||||||
.el-input__icon {
|
|
||||||
font-size: 12px;
|
|
||||||
width: 14px;
|
|
||||||
height: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
right: 5px;
|
|
||||||
&:hover {
|
|
||||||
border-radius: 50%;
|
|
||||||
color: #c0c4cc;
|
|
||||||
background: #ecedee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.el-icon-circle-close:before {
|
.el-icon-circle-close:before {
|
||||||
content: "\e6db";
|
content: "\e6db";
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agTable from './src';
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agTable.install = function (Vue) {
|
||||||
|
Vue.component(agTable.name, agTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agTable;
|
|
@ -0,0 +1,90 @@
|
||||||
|
<template>
|
||||||
|
<div class="agtablebox">
|
||||||
|
<el-table v-bind="$attrs" v-on="$listeners" :data="data" size="small" :header-cell-style="$attrs.headerCellStyle||{backgroundColor:'#f7f7f7'}" ref="tableref">
|
||||||
|
<el-table-column v-for="item,index in columns" :key="index" v-bind="item">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div v-if="item.soltName">
|
||||||
|
<slot :name="item.soltName" :row="scope.row" >
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
{{scope.row[item.prop]}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="agtablefooter">
|
||||||
|
<el-pagination
|
||||||
|
ref="paginationref"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
:current-page.sync="currentPage"
|
||||||
|
:page-sizes="pageSizes||[10,100,200,500]"
|
||||||
|
:page-size="pageSize"
|
||||||
|
layout="sizes,prev, pager, next, jumper"
|
||||||
|
:total="total">
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "agTable",
|
||||||
|
props:["columns","data",'pageSize','currentPage','total','pageSizes'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
for(const key in this.$refs.tableref){
|
||||||
|
if(!this[key]&&key!='value'){
|
||||||
|
this[key]=this.$refs.tableref[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(const key in this.$refs.paginationref){
|
||||||
|
if(!this[key]&&key!='value'&&key!='pageSizes'){
|
||||||
|
this[key]=this.$refs.paginationref[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSizeChange(e){
|
||||||
|
if(this.$listeners.onSizeChange){
|
||||||
|
this.$emit('onSizeChange',e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleCurrentChange(e){
|
||||||
|
if(this.$listeners.onCurrentChange){
|
||||||
|
this.$emit('onCurrentChange',e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.agtablebox{
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
height:100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.agtablefooter{
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding:12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::v-deep {
|
||||||
|
.el-table {
|
||||||
|
width: 100%;
|
||||||
|
height:100%;
|
||||||
|
}
|
||||||
|
.el-table__empty-block{
|
||||||
|
min-height:300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -6,4 +6,4 @@ agTabs.install = function (Vue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出组件
|
// 导出组件
|
||||||
export default agTabs
|
export default agTabs;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<el-tabs class="ag-tabs" v-bind="$attrs" v-on="$listeners">
|
<el-tabs class="ag-tabs" v-bind="$attrs" v-on="$listeners" ref="tabsref">
|
||||||
<slot v-if="!tabsData.length" name="default" />
|
<slot v-if="!tabsData.length" name="default" />
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
v-else
|
v-else
|
||||||
|
@ -31,6 +31,13 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
for(const key in this.$refs.tabsref){
|
||||||
|
if(!this[key]&&key!='value'){
|
||||||
|
this[key]=this.$refs.tabsref[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import agUpload from './src'
|
||||||
|
|
||||||
|
// 为组件提供 install 安装方法,供按需引入
|
||||||
|
agUpload.install = function (Vue) {
|
||||||
|
Vue.component(agUpload.name, agUpload)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出组件
|
||||||
|
export default agUpload;
|
|
@ -0,0 +1,692 @@
|
||||||
|
<template>
|
||||||
|
<div class="uploadbox">
|
||||||
|
<div class="uploadimgbox" :style="{height:width+'px'}" v-if="listType=='picture-card'">
|
||||||
|
<div v-for="img,index in imageList" :key="index" :style="{width:width+'px'}" :draggable="dragmove" class="imgitem" :class="dragmove&&dragmoveclass" @dragstart="onDragstart" @dragenter="onDragenter" @dragover="onDragover" @dragend="onDragend" @dragleave="onMouseup" >
|
||||||
|
<slot name="file" :file="img">
|
||||||
|
<img :src="img.url" class="img" v-if="img.type.indexOf('image')>-1"/>
|
||||||
|
<div v-else class="filetext">
|
||||||
|
<div class="filetitletext">文件</div>
|
||||||
|
<div>{{img.name}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="uploadimgmask" v-if="clear||isPrew" >
|
||||||
|
<i class="el-icon-search" v-if="isPrew&&img.type.indexOf('image')>-1" @click="handlePictureCardPreview(img)"></i>
|
||||||
|
<i class="el-icon-delete" v-if="clear" @click="handleRemove(img.raw,index)"></i>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<div class="uploadcontain" :style="{height:width+'px',aspectRatio:isDrap?4/3:1/1}"
|
||||||
|
:draggable="isDrap"
|
||||||
|
@dragover.prevent
|
||||||
|
@dragenter.prevent
|
||||||
|
@drop="onUploadDrap"
|
||||||
|
v-if="limit>imageList.length">
|
||||||
|
<label for="uploadinput" class="uploadlabel" @click="onInputClick">
|
||||||
|
<slot>
|
||||||
|
<i class="el-icon-plus"></i>
|
||||||
|
<span class="draptiptext">{{isDrap?'拖拽上传':'上传'}}</span>
|
||||||
|
</slot>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="uploadtextbox" v-if="listType=='text'||listType=='picture'">
|
||||||
|
<div class="uploadtextcontain"
|
||||||
|
:draggable="isDrap"
|
||||||
|
@dragover.prevent
|
||||||
|
@dragenter.prevent
|
||||||
|
@drop="onUploadDrap"
|
||||||
|
>
|
||||||
|
<label for="uploadinput" class="uploadlabel" @click="onInputClick" >
|
||||||
|
<slot>
|
||||||
|
<el-button type="primary" size="small"><i class="el-icon-plus"></i> {{isDrap?'拖拽上传':'上传'}}</el-button>
|
||||||
|
</slot>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<slot name="tip">
|
||||||
|
</slot>
|
||||||
|
<ul class="uploadtextlist" :class="'upload-list--'+listType">
|
||||||
|
<li v-for="img,index in imageList" :key="index" class="uploadtextitem" >
|
||||||
|
<div class="ag-upload-list__item-namebox" @click="handlePictureCardPreview(img)">
|
||||||
|
<slot name="icon">
|
||||||
|
<i class="el-icon-document ag-icon-document"></i>
|
||||||
|
</slot>
|
||||||
|
<slot name="file" :file="img">
|
||||||
|
<img v-if="listType=='picture'" :src="img.url" class="ag-upload-list__item-thumbnail" />
|
||||||
|
<a class="ag-upload-list__item-name" >{{img.name}}</a>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<div class="uploadrightbox">
|
||||||
|
<slot name="status" :file="img">
|
||||||
|
<span class="uploadstatusbpx">
|
||||||
|
<i v-if="img.status==='uploading'" class="el-icon-loading uploadingicon" ></i>
|
||||||
|
<i v-if="img.status==='success'" class="el-icon-circle-check statusicon"></i>
|
||||||
|
<i v-if="img.status==='failed'" class="el-icon-circle-close failedicon"></i>
|
||||||
|
<span v-if="img.msg" class="uploadmsg">{{img.msg}}</span>
|
||||||
|
</span>
|
||||||
|
</slot>
|
||||||
|
<el-popconfirm
|
||||||
|
:title="`确定移除${img.name}吗?`"
|
||||||
|
@confirm="handleRemove(img.raw,index)"
|
||||||
|
>
|
||||||
|
<i class="el-icon-close ag-icon-close" slot="reference"></i>
|
||||||
|
</el-popconfirm>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<input type="file" style="display:none;" :multiple="limit>1&&$attrs.multiple" :accept="$attrs.accept" id="uploadinput" @change="onUpdate" ref="fileinputref"/>
|
||||||
|
<el-dialog :visible.sync="dialogVisible">
|
||||||
|
<img width="100%" :src="dialogImageUrl" alt="">
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "agUpload",
|
||||||
|
props:{
|
||||||
|
isPrew:{
|
||||||
|
type:Boolean,
|
||||||
|
default:true
|
||||||
|
},
|
||||||
|
clear:{
|
||||||
|
type:Boolean,
|
||||||
|
default:true
|
||||||
|
},
|
||||||
|
width:{
|
||||||
|
type:Number,
|
||||||
|
default:80
|
||||||
|
},
|
||||||
|
dragmove:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
isDrap:{
|
||||||
|
type:Boolean,
|
||||||
|
default:false
|
||||||
|
},
|
||||||
|
limit:{
|
||||||
|
type:Number,
|
||||||
|
default:1
|
||||||
|
},
|
||||||
|
|
||||||
|
fileList:{
|
||||||
|
type:Array,
|
||||||
|
default(){
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
listType:{
|
||||||
|
type:String,
|
||||||
|
default:'picture-card'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'fileList', // 明确指定 prop 为 'value'
|
||||||
|
event: 'onUpload' // 自定义事件名,用于更新 value
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if(this.fileList.length>0){
|
||||||
|
let list=[];
|
||||||
|
this.fileList.map((h)=>{
|
||||||
|
if(typeof(h)=='object'){
|
||||||
|
list.push(h);
|
||||||
|
}else{
|
||||||
|
let imgurl=h.split("/");
|
||||||
|
let filename=imgurl[imgurl.length-1];
|
||||||
|
let extarr=h.split(".");
|
||||||
|
let extname=extarr[extarr.length-1];
|
||||||
|
if(['jpg','jpeg','png','gif','svg'].indexOf(extname)>-1){
|
||||||
|
list.push({
|
||||||
|
name:filename,
|
||||||
|
url:h,
|
||||||
|
type:'image/'+extname.toLowerCase(),
|
||||||
|
raw:null
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
list.push({
|
||||||
|
name:filename,
|
||||||
|
url:h,
|
||||||
|
type:'other/'+extname.toLowerCase(),
|
||||||
|
raw:null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.imageList=list;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch:{
|
||||||
|
fileList(val){
|
||||||
|
if(val.length>0){
|
||||||
|
let list=[];
|
||||||
|
val.map((h)=>{
|
||||||
|
if(typeof(h)=='object'){
|
||||||
|
list.push(h);
|
||||||
|
}else{
|
||||||
|
let imgurl=h.split("/");
|
||||||
|
let filename=imgurl[imgurl.length-1];
|
||||||
|
let extarr=h.split(".");
|
||||||
|
let extname=extarr[extarr.length-1];
|
||||||
|
if(['jpg','jpeg','png','gif','svg'].indexOf(extname)>-1){
|
||||||
|
list.push({
|
||||||
|
name:filename,
|
||||||
|
url:h,
|
||||||
|
type:'image/'+extname.toLowerCase(),
|
||||||
|
raw:null
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
list.push({
|
||||||
|
name:filename,
|
||||||
|
url:h,
|
||||||
|
type:'other/'+extname.toLowerCase(),
|
||||||
|
raw:null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.imageList=list;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialogImageUrl: '',
|
||||||
|
dialogVisible: false,
|
||||||
|
imageList:[],
|
||||||
|
sourceNode:null,
|
||||||
|
partNode:null,
|
||||||
|
selectTop:false,
|
||||||
|
drag:false,
|
||||||
|
dragmoveclass:'imghover'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleRemove(file,index) {
|
||||||
|
this.imageList=this.imageList.filter((item,inkey)=>{
|
||||||
|
return inkey !== index;
|
||||||
|
});
|
||||||
|
this.$emit('onRemove',file,this.imageList);
|
||||||
|
},
|
||||||
|
handlePictureCardPreview(file) {
|
||||||
|
if(file.type.indexOf('image/')>-1){
|
||||||
|
this.dialogImageUrl = file.url;
|
||||||
|
this.dialogVisible = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onUpdate(e){
|
||||||
|
if(this.limit<=this.imageList.length){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
let uplist=[];
|
||||||
|
let files=[...e.target.files].slice(0,this.limit-this.imageList.length);
|
||||||
|
const find=files.find((f,i)=>{
|
||||||
|
if(this.$attrs.accept){
|
||||||
|
let acceptarr=this.$attrs.accept.split(",");
|
||||||
|
if(!acceptarr.includes(f.type)){
|
||||||
|
if(this.$listeners.onError){
|
||||||
|
this.$emit('onError',`其中第${i+1}张文件类型错误`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(this.$attrs.maxSize){
|
||||||
|
if(f.size>this.$attrs.maxSize){
|
||||||
|
if(this.$listeners.onError){
|
||||||
|
this.$emit('onError',`其中第${i+1}张文件大小不能超过${this.$attrs.maxSize/1024/1024}M"`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(find){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
files.map((item,index) => {
|
||||||
|
if(item.type.indexOf("image")>-1){
|
||||||
|
let filerender=new FileReader();
|
||||||
|
filerender.onload=function(e){
|
||||||
|
uplist.push({
|
||||||
|
name:item.name,
|
||||||
|
url:e.target.result,
|
||||||
|
type:item.type,
|
||||||
|
size:item.size,
|
||||||
|
raw:item,
|
||||||
|
status:'init',
|
||||||
|
msg:""
|
||||||
|
});
|
||||||
|
if(files.length==uplist.length){
|
||||||
|
if(this.$listeners.onUpload){
|
||||||
|
this.fileList.push(...uplist);
|
||||||
|
this.$emit('onUpload',this.fileList,uplist);
|
||||||
|
}else{
|
||||||
|
this.imageList.push(...uplist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
filerender.readAsDataURL(item);
|
||||||
|
}else{
|
||||||
|
uplist.push({
|
||||||
|
name:item.name,
|
||||||
|
type:item.type,
|
||||||
|
size:item.size,
|
||||||
|
raw:item,
|
||||||
|
status:'init',
|
||||||
|
msg:""
|
||||||
|
});
|
||||||
|
if(files.length==uplist.length){
|
||||||
|
if(this.$listeners.onUpload){
|
||||||
|
this.fileList.push(...uplist);
|
||||||
|
this.$emit('onUpload',this.fileList,uplist);
|
||||||
|
}else{
|
||||||
|
this.imageList.push(...uplist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}catch(err){
|
||||||
|
console.log(err,"uploaderr");
|
||||||
|
|
||||||
|
if(this.$listeners.onError){
|
||||||
|
this.$emit('onError',e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onDragstart(e){
|
||||||
|
this.sourceNode=e.target;
|
||||||
|
this.partNode=e.target.parentNode;
|
||||||
|
e.target.classList.add("tabsbg");
|
||||||
|
setTimeout(()=>{
|
||||||
|
e.target.classList.remove("tabsbg");
|
||||||
|
e.target.classList.add("moving");
|
||||||
|
},1);
|
||||||
|
},
|
||||||
|
onDragenter(e){
|
||||||
|
e.preventDefault();
|
||||||
|
if(!this.dragmove){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(this.partNode===e.target||e.target===this.sourceNode){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const childrens=[...this.partNode.children];
|
||||||
|
let thistarget=childrens.find((f)=>f==e.target);
|
||||||
|
if(!thistarget){
|
||||||
|
thistarget=e.target.parentNode;
|
||||||
|
}
|
||||||
|
if(!thistarget){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceIndex=childrens.indexOf(this.sourceNode);
|
||||||
|
const targetIndex=childrens.indexOf(thistarget);
|
||||||
|
if(sourceIndex<targetIndex){
|
||||||
|
this.partNode.insertBefore(this.sourceNode,thistarget.nextElementSibling);
|
||||||
|
}else{
|
||||||
|
this.partNode.insertBefore(this.sourceNode,thistarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
onDragover(e){
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
|
onMouseup(e){
|
||||||
|
e.preventDefault();
|
||||||
|
if(!this.dragmove){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(this.partNode===e.target||e.target===this.sourceNode){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.sourceNode.classList.remove("moving");
|
||||||
|
},
|
||||||
|
onDragend(e){
|
||||||
|
e.preventDefault();
|
||||||
|
if(!this.dragmove){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
e.target.classList.remove("moving");
|
||||||
|
e.target.classList.remove("tabsbg");
|
||||||
|
this.sourceNode.classList.remove("moving");
|
||||||
|
if(this.partNode===e.target||e.target===this.sourceNode){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const childrens=[...this.partNode.children];
|
||||||
|
|
||||||
|
const sourceIndex=childrens.indexOf(this.sourceNode);
|
||||||
|
const item = this.imageList.splice(sourceIndex, 1)[0];
|
||||||
|
this.imageList.splice(sourceIndex, 0, item);
|
||||||
|
this.sourceNode=null;
|
||||||
|
this.partNode=null;
|
||||||
|
},
|
||||||
|
onUploadDrap(e){
|
||||||
|
e.preventDefault(); // 阻止默认行为(打开文件)
|
||||||
|
e.stopPropagation(); // 停止事件冒泡
|
||||||
|
if(this.drap){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const files = event.dataTransfer.files;
|
||||||
|
this.onUpdate({target:{files: files}});
|
||||||
|
},
|
||||||
|
onInputClick(e){
|
||||||
|
e.preventDefault(); // 阻止默认行为(打开文件)
|
||||||
|
e.stopPropagation(); // 停止事件冒泡
|
||||||
|
this.$refs.fileinputref.click();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.uploadcontain{
|
||||||
|
position: relative;
|
||||||
|
width:100px;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
.uploadlabel{
|
||||||
|
font-size: 16px;
|
||||||
|
color:#97a8be;
|
||||||
|
display: block;
|
||||||
|
width:100%;
|
||||||
|
cursor: pointer;
|
||||||
|
height:100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
.draptiptext{
|
||||||
|
font-size:13px;
|
||||||
|
color:#666;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.uploadimgbox{
|
||||||
|
position: relative;
|
||||||
|
width: auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap:5px;
|
||||||
|
.imgitem{
|
||||||
|
position: relative;
|
||||||
|
width:100px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow: hidden;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
transition: all .3s;
|
||||||
|
&.imghover:hover{
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
&.tabsbg{
|
||||||
|
border-radius:6px 6px 0 0;
|
||||||
|
background:#fff;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
&.opcacityzero{
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
&.moving{
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
img{
|
||||||
|
display: block;
|
||||||
|
aspect-ratio: 1/1;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
.uploadimgmask{
|
||||||
|
position: absolute;
|
||||||
|
top:0;
|
||||||
|
display: none;
|
||||||
|
left: 0;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
background-color: rgba(0,0,0,.3);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap:6px;
|
||||||
|
z-index: 1;
|
||||||
|
i{
|
||||||
|
font-size: 20px;
|
||||||
|
color:#fff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
.uploadimgmask{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.filetext{
|
||||||
|
font-size:12px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
padding:5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
height:100%;
|
||||||
|
white-space: nowrap; /* 文本不换行 */
|
||||||
|
overflow: hidden; /* 隐藏溢出的内容 */
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
text-align: center;
|
||||||
|
.filetitletext{
|
||||||
|
font-size:15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.uploadtextbox{
|
||||||
|
.uploadtextcontain{
|
||||||
|
margin-bottom:7px;
|
||||||
|
.uploadtextcontaindefaultbtn{
|
||||||
|
display:flex;
|
||||||
|
align-items:center;
|
||||||
|
gap:5px;
|
||||||
|
background: #fff;
|
||||||
|
width:fit-content;
|
||||||
|
padding:5px 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-radius:4px;
|
||||||
|
font-size:13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.uploadtextlist{
|
||||||
|
display: block;
|
||||||
|
list-style-type: disc;
|
||||||
|
margin-inline-start: 0px;
|
||||||
|
margin-inline-end: 0px;
|
||||||
|
padding-inline-start: 40px;
|
||||||
|
unicode-bidi: isolate;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
margin-top:12px;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.upload-list--text{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
&:first-child{
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploadtextitem{
|
||||||
|
position: relative;
|
||||||
|
list-style: none;
|
||||||
|
transition: all .5s cubic-bezier(.55,0,.1,1);
|
||||||
|
font-size: 14px;
|
||||||
|
color: #606266;
|
||||||
|
line-height:1;
|
||||||
|
margin-top: 5px;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
padding: 5px 10px;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 100%;
|
||||||
|
&:hover{
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
.ag-icon-close{
|
||||||
|
display:inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ag-upload-list__item-namebox{
|
||||||
|
margin-right: 40px;
|
||||||
|
padding-left: 4px;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
.ag-upload-list__item-name{
|
||||||
|
text-decoration: none;
|
||||||
|
color: #606266;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
transition: color .3s;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-size: 14px;
|
||||||
|
|
||||||
|
.ag-icon-document{
|
||||||
|
height: 100%;
|
||||||
|
margin-right: 7px;
|
||||||
|
color: #909399;
|
||||||
|
line-height: inherit;
|
||||||
|
&:hover{
|
||||||
|
color: #409eff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-icon-close{
|
||||||
|
position: relative;
|
||||||
|
right: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: .75;
|
||||||
|
color: #606266;
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.upload-list--picture{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style: none;
|
||||||
|
.uploadtextitem{
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #c0ccda;
|
||||||
|
border-radius: 6px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px 10px 10px 90px;
|
||||||
|
height: 92px;
|
||||||
|
gap:10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover{
|
||||||
|
.ag-icon-close{
|
||||||
|
display:inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ag-upload-list__item-thumbnail{
|
||||||
|
vertical-align: middle;
|
||||||
|
display: inline-block;
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
float:left;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
margin-left: -80px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-upload-list__item-namebox{
|
||||||
|
margin-right: 40px;
|
||||||
|
padding-left: 4px;
|
||||||
|
line-height: 1.8;
|
||||||
|
}
|
||||||
|
.ag-upload-list__item-name{
|
||||||
|
flex:1;
|
||||||
|
color: #606266;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
transition: color .3s;
|
||||||
|
white-space: nowrap;
|
||||||
|
line-height: 70px;
|
||||||
|
font-size:14px;
|
||||||
|
margin-top: 0;
|
||||||
|
text-decoration: none;
|
||||||
|
.ag-icon-document{
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
color: #409eff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ag-icon-close{
|
||||||
|
position: absolute;
|
||||||
|
font-family: element-icons !important;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-variant: normal;
|
||||||
|
text-transform: none;
|
||||||
|
line-height: 1;
|
||||||
|
vertical-align: baseline;
|
||||||
|
display: none;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
line-height: 1;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: .75;
|
||||||
|
color: #606266;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.uploadrightbox{
|
||||||
|
display:flex;
|
||||||
|
justify-content:flex-end;
|
||||||
|
align-items: center;
|
||||||
|
.uploadstatusbpx{
|
||||||
|
margin-right: 7px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.uploadingicon{
|
||||||
|
color:#409eff;
|
||||||
|
}
|
||||||
|
.failedicon{
|
||||||
|
color:red;
|
||||||
|
}
|
||||||
|
.statusicon{
|
||||||
|
color:green;
|
||||||
|
}
|
||||||
|
.uploadmsg{
|
||||||
|
margin:0 7px;
|
||||||
|
}
|
||||||
|
::v-deep {
|
||||||
|
.el-table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,11 +1,45 @@
|
||||||
// 导入组件
|
// 导入组件
|
||||||
import agInput from './agInput/index'
|
import agInput from './agInput/index';
|
||||||
import agSelect from './agSelect/index'
|
import agSelect from './agSelect/index';
|
||||||
|
import agUpload from './agUpload';
|
||||||
|
import agForm from './agForm';
|
||||||
|
import agColorPicker from './agColorPicker';
|
||||||
|
import agQuery from './agQuery';
|
||||||
|
import agTable from './agTable';
|
||||||
|
import agTabs from './agTabs';
|
||||||
|
import agDialog from './agDialog';
|
||||||
|
import agPagination from './agPagination';
|
||||||
|
import agRow from './agRow';
|
||||||
|
import agCol from './agCol';
|
||||||
|
import agMutionCheckbox from './agMutionCheckbox';
|
||||||
|
import agSearch from './agSearch';
|
||||||
|
import agDatePicker from "./agDatePicker";
|
||||||
|
import agNumberRange from "./agNumberRange";
|
||||||
|
import agMultionDatePicker from "./agMultionDatePicker";
|
||||||
|
import agMultionInput from "./agMultionInput";
|
||||||
|
|
||||||
|
// 注册组件
|
||||||
|
|
||||||
// 组件列表
|
// 组件列表
|
||||||
const components = [
|
const components = [
|
||||||
agInput,
|
agInput,
|
||||||
agSelect
|
agSelect,
|
||||||
|
agUpload,
|
||||||
|
agForm,
|
||||||
|
agColorPicker,
|
||||||
|
agQuery,
|
||||||
|
agTable,
|
||||||
|
agDialog,
|
||||||
|
agTabs,
|
||||||
|
agPagination,
|
||||||
|
agCol,
|
||||||
|
agRow,
|
||||||
|
agDatePicker,
|
||||||
|
agMutionCheckbox,
|
||||||
|
agSearch,
|
||||||
|
agNumberRange,
|
||||||
|
agMultionDatePicker,
|
||||||
|
agMultionInput
|
||||||
]
|
]
|
||||||
|
|
||||||
// 定义 install 方法,接收 Vue 作为参数(使用 use 注册插件,那么所有的组件都会被注册)
|
// 定义 install 方法,接收 Vue 作为参数(使用 use 注册插件,那么所有的组件都会被注册)
|
||||||
|
@ -13,20 +47,20 @@
|
||||||
// 判断是否安装
|
// 判断是否安装
|
||||||
if (install.installed) return
|
if (install.installed) return
|
||||||
// 遍历注册全局组件
|
// 遍历注册全局组件
|
||||||
components.map(component => Vue.component(component.name, component))
|
components.forEach(component => {
|
||||||
|
Vue.component(component.name, component);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否是直接引入文件
|
// 判断是否是直接引入文件
|
||||||
if (typeof window !== 'undefined' && window.Vue) {
|
if (typeof window !== 'undefined' && window.Vue) {
|
||||||
install(window.Vue)
|
install(window.Vue)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
version:'2.15.14',
|
||||||
// 导出的对象必须具有 install,才能被 Vue.use() 方法安装
|
// 导出的对象必须具有 install,才能被 Vue.use() 方法安装
|
||||||
install,
|
install,
|
||||||
}
|
|
||||||
export {
|
|
||||||
// 以下是具体的组件列表
|
// 以下是具体的组件列表
|
||||||
agInput,
|
...components
|
||||||
agSelect
|
|
||||||
}
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||||
|
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_4285161_67f087o652k.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript>
|
||||||
|
|
333
src/App.vue
333
src/App.vue
|
@ -2,26 +2,153 @@
|
||||||
<div>
|
<div>
|
||||||
<el-button type="success" @click="abb = true">点击打开 Dialog</el-button>
|
<el-button type="success" @click="abb = true">点击打开 Dialog</el-button>
|
||||||
<ag-dialog :visible.sync="abb"> </ag-dialog>
|
<ag-dialog :visible.sync="abb"> </ag-dialog>
|
||||||
<ag-datePicker :value="values"> </ag-datePicker>
|
<ag-date-picker v-model="date_value" :showTime="true" :range="true" @change="onPicker">
|
||||||
<ag-input :visible.sync="abb"> </ag-input>
|
</ag-date-picker>
|
||||||
<ag-select :visible.sync="abb" :options="a_options" v-model="value">
|
|
||||||
|
<ag-input v-model="inputValue" placeholder="请输入" @change="onInputChange" ref="aginputref">
|
||||||
|
</ag-input>
|
||||||
|
<ag-select :options="a_options" v-model="value">
|
||||||
</ag-select>
|
</ag-select>
|
||||||
|
<ag-NumberRange v-model="values"> </ag-NumberRange>
|
||||||
|
<el-form
|
||||||
|
:model="ruleForm"
|
||||||
|
:rules="rules"
|
||||||
|
ref="ruleForm"
|
||||||
|
class="demo-ruleForm"
|
||||||
|
>
|
||||||
|
<el-form-item prop="pass">
|
||||||
|
<ag-CascadeOptional
|
||||||
|
size="small"
|
||||||
|
ref="ttt"
|
||||||
|
v-model="ruleForm.pass"
|
||||||
|
:after_clearable="true"
|
||||||
|
:ago_options="a_options"
|
||||||
|
>
|
||||||
|
</ag-CascadeOptional>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
<div class="div"><span>888</span></div>
|
<ag-multion-input
|
||||||
|
size="small"
|
||||||
|
ref="ttt"
|
||||||
|
v-model="values"
|
||||||
|
:showExtra="true"
|
||||||
|
:clearable="true"
|
||||||
|
:options="a_options"
|
||||||
|
@change="onInputinput"
|
||||||
|
@blur="onblur"
|
||||||
|
>
|
||||||
|
</ag-multion-input>
|
||||||
|
<ag-color-picker size="small" v-model="colorvalue"/>
|
||||||
|
<agQuery :inputs="inputs" @onSearch="onSearch"/>
|
||||||
|
<agTable :columns="columns" :data="tabledata" :currentPage="2" :pageSize="100" :total="500" >
|
||||||
|
<template #name="{row}">
|
||||||
|
<div>{{row.name}}11</div>
|
||||||
|
</template>
|
||||||
|
<template #date="{row}">
|
||||||
|
<div>{{row.date}} </div>
|
||||||
|
</template>
|
||||||
|
</agTable>
|
||||||
|
<agUpload @onUpload="onUpload" isDrap dragmove multiple :limit="5" @onError="onError" :maxSize="1024*1024" :value="filelist">
|
||||||
|
<div slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||||
|
</agUpload>
|
||||||
|
<ag-form :data="formdata" label-width="120px" label-position="left" v-model="formvalue">
|
||||||
|
</ag-form>
|
||||||
|
<ag-mution-checkbox :datas="checklist" @onSearch="onCheckSearch" v-model="checkvalue"> </ag-mution-checkbox>
|
||||||
|
|
||||||
|
<!-- <el-input agMultionCheckbox
|
||||||
|
size="small"
|
||||||
|
placeholder="请输入内容"
|
||||||
|
v-model="value"
|
||||||
|
class="input-with-select"
|
||||||
|
>
|
||||||
|
<el-select v-model="a_value" slot="prepend" size="small" placeholder="请选择">
|
||||||
|
<el-option label="餐厅名" value="1"></el-option>
|
||||||
|
<el-option label="订单号" value="2"></el-option>
|
||||||
|
<el-option label="用户电话" value="3"></el-option>
|
||||||
|
</el-select>
|
||||||
|
<el-button slot="append" icon="el-icon-search"></el-button>
|
||||||
|
</el-input> -->
|
||||||
|
<ag-multion-date-picker size="small"
|
||||||
|
ref="ttt"
|
||||||
|
v-model="datevalues"
|
||||||
|
:showExtra="true"
|
||||||
|
:clearable="true"
|
||||||
|
:range="true"
|
||||||
|
:options="a_options" />
|
||||||
|
<ag-search :data="searchdatas" v-model="searchvalue" @onRest="onRest" @onSearch="onSearch"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import agDialog from "../packages/agDialog/src/index.vue";
|
import ElementUI from 'element-ui';
|
||||||
import agDatePicker from "../packages/agDatePicker/src/index.vue";
|
import Vue from 'vue';
|
||||||
import agInput from "../packages/agInput/src/index.vue";
|
import agCascadeOptional from "../packages/agCascadeOptional/src/index.vue";
|
||||||
import agSelect from "../packages/agSelect/src/index.vue";
|
import vuedraggable from 'vuedraggable';
|
||||||
|
import agElemUI from "../packages/index.js";
|
||||||
|
|
||||||
|
|
||||||
|
Vue.use(ElementUI);
|
||||||
|
Vue.use(agElemUI);
|
||||||
|
// Vue.use(vuedraggable);
|
||||||
|
Vue.component('vuedraggable', window.vuedraggable)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { agDialog, agDatePicker, agInput, agSelect },
|
|
||||||
|
components: {
|
||||||
|
agCascadeOptional,
|
||||||
|
vuedraggable
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
|
var validatePass = (rule, value, callback) => {
|
||||||
|
for (const key in value) {
|
||||||
|
if (!value[key]) {
|
||||||
|
alert("错误");
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (value === "") {
|
||||||
|
// callback(new Error("请输入密码"));
|
||||||
|
// } else {
|
||||||
|
// if (this.ruleForm.checkPass !== "") {
|
||||||
|
// this.$refs.ruleForm.validateField("checkPass");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
value: "",
|
colorvalue:"#ffffff",
|
||||||
values: [],
|
ruleForm: {
|
||||||
|
pass: [],
|
||||||
|
},
|
||||||
|
columns:[
|
||||||
|
{soltName: "date", width:200,type:"expand" },
|
||||||
|
{soltName: "name", label: "姓名" },
|
||||||
|
{prop: "xinghao", label: "型号",width:120 },
|
||||||
|
{prop: "dianchi", label: "电池" ,width:500},
|
||||||
|
{prop: "pinpai", label: "品牌" ,width:200},
|
||||||
|
{prop: "address", label: "地址" ,fixed:'right',width:100}
|
||||||
|
],
|
||||||
|
tabledata:[
|
||||||
|
{date: "2016-05-02", name: "王小虎1", address: "上海市普陀区金沙江路 1518 弄"},
|
||||||
|
{date: "2016-05-03", name: "王小虎2", address: "上海市普陀区金沙江路 1518 弄"},
|
||||||
|
{date: "2016-05-04", name: "王小虎3", address: "上海市普陀区金沙江路 1518 弄"},
|
||||||
|
{date: "2016-05-05", name: "王小虎4", address: "上海市普陀区金沙江路 1518 弄"}
|
||||||
|
],
|
||||||
|
checklist:[
|
||||||
|
{label:"方法1",value:"1"},
|
||||||
|
{label:"方法2",value:"2"}
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
pass: [{ validator: validatePass, trigger: "blur" }],
|
||||||
|
},
|
||||||
|
inputValue:"",
|
||||||
|
date_value:null,
|
||||||
|
checkvalue:[],
|
||||||
|
value: "选项1",
|
||||||
|
a_value: "59584",
|
||||||
|
datevalues:["4",["2022-12-12","2022-12-13 "]],
|
||||||
|
values: ["4",""],
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: "热门城市",
|
label: "热门城市",
|
||||||
|
@ -58,6 +185,56 @@ export default {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
inputs:[
|
||||||
|
{
|
||||||
|
label:"分类",
|
||||||
|
elem:'el-select',
|
||||||
|
name:"class",
|
||||||
|
options:[
|
||||||
|
{
|
||||||
|
value: "Chengdu",
|
||||||
|
label: "成都",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "Shenzhen",
|
||||||
|
label: "深圳",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "Guangzhou",
|
||||||
|
label: "广州",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "Dalian",
|
||||||
|
label: "大连",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:"品牌",
|
||||||
|
elem:'el-select',
|
||||||
|
name:"brand",
|
||||||
|
placeholder:"请输入品牌",
|
||||||
|
options:[]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:"型号",
|
||||||
|
elem:'el-input',
|
||||||
|
name:"model",
|
||||||
|
options: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:"颜色",
|
||||||
|
elem:'el-select',
|
||||||
|
name:"color",
|
||||||
|
options:[]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label:"容量",
|
||||||
|
elem:'el-select',
|
||||||
|
name:"capacity",
|
||||||
|
options:[]
|
||||||
|
}
|
||||||
|
],
|
||||||
pickerOptions: {
|
pickerOptions: {
|
||||||
shortcuts: [
|
shortcuts: [
|
||||||
{
|
{
|
||||||
|
@ -131,42 +308,156 @@ export default {
|
||||||
innerVisible: false,
|
innerVisible: false,
|
||||||
a_options: [
|
a_options: [
|
||||||
{
|
{
|
||||||
value: "选项1",
|
value: "1",
|
||||||
label: "黄金糕",
|
label: "黄金糕",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "选项2",
|
value: "2",
|
||||||
label: "双皮奶",
|
label: "双皮奶",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "选项3",
|
value: "3",
|
||||||
label: "蚵仔煎",
|
label: "蚵仔煎",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "选项4",
|
value: "4",
|
||||||
label: "龙须面",
|
label: "龙须面",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: "选项5",
|
value: "5",
|
||||||
label: "北京烤鸭",
|
label: "IMEI/机器编号",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
select: "",
|
||||||
|
input: "",
|
||||||
|
queryTerm: [
|
||||||
|
{
|
||||||
|
label: "IMEI/机器编号",
|
||||||
|
type: "ag-MultifunctionSearch",
|
||||||
|
value: "imei",
|
||||||
|
input: "",
|
||||||
|
placeholder: "请输入imei",
|
||||||
|
size: "small ",
|
||||||
|
clearable: true,
|
||||||
|
show: true,
|
||||||
|
change: () => {},
|
||||||
|
options: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "质检码",
|
||||||
|
type: "ag-MultifunctionSearch",
|
||||||
|
value: "business_id",
|
||||||
|
placeholder: "请输入imei",
|
||||||
|
size: "small ",
|
||||||
|
clearable: true,
|
||||||
|
show: true,
|
||||||
|
options: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
lable: "入库时间",
|
||||||
|
type: "el-date-picker",
|
||||||
|
enName: "time",
|
||||||
|
TimeType: "daterange",
|
||||||
|
clearable: true,
|
||||||
|
startPlaceholder: "开始日期",
|
||||||
|
endPlaceholder: "结束日期",
|
||||||
|
rangeSeparator: "至",
|
||||||
|
format: "timestamp",
|
||||||
|
placeholder: "请选择日期",
|
||||||
|
filterable: true,
|
||||||
|
display: false,
|
||||||
|
show: true,
|
||||||
|
size: "small",
|
||||||
|
focus: () => {},
|
||||||
|
blur: () => {},
|
||||||
|
handleChange: () => {},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
filelist:['https://git.aiguoai.com/assets/img/logo.svg'],
|
||||||
|
formdata:[
|
||||||
|
{label:"订单编号",span:10,type:"ag-input",enName:'order_sn',placeholder:'请输入洗碗机',size:'small',clearable:true,show:true,value:false,required:true,options:[{label:"是",value:'1'},{label:"否",value:'2'}]},
|
||||||
|
{label:"IMEI/机器编号",span:10,type:"ag-input-number",enName:'imei',labelWidth:'120px',placeholder:'请输入IMEI/机器编号',size:'small',clearable:true,max:10,min:2,step:2,show:true},
|
||||||
|
{label:"质检码",span:12,type:"ag-rate",value:'',enName:'ser_sn',placeholder:'请输入质检码',size:'small',clearable:true,show:true,options:[{value:'1',label:'112'},{value:'2',label:'2223'}]},
|
||||||
|
{label:"质检时间",span:12,type:"ag-multifunction-search",enName:'time',showAlpha:true,size:'small',colorFormat:'hsv',show:true},
|
||||||
|
|
||||||
|
],
|
||||||
|
searchdatas:[
|
||||||
|
{label:"IMEI",span:4,type:"ag-input",enName:'order_sn',placeholder:'请输入洗碗机',size:'small',clearable:true,show:true,value:false,required:true,options:[{label:"是",value:'1'},{label:"否",value:'2'}]},
|
||||||
|
{label:"订单编号",span:4,type:"ag-input-number",enName:'imei',labelWidth:'120px',placeholder:'请输入IMEI/机器编号',size:'small',clearable:true,max:10,min:2,step:2,show:true},
|
||||||
|
{label:"质检码",span:4,type:"ag-rate",value:'',enName:'ser_sn',placeholder:'请输入质检码',size:'small',clearable:true,show:true,},
|
||||||
|
{label:"质检时间",span:6,type:"ag-multion-input",enName:'time',showAlpha:true,size:'small',colorFormat:'hsv',options:[{value:'1',label:'112'},{value:'2',label:'2223'}],show:true},
|
||||||
|
],
|
||||||
|
searchvalue:{
|
||||||
|
order_sn:"11",
|
||||||
|
imei:'',
|
||||||
|
ser_sn:2,
|
||||||
|
timer:['1','2']
|
||||||
|
},
|
||||||
|
formvalue:{
|
||||||
|
order_sn:"11",
|
||||||
|
imei:'',
|
||||||
|
ser_sn:2,
|
||||||
|
time:['11','2'],
|
||||||
|
avatar:["https://git.aiguoai.com/assets/img/logo.svg"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted(){
|
||||||
|
this.$refs.aginputref.value=123;
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleClick() {
|
onUpload(files,list){
|
||||||
console.log(1111);
|
console.log("onUpload",files,list);
|
||||||
|
this.filelist=list;
|
||||||
|
|
||||||
|
},
|
||||||
|
onError(err){
|
||||||
|
console.log("onError",err);
|
||||||
|
},
|
||||||
|
onblur(val,elem){
|
||||||
|
console.log("onblur",val,elem,this);
|
||||||
|
|
||||||
|
},
|
||||||
|
onInputChange(value){
|
||||||
|
console.log(value,"onSearch");
|
||||||
|
},
|
||||||
|
onPicker(value){
|
||||||
|
this.date_value=value;
|
||||||
|
},
|
||||||
|
onSearch(values){
|
||||||
|
console.log(values,"onSearch");
|
||||||
|
},
|
||||||
|
onInputinput(value){
|
||||||
|
console.log(value,"oninput222");
|
||||||
|
this.values=value;
|
||||||
|
},
|
||||||
|
change() {
|
||||||
|
console.log(this.values, "48484");
|
||||||
|
},
|
||||||
|
submit() {
|
||||||
|
this.$refs.ttt.values;
|
||||||
|
},
|
||||||
|
onCheckSearch(val){
|
||||||
|
console.log(val,'onCheckSearch',this.checkvalue);
|
||||||
|
},
|
||||||
|
changes(val) {
|
||||||
|
console.log(val);
|
||||||
|
console.log(999);
|
||||||
},
|
},
|
||||||
handleSizeChange() {},
|
handleSizeChange() {},
|
||||||
handleCurrentChange() {},
|
handleCurrentChange() {},
|
||||||
handleClose() {},
|
handleClose() {},
|
||||||
|
onRest(val){
|
||||||
|
console.log(val,"onRest")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
body {
|
body {
|
||||||
background: #918d8d;
|
background: #f8f8f8;
|
||||||
}
|
}
|
||||||
.div {
|
.div {
|
||||||
span {
|
span {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue