mirror of
https://gitee.com/orangeform/orange-admin.git
synced 2026-01-17 18:46:36 +08:00
created
This commit is contained in:
304
orange-admin-web/src/components/DateRange/index.vue
Normal file
304
orange-admin-web/src/components/DateRange/index.vue
Normal file
@@ -0,0 +1,304 @@
|
||||
<template>
|
||||
<div class="date-range">
|
||||
<!--<year-range-panel />-->
|
||||
<el-select v-model="dateType" :size="size" style="max-width: 100px; min-width: 100px; margin-right: 10px;" v-if="!hideTypeOnlyOne || validTypeList.length > 1">
|
||||
<el-option v-for="type in validTypeList" :key="type.value" :value="type.value" :label="type.label" />
|
||||
</el-select>
|
||||
<el-date-picker style="flex-grow: 1;" v-model="currentDates" :size="size" :placeholder="placeholder" :type="innerDateType"
|
||||
:disabled="disabled" :format="innerDateFormat" :readonly="readonly" :editable="editable"
|
||||
:clearable="clearable" :start-placeholder="startPlaceholder" :end-placeholder="endPlaceholder"
|
||||
:align="align" :range-separator="rangeSeparator" :value-format="valueFormat"
|
||||
:prefix-icon="prefixIcon" :clear-icon="clearIcon" @change="onValueChange"></el-date-picker>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { formatDate, parseDate } from 'element-ui/src/utils/date-util';
|
||||
|
||||
const allTypeList = [{
|
||||
value: 'day',
|
||||
label: '自然日'
|
||||
}, {
|
||||
value: 'month',
|
||||
label: '自然月'
|
||||
}, {
|
||||
value: 'year',
|
||||
label: '自然年'
|
||||
}];
|
||||
|
||||
export default {
|
||||
name: 'DateRange',
|
||||
props: {
|
||||
/**
|
||||
* 绑定的数据
|
||||
*/
|
||||
value: {
|
||||
type: [Array],
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 默认显示的数据选择方式,如果不存在与allowTypes中则显示allowTypes中的第一个
|
||||
*/
|
||||
defaultDateType: {
|
||||
type: String,
|
||||
default: 'day'
|
||||
},
|
||||
/**
|
||||
* 组件大小(medium / small / mini)
|
||||
*/
|
||||
size: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* 数据选择方式只有一个的时候是否隐藏数据选择方式下拉
|
||||
*/
|
||||
hideTypeOnlyOne: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 允许的数据选择方式(day, month, year)
|
||||
* 默认值['day', 'month', 'year']
|
||||
*/
|
||||
allowTypes: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return allTypeList.map((item) => {
|
||||
return item.value;
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 是否范围选择
|
||||
*/
|
||||
isRange: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 输出字符串的format
|
||||
*/
|
||||
outputFormat: {
|
||||
type: String,
|
||||
default: 'yyyy-MM-dd HH:mm:ss'
|
||||
},
|
||||
/**
|
||||
* 非范围选择时的占位内容
|
||||
*/
|
||||
placeholder: String,
|
||||
/**
|
||||
* 范围选择时开始日期的占位内容
|
||||
*/
|
||||
startPlaceholder: String,
|
||||
/**
|
||||
* 范围选择时结束日期的占位内容
|
||||
*/
|
||||
endPlaceholder: String,
|
||||
/**
|
||||
* 完全只读
|
||||
*/
|
||||
readonly: Boolean,
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
disabled: Boolean,
|
||||
/**
|
||||
* 文本框可输入
|
||||
*/
|
||||
editable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 是否显示清除按钮
|
||||
*/
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 对齐方式(left, center, right)
|
||||
*/
|
||||
align: {
|
||||
type: String,
|
||||
default: 'left'
|
||||
},
|
||||
/**
|
||||
* 选择范围时的分隔符
|
||||
*/
|
||||
rangeSeparator: {
|
||||
type: String,
|
||||
default: '-'
|
||||
},
|
||||
/**
|
||||
* 可选,绑定值的格式。不指定则绑定值为 Date 对象
|
||||
*/
|
||||
valueFormat: {
|
||||
type: String,
|
||||
default: 'yyyy-MM-dd'
|
||||
},
|
||||
/**
|
||||
* 自定义头部图标的类名
|
||||
*/
|
||||
prefixIcon: {
|
||||
type: String,
|
||||
default: 'el-icon-date'
|
||||
},
|
||||
/**
|
||||
* 自定义清空图标的类名
|
||||
*/
|
||||
clearIcon: {
|
||||
type: String,
|
||||
default: 'el-icon-circle-close'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
dateType: this.defaultDateType,
|
||||
currentDates: undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onValueChange (values) {
|
||||
this.$nextTick(() => {
|
||||
this.emitChange();
|
||||
});
|
||||
},
|
||||
emitChange () {
|
||||
let outputDate = [];
|
||||
if (this.currentDates != null) {
|
||||
if (!this.isRange) {
|
||||
outputDate[0] = new Date(this.currentDates);
|
||||
outputDate[1] = new Date(this.currentDates);
|
||||
} else {
|
||||
if (Array.isArray(this.currentDates) && this.currentDates.length === 2) {
|
||||
outputDate[0] = new Date(this.currentDates[0]);
|
||||
outputDate[1] = new Date(this.currentDates[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (outputDate[0] != null && outputDate[1] != null) {
|
||||
outputDate[0].setHours(0, 0, 0, 0);
|
||||
outputDate[1].setHours(0, 0, 0, 0);
|
||||
switch (this.dateType) {
|
||||
case 'day':
|
||||
outputDate[1].setDate(outputDate[1].getDate() + 1);
|
||||
break;
|
||||
case 'month':
|
||||
outputDate[1].setDate(1);
|
||||
outputDate[0].setDate(1);
|
||||
outputDate[1].setMonth(outputDate[1].getMonth() + 1);
|
||||
break;
|
||||
case 'year':
|
||||
outputDate[1].setMonth(0);
|
||||
outputDate[1].setDate(1);
|
||||
outputDate[0].setMonth(0);
|
||||
outputDate[0].setDate(1);
|
||||
outputDate[1].setFullYear(outputDate[1].getFullYear() + 1);
|
||||
break;
|
||||
}
|
||||
outputDate[1] = new Date(outputDate[1].getTime() - 1);
|
||||
|
||||
outputDate[0] = formatDate(outputDate[0], this.outputFormat);
|
||||
outputDate[1] = formatDate(outputDate[1], this.outputFormat);
|
||||
}
|
||||
}
|
||||
this.$emit('input', outputDate);
|
||||
this.$emit('change', outputDate);
|
||||
},
|
||||
getCurrentStatsDateType () {
|
||||
return this.dateType;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
validTypeList () {
|
||||
return allTypeList.filter((item) => {
|
||||
return this.allowTypes.indexOf(item.value) !== -1;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* el-date-picker使用的type
|
||||
*/
|
||||
innerDateType () {
|
||||
switch (this.dateType) {
|
||||
case 'day': return this.isRange ? 'daterange' : 'date';
|
||||
case 'month': return this.isRange ? 'monthrange' : 'month';
|
||||
case 'year': return this.isRange ? 'monthrange' : 'year';
|
||||
default: return this.isRange ? 'daterange' : 'date';
|
||||
}
|
||||
},
|
||||
/**
|
||||
* el-date-picker使用的format
|
||||
*/
|
||||
innerDateFormat () {
|
||||
switch (this.dateType) {
|
||||
case 'day': return 'yyyy-MM-dd';
|
||||
case 'month': return 'yyyy-MM';
|
||||
case 'year': return 'yyyy';
|
||||
default: return 'yyyy-MM-dd';
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler: function (newValue, oldValue) {
|
||||
if (newValue == null || newValue.length < 2) {
|
||||
this.currentDates = this.isRange ? [] : undefined;
|
||||
} else {
|
||||
if (this.currentDates == null) this.currentDates = [];
|
||||
if (this.isRange) {
|
||||
this.currentDates = [
|
||||
parseDate(newValue[0], this.valueFormat),
|
||||
parseDate(newValue[1], this.valueFormat)
|
||||
];
|
||||
} else {
|
||||
this.currentDates = parseDate(newValue[0], this.valueFormat);
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
},
|
||||
dateType: {
|
||||
handler: function (newValue, oldValue) {
|
||||
if (this.allowTypes.indexOf(this.dateType) === -1) {
|
||||
this.dateType = this.allowTypes[0] || 'day';
|
||||
}
|
||||
this.emitChange();
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
defaultDateType: {
|
||||
handler: function (newValue, oldValue) {
|
||||
if (this.allowTypes.indexOf(newValue) !== -1) {
|
||||
this.dateType = newValue;
|
||||
} else {
|
||||
this.dateType = this.allowTypes[0];
|
||||
}
|
||||
}
|
||||
},
|
||||
isRange: {
|
||||
handler: function (newValue, oldValue) {
|
||||
let temp;
|
||||
if (newValue) {
|
||||
temp = [this.currentDates, this.currentDates];
|
||||
} else {
|
||||
temp = this.currentDates[0];
|
||||
}
|
||||
|
||||
this.currentDates = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.date-range {
|
||||
display: flex;
|
||||
justify-content: start;
|
||||
}
|
||||
|
||||
</style>
|
||||
77
orange-admin-web/src/components/Dialog/index.js
Normal file
77
orange-admin-web/src/components/Dialog/index.js
Normal file
@@ -0,0 +1,77 @@
|
||||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
import router from '@/router';
|
||||
import store from '@/store';
|
||||
|
||||
window.jQuery = $;
|
||||
const layer = require('layui-layer');
|
||||
|
||||
class Dialog {
|
||||
/**
|
||||
* 关闭弹窗
|
||||
* @param {*} index 要关闭的弹窗的index
|
||||
*/
|
||||
static close (index) {
|
||||
layer.close(index);
|
||||
}
|
||||
/**
|
||||
* 关闭所有弹窗
|
||||
*/
|
||||
static closeAll () {
|
||||
layer.closeAll();
|
||||
}
|
||||
/**
|
||||
* 打开弹窗
|
||||
* @param {*} title 弹窗标题
|
||||
* @param {*} component 弹窗内容的组件
|
||||
* @param {*} options 弹窗设置(详情请见layui官网)
|
||||
* @param {*} params 弹窗组件参数
|
||||
*/
|
||||
static show (title, component, options, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let layerOptions = {
|
||||
title: title,
|
||||
type: 1,
|
||||
skin: 'layer-dialog',
|
||||
resize: false,
|
||||
offset: 'auto',
|
||||
zIndex: 1000,
|
||||
index: 0,
|
||||
contentDom: null
|
||||
};
|
||||
|
||||
layerOptions = {...layerOptions, ...options};
|
||||
layerOptions.end = () => {
|
||||
if (layerOptions.contentDom) document.body.removeChild(layerOptions.contentDom);
|
||||
}
|
||||
|
||||
let observer = {
|
||||
cancel: function (isSuccess = false) {
|
||||
layer.close(this.index);
|
||||
if (isSuccess) {
|
||||
resolve();
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
},
|
||||
index: -1
|
||||
}
|
||||
layerOptions.cancel = () => {
|
||||
reject();
|
||||
}
|
||||
let dom = document.createElement('div');
|
||||
document.body.appendChild(dom);
|
||||
let Content = Vue.extend(component);
|
||||
let vueObj = new Content({router: router, store: store, propsData: params});
|
||||
vueObj.observer = observer;
|
||||
vueObj.$mount(dom);
|
||||
layerOptions.contentDom = vueObj.$el;
|
||||
layerOptions.content = $(layerOptions.contentDom);
|
||||
observer.index = layer.open(layerOptions);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Vue.prototype.$dialog = Dialog;
|
||||
|
||||
export default Dialog;
|
||||
134
orange-admin-web/src/components/FilterBox/index.vue
Normal file
134
orange-admin-web/src/components/FilterBox/index.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<el-row class="flex-box" type="flex" :justify="rowJustify">
|
||||
<slot />
|
||||
<div v-for="item in tempDomCount" :key="item" :style="{width: tempDomWidth}" />
|
||||
<el-row type="flex" :justify="operatorPosition" :style="getMenuBoxStyle">
|
||||
<slot name="operator" />
|
||||
</el-row>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import $ from 'jquery';
|
||||
|
||||
export default {
|
||||
name: 'FilterBox',
|
||||
props: {
|
||||
/**
|
||||
* 每一个过滤项宽度(包含标题和输入框宽度总和)
|
||||
*/
|
||||
itemWidth: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
/**
|
||||
* 每一项下间距
|
||||
*/
|
||||
marginBottom: {
|
||||
type: String,
|
||||
default: '18px'
|
||||
},
|
||||
/**
|
||||
* 按钮块最小宽度默认350,当每一行剩余空间大于此值,按钮块将不会折行
|
||||
*/
|
||||
minMenuWidth: {
|
||||
type: Number,
|
||||
default: 350
|
||||
},
|
||||
/**
|
||||
* 按钮位置,默认为end,可选值为start/end/center/space-around/space-between
|
||||
*/
|
||||
operatorPosition: {
|
||||
type: String,
|
||||
default: 'end'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tempDomCount: 0,
|
||||
tempDomWidth: undefined,
|
||||
operatorWidth: undefined,
|
||||
oldFilterItemCount: 0,
|
||||
oldHasOperator: false,
|
||||
oldWidth: 0,
|
||||
rowJustify: 'space-between'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getMenuBoxStyle () {
|
||||
return {
|
||||
'width': this.operatorWidth,
|
||||
'margin-bottom': this.marginBottom,
|
||||
'flex-grow': this.operatorWidth ? undefined : '1'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onUpdate () {
|
||||
setTimeout(() => {
|
||||
let filterItemCount = Array.isArray(this.$slots.default) ? this.$slots.default.filter(item => item.context).length : 0;
|
||||
let hasOperator = Array.isArray(this.$slots.operator) && this.$slots.operator.length > 0;
|
||||
let width = $(this.$el).width();
|
||||
if (filterItemCount === this.oldFilterItemCount && hasOperator === this.oldHasOperator && width === this.oldWidth) {
|
||||
return;
|
||||
}
|
||||
let lineCount = this.itemWidth > 0 ? parseInt(width / this.itemWidth) : 1;
|
||||
lineCount = Math.max(1, lineCount);
|
||||
let residueCount = filterItemCount % lineCount;
|
||||
|
||||
this.tempDomCount = 0;
|
||||
this.tempDomWidth = undefined;
|
||||
this.rowJustify = 'space-between';
|
||||
let tempCount = residueCount === 0 ? 0 : (lineCount - residueCount);
|
||||
if (hasOperator) {
|
||||
let residueWidth = width - ((lineCount - residueCount) * this.itemWidth) - 20;
|
||||
// 判断剩余的空间是否够放下操作按钮
|
||||
if (residueWidth >= this.minMenuWidth && residueCount === 0) {
|
||||
this.rowJustify = 'start';
|
||||
this.operatorWidth = undefined;
|
||||
} else {
|
||||
// 剩余空位数大于1,需要占位dom
|
||||
if (tempCount >= 1) {
|
||||
if (residueWidth >= this.minMenuWidth) {
|
||||
this.tempDomCount = tempCount - 1;
|
||||
this.tempDomWidth = this.tempDomCount > 0 ? (20 / this.tempDomCount) + 'px' : undefined;
|
||||
this.operatorWidth = this.tempDomCount > 0 ? (((tempCount * this.itemWidth) - 20) + 'px') : (this.itemWidth + 'px');
|
||||
} else {
|
||||
this.tempDomCount = tempCount;
|
||||
this.tempDomWidth = (residueWidth / this.tempDomCount) + 'px';
|
||||
this.operatorWidth = '100%';
|
||||
}
|
||||
} else {
|
||||
this.operatorWidth = '100%';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.tempDomCount = tempCount;
|
||||
this.tempDomWidth = this.itemWidth + 'px';
|
||||
}
|
||||
|
||||
this.oldFilterItemCount = filterItemCount;
|
||||
this.oldHasOperator = hasOperator;
|
||||
this.oldWidth = width;
|
||||
});
|
||||
}
|
||||
},
|
||||
beforeUpdate () {
|
||||
this.onUpdate();
|
||||
},
|
||||
mounted () {
|
||||
setTimeout(() => {
|
||||
this.onUpdate();
|
||||
});
|
||||
},
|
||||
created () {
|
||||
window.addEventListener('resize', this.onUpdate);
|
||||
},
|
||||
beforeDestroy () {
|
||||
window.removeEventListener('resize', this.onUpdate);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
44
orange-admin-web/src/components/Hamburger/index.vue
Normal file
44
orange-admin-web/src/components/Hamburger/index.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<svg t="1492500959545" @click="toggleClick" class="hamburger" :class="{'is-active':isActive}" style="" viewBox="0 0 1024 1024"
|
||||
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
|
||||
<path d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
|
||||
p-id="1692"></path>
|
||||
<path d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
|
||||
p-id="1693"></path>
|
||||
<path d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
|
||||
p-id="1694"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'hamburger',
|
||||
props: {
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
toggleClick: {
|
||||
type: Function,
|
||||
default: null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.hamburger {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transform: rotate(90deg);
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
|
||||
.hamburger.is-active {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
</style>
|
||||
280
orange-admin-web/src/components/IconSelect/icon.json
Normal file
280
orange-admin-web/src/components/IconSelect/icon.json
Normal file
@@ -0,0 +1,280 @@
|
||||
[
|
||||
"el-icon-delete-solid",
|
||||
"el-icon-delete",
|
||||
"el-icon-s-tools",
|
||||
"el-icon-setting",
|
||||
"el-icon-user-solid",
|
||||
"el-icon-user",
|
||||
"el-icon-phone",
|
||||
"el-icon-phone-outline",
|
||||
"el-icon-more",
|
||||
"el-icon-more-outline",
|
||||
"el-icon-star-on",
|
||||
"el-icon-star-off",
|
||||
"el-icon-s-goods",
|
||||
"el-icon-goods",
|
||||
"el-icon-warning",
|
||||
"el-icon-warning-outline",
|
||||
"el-icon-question",
|
||||
"el-icon-info",
|
||||
"el-icon-remove",
|
||||
"el-icon-circle-plus",
|
||||
"el-icon-success",
|
||||
"el-icon-error",
|
||||
"el-icon-zoom-in",
|
||||
"el-icon-zoom-out",
|
||||
"el-icon-remove-outline",
|
||||
"el-icon-circle-plus-outline",
|
||||
"el-icon-circle-check",
|
||||
"el-icon-circle-close",
|
||||
"el-icon-s-help",
|
||||
"el-icon-help",
|
||||
"el-icon-minus",
|
||||
"el-icon-plus",
|
||||
"el-icon-check",
|
||||
"el-icon-close",
|
||||
"el-icon-picture",
|
||||
"el-icon-picture-outline",
|
||||
"el-icon-picture-outline-round",
|
||||
"el-icon-upload",
|
||||
"el-icon-upload2",
|
||||
"el-icon-download",
|
||||
"el-icon-camera-solid",
|
||||
"el-icon-camera",
|
||||
"el-icon-video-camera-solid",
|
||||
"el-icon-video-camera",
|
||||
"el-icon-message-solid",
|
||||
"el-icon-bell",
|
||||
"el-icon-s-cooperation",
|
||||
"el-icon-s-order",
|
||||
"el-icon-s-platform",
|
||||
"el-icon-s-fold",
|
||||
"el-icon-s-unfold",
|
||||
"el-icon-s-operation",
|
||||
"el-icon-s-promotion",
|
||||
"el-icon-s-home",
|
||||
"el-icon-s-release",
|
||||
"el-icon-s-ticket",
|
||||
"el-icon-s-management",
|
||||
"el-icon-s-open",
|
||||
"el-icon-s-shop",
|
||||
"el-icon-s-marketing",
|
||||
"el-icon-s-flag",
|
||||
"el-icon-s-comment",
|
||||
"el-icon-s-finance",
|
||||
"el-icon-s-claim",
|
||||
"el-icon-s-custom",
|
||||
"el-icon-s-opportunity",
|
||||
"el-icon-s-data",
|
||||
"el-icon-s-check",
|
||||
"el-icon-s-grid",
|
||||
"el-icon-menu",
|
||||
"el-icon-share",
|
||||
"el-icon-d-caret",
|
||||
"el-icon-caret-left",
|
||||
"el-icon-caret-right",
|
||||
"el-icon-caret-bottom",
|
||||
"el-icon-caret-top",
|
||||
"el-icon-bottom-left",
|
||||
"el-icon-bottom-right",
|
||||
"el-icon-back",
|
||||
"el-icon-right",
|
||||
"el-icon-bottom",
|
||||
"el-icon-top",
|
||||
"el-icon-top-left",
|
||||
"el-icon-top-right",
|
||||
"el-icon-arrow-left",
|
||||
"el-icon-arrow-right",
|
||||
"el-icon-arrow-down",
|
||||
"el-icon-arrow-up",
|
||||
"el-icon-d-arrow-left",
|
||||
"el-icon-d-arrow-right",
|
||||
"el-icon-video-pause",
|
||||
"el-icon-video-play",
|
||||
"el-icon-refresh",
|
||||
"el-icon-refresh-right",
|
||||
"el-icon-refresh-left",
|
||||
"el-icon-finished",
|
||||
"el-icon-sort",
|
||||
"el-icon-sort-up",
|
||||
"el-icon-sort-down",
|
||||
"el-icon-rank",
|
||||
"el-icon-loading",
|
||||
"el-icon-view",
|
||||
"el-icon-c-scale-to-original",
|
||||
"el-icon-date",
|
||||
"el-icon-edit",
|
||||
"el-icon-edit-outline",
|
||||
"el-icon-folder",
|
||||
"el-icon-folder-opened",
|
||||
"el-icon-folder-add",
|
||||
"el-icon-folder-remove",
|
||||
"el-icon-folder-delete",
|
||||
"el-icon-folder-checked",
|
||||
"el-icon-tickets",
|
||||
"el-icon-document-remove",
|
||||
"el-icon-document-delete",
|
||||
"el-icon-document-copy",
|
||||
"el-icon-document-checked",
|
||||
"el-icon-document",
|
||||
"el-icon-document-add",
|
||||
"el-icon-printer",
|
||||
"el-icon-paperclip",
|
||||
"el-icon-takeaway-box",
|
||||
"el-icon-search",
|
||||
"el-icon-monitor",
|
||||
"el-icon-attract",
|
||||
"el-icon-mobile",
|
||||
"el-icon-scissors",
|
||||
"el-icon-umbrella",
|
||||
"el-icon-headset",
|
||||
"el-icon-brush",
|
||||
"el-icon-mouse",
|
||||
"el-icon-coordinate",
|
||||
"el-icon-magic-stick",
|
||||
"el-icon-reading",
|
||||
"el-icon-data-line",
|
||||
"el-icon-data-board",
|
||||
"el-icon-pie-chart",
|
||||
"el-icon-data-analysis",
|
||||
"el-icon-collection-tag",
|
||||
"el-icon-film",
|
||||
"el-icon-suitcase",
|
||||
"el-icon-suitcase-1",
|
||||
"el-icon-receiving",
|
||||
"el-icon-collection",
|
||||
"el-icon-files",
|
||||
"el-icon-notebook-1",
|
||||
"el-icon-notebook-2",
|
||||
"el-icon-toilet-paper",
|
||||
"el-icon-office-building",
|
||||
"el-icon-school",
|
||||
"el-icon-table-lamp",
|
||||
"el-icon-house",
|
||||
"el-icon-no-smoking",
|
||||
"el-icon-smoking",
|
||||
"el-icon-shopping-cart-full",
|
||||
"el-icon-shopping-cart-1",
|
||||
"el-icon-shopping-cart-2",
|
||||
"el-icon-shopping-bag-1",
|
||||
"el-icon-shopping-bag-2",
|
||||
"el-icon-sold-out",
|
||||
"el-icon-sell",
|
||||
"el-icon-present",
|
||||
"el-icon-box",
|
||||
"el-icon-bank-card",
|
||||
"el-icon-money",
|
||||
"el-icon-coin",
|
||||
"el-icon-wallet",
|
||||
"el-icon-discount",
|
||||
"el-icon-price-tag",
|
||||
"el-icon-news",
|
||||
"el-icon-guide",
|
||||
"el-icon-male",
|
||||
"el-icon-female",
|
||||
"el-icon-thumb",
|
||||
"el-icon-cpu",
|
||||
"el-icon-link",
|
||||
"el-icon-connection",
|
||||
"el-icon-open",
|
||||
"el-icon-turn-off",
|
||||
"el-icon-set-up",
|
||||
"el-icon-chat-round",
|
||||
"el-icon-chat-line-round",
|
||||
"el-icon-chat-square",
|
||||
"el-icon-chat-dot-round",
|
||||
"el-icon-chat-dot-square",
|
||||
"el-icon-chat-line-square",
|
||||
"el-icon-message",
|
||||
"el-icon-postcard",
|
||||
"el-icon-position",
|
||||
"el-icon-turn-off-microphone",
|
||||
"el-icon-microphone",
|
||||
"el-icon-close-notification",
|
||||
"el-icon-bangzhu",
|
||||
"el-icon-time",
|
||||
"el-icon-odometer",
|
||||
"el-icon-crop",
|
||||
"el-icon-aim",
|
||||
"el-icon-switch-button",
|
||||
"el-icon-full-screen",
|
||||
"el-icon-copy-document",
|
||||
"el-icon-mic",
|
||||
"el-icon-stopwatch",
|
||||
"el-icon-medal-1",
|
||||
"el-icon-medal",
|
||||
"el-icon-trophy",
|
||||
"el-icon-trophy-1",
|
||||
"el-icon-first-aid-kit",
|
||||
"el-icon-discover",
|
||||
"el-icon-place",
|
||||
"el-icon-location",
|
||||
"el-icon-location-outline",
|
||||
"el-icon-location-information",
|
||||
"el-icon-add-location",
|
||||
"el-icon-delete-location",
|
||||
"el-icon-map-location",
|
||||
"el-icon-alarm-clock",
|
||||
"el-icon-timer",
|
||||
"el-icon-watch-1",
|
||||
"el-icon-watch",
|
||||
"el-icon-lock",
|
||||
"el-icon-unlock",
|
||||
"el-icon-key",
|
||||
"el-icon-service",
|
||||
"el-icon-mobile-phone",
|
||||
"el-icon-bicycle",
|
||||
"el-icon-truck",
|
||||
"el-icon-ship",
|
||||
"el-icon-basketball",
|
||||
"el-icon-football",
|
||||
"el-icon-soccer",
|
||||
"el-icon-baseball",
|
||||
"el-icon-wind-power",
|
||||
"el-icon-light-rain",
|
||||
"el-icon-lightning",
|
||||
"el-icon-heavy-rain",
|
||||
"el-icon-sunrise",
|
||||
"el-icon-sunrise-1",
|
||||
"el-icon-sunset",
|
||||
"el-icon-sunny",
|
||||
"el-icon-cloudy",
|
||||
"el-icon-partly-cloudy",
|
||||
"el-icon-cloudy-and-sunny",
|
||||
"el-icon-moon",
|
||||
"el-icon-moon-night",
|
||||
"el-icon-dish",
|
||||
"el-icon-dish-1",
|
||||
"el-icon-food",
|
||||
"el-icon-chicken",
|
||||
"el-icon-fork-spoon",
|
||||
"el-icon-knife-fork",
|
||||
"el-icon-burger",
|
||||
"el-icon-tableware",
|
||||
"el-icon-sugar",
|
||||
"el-icon-dessert",
|
||||
"el-icon-ice-cream",
|
||||
"el-icon-hot-water",
|
||||
"el-icon-water-cup",
|
||||
"el-icon-coffee-cup",
|
||||
"el-icon-cold-drink",
|
||||
"el-icon-goblet",
|
||||
"el-icon-goblet-full",
|
||||
"el-icon-goblet-square",
|
||||
"el-icon-goblet-square-full",
|
||||
"el-icon-refrigerator",
|
||||
"el-icon-grape",
|
||||
"el-icon-watermelon",
|
||||
"el-icon-cherry",
|
||||
"el-icon-apple",
|
||||
"el-icon-pear",
|
||||
"el-icon-orange",
|
||||
"el-icon-coffee",
|
||||
"el-icon-ice-tea",
|
||||
"el-icon-ice-drink",
|
||||
"el-icon-milk-tea",
|
||||
"el-icon-potato-strips",
|
||||
"el-icon-lollipop",
|
||||
"el-icon-ice-cream-square",
|
||||
"el-icon-ice-cream-round"
|
||||
]
|
||||
105
orange-admin-web/src/components/IconSelect/index.vue
Normal file
105
orange-admin-web/src/components/IconSelect/index.vue
Normal file
@@ -0,0 +1,105 @@
|
||||
<template>
|
||||
<el-popover width="510" v-model="showDropdown" @show="onDropdownShow">
|
||||
<div class="icon-select-dropdown">
|
||||
<el-row type="flex" style="flex-wrap: wrap">
|
||||
<el-col :span="3" v-for="icon in getIconList" :key="icon" class="icon-item"
|
||||
:class="{active: (value === icon)}" @click.native="onIconClick(icon)">
|
||||
<i :class="icon" />
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row type="flex" justify="space-between">
|
||||
<el-button type="text" @click="onClearClick" style="margin-left: 10px;">清空</el-button>
|
||||
<el-pagination
|
||||
:current-page.sync="currentPage"
|
||||
:page-size="pageSize"
|
||||
layout="prev, pager, next"
|
||||
:total="getIconCount">
|
||||
</el-pagination>
|
||||
</el-row>
|
||||
</div>
|
||||
<div slot="reference" class="icon-select"
|
||||
:style="{width: height + 'px', height: height + 'px', 'line-height': height + 'px', 'font-size': height * 0.5 + 'px'}">
|
||||
<i :class="value" />
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import iconList from './icon.json';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
/**
|
||||
* 绑定字段
|
||||
*/
|
||||
value: String,
|
||||
/**
|
||||
* 组件高度,单位px
|
||||
*/
|
||||
height: {
|
||||
type: Number,
|
||||
default: 45
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showDropdown: false,
|
||||
currentPage: 1,
|
||||
pageSize: 32
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onIconClick (icon) {
|
||||
this.$emit('input', icon);
|
||||
this.showDropdown = false;
|
||||
},
|
||||
onClearClick () {
|
||||
this.$emit('input');
|
||||
this.showDropdown = false;
|
||||
},
|
||||
onDropdownShow () {
|
||||
this.currentPage = 1
|
||||
let pos = iconList.indexOf(this.value);
|
||||
if (pos >= 0) {
|
||||
this.currentPage += Math.floor(pos / this.pageSize);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getIconCount () {
|
||||
return iconList.length;
|
||||
},
|
||||
getIconList () {
|
||||
let beginPos = (this.currentPage - 1) * this.pageSize;
|
||||
let endPos = beginPos + this.pageSize;
|
||||
return iconList.slice(beginPos, endPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.icon-select {
|
||||
text-align: center;
|
||||
color: #5F6266;
|
||||
border: 1px solid #DCDFE6;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.icon-item {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
color: #5F6266;
|
||||
border-radius: 3px;
|
||||
border: 1px solid #DCDFE6;
|
||||
margin: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.active {
|
||||
color: #EF5E1C;
|
||||
}
|
||||
|
||||
</style>
|
||||
226
orange-admin-web/src/components/InputNumberRange/index.vue
Normal file
226
orange-admin-web/src/components/InputNumberRange/index.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<div class="el-input el-date-editor el-range-editor el-input__inner el-input-number-range"
|
||||
:class="
|
||||
[
|
||||
inputSize ? 'el-range-editor--' + inputSize : '',
|
||||
focused ? 'is-active' : '',
|
||||
{
|
||||
'is-disabled': inputDisabled,
|
||||
'el-input--prefix': prefixIcon
|
||||
}
|
||||
]"
|
||||
@mouseenter="showClose = true"
|
||||
@mouseleave="showClose = false">
|
||||
<div class="el-input__icon el-range__icon" :class="prefixIcon">
|
||||
<slot name="prepend"></slot>
|
||||
</div>
|
||||
<input
|
||||
autocomplete="off"
|
||||
:placeholder="startPlaceholder"
|
||||
:value="userInput && userInput[0]"
|
||||
:disabled="inputDisabled"
|
||||
:readonly="readonly"
|
||||
:name="name && name[0]"
|
||||
@input="handleStartInput"
|
||||
@change="handleStartChange"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
class="el-range-input">
|
||||
<slot name="range-separator">
|
||||
<span class="el-range-separator">{{ rangeSeparator }}</span>
|
||||
</slot>
|
||||
<input
|
||||
autocomplete="off"
|
||||
:placeholder="endPlaceholder"
|
||||
:value="userInput && userInput[1]"
|
||||
:disabled="inputDisabled"
|
||||
:readonly="readonly"
|
||||
:name="name && name[1]"
|
||||
@input="handleEndInput"
|
||||
@change="handleEndChange"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
class="el-range-input">
|
||||
<i class="el-input__icon el-range__close-icon"
|
||||
:class="[showClear ? 'el-icon-circle-close' : '']"
|
||||
@click="handleClickClear">
|
||||
</i>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import emitter from 'element-ui/src/mixins/emitter';
|
||||
|
||||
function isNumber (val) {
|
||||
var regPos = /^\d+(\.\d+)?$/; // 非负浮点数
|
||||
var regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/; // 负浮点数
|
||||
if (regPos.test(val) || regNeg.test(val)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'InputNumberRange',
|
||||
componentName: 'InputNumberRange',
|
||||
mixins: [emitter],
|
||||
props: {
|
||||
/**
|
||||
* 绑定字段
|
||||
*/
|
||||
value: {
|
||||
type: Array,
|
||||
default: function () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 组件大小(medium / small / mini)
|
||||
*/
|
||||
size: String,
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
disabled: Boolean,
|
||||
/**
|
||||
* 完全只读
|
||||
*/
|
||||
readonly: Boolean,
|
||||
/**
|
||||
* 是否显示清除按钮
|
||||
*/
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* 自定义头部图标的类名
|
||||
*/
|
||||
prefixIcon: String,
|
||||
/**
|
||||
* 范围选择时最小值的占位内容
|
||||
*/
|
||||
startPlaceholder: String,
|
||||
/**
|
||||
* 范围选择时最大值的占位内容
|
||||
*/
|
||||
endPlaceholder: String,
|
||||
/**
|
||||
* 原生属性
|
||||
*/
|
||||
name: {
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 选择范围时的分隔符
|
||||
*/
|
||||
rangeSeparator: {
|
||||
type: String,
|
||||
default: '-'
|
||||
},
|
||||
validateEvent: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
hovering: false,
|
||||
focused: false,
|
||||
userInput: this.value,
|
||||
showClose: false
|
||||
};
|
||||
},
|
||||
inject: {
|
||||
elForm: {
|
||||
default: ''
|
||||
},
|
||||
elFormItem: {
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
_elFormItemSize () {
|
||||
return (this.elFormItem || {}).elFormItemSize;
|
||||
},
|
||||
inputSize () {
|
||||
let temp = this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
|
||||
return temp;
|
||||
},
|
||||
inputDisabled () {
|
||||
return this.disabled || (this.elForm || {}).disabled;
|
||||
},
|
||||
showClear () {
|
||||
let temp = this.clearable && !this.inputDisabled && !this.readonly && this.showClose &&
|
||||
this.userInput != null && Array.isArray(this.userInput) && this.userInput.length > 0 &&
|
||||
(this.userInput[0] != null || this.userInput[1] != null);
|
||||
return temp;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleStartInput (event) {
|
||||
if (this.userInput) {
|
||||
this.userInput = [event.target.value, this.userInput[1]];
|
||||
} else {
|
||||
this.userInput = [event.target.value, null];
|
||||
}
|
||||
},
|
||||
|
||||
handleEndInput (event) {
|
||||
if (this.userInput) {
|
||||
this.userInput = [this.userInput[0], event.target.value];
|
||||
} else {
|
||||
this.userInput = [null, event.target.value];
|
||||
}
|
||||
},
|
||||
handleStartChange (event) {
|
||||
let value = this.userInput && this.userInput[0];
|
||||
value = isNumber(value) ? value : null;
|
||||
value = value ? Number.parseFloat(value) : null;
|
||||
if (this.userInput) {
|
||||
this.userInput[0] = value;
|
||||
} else {
|
||||
this.userInput = [value, null];
|
||||
}
|
||||
event.srcElement.value = value;
|
||||
this.emitInput(this.userInput);
|
||||
},
|
||||
handleEndChange (event) {
|
||||
let value = this.userInput && this.userInput[1];
|
||||
value = isNumber(value) ? value : null;
|
||||
value = value ? Number.parseFloat(value) : null;
|
||||
if (this.userInput) {
|
||||
this.userInput[1] = value;
|
||||
} else {
|
||||
this.userInput = [null, value];
|
||||
}
|
||||
event.srcElement.value = value;
|
||||
this.emitInput(this.userInput);
|
||||
},
|
||||
handleClickClear () {
|
||||
this.userInput = undefined;
|
||||
this.emitInput(this.userInput);
|
||||
},
|
||||
valueEquals (val, oldVal) {
|
||||
return JSON.stringify(val) === JSON.stringify(oldVal);
|
||||
},
|
||||
emitInput (values) {
|
||||
this.$emit('input', values);
|
||||
this.$emit('change', values);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler: function (val, oldVal) {
|
||||
if (!this.valueEquals(val, oldVal) && this.validateEvent) {
|
||||
this.dispatch('ElFormItem', 'el.form.change', val);
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
44
orange-admin-web/src/components/Progress/index.vue
Normal file
44
orange-admin-web/src/components/Progress/index.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<el-progress v-bind="$attrs" :percentage="getPercentage" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Progress',
|
||||
props: {
|
||||
/**
|
||||
* 组件最小值
|
||||
*/
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* 组件最大值
|
||||
*/
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
/**
|
||||
* 组件当前值
|
||||
*/
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getPercentage () {
|
||||
let value = Math.min(this.max, Math.max(this.min, this.value));
|
||||
value = value - this.min;
|
||||
if ((this.max - this.min) === 0) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = ((value * 100) / (this.max - this.min));
|
||||
}
|
||||
return Number.isInteger(value) ? value : parseInt(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
129
orange-admin-web/src/components/RichEditor/index.vue
Normal file
129
orange-admin-web/src/components/RichEditor/index.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<div class="uditor-class" ref="editor"></div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WEditor from 'wangeditor';
|
||||
|
||||
const defaultConfigs = {
|
||||
uploadImgServer: undefined,
|
||||
uploadFileName: 'imageFile',
|
||||
uploadImgMaxSize: 1 * 1024 * 1024,
|
||||
uploadImgShowBase64: true,
|
||||
uploadImgMaxLength: 5,
|
||||
uploadImgParams: undefined,
|
||||
uploadImgParamsWithUrl: true,
|
||||
withCredentials: true,
|
||||
uploadImgTimeout: 5000,
|
||||
uploadImgHeaders: undefined,
|
||||
uploadImgHooks: undefined,
|
||||
zIndex: 0,
|
||||
lang: undefined,
|
||||
pasteFilterStyle: true,
|
||||
pasteIgnoreImg: false,
|
||||
onchangeTimeout: 10,
|
||||
menus: [
|
||||
// 标题
|
||||
'head',
|
||||
// 粗体
|
||||
'bold',
|
||||
// 字号
|
||||
'fontSize',
|
||||
// 字体
|
||||
'fontName',
|
||||
// 斜体
|
||||
'italic',
|
||||
// 下划线
|
||||
'underline',
|
||||
// 删除线
|
||||
'strikeThrough',
|
||||
// 文字颜色
|
||||
'foreColor',
|
||||
// 背景颜色
|
||||
'backColor',
|
||||
// 插入链接
|
||||
'link',
|
||||
// 列表
|
||||
'list',
|
||||
// 对齐方式
|
||||
'justify',
|
||||
// 引用
|
||||
'quote',
|
||||
// 插入图片
|
||||
'image',
|
||||
// 撤销
|
||||
'undo',
|
||||
// 重复
|
||||
'redo'
|
||||
]
|
||||
}
|
||||
|
||||
export default {
|
||||
props: {
|
||||
/**
|
||||
* 绑定字段
|
||||
*/
|
||||
value: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* 配置项,详情请参考wangEditor文档
|
||||
*/
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return defaultConfigs;
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
editor: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
getConfigs () {
|
||||
return {...this.config, ...defaultConfigs};
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.editor = new WEditor(this.$refs.editor);
|
||||
this.editor.customConfig = {...this.getConfigs};
|
||||
this.editor.customConfig.pasteTextHandle = (content) => {
|
||||
// content 即粘贴过来的内容(html 或 纯文本),可进行自定义处理然后返回
|
||||
return content;
|
||||
}
|
||||
this.editor.customConfig.linkImgCallback = (url) => {
|
||||
console.log(url) // url 即插入图片的地址
|
||||
}
|
||||
this.editor.customConfig.linkCheck = (text, link) => {
|
||||
return true // 返回 true 表示校验成功
|
||||
// return '验证失败' // 返回字符串,即校验失败的提示信息
|
||||
}
|
||||
|
||||
this.editor.customConfig.linkImgCheck = (src) => {
|
||||
return true // 返回 true 表示校验成功
|
||||
// return '验证失败' // 返回字符串,即校验失败的提示信息
|
||||
}
|
||||
// 失去焦点后更新数据
|
||||
this.editor.customConfig.onblur = (html) => {
|
||||
console.log(html)
|
||||
this.$emit('input', html);
|
||||
}
|
||||
|
||||
this.editor.create();
|
||||
this.editor.txt.html(this.value);
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler (newValue) {
|
||||
if (this.editor) this.editor.txt.html(this.value);
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
119
orange-admin-web/src/components/TableProgressColumn/index.vue
Normal file
119
orange-admin-web/src/components/TableProgressColumn/index.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<el-table-column v-bind="$attrs">
|
||||
<template slot-scope="scope">
|
||||
<orange-progress :stroke-width="strokeWidth" :type="type" :text-inside="textInside" :status="status" :color="color"
|
||||
:width="width" :show-text="showText" :min="getMinValue(scope.row)" :max="getMaxValue(scope.row)"
|
||||
:value="getValue(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Progress from '@/components/Progress/index.vue';
|
||||
|
||||
export default {
|
||||
name: 'TableProgressColumn',
|
||||
components: {
|
||||
'orange-progress': Progress
|
||||
},
|
||||
props: {
|
||||
/**
|
||||
* 固定值最小值
|
||||
*/
|
||||
min: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* 固定值最大值
|
||||
*/
|
||||
max: {
|
||||
type: Number,
|
||||
default: 100
|
||||
},
|
||||
/**
|
||||
* 固定值当前值
|
||||
*/
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
/**
|
||||
* 表格最小值字段名
|
||||
*/
|
||||
minColumn: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* 表格最大值字段名
|
||||
*/
|
||||
maxColumn: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* 表格当前值字段名
|
||||
*/
|
||||
valueColumn: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* 进度条的宽度,单位 px
|
||||
*/
|
||||
strokeWidth: {
|
||||
type: Number,
|
||||
default: 16
|
||||
},
|
||||
/**
|
||||
* 进度条类型(line/circle/dashboard)
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
default: 'line'
|
||||
},
|
||||
/**
|
||||
* 进度条显示文字内置在进度条内(只在 type=line 时可用)
|
||||
*/
|
||||
textInside: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* 进度条当前状态(success/exception/warning)
|
||||
*/
|
||||
status: {
|
||||
type: String
|
||||
},
|
||||
/**
|
||||
* 进度条背景色(会覆盖 status 状态颜色)
|
||||
*/
|
||||
color: {
|
||||
type: [String, Function, Array]
|
||||
},
|
||||
/**
|
||||
* 环形进度条画布宽度(只在 type 为 circle 或 dashboard 时可用)
|
||||
*/
|
||||
width: {
|
||||
type: Number,
|
||||
default: 126
|
||||
},
|
||||
/**
|
||||
* 是否显示进度条文字内容
|
||||
*/
|
||||
showText: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getValue (row) {
|
||||
return this.valueColumn ? row[this.valueColumn] : this.value;
|
||||
},
|
||||
getMinValue (row) {
|
||||
return this.minColumn ? row[this.minColumn] : this.min;
|
||||
},
|
||||
getMaxValue (row) {
|
||||
return this.maxColumn ? row[this.maxColumn] : this.max;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
300
orange-admin-web/src/components/TreeSelect/index.vue
Normal file
300
orange-admin-web/src/components/TreeSelect/index.vue
Normal file
@@ -0,0 +1,300 @@
|
||||
<template>
|
||||
<el-popover ref="popover" placement="bottom-start" trigger="click" popper-class="tree-select-popover"
|
||||
:width="width" @show="onShowPopover">
|
||||
<el-scrollbar :style="{'height': this.height, 'min-width': this.width}" ref="scrollbar">
|
||||
<el-tree ref="dropdownTree" :props="getTreeProps" :highlightCurrent="highlightCurrent" :nodeKey="getDataProps.value"
|
||||
:defaultExpandAll="defaultExpandAll" :expandOnClickNode="expandOnClickNode" :checkOnClickNode="checkOnClickNode"
|
||||
:autoExpandParent="autoExpandParent" :defaultExpandedKeys="defaultExpandedKeys" :showCheckbox="showCheckbox"
|
||||
:checkStrictly="checkStrictly" :defaultCheckedKeys="defaultCheckedKeys" :currentNodeKey="getCurrentNodeKey"
|
||||
:accordion="accordion" :indent="indent" :iconClass="iconClass" :load="loadChildrenNodes" lazy :show-checkbox="multiple"
|
||||
@node-click="onTreeNodeClick" @check="onTreeNodeCheck">
|
||||
<span :style="getNodeStyle(data)" slot-scope="{ node, data }">{{data[getDataProps.label]}}</span>
|
||||
</el-tree>
|
||||
</el-scrollbar>
|
||||
<el-select slot="reference" v-model="selectKeys" :multiple="multiple" :disabled="false" :size="size"
|
||||
:clearable="clearable" :collapseTags="collapseTags" :placeholder="placeholder" popper-class="select-tree-popper"
|
||||
@clear="onClear" @remove-tag="onClear">
|
||||
<el-option v-for="item in selectNodes" :key="item[getDataProps.value]"
|
||||
:value="item[getDataProps.value]" :label="item[getDataProps.label]" />
|
||||
</el-select>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { findTreeNode } from '@/utils';
|
||||
|
||||
export default {
|
||||
name: 'TreeSelect',
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number]
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
type: String
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '200px'
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '300px'
|
||||
},
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: '#EF5E1C'
|
||||
},
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
collapseTags: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
placeholder: {
|
||||
type: String
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
loadingText: {
|
||||
type: String,
|
||||
default: '加载中'
|
||||
},
|
||||
// 树属性
|
||||
data: {
|
||||
type: Array
|
||||
},
|
||||
props: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {
|
||||
label: 'label',
|
||||
value: 'value',
|
||||
parentKey: 'parentId',
|
||||
children: 'children',
|
||||
disabled: 'disabled'
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultExpandAll: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
expandOnClickNode: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
checkOnClickNode: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
autoExpandParent: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
defaultExpandedKeys: {
|
||||
type: Array
|
||||
},
|
||||
checkStrictly: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
currentNodeKey: {
|
||||
type: [String, Number]
|
||||
},
|
||||
accordion: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
indent: {
|
||||
type: Number,
|
||||
default: 16
|
||||
},
|
||||
iconClass: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
rootNode: undefined,
|
||||
rootResolve: undefined,
|
||||
allTreeNode: [],
|
||||
selectNodes: [],
|
||||
scrollTop: 0,
|
||||
selectKeys: undefined
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onShowPopover () {
|
||||
setTimeout(() => {
|
||||
this.$refs.scrollbar.wrap.scrollTop = this.scrollTop;
|
||||
// this.$refs.scrollbar.update();
|
||||
}, 20);
|
||||
if (!this.multiple) {
|
||||
this.$refs.dropdownTree.setCurrentKey(this.value);
|
||||
}
|
||||
},
|
||||
onClear () {
|
||||
this.$nextTick(() => {
|
||||
this.$emit('input', this.selectKeys);
|
||||
});
|
||||
},
|
||||
onTreeNodeClick (data, node) {
|
||||
this.$refs.popover.showPopper = false;
|
||||
if (!this.multiple) {
|
||||
this.scrollTop = this.$refs.scrollbar.wrap.scrollTop;
|
||||
this.$emit('input', data[this.getDataProps.value]);
|
||||
this.$emit('change', data[this.getDataProps.value]);
|
||||
}
|
||||
},
|
||||
onTreeNodeCheck (data, {checkedNodes, checkedKeys, halfCheckedNodes, halfCheckedKeys}) {
|
||||
this.scrollTop = this.$refs.scrollbar.wrap.scrollTop
|
||||
this.$emit('input', checkedKeys);
|
||||
this.$emit('change', checkedKeys);
|
||||
},
|
||||
parseNode (node) {
|
||||
if (Array.isArray(node) && node.length > 0) {
|
||||
node.forEach((item) => {
|
||||
item['__node_is_leaf__'] = !(Array.isArray(item[this.getDataProps.children]) && item[this.getDataProps.children].length > 0);
|
||||
});
|
||||
return node;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
loadChildrenNodes (node, resolve) {
|
||||
if (node.level === 0) {
|
||||
this.rootNode = node;
|
||||
this.rootResolve = resolve;
|
||||
return resolve(this.parseNode(this.allTreeNode));
|
||||
} else {
|
||||
return resolve(this.parseNode(node.data[this.getDataProps.children]));
|
||||
}
|
||||
},
|
||||
getNodeStyle (data) {
|
||||
if (!this.multiple && (this.selectNodes[0] || {})[this.getDataProps.value] === data[this.getDataProps.value]) {
|
||||
return {
|
||||
color: this.activeColor,
|
||||
'font-weight': 700
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showCheckbox () {
|
||||
return this.multiple;
|
||||
},
|
||||
getCurrentNodeKey () {
|
||||
if (!this.multiple && Array.isArray(this.selectNodes) && this.selectNodes.length > 0) {
|
||||
return this.selectNodes[0][this.getDataProps.value];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
highlightCurrent () {
|
||||
return this.multiple;
|
||||
},
|
||||
defaultCheckedKeys () {
|
||||
return this.multiple ? this.selectNodes : undefined
|
||||
},
|
||||
getDataProps () {
|
||||
return {
|
||||
label: this.props.label || 'label',
|
||||
value: this.props.value || 'value',
|
||||
parentKey: this.props.parentKey || 'parentId',
|
||||
children: this.props.children || 'children',
|
||||
disabled: this.props.disabled || 'disabled'
|
||||
}
|
||||
},
|
||||
getTreeProps () {
|
||||
return {
|
||||
label: this.getDataProps.label,
|
||||
children: '__children_list__',
|
||||
disabled: this.getDataProps.disabled,
|
||||
isLeaf: '__node_is_leaf__'
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
data: {
|
||||
handler (newValue, oldValue) {
|
||||
this.allTreeNode = newValue;
|
||||
if (this.rootNode != null && this.rootResolve != null) {
|
||||
this.rootNode.childNodes = [];
|
||||
this.loadChildrenNodes(this.rootNode, this.rootResolve);
|
||||
}
|
||||
this.selectNodes = [];
|
||||
if (this.multiple) {
|
||||
if (Array.isArray(this.value)) {
|
||||
this.value.forEach((item) => {
|
||||
let data = findTreeNode(this.allTreeNode, item, this.getDataProps.value, this.getDataProps.children);
|
||||
if (data) this.selectNodes.push(data);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let data = findTreeNode(this.allTreeNode, this.value, this.getDataProps.value, this.getDataProps.children);
|
||||
if (data) this.selectNodes.push(data);
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
value: {
|
||||
handler (newValue) {
|
||||
this.selectNodes = [];
|
||||
if (Array.isArray(newValue)) {
|
||||
newValue.forEach((item) => {
|
||||
let data = findTreeNode(this.allTreeNode, item, this.getDataProps.value, this.getDataProps.children);
|
||||
if (data) this.selectNodes.push(data);
|
||||
});
|
||||
this.selectKeys = newValue;
|
||||
} else {
|
||||
let data = findTreeNode(this.allTreeNode, newValue, this.getDataProps.value, this.getDataProps.children);
|
||||
if (data) this.selectNodes.push(data);
|
||||
this.selectKeys = newValue;
|
||||
}
|
||||
if (this.$refs.dropdownTree) {
|
||||
this.multiple ? this.$refs.dropdownTree.setCheckedKeys(newValue) : this.$refs.dropdownTree.setCurrentKey(newValue);
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.select-tree-popper {
|
||||
display: none;
|
||||
}
|
||||
.tree-select-popover {
|
||||
padding: 6px 0px;
|
||||
}
|
||||
.tree-select-popover .popper__arrow {
|
||||
left: 35px!important;
|
||||
}
|
||||
.tree-select-popover .el-tree .el-tree-node__content {
|
||||
height: 34px;
|
||||
line-height: 34px;
|
||||
}
|
||||
/*
|
||||
.tree-select-popover .el-tree .el-tree-node.is-current .el-tree-node__content {
|
||||
color: #fdb95c;
|
||||
font-weight: 700;
|
||||
}
|
||||
*/
|
||||
.current-node {
|
||||
color: #EF5E1C;
|
||||
font-weight: 700;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user