2.1.3 大屏版本发布

This commit is contained in:
zhangdaihao
2019-12-25 13:25:10 +08:00
parent ea5ef384f2
commit 9c44ffaa8e
60 changed files with 2970 additions and 806 deletions

View File

@ -1,7 +1,7 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<div :style="{ padding: '0 50px 32px 0' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale">
<v-chart :forceFit="true" :height="height" :data="data" :scale="scale" :padding=" padding">
<v-tooltip/>
<v-legend/>
<v-axis/>
@ -23,13 +23,13 @@
dataSource: {
type: Array,
default: () => [
{ type: '10:10', bar: 2, line: 2 },
{ type: '10:15', bar: 6, line: 3 },
{ type: '10:20', bar: 2, line: 5 },
{ type: '10:25', bar: 9, line: 1 },
{ type: '10:30', bar: 2, line: 3 },
{ type: '10:35', bar: 2, line: 1 },
{ type: '10:40', bar: 1, line: 2 }
{ type: '10:10', bar: 200, line: 1000 },
{ type: '10:15', bar: 600, line: 1000},
{ type: '10:20', bar: 200, line: 1000},
{ type: '10:25', bar: 900, line: 1000},
{ type: '10:30', bar: 200, line: 1000},
{ type: '10:35', bar: 200, line: 1000},
{ type: '10:40', bar: 100, line: 1000}
]
},
height: {
@ -39,6 +39,7 @@
},
data() {
return {
padding: { top:50, right:50, bottom:100, left:50 },
scale: [{
dataKey: 'bar',
min: 0

View File

@ -1,7 +1,7 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart :forceFit="true" :height="height" :data="data">
<v-chart :forceFit="true" :height="254" :data="chartData" :padding="['auto', 'auto', '40', '50']">
<v-tooltip />
<v-axis />
<v-legend />
@ -13,6 +13,11 @@
<script>
import { DataSet } from '@antv/data-set'
const sourceDataConst = [
{ type: 'Jeecg', 'Jan.': 18.9, 'Feb.': 28.8, 'Mar.': 39.3, 'Apr.': 81.4, 'May': 47, 'Jun.': 20.3, 'Jul.': 24, 'Aug.': 35.6 },
{ type: 'Jeebt', 'Jan.': 12.4, 'Feb.': 23.2, 'Mar.': 34.5, 'Apr.': 99.7, 'May': 52.6, 'Jun.': 35.5, 'Jul.': 37.4, 'Aug.': 42.4 },
];
const fieldsConst = ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.'];
export default {
name: 'BarMultid',
props: {
@ -20,62 +25,47 @@
type: String,
default: ''
},
dataSource:{
type: Array,
default: () => [
{ type: 'Jeecg', 'Jan.': 18.9, 'Feb.': 28.8, 'Mar.': 39.3, 'Apr.': 81.4, 'May': 47, 'Jun.': 20.3, 'Jul.': 24, 'Aug.': 35.6 },
{ type: 'Jeebt', 'Jan.': 12.4, 'Feb.': 23.2, 'Mar.': 34.5, 'Apr.': 99.7, 'May': 52.6, 'Jun.': 35.5, 'Jul.': 37.4, 'Aug.': 42.4 }
]
sourceData:{
type:Array,
default:()=>[]
},
fields:{
type: Array,
default: () => ['Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'Jun.', 'Jul.', 'Aug.']
},
// 别名,需要的格式:[{field:'name',alias:'姓名'}, {field:'sex',alias:'性别'}]
aliases:{
type: Array,
default: () => []
},
height: {
type: Number,
default: 254
type:Array,
default:()=>[]
}
},
data() {
return {
chartData:"",
height: 400,
adjust: [{
type: 'dodge',
marginRatio: 1 / 32
}]
marginRatio: 1 / 32,
}],
};
},
watch: {
'sourceData': function () {
this.drawChart();
}
},
computed: {
data() {
const dv = new DataSet.View().source(this.dataSource)
mounted(){
this.drawChart()
},
methods:{
drawChart(){
let temp = sourceDataConst;
if(this.sourceData && this.sourceData.length>0){
temp = this.sourceData
}
const dv = new DataSet.View().source(temp);
dv.transform({
type: 'fold',
fields: this.fields,
fields:(!this.fields||this.fields.length==0)?fieldsConst:this.fields,
key: 'x',
value: 'y'
})
// bar 使用不了 - 和 / 所以替换下
let rows = dv.rows.map(row => {
if (typeof row.x === 'string') {
row.x = row.x.replace(/[-/]/g, '_')
}
return row
})
// 替换别名
rows.forEach(row => {
for (let item of this.aliases) {
if (item.field === row.type) {
row.type = item.alias
break
}
}
})
return rows
value: 'y',
});
this.chartData=dv.rows;
}
}
}

View File

@ -1,6 +1,6 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<v-chart :forceFit="true" :height="350" :data="chartData" :scale="scale">
<v-chart :forceFit="true" :height="300" :data="chartData" :scale="scale">
<v-coord type="polar" :startAngle="-202.5" :endAngle="22.5" :radius="0.75"></v-coord>
<v-axis
dataKey="value"
@ -32,7 +32,7 @@
type="arc"
:zIndex="1"
:start="arcGuide2Start"
:end="getArcGuide2End()"
:end="getArcGuide2End"
:vStyle="arcGuide2Style"
></v-guide>
<v-guide
@ -88,7 +88,7 @@
}];
const data = [
{ value: 0},
{ value: 7.0 },
];
export default {
@ -96,7 +96,7 @@
props:{
datasource:{
type: Number,
default:0
default:7
},
title: {
type: String,

View File

@ -0,0 +1,61 @@
<template>
<div :style="{ padding: '0 0 32px 32px' }">
<h4 :style="{ marginBottom: '20px' }">{{ title }}</h4>
<v-chart
height="254"
:data="datasource"
:forceFit="true"
:padding="['auto', 'auto', '40', '50']">
<v-tooltip />
<v-axis />
<v-bar position="x*y"/>
</v-chart>
</div>
</template>
<script>
const data = []
for (let i = 0; i < 12; i += 1) {
data.push({
x: `${i + 1}`,
y: Math.floor(Math.random() * 1000) + 200
})
}
const tooltip = [
'x*y',
(x, y) => ({
name: x,
value: y
})
]
const scale = [{
dataKey: 'x',
min: 2
}, {
dataKey: 'y',
title: '时间',
min: 1,
max: 22
}]
export default {
name: "Bar",
props: {
title: {
type: String,
default: ''
}
},
mounted(){
this.datasource = data
},
data () {
return {
datasource:[],
scale,
tooltip
}
}
}
</script>

View File

@ -3,7 +3,7 @@
<a-radio v-for="(item, key) in dictOptions" :key="key" :value="item.value">{{ item.text }}</a-radio>
</a-radio-group>
<a-select v-else-if="tagType=='select'" :placeholder="placeholder" :disabled="disabled" :value="value" @change="handleInput">
<a-select v-else-if="tagType=='select'" :getPopupContainer = "(target) => target.parentNode" :placeholder="placeholder" :disabled="disabled" :value="value" @change="handleInput">
<a-select-option value="">请选择</a-select-option>
<a-select-option v-for="(item, key) in dictOptions" :key="key" :value="item.value">
<span style="display: inline-block;width: 100%" :title=" item.text || item.label ">

View File

@ -119,7 +119,7 @@
/** 数据回显*/
loadItemByCode(){
if(!this.value || this.value=="0"){
this.treeValue = ""
this.treeValue = []
}else{
getAction(this.view,{ids:this.value}).then(res=>{
console.log(124345)

View File

@ -76,7 +76,7 @@
<div v-if="rows.length===0" class="tr-nodata">
<span>暂无数据</span>
</div>
<!-- v-model="rows"-->
<!-- v-model="rows"-->
<draggable :value="rows" handle=".td-ds-icons" @end="handleDragMoveEnd">
<!-- 动态生成tr -->
@ -96,10 +96,19 @@
<!-- 左侧固定td -->
<div v-if="dragSort" class="td td-ds" :style="style.tdLeftDs">
<div class="td-ds-icons">
<a-icon type="align-left"/>
<a-icon type="align-right"/>
</div>
<a-dropdown :trigger="['click']" :getPopupContainer="getParentContainer">
<div class="td-ds-icons">
<a-icon type="align-left"/>
<a-icon type="align-right"/>
</div>
<a-menu slot="overlay">
<a-menu-item key="0" :disabled="rowIndex===0" @click="_handleRowMoveUp(rowIndex)">向上移</a-menu-item>
<a-menu-item key="1" :disabled="rowIndex===(rows.length-1)" @click="_handleRowMoveDown(rowIndex)">向下移</a-menu-item>
<a-menu-divider/>
<a-menu-item key="3" @click="_handleRowInsertDown(rowIndex)">插入一行</a-menu-item>
</a-menu>
</a-dropdown>
</div>
<div v-if="rowSelection" class="td td-cb" :style="style.tdLeft">
@ -245,14 +254,24 @@
</a-tooltip>
</template>
<template slot="addonAfter" style="width: 30px">
<a-tooltip title="删除并重新上传">
<a-icon
v-if="file.status!=='uploading'"
type="close-circle"
style="cursor: pointer;"
@click="()=>handleClickDelFile(id)"/>
</a-tooltip>
<template v-if="col.allowDownload!==false || col.allowRemove!==false" slot="addonAfter" style="width: 30px">
<a-dropdown :trigger="['click']" placement="bottomRight" :getPopupContainer="getParentContainer">
<a-tooltip title="操作" :getPopupContainer="getParentContainer">
<a-icon
v-if="file.status!=='uploading'"
type="setting"
style="cursor: pointer;"/>
</a-tooltip>
<a-menu slot="overlay">
<a-menu-item v-if="col.allowDownload!==false" @click="handleClickDownloadFile(id)">
<span><a-icon type="download"/>&nbsp;下载</span>
</a-menu-item>
<a-menu-item v-if="col.allowRemove!==false" @click="handleClickDelFile(id)">
<span><a-icon type="delete"/>&nbsp;删除</span>
</a-menu-item>
</a-menu>
</a-dropdown>
</template>
</a-input>
@ -501,17 +520,33 @@
<div v-else-if="col.type === formTypes.slot" :key="i">
<slot
:name="(col.slot || col.slotName) || col.key"
:index="rowIndex"
:text="inputValues[rowIndex][col.key]"
:column="col"
:rowId="removeCaseId(row.id)"
:getValue="()=>_getValueForSlot(row.id)"
:caseId="caseId"
:allValues="_getAllValuesForSlot()"
:target="getVM()"
/>
<a-tooltip
:key="i"
:id="id"
placement="top"
:title="(tooltips[id] || {}).title"
:visible="(tooltips[id] || {}).visible || false"
:autoAdjustOverflow="true">
<span
@mouseover="()=>{handleMouseoverCommono(row,col)}"
@mouseout="()=>{handleMouseoutCommono(row,col)}">
<slot
:name="(col.slot || col.slotName) || col.key"
:index="rowIndex"
:text="slotValues[id]"
:value="slotValues[id]"
:column="col"
:rowId="removeCaseId(row.id)"
:getValue="()=>_getValueForSlot(row.id)"
:caseId="caseId"
:allValues="_getAllValuesForSlot()"
:target="getVM()"
:handleChange="(v)=>handleChangeSlotCommon(v,id,row,col)"
:isNotPass="notPassedIds.includes(col.key+row.id)"
/>
</span>
</a-tooltip>
</div>
<!-- else (normal) -->
@ -636,15 +671,17 @@
checkboxValues: {},
// 绑定 jdate 的值
jdateValues: {},
// 绑定插槽数据
slotValues: {},
// file 信息
uploadValues: {},
//popup信息
popupValues:{},
popupValues: {},
radioValues:{},
metaCheckboxValues:{},
multiSelectValues:{},
searchSelectValues:{},
radioValues: {},
metaCheckboxValues: {},
multiSelectValues: {},
searchSelectValues: {},
// 绑定左侧选择框已选择的id
selectedRowIds: [],
// 存储被删除行的id
@ -717,9 +754,9 @@
},
// 侦听器
watch: {
rows:{
immediate:true,
handler(val,old) {
rows: {
immediate: true,
handler(val, old) {
// val.forEach(item => {
// for (let inputValue of this.inputValues) {
// if (inputValue.id === item.id) {
@ -740,8 +777,9 @@
let checkboxValues = {}
let selectValues = {}
let jdateValues = {}
let slotValues = {}
let uploadValues = {}
let popupValues={}
let popupValues = {}
let radioValues = {}
let multiSelectValues = {}
let searchSelectValues = {}
@ -783,9 +821,9 @@
} else if (column.type === FormTypes.slot) {
if (sourceValue !== 0 && !sourceValue) {
value[column.key] = column.defaultValue
slotValues[inputId] = column.defaultValue
} else {
value[column.key] = sourceValue
slotValues[inputId] = sourceValue
}
} else if (column.type === FormTypes.popup) {
@ -795,18 +833,18 @@
} else if (column.type === FormTypes.sel_search) {
searchSelectValues[inputId] = sourceValue
} else if (column.type === FormTypes.list_multi) {
if(sourceValue.length>0){
multiSelectValues[inputId] = sourceValue.split(",")
}else{
if (sourceValue.length > 0) {
multiSelectValues[inputId] = sourceValue.split(',')
} else {
multiSelectValues[inputId] = []
}
} else if (column.type === FormTypes.file || column.type === FormTypes.image) {
if(sourceValue){
let fileName = sourceValue.substring(sourceValue.lastIndexOf("/")+1)
} else if (column.type === FormTypes.upload || column.type === FormTypes.file || column.type === FormTypes.image) {
if (sourceValue) {
let fileName = sourceValue.substring(sourceValue.lastIndexOf('/') + 1)
uploadValues[inputId] = {
name: fileName,
status: 'done',
path:sourceValue
path: sourceValue
}
}
} else {
@ -839,6 +877,7 @@
this.checkboxValues = checkboxValues
this.selectValues = selectValues
this.jdateValues = jdateValues
this.slotValues = slotValues
this.rows = rows
this.uploadValues = uploadValues
this.popupValues = popupValues
@ -935,12 +974,13 @@
this.selectValues = {}
this.checkboxValues = {}
this.jdateValues = {}
this.slotValues = {}
this.selectedRowIds = []
this.tooltips = {}
this.notPassedIds = []
this.uploadValues=[]
this.popupValues=[]
this.radioValues=[]
this.uploadValues = []
this.popupValues = []
this.radioValues = []
this.multiSelectValues = []
this.searchSelectValues = []
this.scrollTop = 0
@ -987,7 +1027,7 @@
return `${this.caseId}${timestamp}${rows.length}`
},
/** push 一条数据 */
push(record, update = true, rows) {
push(record, update = true, rows, insertIndex = null) {
if (!(rows instanceof Array)) {
rows = cloneObject(this.rows) || []
}
@ -1005,6 +1045,7 @@
let checkboxValues = Object.assign({}, this.checkboxValues)
let selectValues = Object.assign({}, this.selectValues)
let jdateValues = Object.assign({}, this.jdateValues)
let slotValues = Object.assign({}, this.slotValues)
this.columns.forEach(column => {
let key = column.key
let inputId = key + row.id
@ -1039,17 +1080,23 @@
jdateValues[inputId] = recordHasValue ? record[key] : column.defaultValue
} else if (column.type === FormTypes.slot) {
value[key] = recordHasValue ? record[key] : (column.defaultValue || '')
slotValues[inputId] = recordHasValue ? record[key] : (column.defaultValue || '')
} else {
value[key] = recordHasValue ? record[key] : ''
}
})
rows.push(row)
this.inputValues.push(value)
if (typeof insertIndex === 'number') {
rows.splice(insertIndex, 0, row)
this.inputValues.splice(insertIndex, 0, value)
} else {
rows.push(row)
this.inputValues.push(value)
}
this.checkboxValues = checkboxValues
this.selectValues = selectValues
this.jdateValues = jdateValues
this.slotValues = slotValues
if (this.dragSort) {
this.inputValues.forEach((item, index) => {
@ -1097,17 +1144,16 @@
}
this.rows = rows
let rowValue = this.getValuesSync({
validate: false,
rowIds: [this.removeCaseId(row.id)]
}).values[0]
this.$nextTick(() => {
this.updateFormValues()
})
// 触发add事件
this.$emit('added', {
row: rowValue,
row: (() => {
let r = Object.assign({}, row)
r.id = this.removeCaseId(r.id)
return r
})(),
target: this
})
// 设置滚动条位置
@ -1124,6 +1170,36 @@
tbody.scrollTop = tbody.scrollHeight
})
},
/**
* 在指定位置添加一行
* @param insertIndex 添加位置下标
* @param num 添加的行数默认1
*/
insert(insertIndex, num = 1) {
if (!insertIndex && num < 1) return
let rows = this.rows
let newRows = []
for (let i = 0; i < num; i++) {
let row = { id: this.generateId(rows) }
rows = this.push(row, false, rows, insertIndex)
newRows.push(row)
}
// 同步更改
this.rows = rows
this.$nextTick(() => {
this.updateFormValues()
})
// 触发 insert 事件
this.$emit('inserted', {
rows: newRows.map(row => {
let r = cloneObject(row)
r.id = this.removeCaseId(r.id)
return r
}),
num, insertIndex,
target: this
})
},
/** 删除被选中的行 */
removeSelectedRows() {
this.removeRows(this.selectedRowIds)
@ -1161,7 +1237,7 @@
}
})
this.rows = rows
this.$emit('deleted', this.getDeleteIds())
this.$emit('deleted', this.getDeleteIds(), this)
this.$nextTick(() => {
// 更新formValues
this.updateFormValues()
@ -1225,24 +1301,26 @@
} else if (column.type === FormTypes.image || column.type === FormTypes.file) {
let currUploadObj = cloneObject(this.uploadValues[inputId] || null)
if(currUploadObj){
if (currUploadObj) {
value[column.key] = currUploadObj['path'] || null
}
} else if (column.type === FormTypes.popup) {
if(!value[column.key]){
if (!value[column.key]) {
value[column.key] = this.popupValues[inputId] || null
}
} else if (column.type === FormTypes.radio) {
value[column.key] = this.radioValues[inputId]
}else if (column.type === FormTypes.sel_search) {
} else if (column.type === FormTypes.sel_search) {
value[column.key] = this.searchSelectValues[inputId]
}else if (column.type === FormTypes.list_multi) {
if(!this.multiSelectValues[inputId] || this.multiSelectValues[inputId].length==0){
} else if (column.type === FormTypes.list_multi) {
if (!this.multiSelectValues[inputId] || this.multiSelectValues[inputId].length == 0) {
value[column.key] = ''
}else{
value[column.key] = this.multiSelectValues[inputId].join(",")
} else {
value[column.key] = this.multiSelectValues[inputId].join(',')
}
} else if (column.type === FormTypes.slot) {
value[column.key] = this.slotValues[inputId]
}
@ -1326,6 +1404,7 @@
selectValues: this.selectValues,
checkboxValues: this.checkboxValues,
jdateValues: this.jdateValues,
slotValues: this.slotValues,
uploadValues: this.uploadValues,
popupValues: this.popupValues,
radioValues: this.radioValues,
@ -1371,6 +1450,11 @@
this.jdateValues[modelKey] = newValue
edited = true
}
// 在 slotValues 中寻找值
if (!edited && this.slotValues.hasOwnProperty(modelKey)) {
this.slotValues[modelKey] = newValue
edited = true
}
}
}
})
@ -1397,7 +1481,7 @@
let inputId = column.key + row.id
tooltips[inputId] = tooltips[inputId] ? tooltips[inputId] : {}
let [passed, message] = this.validateValue(column.validateRules, value)
let [passed, message] = this.validateValue(column, value)
const nextThen = res => {
let [passed, message] = res
@ -1433,6 +1517,9 @@
}
element.style.borderColor = borderColor
element.style.boxShadow = boxShadow
if (element.tagName === 'SPAN') {
element.style.display = 'block'
}
}
// 是否更新到data
if (update) {
@ -1450,23 +1537,22 @@
if (typeof msg === 'string') {
message = msg
}
if (flag == null) {
nextThen([null, message])
}else if (typeof flag === 'boolean' && flag) {
if (flag == null || flag === true) {
nextThen([true, message])
} else {
nextThen([false, message])
}
}, this)
} else {
nextThen([passed, message])
}
return [tooltips[inputId], notPassedIds]
},
/** 通过规则验证值是否正确 */
validateValue(rules, value) {
validateValue(column, value) {
let rules = column.validateRules
let passed = true, message = ''
// 判断有没有验证规则或验证规则格式正不正确,若条件不符合则默认通过
if (rules instanceof Array) {
@ -1477,12 +1563,24 @@
if (rule.required === true && isNull) {
passed = false
} else // 使用 else-if 是为了防止一个 rule 中出现两个规则
// 验证规则:唯一校验
if (rule.unique === true || rule.pattern === 'only') {
let { values } = this.getValuesSync({ validate: false })
let findCount = 0
for (let val of values) {
if (val[column.key] === value) {
if (++findCount >= 2) {
passed = false
break
}
}
}
} else
// 验证规则:正则表达式
if (!!rule.pattern && !isNull) {
// 兼容 online 的规则
let foo = [
{ title: '唯一校验', value: 'only', pattern: null },
{ title: '6到16位数字', value: 'n6-16', pattern: /\d{6,18}/ },
{ title: '6到16位任意字符', value: '*6-16', pattern: /^.{6,16}$/ },
{ title: '网址', value: 'url', pattern: /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/ },
@ -1491,7 +1589,7 @@
{ title: '邮政编码', value: 'p', pattern: /^[1-9]\d{5}$/ },
{ title: '字母', value: 's', pattern: /^[A-Z|a-z]+$/ },
{ title: '数字', value: 'n', pattern: /^-?\d+\.?\d*$/ },
{ title: '整数', value: 'z', pattern: /^[1-9]\d*$/ },
{ title: '整数', value: 'z', pattern: /^-?\d+$/ },
{ title: '非空', value: '*', pattern: /^.+$/ },
{ title: '6到18位字符串', value: 's6-18', pattern: /^.{6,18}$/ },
{ title: '金额', value: 'money', pattern: /^(([1-9][0-9]*)|([0]\.\d{0,2}|[1-9][0-9]*\.\d{0,2}))$/ },
@ -1505,7 +1603,9 @@
}
}
if (!flag) passed = new RegExp(rule.pattern).test(value)
} else if (typeof rule.handler === 'function') {
} else
// 校验规则:自定义函数校验
if (typeof rule.handler === 'function') {
return [rule.handler, rule.message]
}
// 如果没有通过验证,则跳出循环。如果通过了验证,则继续验证下一条规则
@ -1652,6 +1752,11 @@
}
},
/** 触发已拖动事件 */
emitDragged(oldIndex, newIndex) {
this.$emit('dragged', { oldIndex, newIndex, target: this })
},
/** 拖动结束交换inputValue中的值 */
handleDragMoveEnd(event) {
let { oldIndex, newIndex, item: { dataset: { idx: dataIdx } } } = event
@ -1662,13 +1767,7 @@
newIndex += diff
this.rowResort(oldIndex, newIndex)
// 触发已拖动事件
this.$emit('dragged', {
oldIndex,
newIndex,
target: this
})
this.emitDragged(oldIndex, newIndex)
},
/** 行重新排序 */
@ -1690,6 +1789,30 @@
this.forceUpdateFormValues()
},
/** 当前行向上移一位 */
_handleRowMoveUp(rowIndex) {
if (rowIndex > 0) {
let newIndex = rowIndex - 1
this.rowResort(rowIndex, newIndex)
this.emitDragged(rowIndex, newIndex)
}
},
/** 当前行向下移一位 */
_handleRowMoveDown(rowIndex) {
if (rowIndex < (this.rows.length - 1)) {
let newIndex = rowIndex + 1
this.rowResort(rowIndex, newIndex)
this.emitDragged(rowIndex, newIndex)
}
},
/** 在当前行下面插入一行 */
_handleRowInsertDown(rowIndex) {
let insertIndex = (rowIndex + 1)
this.insert(insertIndex)
},
/* --- common function begin --- */
/** 鼠标移入 */
@ -1732,6 +1855,14 @@
this.elemValueChange(type, row, column, value)
}
},
/** slot Change */
handleChangeSlotCommon(value, id, row, column) {
this.slotValues = this.bindValuesChange(value, id, 'slotValues')
// 做单个表单验证
this.validateOneInput(value, row, column, this.notPassedIds, true, 'change')
// 触发valueChange 事件
this.elemValueChange(FormTypes.slot, row, column, value)
},
handleBlurCommono(target, index, row, column) {
let { value } = target
// 做单个表单验证
@ -1775,16 +1906,18 @@
if (column.responseName && file.response) {
value['responseName'] = file.response[column.responseName]
}
if(file.status =='done'){
if (file.status == 'done') {
value['path'] = file.response[column.responseName]
}
this.uploadValues = this.bindValuesChange(value, id, 'uploadValues')
},
/** 记录用到数据绑定的组件的值 */
bindValuesChange(value, id, key) {
let values = Object.assign({}, this[key])
values[id] = value
return values
// let values = Object.assign({}, this[key])
// values[id] = value
// return values
this.$set(this[key], id, value)
return this[key]
},
/** 显示或隐藏tooltip */
@ -1823,7 +1956,13 @@
handleClickDelFile(id) {
this.uploadValues[id] = null
},
handleClickDownloadFile(id) {
let { path } = this.uploadValues[id] || {}
if (path) {
let url = window._CONFIG['downloadUrl'] + '/' + path
window.open(url)
}
},
/** 加载数据字典并合并到 options */
_loadDictConcatToOptions(column) {
initDictOptions(column.dictCode).then((res) => {
@ -1980,42 +2119,42 @@
return headers
},
/** 上传请求地址 */
getUploadAction(value){
if(!value){
return window._CONFIG['domianURL']+"/sys/common/upload"
}else{
getUploadAction(value) {
if (!value) {
return window._CONFIG['domianURL'] + '/sys/common/upload'
} else {
return value
}
},
/** 预览图片地址 */
getCellImageView(id){
getCellImageView(id) {
let currUploadObj = this.uploadValues[id] || null
if(currUploadObj && currUploadObj['path']){
return window._CONFIG['domianURL']+"/sys/common/view/"+currUploadObj['path']
}else{
if (currUploadObj && currUploadObj['path']) {
return window._CONFIG['domianURL'] + '/sys/common/view/' + currUploadObj['path']
} else {
return ''
}
},
/** popup回调 */
popupCallback(value,others,id,row,column,index){
popupCallback(value, others, id, row, column, index) {
// 存储输入的值
this.popupValues[id]=value
if(others){
Object.keys(others).map((key)=>{
this.popupValues[id] = value
if (others) {
Object.keys(others).map((key) => {
this.inputValues[index][key] = others[key]
})
}
// 做单个表单验证
this.validateOneInput(value, row, column, this.notPassedIds, true, 'change')
// 触发valueChange 事件
this.elemValueChange("input", row, column, value)
this.elemValueChange('input', row, column, value)
// 更新form表单的值
this.$nextTick(() => {
this.forceUpdateFormValues()
})
},
/** popup输入框回显 */
getPopupValue(id){
getPopupValue(id) {
return this.popupValues[id]
},
handleRadioChange(value, id, row, column) {

View File

@ -14,6 +14,7 @@
import Editor from '@tinymce/tinymce-vue'
import 'tinymce/themes/silver/theme'
import 'tinymce/plugins/image'
import 'tinymce/plugins/link'
import 'tinymce/plugins/media'
import 'tinymce/plugins/table'
import 'tinymce/plugins/lists'
@ -42,11 +43,12 @@
},
plugins: {
type: [String, Array],
default: 'lists image media table textcolor wordcount contextmenu fullscreen'
default: 'lists image link media table textcolor wordcount contextmenu fullscreen'
},
toolbar: {
type: [String, Array],
default: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists image media table | removeformat | fullscreen'
default: 'undo redo | formatselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | lists link unlink image media table | removeformat | fullscreen',
branding:false
}
},
data() {

View File

@ -1,11 +1,22 @@
<template>
<div class="j-super-query-box">
<slot>
<a-tooltip v-if="superQueryFlag" title="已有高级查询条件生效">
<a-button type="primary" @click="visible=true">
<a-icon type="appstore" theme="twoTone" :spin="true"></a-icon>
<span>高级查询</span>
</a-button>
</a-tooltip>
<a-button v-else type="primary" icon="filter" @click="visible=true">高级查询</a-button>
</slot>
<a-modal
title="高级查询构造器"
:width="1000"
:visible="visible"
@cancel="handleCancel"
:mask="false"
wrapClassName="ant-modal-cust-warp"
class="j-super-query-modal"
style="top:5%;max-height: 95%;">
@ -33,7 +44,7 @@
<a-form v-else layout="inline">
<a-form-item label="过滤条件匹配" style="margin-bottom: 12px;">
<a-select v-model="selectValue">
<a-select v-model="selectValue" :getPopupContainer="node=>node.parentNode">
<a-select-option value="and">AND所有条件都要求匹配</a-select-option>
<a-select-option value="or">OR条件中的任意一个匹配</a-select-option>
</a-select>
@ -42,13 +53,23 @@
<a-row type="flex" style="margin-bottom:10px" :gutter="16" v-for="(item, index) in queryParamsModel" :key="index">
<a-col :span="8">
<a-select placeholder="选择查询字段" v-model="item.field" @select="(val,option)=>handleSelected(option,item)">
<a-select-option v-for="(f,fIndex) in fieldList" :key=" 'field'+fIndex" :value="f.value" :data-idx="fIndex">{{ f.text }}</a-select-option>
</a-select>
<a-tree-select
showSearch
v-model="item.field"
:treeData="fieldTreeData"
:dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
placeholder="选择查询字段"
allowClear
treeDefaultExpandAll
:getPopupContainer="node=>node.parentNode"
style="width: 100%"
@select="(val,option)=>handleSelected(option,item)"
>
</a-tree-select>
</a-col>
<a-col :span="4">
<a-select placeholder="匹配规则" v-model="item.rule">
<a-select placeholder="匹配规则" v-model="item.rule" :getPopupContainer="node=>node.parentNode">
<a-select-option value="eq">等于</a-select-option>
<a-select-option value="ne">不等于</a-select-option>
<a-select-option value="gt">大于</a-select-option>
@ -90,6 +111,7 @@
placeholder="请选择部门"
:customReturnField="item.customReturnField || 'id'"
/>
<a-select v-else-if="item.options instanceof Array" v-model="item.val" :options="item.options" allowClear placeholder="请选择"/>
<j-date v-else-if=" item.type=='date' " v-model="item.val" placeholder="请选择日期" style="width: 100%"></j-date>
<j-date v-else-if=" item.type=='datetime' " v-model="item.val" placeholder="请选择时间" :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" style="width: 100%"></j-date>
<a-input-number v-else-if=" item.type=='int'||item.type=='number' " style="width: 100%" placeholder="请输入数值" v-model="item.val"/>
@ -137,6 +159,7 @@
</a-modal>
</a-modal>
</div>
</template>
<script>
@ -186,6 +209,7 @@
},
data() {
return {
fieldTreeData: [],
prompt: {
visible: false,
@ -199,6 +223,7 @@
// 保存查询条件的前缀名
saveCodeBefore: 'JSuperQuerySaved_',
selectValue: 'and',
superQueryFlag: false
}
},
watch: {
@ -214,6 +239,35 @@
})
}
}
},
fieldList: {
deep: true,
immediate: true,
handler(val) {
let mainData = [], subData = []
val.forEach(item => {
let data = { ...item }
data.label = data.label || data.text
let hasChildren = (data.children instanceof Array)
data.disabled = hasChildren
data.selectable = !hasChildren
if (hasChildren) {
data.children = data.children.map(item2 => {
let child = { ...item2 }
child.label = child.label || child.text
child.label = data.label + '-' + child.label
child.value = data.value + ',' + child.value
child.val = ''
return child
})
data.val = ''
subData.push(data)
} else {
mainData.push(data)
}
})
this.fieldTreeData = mainData.concat(subData)
}
}
},
@ -225,17 +279,21 @@
this.visible = true
},
handleOk() {
console.log('---高级查询参数--->', this.queryParamsModel)
if (!this.isNullArray(this.queryParamsModel)) {
let event = {
matchType: this.selectValue,
params: this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
}
this.$emit(this.callback, event.params, event.matchType)
console.log('---高级查询参数--->', event)
this.emitCallback(event.params, event.matchType)
} else {
this.$emit(this.callback)
this.emitCallback()
}
},
emitCallback(params, matchType) {
this.superQueryFlag = !!params
this.$emit(this.callback, params, matchType)
},
handleCancel() {
this.close()
},
@ -249,19 +307,19 @@
handleDel(index) {
this.queryParamsModel.splice(index, 1)
},
handleSelected(option, item) {
let index = option.data.attrs['data-idx']
let { type, dictCode, dictTable, customReturnField } = this.fieldList[index]
handleSelected(node, item) {
let { type, options, dictCode, dictTable, customReturnField } = node.dataRef
item['type'] = type
item['options'] = options
item['dictCode'] = dictCode
item['dictTable'] = dictTable
item['customReturnField'] = customReturnField
this.$set(item, 'val', '')
this.$set(item, 'val', undefined)
},
handleReset() {
this.superQueryFlag = false
this.queryParamsModel = [{}]
this.$emit(this.callback)
this.emitCallback()
},
handleSave() {
let queryParams = this.removeEmptyObject(utils.cloneObject(this.queryParamsModel))
@ -332,7 +390,7 @@
}
if (array.length === 1) {
let obj = array[0]
if (!obj.field || !obj.val || !obj.rule) {
if (!obj.field || (obj.val == null || obj.val === '') || !obj.rule) {
return true
}
}
@ -344,6 +402,9 @@
let item = array[i]
if (item == null || Object.keys(item).length <= 0) {
array.splice(i--, 1)
} else {
// 去掉特殊属性
delete item.options
}
}
return array
@ -354,10 +415,11 @@
<style lang="scss" scoped>
.j-super-query-modal {
.j-super-query-box {
display: inline-block;
}
/deep/ {
}
.j-super-query-modal {
.j-super-query-history-card /deep/ {
.ant-card-body,

View File

@ -22,7 +22,7 @@
data(){
return {
treeData:[],
treeValue:"",
treeValue: null,
url_root:"/sys/category/loadTreeRoot",
url_children:"/sys/category/loadTreeChildren",
url_view:'/sys/category/loadOne',
@ -97,7 +97,7 @@
methods:{
loadViewInfo(){
if(!this.value || this.value=="0"){
this.treeValue = ""
this.treeValue = null
}else{
let param = {
field:this.field,

View File

@ -77,7 +77,7 @@
},
data () {
return {
treeValue:"",
treeValue: null,
treeData:[],
url:"/sys/dict/loadTreeData",
view:'/sys/dict/loadDictItem/',
@ -106,7 +106,7 @@
methods: {
loadItemByCode(){
if(!this.value || this.value=="0"){
this.treeValue = ""
this.treeValue = null
}else{
getAction(`${this.view}${this.dict}`,{key:this.value}).then(res=>{
if(res.success){
@ -211,7 +211,7 @@
onChange(value){
if(!value){
this.$emit('change', '');
this.treeValue = ''
this.treeValue = null
} else if (value instanceof Array) {
this.$emit('change', value.map(item => item.value).join(','))
this.treeValue = value

View File

@ -61,7 +61,7 @@
default:"temp"
},
value:{
type:String,
type:[String,Array],
required:false
},
// update-begin- --- author:wangshuai ------ date:20190929 ---- for:Jupload组件增加是否能够点击
@ -80,7 +80,11 @@
},
watch:{
value(val){
this.initFileList(val)
if (val instanceof Array) {
this.initFileList(val.join(','))
} else {
this.initFileList(val)
}
}
},
created(){

View File

@ -2,7 +2,7 @@
<a-modal
centered
:title="name + '选择'"
:width="900"
:width="width"
:visible="visible"
@ok="handleOk"
@cancel="close"
@ -17,7 +17,7 @@
<a-col :span="14">
<a-form-item :label="(queryParamText||name)">
<a-input :placeholder="'请输入' + (queryParamText||name)" v-model="queryParam[valueKey]"></a-input>
<a-input v-model="queryParam[queryParamCode||valueKey]" :placeholder="'请输入' + (queryParamText||name)" @pressEnter="searchQuery"/>
</a-form-item>
</a-col>
<a-col :span="8">
@ -34,8 +34,8 @@
<a-table
size="small"
bordered
rowKey="id"
:columns="columns"
:rowKey="rowKey"
:columns="innerColumns"
:dataSource="dataSource"
:pagination="ipagination"
:loading="loading"
@ -49,7 +49,7 @@
<a-col :span="8">
<a-card :title="'已选' + name" :bordered="false" :head-style="{padding:0}" :body-style="{padding:0}">
<a-table rowKey="id" size="small" bordered v-bind="selectedTable">
<a-table size="small" :rowKey="rowKey" bordered v-bind="selectedTable">
<span slot="action" slot-scope="text, record, index">
<a @click="handleDeleteSelected(record, index)">删除</a>
</span>
@ -62,7 +62,9 @@
</template>
<script>
import { getAction } from '@/api/manage'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import { cloneObject, pushIfNotExist } from '@/utils/util'
export default {
name: 'JSelectBizComponentModal',
@ -84,6 +86,10 @@
type: Boolean,
default: true
},
width: {
type: Number,
default: 900
},
name: {
type: String,
@ -94,60 +100,110 @@
required: true,
default: ''
},
// 根据 value 获取显示文本的地址,例如存的是 username可以通过该地址获取到 realname
valueUrl: {
type: String,
default: ''
},
displayKey: {
type: String,
default: null
},
propColumns: {
columns: {
type: Array,
required: true,
default: () => []
},
// 查询条件Code
queryParamCode: {
type: String,
default: null
},
// 查询条件文字
queryParamText: {
type: String,
default: null
},
rowKey: {
type: String,
default: 'id'
},
},
data() {
return {
innerValue: [],
// 表头
columns: this.propColumns,
innerColumns: this.columns,
// 已选择列表
selectedTable: {
pagination: false,
scroll: { y: 240 },
columns: [
this.propColumns[0],
{
...this.columns[0],
width: this.columns[0].widthRight || this.columns[0].width,
},
{ title: '操作', dataIndex: 'action', align: 'center', width: 60, scopedSlots: { customRender: 'action' }, }
],
dataSource: [],
},
url: { list: this.listUrl }
url: { list: this.listUrl },
/* 分页参数 */
ipagination: {
current: 1,
pageSize: 5,
pageSizeOptions: ['5', '10', '20', '30'],
showTotal: (total, range) => {
return range[0] + '-' + range[1] + ' 共' + total + '条'
},
showQuickJumper: true,
showSizeChanger: true,
total: 0
},
options: [],
dataSourceMap: {},
}
},
watch: {
value: {
deep: true,
immediate: true,
handler(val) {
this.innerValue = cloneObject(val)
this.selectedRowKeys = []
this.valueWatchHandler(val)
this.queryOptionsByValue(val)
}
},
dataSource: {
deep: true,
handler(val) {
let options = val.map(data => ({ label: data[this.displayKey || this.valueKey], value: data[this.valueKey] }))
this.$emit('ok', options)
this.valueWatchHandler(this.value)
this.emitOptions(val)
this.valueWatchHandler(this.innerValue)
}
},
selectionRows: {
selectedRowKeys: {
immediate: true,
deep: true,
handler(val) {
this.selectedTable.dataSource = val
this.selectedTable.dataSource = val.map(key => {
for (let data of this.dataSource) {
if (data[this.rowKey] === key) {
pushIfNotExist(this.innerValue, data[this.valueKey])
return data
}
}
for (let data of this.selectedTable.dataSource) {
if (data[this.rowKey] === key) {
pushIfNotExist(this.innerValue, data[this.valueKey])
return data
}
}
console.warn('未找到选择的行信息key' + key)
return {}
})
},
},
}
},
methods: {
@ -158,18 +214,63 @@
},
valueWatchHandler(val) {
let dataSource = []
let selectedRowKeys = []
val.forEach(item => {
this.dataSource.forEach(data => {
this.dataSource.concat(this.selectedTable.dataSource).forEach(data => {
if (data[this.valueKey] === item) {
dataSource.push(data)
selectedRowKeys.push(data.id)
pushIfNotExist(this.selectedRowKeys, data[this.rowKey])
}
})
})
this.selectedTable.dataSource = dataSource
this.selectedRowKeys = selectedRowKeys
},
queryOptionsByValue(value) {
if (!value || value.length === 0) {
return
}
// 判断options是否存在value如果已存在数据就不再请求后台了
let notExist = false
for (let val of value) {
let find = false
for (let option of this.options) {
if (val === option.value) {
find = true
break
}
}
if (!find) {
notExist = true
break
}
}
if (!notExist) return
getAction(this.valueUrl || this.listUrl, {
// 这里最后加一个 , 的原因是因为无论如何都要使用 in 查询,防止后台进行了模糊匹配,导致查询结果不准确
[this.valueKey]: value.join(',') + ',',
pageNo: 1,
pageSize: value.length
}).then((res) => {
if (res.success) {
let dataSource = res.result
if (!(dataSource instanceof Array)) {
dataSource = res.result.records
}
this.emitOptions(dataSource, (data) => {
pushIfNotExist(this.innerValue, data[this.valueKey])
pushIfNotExist(this.selectedRowKeys, data[this.rowKey])
pushIfNotExist(this.selectedTable.dataSource, data, this.rowKey)
})
}
})
},
emitOptions(dataSource, callback) {
dataSource.forEach(data => {
let key = data[this.valueKey]
this.dataSourceMap[key] = data
pushIfNotExist(this.options, { label: data[this.displayKey || this.valueKey], value: key }, 'value')
typeof callback === 'function' ? callback(data) : ''
})
this.$emit('options', this.options, this.dataSourceMap)
},
/** 完成选择 */
@ -181,22 +282,30 @@
/** 删除已选择的 */
handleDeleteSelected(record, index) {
this.selectedRowKeys.splice(this.selectedRowKeys.indexOf(record.id), 1)
this.selectedRowKeys.splice(this.selectedRowKeys.indexOf(record[this.rowKey]), 1)
this.selectedTable.dataSource.splice(index, 1)
},
customRowFn(record) {
if (!this.multiple) {
return {
on: {
click: () => {
this.selectedRowKeys = [record.id]
return {
on: {
click: () => {
let key = record[this.rowKey]
if (!this.multiple) {
this.selectedRowKeys = [key]
this.selectedTable.dataSource = [record]
} else {
let index = this.selectedRowKeys.indexOf(key)
if (index === -1) {
this.selectedRowKeys.push(key)
this.selectedTable.dataSource.push(record)
} else {
this.handleDeleteSelected(record, index)
}
}
}
}
}
return {}
},
}

View File

@ -16,11 +16,21 @@ export default {
### 配置参数
- `name`:`String` 显示名字,例如选择部门就填写'部门'
- `listUrl`:`String` 数据请求地址,必须是封装了分页的地址
- `displayKey`:`String` 显示在标签上的字段 key
- `returnKeys`:`Array` v-model 绑定的 keys是个数组默认使用第二项当配置了 `returnId=true` 就返回第一项
- `returnId`:`Boolean` 返回ID设为true后将返回配置的 `returnKeys` 中的第一项
- `selectButtonText`:`String` 选择按钮的文字
- `queryParamText`:`String` 查询条件显示文字
- `columns`:`Array` 列配置项与a-table的列配置项相同会将第一项配置成已选择的列表
| 参数名 | 类型 | 必填 | 默认值 | 备注 |
|-----------------------|---------|------|--------------|--------------------------------------------------------------------------------------|
| rowKey | String | | "id" | 唯一标识的字段名 |
| value(v-model) | String | | "" | 默认选择的数据,多个用半角逗号分割 |
| name | String | | "" | 显示名字,例如选择用户就填写"用户" |
| listUrl | String | 是 | | 数据请求地址,必须是封装了分页的地址 |
| valueUrl | String | | "" | 获取显示文本的地址,例如存的是 username可以通过该地址获取到 realname |
| displayKey | String | | null | 显示在标签上的字段 key ,不传则直接显示数据 |
| returnKeys | Array | | ['id', 'id'] | v-model 绑定的 keys是个数组默认使用第二项当配置了 `returnId=true` 就返回第一项 |
| returnId | Boolean | | false | 返回ID设为true后将返回配置的 `returnKeys` 中的第一项 |
| selectButtonText | String | | "选择" | 选择按钮的文字 |
| queryParamText | String | | null | 查询条件显示文字,不传则使用 `name` |
| columns | Array | 是 | | 列配置项与antd的table的配置完全一致。列的第一项会被配置成右侧已选择的列表上 |
| columns[0].widthRight | Array | | null | 仅列的第一项可以应用此配置,表示右侧已选择列表的宽度,建议 `70%`,不传则应用`width` |
| placeholder | String | | "请选择" | 占位符 |
| disabled | Boolean | | false | 是否禁用 |
| multiple | Boolean | | false | 是否可多选 |
| buttons | Boolean | | true | 是否显示"选择"按钮,如果不显示,可以直接点击文本框打开选择界面 |

View File

@ -1,17 +1,19 @@
<template>
<a-row class="j-select-biz-component-box" type="flex" :gutter="8">
<a-col class="left" :class="{'full': !buttons}">
<a-select
mode="multiple"
:placeholder="placeholder"
v-model="selectValue"
:options="selectOptions"
allowClear
:disabled="disabled"
:open="false"
style="width: 100%;"
@click.native="visible=(buttons?visible:true)"
/>
<slot name="left">
<a-select
mode="multiple"
:placeholder="placeholder"
v-model="selectValue"
:options="selectOptions"
allowClear
:disabled="disabled"
:open="false"
style="width: 100%;"
@click.native="visible=(buttons?visible:true)"
/>
</slot>
</a-col>
<a-col v-if="buttons" class="right">
@ -20,11 +22,9 @@
<j-select-biz-component-modal
v-model="selectValue"
:name="name" :listUrl="listUrl" :returnKeys="returnKeys" :displayKey="displayKey"
:propColumns="columns" :queryParamText="queryParamText" :multiple="multiple"
:visible.sync="visible"
:valueKey="valueKey"
@ok="selectOptions=$event"
v-bind="modalProps"
@options="handleOptions"
/>
</a-row>
</template>
@ -63,20 +63,6 @@
type: Boolean,
default: true
},
/* 可复用属性 */
// 被选择的名字,例如选择部门就填写'部门'
name: {
type: String,
default: ''
},
// list 接口地址
listUrl: {
type: String,
required: true,
default: ''
},
// 显示的 Key
displayKey: {
type: String,
@ -92,29 +78,28 @@
type: String,
default: '选择'
},
// 查询条件文字
queryParamText: {
type: String,
default: null
},
// columns
columns: {
type: Array,
default: () => []
}
},
data() {
return {
selectValue: [],
selectOptions: [],
dataSourceMap: {},
visible: false
}
},
computed: {
valueKey() {
return this.returnId ? this.returnKeys[0] : this.returnKeys[1]
}
},
modalProps() {
return Object.assign({
valueKey: this.valueKey,
multiple: this.multiple,
returnKeys: this.returnKeys,
displayKey: this.displayKey || this.valueKey
}, this.$attrs)
},
},
watch: {
value: {
@ -130,23 +115,23 @@
selectValue: {
deep: true,
handler(val) {
const data = val.join(',')
let rows = val.map(key => this.dataSourceMap[key])
this.$emit('select', rows)
let data = val.join(',')
this.$emit('input', data)
this.$emit('change', data)
}
}
},
methods: {}
methods: {
handleOptions(options, dataSourceMap) {
this.selectOptions = options
this.dataSourceMap = dataSourceMap
},
}
}
</script>
<style lang="scss">
.j-select-biz-component-box {
.ant-select-search__field {
display: none !important;
}
}
</style>
<style lang="scss" scoped>
.j-select-biz-component-box {
@ -163,5 +148,11 @@
.full {
width: 100%;
}
/deep/ {
.ant-select-search__field {
display: none !important;
}
}
}
</style>

View File

@ -1,16 +1,11 @@
<template>
<!-- 定义在这里的参数都是不可在外部覆盖的防止出现问题 -->
<j-select-biz-component
:value="value"
name="用户"
displayKey="realname"
:listUrl="url.list"
:columns="columns"
queryParamText="账号"
v-on="$listeners"
v-bind="$attrs"
v-bind="attrs"
/>
</template>
@ -25,22 +20,24 @@
return {
url: { list: '/sys/user/list' },
columns: [
{ title: '姓名', align: 'center', width: 100, dataIndex: 'realname' },
{ title: '账号', align: 'center', width: 100, dataIndex: 'username' },
{ title: '电话', align: 'center', width: 100, dataIndex: 'phone' },
{ title: '出生日期', align: 'center', width: 100, dataIndex: 'birthday' }
]
{ title: '姓名', align: 'center', width: '20%', widthRight: '70%', dataIndex: 'realname' },
{ title: '账号', align: 'center', width: '20%', dataIndex: 'username' },
{ title: '电话', align: 'center', width: '23%', dataIndex: 'phone' },
{ title: '出生日期', align: 'center', width: '23%', dataIndex: 'birthday' }
],
// 定义在这里的参数都是可以在外部传递覆盖的,可以更灵活的定制化使用的组件
default: {
name: '用户',
width: 1000,
displayKey: 'realname',
returnKeys: ['id', 'username'],
queryParamText: '账号',
}
}
},
watch: {
$attrs: {
deep: true,
immediate: true,
handler(val) {
if (!val.returnKeys) {
val.returnKeys = ['id', 'username']
}
}
computed: {
attrs() {
return Object.assign(this.default, this.$attrs)
}
}
}

View File

@ -1,5 +1,5 @@
<template>
<j-select-biz-component v-bind="configs" v-on="$listeners"/>
<j-select-biz-component :width="1000" v-bind="configs" v-on="$listeners"/>
</template>
<script>
@ -16,11 +16,12 @@
displayKey: 'name',
returnKeys: ['id', 'code'],
listUrl: '/sys/position/list',
queryParamText: '职务编码',
queryParamCode: 'name',
queryParamText: '职务名称',
columns: [
{ title: '职务名称', dataIndex: 'name', align: 'center', width: 100 },
{ title: '职务编码', dataIndex: 'code', align: 'center', width: 100 },
{ title: '职级', dataIndex: 'rank_dictText', align: 'center', width: 100 }
{ title: '职务名称', dataIndex: 'name', align: 'center', width: '30%', widthRight: '70%' },
{ title: '职务编码', dataIndex: 'code', align: 'center', width: '35%' },
{ title: '职级', dataIndex: 'rank_dictText', align: 'center', width: '25%' }
]
}
}

View File

@ -75,11 +75,6 @@
align: 'center',
dataIndex: 'realname'
},
{
title: '角色名称',
align: 'center',
dataIndex: 'roleName'
},
{
title: '性别',
align: 'center',
@ -167,6 +162,9 @@
names = names.substring(1)
}
this.$emit("initComp", names)
}else{
// JSelectUserByDep组件bug issues/I16634
this.$emit("initComp", "")
}
},
async loadData(arg) {

View File

@ -255,7 +255,7 @@
}
</script>
<style lang="scss">
<style lang="less">
/*
* The following styles are auto-applied to elements with
@ -333,7 +333,7 @@
border-bottom: 1px solid transparent !important;
}
.ant-tabs-tab-active {
border-color: #1890ff !important;
border-color: @primary-color!important;
}
}

View File

@ -145,7 +145,7 @@
</style>
<!-- update_begin author:sunjianlei date:20190530 for: 选中首页的时候不显示背景颜色 -->
<style lang="scss">
<style lang="less">
.ant-menu.ant-menu-root {
& > .ant-menu-item:first-child {
background-color: transparent;
@ -156,7 +156,7 @@
&.ant-menu-item-selected {
& > a, & > a:hover {
color: #1890ff;
color: @primary-color;
}
}
}

View File

@ -161,10 +161,10 @@
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
/* update_begin author:scott date:20190220 for: 缩小首页布局顶部的高度*/
$height: 59px;
@height: 59px;
.layout {
@ -174,8 +174,8 @@
margin-left: 10px;
.ant-menu.ant-menu-horizontal {
height: $height;
line-height: $height;
height: @height;
line-height: @height;
}
}
.trigger {
@ -189,15 +189,15 @@
.header {
z-index: 2;
color: white;
height: $height;
background-color: #1890ff;
height: @height;
background-color: @primary-color;
transition: background 300ms;
/* dark 样式 */
&.dark {
color: #000000;
box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
background-color: white !important;
background-color: @primary-color;
}
}
@ -209,8 +209,8 @@
}
.ant-layout-header {
height: $height;
line-height: $height;
height: @height;
line-height: @height;
}
/* update_end author:scott date:20190220 for: 缩小首页布局顶部的高度*/

View File

@ -31,7 +31,7 @@
<a-list>
<a-list-item :key="index" v-for="(record, index) in announcement1">
<div style="margin-left: 5%;width: 80%">
<p><a @click="showAnnouncement(record)">标题{{ record.titile }}</a></p>
<p><a @click="showAnnouncement(record)">{{ record.titile }}</a></p>
<p style="color: rgba(0,0,0,.45);margin-bottom: 0px">{{ record.createTime }} 发布</p>
</div>
<div style="text-align: right">
@ -49,7 +49,7 @@
<a-list>
<a-list-item :key="index" v-for="(record, index) in announcement2">
<div style="margin-left: 5%;width: 80%">
<p><a @click="showAnnouncement(record)">标题{{ record.titile }}</a></p>
<p><a @click="showAnnouncement(record)">{{ record.titile }}</a></p>
<p style="color: rgba(0,0,0,.45);margin-bottom: 0px">{{ record.createTime }} 发布</p>
</div>
<div style="text-align: right">
@ -191,24 +191,24 @@
// WebSocket与普通的请求所用协议有所不同ws等同于httpwss等同于https
var userId = store.getters.userInfo.id;
var url = window._CONFIG['domianURL'].replace("https://","wss://").replace("http://","ws://")+"/websocket/"+userId;
//console.log(url);
console.log(url);
this.websock = new WebSocket(url);
this.websock.onopen = this.websocketonopen;
this.websock.onerror = this.websocketonerror;
this.websock.onmessage = this.websocketonmessage;
this.websock.onclose = this.websocketclose;
this.websock.onopen = this.websocketOnopen;
this.websock.onerror = this.websocketOnerror;
this.websock.onmessage = this.websocketOnmessage;
this.websock.onclose = this.websocketOnclose;
},
websocketonopen: function () {
websocketOnopen: function () {
console.log("WebSocket连接成功");
//心跳检测重置
this.heartCheck.reset().start();
},
websocketonerror: function (e) {
websocketOnerror: function (e) {
console.log("WebSocket连接发生错误");
this.reconnect();
},
websocketonmessage: function (e) {
//console.log("-----接收消息-------",e.data);
websocketOnmessage: function (e) {
console.log("-----接收消息-------",e.data);
var data = eval("(" + e.data + ")"); //解析对象
if(data.cmd == "topic"){
//系统通知
@ -217,22 +217,20 @@
//用户消息
this.loadData();
}
//心跳检测重置
this.heartCheck.reset().start();
},
websocketsend(text) { // 数据发送
websocketOnclose: function (e) {
console.log("connection closed (" + e.code + ")");
this.reconnect();
},
websocketSend(text) { // 数据发送
try {
this.websock.send(text);
} catch (err) {
console.log("send failed (" + err.code + ")");
}
},
websocketclose: function (e) {
console.log("connection closed (" + e.code + ")");
this.reconnect();
},
openNotification (data) {
var text = data.msgTxt;
@ -284,7 +282,7 @@
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
that.websocketsend("HeartBeat");
that.websocketSend("HeartBeat");
console.info("客户端发送心跳");
//self.serverTimeoutObj = setTimeout(function(){//如果超过一定时间还没重置,说明后端主动断开了
// that.websock.close();//如果onclose会执行reconnect我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次

View File

@ -32,15 +32,15 @@
}
}
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
/*缩小首页布 局顶部的高度*/
$height: 59px;
@height: 59px;
.sider {
box-shadow: none !important;
.logo {
height: $height !important;
line-height: $height !important;
height: @height !important;
line-height: @height !important;
box-shadow: none !important;
transition: background 300ms;
@ -53,7 +53,7 @@
}
&.light .logo {
background-color: #1890ff;
background-color: @primary-color;
}
}
</style>

View File

@ -1,5 +1,26 @@
<template>
<div class="user-wrapper" :class="theme">
<!-- update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航 -->
<!-- update-begin author:sunjianlei date:20191@20 for: 解决全局样式冲突的问题 -->
<span class="action" @click="showClick">
<a-icon type="search"></a-icon>
</span>
<span v-show="shows" class="borders">
<a-select
class="search-input"
showSearch
:showArrow="false"
placeholder="搜索菜单"
optionFilterProp="children"
:filterOption="filterOption"
@change="searchMethods"
@blur="hiddenClick"
>
<a-select-option v-for="site in search " :value="site.id">{{site.meta.title}}</a-select-option>
</a-select>
</span>
<!-- update-end author:sunjianlei date:20191@20 for: 解决全局样式冲突的问题 -->
<!-- update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航 -->
<span class="action">
<a class="logout_title" target="_blank" href="http://jeecg-boot.mydoc.io">
<a-icon type="question-circle-o"></a-icon>
@ -66,12 +87,19 @@
import UserPassword from './UserPassword'
import SettingDrawer from "@/components/setting/SettingDrawer";
import DepartSelect from './DepartSelect'
import { mapActions, mapGetters } from 'vuex'
import { mapActions, mapGetters,mapState } from 'vuex'
import { mixinDevice } from '@/utils/mixin.js'
export default {
name: "UserMenu",
mixins: [mixinDevice],
data(){
return{
//菜单搜索
search:[],
shows:false
}
},
components: {
HeaderNotice,
UserPassword,
@ -85,7 +113,31 @@
default: 'dark'
}
},
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
created() {
let lists = []
console.log("permissionMenuList: ",this.permissionMenuList)
this.searchMenus(lists,this.permissionMenuList)
this.search=[...lists]
console.log(this.search)
},
computed: {
...mapState({
// 后台菜单
permissionMenuList: state => state.user.permissionList
})
},
/* update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
methods: {
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
showClick(){
this.shows = !this.shows
},
hiddenClick(){
this.shows = false
},
/* update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
...mapActions(["Logout"]),
...mapGetters(["nickname", "avatar","userInfo"]),
getAvatar(){
@ -122,11 +174,54 @@
},
systemSetting(){
this.$refs.settingDrawer.showDrawer()
},
/* update_begin author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
searchMenus(arr,menus){
for(let i of menus){
if(!i.hidden && "layouts/RouteView"!==i.component){
arr.push(i)
}
if(i.children&& i.children.length>0){
this.searchMenus(arr,i.children)
}
}
},
filterOption(input, option) {
return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
},
searchMethods(value){
let jump = this.search.filter(item=>item.id==value)
this.$router.push({ path:jump[0].path})
}
/*update_end author:zhaoxin date:20191129 for: 做头部菜单栏导航*/
}
}
</script>
<style lang="scss" scoped>
/* update_begin author:zhaoxin date:20191129 for: 让搜索框颜色能随主题颜色变换*/
/* update-begin author:sunjianlei date:20191220 for: 解决全局样式冲突问题 */
.user-wrapper .search-input {
width: 180px;
color: white;
/deep/ {
.ant-select-selection {
background-color: inherit;
border: 0;
border-bottom: 1px solid white;
}
.ant-select-selection__placeholder,
.ant-select-search__field__placeholder {
color: inherit;
}
}
}
/* update-end author:sunjianlei date:20191220 for: 解决全局样式冲突问题 */
/* update_end author:zhaoxin date:20191129 for: 让搜索框颜色能随主题颜色变换*/
</style>
<style scoped>
.logout_title {
color: inherit;