333
This commit is contained in:
parent
11f09906cb
commit
5653581b8c
|
@ -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>
|
||||||
|
|
|
@ -62,9 +62,9 @@ export default {
|
||||||
let config = {};
|
let config = {};
|
||||||
if (this.range) {
|
if (this.range) {
|
||||||
config = {
|
config = {
|
||||||
"start-placeholder":this.$attrs.startplaceholder||"开始日期",
|
"start-placeholder":this.$attrs.startPlaceholder||"开始日期",
|
||||||
"end-placeholder":this.$attrs.endplaceholder|| "结束日期",
|
"end-placeholder":this.$attrs.endPlaceholder|| "结束日期",
|
||||||
"range-separator":this.$attrs.rangeseparator||"-",
|
"range-separator":this.$attrs.rangeSeparator||"-",
|
||||||
"picker-options": {
|
"picker-options": {
|
||||||
disabledDate(time) {
|
disabledDate(time) {
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,16 +1,40 @@
|
||||||
<template>
|
<template>
|
||||||
<el-form v-bind="$attrs" v-on="$listeners" :model="formValue" ref="formref">
|
<el-form v-bind="$attrs" v-on="$listeners" :model="formValue" ref="formref">
|
||||||
<el-row>
|
<ag-row>
|
||||||
<el-col v-for="item,index in data" :key="index" :span="item.span||24">
|
<ag-col v-for="item,index in data" :key="index" :span="item.span||24">
|
||||||
<el-form-item v-bind="item" :prop="item.enName" >
|
<el-form-item v-bind="item" :prop="item.enName" >
|
||||||
<slot :name="item.enName">
|
<slot :name="item.enName">
|
||||||
<ag-input v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-input'"></ag-input>
|
<ag-input v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-input'"></ag-input>
|
||||||
<agDatePicker v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-date-picker'"/>
|
<agDatePicker v-bind="item" v-model="formValue[item.enName]" v-if="item.type=='ag-date-picker'"/>
|
||||||
<agSelect v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-select'" />
|
<agSelect v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-select'" />
|
||||||
|
<el-radio-group v-model="formValue[item.enName]" v-bind="item" v-if="item.type=='ag-radio'&&formValue[item.enName]" size="small" >
|
||||||
|
<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">
|
||||||
|
<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'" ></el-input-number>
|
||||||
|
<el-cascader v-model="formValue[item.enName]" v-bind="item" size="small" v-if="item.type=='ag-cascader'"></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
|
||||||
|
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'"></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>
|
||||||
</slot>
|
</slot>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</ag-col>
|
||||||
</el-row>
|
</ag-row>
|
||||||
<div class="footerbox">
|
<div class="footerbox">
|
||||||
<el-form-item >
|
<el-form-item >
|
||||||
<slot name="button" :value="formValue">
|
<slot name="button" :value="formValue">
|
||||||
|
@ -28,13 +52,21 @@
|
||||||
import agInput from './../../agInput/src/index.vue';
|
import agInput from './../../agInput/src/index.vue';
|
||||||
import agDatePicker from './../../agDatePicker/src/index.vue';
|
import agDatePicker from './../../agDatePicker/src/index.vue';
|
||||||
import agSelect from './../../agSelect/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';
|
||||||
|
|
||||||
export default{
|
export default{
|
||||||
name:"agForm",
|
name:"agForm",
|
||||||
components:{
|
components:{
|
||||||
agInput:agInput,
|
agInput:agInput,
|
||||||
agDatePicker,
|
agDatePicker,
|
||||||
agSelect
|
agSelect,
|
||||||
|
agRow,
|
||||||
|
agCol,
|
||||||
|
agUpload:agUpload,
|
||||||
|
agColorPicker
|
||||||
},
|
},
|
||||||
props:{
|
props:{
|
||||||
data:{
|
data:{
|
||||||
|
@ -56,12 +88,13 @@ export default{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted(){
|
mounted(){
|
||||||
this.formValue=this.$attrs.value;
|
this.formValue=this.$attrs.value;
|
||||||
if(this.$refs.formref){
|
if(this.$refs.formref){
|
||||||
for(const key in this.$refs.formref){
|
for(const key in this.$refs.formref){
|
||||||
if(!this[key]&&key!='value'){
|
if(!this[key]&&key!='value'){
|
||||||
this[key]=this.$refs.formref[key];
|
this[key]=this.$refs.formref[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -107,7 +107,11 @@
|
||||||
default:'picture-card'
|
default:'picture-card'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
model: {
|
||||||
|
prop: 'fileList', // 明确指定 prop 为 'value'
|
||||||
|
event: 'onUpload' // 自定义事件名,用于更新 value
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
if(this.fileList.length>0){
|
if(this.fileList.length>0){
|
||||||
let list=[];
|
let list=[];
|
||||||
this.fileList.map((h)=>{
|
this.fileList.map((h)=>{
|
||||||
|
@ -237,7 +241,7 @@
|
||||||
if(files.length==uplist.length){
|
if(files.length==uplist.length){
|
||||||
if(this.$listeners.onUpload){
|
if(this.$listeners.onUpload){
|
||||||
this.fileList.push(...uplist);
|
this.fileList.push(...uplist);
|
||||||
this.$emit('onUpload',uplist,this.fileList);
|
this.$emit('onUpload',this.fileList,uplist);
|
||||||
}else{
|
}else{
|
||||||
this.imageList.push(...uplist);
|
this.imageList.push(...uplist);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import agSelect from './agSelect/index';
|
import agSelect from './agSelect/index';
|
||||||
import agUpdate from './agUpload';
|
import agUpdate from './agUpload';
|
||||||
import agForm from './agForm';
|
import agForm from './agForm';
|
||||||
|
import agColorPicker from './agColorPicker';
|
||||||
|
|
||||||
// 注册组件
|
// 注册组件
|
||||||
|
|
||||||
|
@ -11,7 +12,8 @@
|
||||||
agInput,
|
agInput,
|
||||||
agSelect,
|
agSelect,
|
||||||
agUpdate,
|
agUpdate,
|
||||||
agForm
|
agForm,
|
||||||
|
agColorPicker
|
||||||
]
|
]
|
||||||
|
|
||||||
// 定义 install 方法,接收 Vue 作为参数(使用 use 注册插件,那么所有的组件都会被注册)
|
// 定义 install 方法,接收 Vue 作为参数(使用 use 注册插件,那么所有的组件都会被注册)
|
||||||
|
|
28
src/App.vue
28
src/App.vue
|
@ -47,10 +47,10 @@
|
||||||
<div>{{row.date}} </div>
|
<div>{{row.date}} </div>
|
||||||
</template>
|
</template>
|
||||||
</agTable>
|
</agTable>
|
||||||
<agUpdate @onUpload="onUpload" isDrap dragmove multiple :limit="5" @onError="onError" :maxSize="1024*1024" :fileList="filelist">
|
<agUpdate @onUpload="onUpload" isDrap dragmove multiple :limit="5" @onError="onError" :maxSize="1024*1024" :value="filelist">
|
||||||
<div slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
<div slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||||
</agUpdate>
|
</agUpdate>
|
||||||
<ag-form :data="formdata" label-width="80px" label-position="right" v-model="formvalue">
|
<ag-form :data="formdata" label-width="120px" label-position="right" v-model="formvalue">
|
||||||
|
|
||||||
</ag-form>
|
</ag-form>
|
||||||
<!-- <el-input
|
<!-- <el-input
|
||||||
|
@ -356,9 +356,9 @@ export default {
|
||||||
enName: "time",
|
enName: "time",
|
||||||
TimeType: "daterange",
|
TimeType: "daterange",
|
||||||
clearable: true,
|
clearable: true,
|
||||||
startplaceholder: "开始日期",
|
startPlaceholder: "开始日期",
|
||||||
endplaceholder: "结束日期",
|
endPlaceholder: "结束日期",
|
||||||
rangeseparator: "至",
|
rangeSeparator: "至",
|
||||||
format: "timestamp",
|
format: "timestamp",
|
||||||
placeholder: "请选择日期",
|
placeholder: "请选择日期",
|
||||||
filterable: true,
|
filterable: true,
|
||||||
|
@ -372,16 +372,18 @@ export default {
|
||||||
],
|
],
|
||||||
filelist:['https://git.aiguoai.com/assets/img/logo.svg'],
|
filelist:['https://git.aiguoai.com/assets/img/logo.svg'],
|
||||||
formdata:[
|
formdata:[
|
||||||
{label:"订单编号",span:12,type:"ag-input",enName:'order_sn',value:'656',placeholder:'请输入洗碗机',size:'small',clearable:true,show:true,value:'123',required:true},
|
{label:"订单编号",span:12,type:"ag-input",enName:'order_sn',value:'656',placeholder:'请输入洗碗机',size:'small',clearable:true,show:true,value:false,required:true,options:[{label:"是",value:'1'},{label:"否",value:'2'}]},
|
||||||
{label:"IMEI/机器编号",span:12,type:"ag-input",enName:'imei',value:'43543',placeholder:'请输入IMEI/机器编号',size:'small',clearable:true,show:true},
|
{label:"IMEI/机器编号",span:12,type:"ag-input-number",enName:'imei',value:'43543',placeholder:'请输入IMEI/机器编号',size:'small',clearable:true,max:10,min:2,step:2,show:true},
|
||||||
{label:"质检码",span:12,type:"ag-select",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-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-date-picker",enName:'time',range:true,showTime:true,startplaceholder:'初始日期1',endplaceholder:'结束日期1',width:200,rangeseparator:'至',placeholder:'请选择日期',filterable:true,size:'small'},
|
{label:"质检时间",span:12,type:"ag-color-picker",enName:'time',showAlpha:true,size:'small',colorFormat:'hsv',show:true},
|
||||||
|
{label:"头像",span:12,type:"ag-upload",enName:'avatar',placeholder:'请输入质检码',size:'small',clearable:true,show:true,limit:4,multiple:true},
|
||||||
],
|
],
|
||||||
formvalue:{
|
formvalue:{
|
||||||
order_sn:'123',
|
order_sn:"11",
|
||||||
imei:'456',
|
imei:'',
|
||||||
ser_sn:'1',
|
ser_sn:2,
|
||||||
time:['2020-12-12 12:33:11','2024-09-11 13:13:13']
|
time:'red',
|
||||||
|
avatar:["https://git.aiguoai.com/assets/img/logo.svg"],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue