mirror of https://github.com/jeecgboot/jeecg-boot
JeecgBoot 2.4.6版本发布
parent
986f909628
commit
664413e5d7
|
@ -1,7 +1,7 @@
|
|||
Ant Design Jeecg Vue
|
||||
====
|
||||
|
||||
当前最新版本: 2.4.5(发布日期:20210607)
|
||||
当前最新版本: 2.4.6(发布日期:20210816)
|
||||
|
||||
Overview
|
||||
----
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "vue-antd-jeecg",
|
||||
"version": "2.4.5",
|
||||
"version": "2.4.6",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"pre": "cnpm install || yarn --registry https://registry.npm.taobao.org || npm install --registry https://registry.npm.taobao.org ",
|
||||
|
@ -11,7 +11,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"ant-design-vue": "^1.7.2",
|
||||
"@jeecg/antd-online-mini": "2.4.5-RC",
|
||||
"@jeecg/antd-online-mini": "2.4.6-beta",
|
||||
"@antv/data-set": "^0.11.4",
|
||||
"viser-vue": "^2.4.8",
|
||||
"axios": "^0.18.0",
|
||||
|
@ -39,7 +39,7 @@
|
|||
"tinymce": "^5.3.2",
|
||||
"@toast-ui/editor": "^2.1.2",
|
||||
"vue-area-linkage": "^5.1.0",
|
||||
"area-data": "^5.0.6",
|
||||
"china-area-data": "^5.0.1",
|
||||
"dom-align": "1.12.0",
|
||||
"xe-utils": "2.4.8",
|
||||
"vxe-table": "2.9.13",
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
<span style="margin-left:5px">{{ ellipsisFileName }}</span>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip v-else :title="file.name">
|
||||
<a-icon type="paper-clip" style="color:red;"/>
|
||||
<span style="color:red;margin-left:5px">{{ ellipsisFileName }}</span>
|
||||
<a-tooltip v-else :title="file.message||'上传失败'">
|
||||
<a-icon type="exclamation-circle" style="color:red;"/>
|
||||
<span style="margin-left:5px">{{ ellipsisFileName }}</span>
|
||||
</a-tooltip>
|
||||
|
||||
<template style="width: 30px">
|
||||
|
@ -179,8 +179,19 @@
|
|||
value['responseName'] = file.response[this.responseName]
|
||||
}
|
||||
if (file.status === 'done') {
|
||||
value['path'] = file.response[this.responseName]
|
||||
this.handleChangeCommon(value)
|
||||
if (typeof file.response.success === 'boolean') {
|
||||
if (file.response.success) {
|
||||
value['path'] = file.response[this.responseName]
|
||||
this.handleChangeCommon(value)
|
||||
} else {
|
||||
value['status'] = 'error'
|
||||
value['message'] = file.response.message || '未知错误'
|
||||
}
|
||||
} else {
|
||||
// 考虑到如果设置action上传路径为非jeecg-boot后台,可能不会返回 success 属性的情况,就默认为成功
|
||||
value['path'] = file.response[this.responseName]
|
||||
this.handleChangeCommon(value)
|
||||
}
|
||||
} else if (file.status === 'error') {
|
||||
value['message'] = file.response.message || '未知错误'
|
||||
}
|
||||
|
|
|
@ -10,20 +10,9 @@
|
|||
<template v-else-if="file['path']">
|
||||
<img class="j-editable-image" :src="imgSrc" alt="无图片" @click="handleMoreOperation"/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-icon type="exclamation-circle" style="color: red;" @click="handleClickShowImageError"/>
|
||||
</template>
|
||||
<template slot="addonBefore" style="width: 30px">
|
||||
<a-tooltip v-if="file.status==='uploading'" :title="`上传中(${Math.floor(file.percent)}%)`">
|
||||
<a-icon type="loading"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip v-else-if="file.status==='done'" title="上传完成">
|
||||
<a-icon type="check-circle" style="color:#00DB00;"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip v-else title="上传失败">
|
||||
<a-icon type="exclamation-circle" style="color:red;"/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<a-tooltip v-else :title="file.message||'上传失败'" @click="handleClickShowImageError">
|
||||
<a-icon type="exclamation-circle" style="color:red;"/>
|
||||
</a-tooltip>
|
||||
|
||||
<template style="width: 30px">
|
||||
<a-dropdown :trigger="['click']" placement="bottomRight" style="margin-left: 10px;">
|
||||
|
@ -196,8 +185,19 @@
|
|||
value['responseName'] = file.response[this.responseName]
|
||||
}
|
||||
if (file.status === 'done') {
|
||||
value['path'] = file.response[this.responseName]
|
||||
this.handleChangeCommon(value)
|
||||
if (typeof file.response.success === 'boolean') {
|
||||
if (file.response.success) {
|
||||
value['path'] = file.response[this.responseName]
|
||||
this.handleChangeCommon(value)
|
||||
} else {
|
||||
value['status'] = 'error'
|
||||
value['message'] = file.response.message || '未知错误'
|
||||
}
|
||||
} else {
|
||||
// 考虑到如果设置action上传路径为非jeecg-boot后台,可能不会返回 success 属性的情况,就默认为成功
|
||||
value['path'] = file.response[this.responseName]
|
||||
this.handleChangeCommon(value)
|
||||
}
|
||||
} else if (file.status === 'error') {
|
||||
value['message'] = file.response.message || '未知错误'
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { pcaa } from 'area-data'
|
||||
|
||||
/**
|
||||
* 省市区
|
||||
*/
|
||||
|
@ -8,7 +6,7 @@ export default class Area {
|
|||
* 构造器
|
||||
* @param express
|
||||
*/
|
||||
constructor() {
|
||||
constructor(pcaa) {
|
||||
let arr = []
|
||||
const province = pcaa['86']
|
||||
Object.keys(province).map(key=>{
|
||||
|
@ -17,9 +15,11 @@ export default class Area {
|
|||
Object.keys(city).map(key2=>{
|
||||
arr.push({id:key2, text:city[key2], pid:key, index:2});
|
||||
const qu = pcaa[key2];
|
||||
Object.keys(qu).map(key3=>{
|
||||
arr.push({id:key3, text:qu[key3], pid:key2, index:3});
|
||||
})
|
||||
if(qu){
|
||||
Object.keys(qu).map(key3=>{
|
||||
arr.push({id:key3, text:qu[key3], pid:key2, index:3});
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
this.all = arr;
|
||||
|
|
|
@ -32,4 +32,15 @@ export const cutStrByFullLength = (str = '', maxLength) => {
|
|||
}
|
||||
return pre
|
||||
}, '')
|
||||
}
|
||||
|
||||
// 下划线转换驼峰
|
||||
export function underLinetoHump(name) {
|
||||
return name.replace(/\_(\w)/g, function(all, letter){
|
||||
return letter.toUpperCase();
|
||||
});
|
||||
}
|
||||
// 驼峰转换下划线
|
||||
export function humptoUnderLine(name) {
|
||||
return name.replace(/([A-Z])/g,"_$1").toLowerCase();
|
||||
}
|
|
@ -29,7 +29,6 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { pcaa } from 'area-data'
|
||||
import Area from '@/components/_util/Area'
|
||||
|
||||
export default {
|
||||
|
@ -53,7 +52,7 @@
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
pcaa,
|
||||
pcaa: this.$Jpcaa,
|
||||
innerValue: [],
|
||||
usedListeners: ['change'],
|
||||
enums: {
|
||||
|
@ -114,7 +113,7 @@
|
|||
/** 通过地区code获取子级 */
|
||||
loadDataByCode(value) {
|
||||
let options = []
|
||||
let data = pcaa[value]
|
||||
let data = this.pcaa[value]
|
||||
if (data) {
|
||||
for (let key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
|
@ -139,7 +138,7 @@
|
|||
},
|
||||
initAreaData(){
|
||||
if(!this.areaData){
|
||||
this.areaData = new Area();
|
||||
this.areaData = new Area(this.$Jpcaa);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -400,6 +400,10 @@
|
|||
.null-tip-hidden{
|
||||
display: none;
|
||||
}
|
||||
/**选中样式偶然出现高度不够的情况*/
|
||||
.CodeMirror-selected{
|
||||
min-height: 19px !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* 全屏样式 */
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
:showTime="showTime"
|
||||
:format="dateFormat"
|
||||
:getCalendarContainer="getCalendarContainer"
|
||||
/>
|
||||
v-bind="$attrs"/>
|
||||
</template>
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
|
|
|
@ -158,7 +158,49 @@ export default {
|
|||
cronValue_c(newVal, oldVal) {
|
||||
this.calTriggerList()
|
||||
this.$emit('change', newVal)
|
||||
|
||||
this.assignInput()
|
||||
},
|
||||
minute() {
|
||||
if (this.second === '*') {
|
||||
this.second = '0'
|
||||
}
|
||||
},
|
||||
hour() {
|
||||
if (this.minute === '*') {
|
||||
this.minute = '0'
|
||||
}
|
||||
},
|
||||
day(day) {
|
||||
if (day !== '?' && this.hour === '*') {
|
||||
this.hour = '0'
|
||||
}
|
||||
},
|
||||
week(week) {
|
||||
if (week !== '?' && this.hour === '*') {
|
||||
this.hour = '0'
|
||||
}
|
||||
},
|
||||
month() {
|
||||
if (this.day === '?' && this.week === '*') {
|
||||
this.week = '1'
|
||||
} else if (this.week === '?' && this.day === '*') {
|
||||
this.day = '1'
|
||||
}
|
||||
},
|
||||
year() {
|
||||
if (this.month === '*') {
|
||||
this.month = '1'
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.formatValue()
|
||||
this.$nextTick(() => {
|
||||
this.calTriggerListInner()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
assignInput() {
|
||||
Object.assign(this.inputValues, {
|
||||
second: this.second,
|
||||
minute: this.minute,
|
||||
|
@ -169,15 +211,7 @@ export default {
|
|||
year: this.year,
|
||||
cron: this.cronValue_c,
|
||||
})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.formatValue()
|
||||
this.$nextTick(() => {
|
||||
this.calTriggerListInner()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
formatValue() {
|
||||
if (!this.cronValue) return
|
||||
const values = this.cronValue.split(' ').filter(item => !!item)
|
||||
|
@ -190,6 +224,7 @@ export default {
|
|||
if (values.length > i) this.month = values[i++]
|
||||
if (values.length > i) this.week = values[i++]
|
||||
if (values.length > i) this.year = values[i]
|
||||
this.assignInput()
|
||||
},
|
||||
calTriggerList: simpleDebounce(function () {
|
||||
this.calTriggerListInner()
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
<a-radio value="TYPE_SPECIFY" class="choice" :disabled="disableChoice">指定</a-radio>
|
||||
<div class="list">
|
||||
<a-checkbox-group v-model="valueList">
|
||||
<template v-for="i in maxValue+1">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i-1}`" :value="i-1" :disabled="type!==TYPE_SPECIFY || disabled">{{i-1}}</a-checkbox>
|
||||
<template v-for="i of specifyRange">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i}`" :value="i" :disabled="type!==TYPE_SPECIFY || disabled">{{i}}</a-checkbox>
|
||||
</template>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
<a-radio value="TYPE_SPECIFY" class="choice" :disabled="disabled">指定</a-radio>
|
||||
<div class="list">
|
||||
<a-checkbox-group v-model="valueList">
|
||||
<template v-for="i in maxValue+1">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i-1}`" :value="i-1" :disabled="type!==TYPE_SPECIFY || disabled">{{i-1}}</a-checkbox>
|
||||
<template v-for="i in specifyRange">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i}`" :value="i" :disabled="type!==TYPE_SPECIFY || disabled">{{i}}</a-checkbox>
|
||||
</template>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
<a-radio value="TYPE_SPECIFY" class="choice" :disabled="disabled">指定</a-radio>
|
||||
<div class="list">
|
||||
<a-checkbox-group v-model="valueList">
|
||||
<template v-for="i in maxValue+1">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i-1}`" :value="i-1" :disabled="type!==TYPE_SPECIFY || disabled">{{i-1}}</a-checkbox>
|
||||
<template v-for="i in specifyRange">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i}`" :value="i" :disabled="type!==TYPE_SPECIFY || disabled">{{i}}</a-checkbox>
|
||||
</template>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
|
|
|
@ -89,6 +89,9 @@ export default {
|
|||
result.push('L')
|
||||
break
|
||||
case TYPE_SPECIFY:
|
||||
if (this.valueList.length === 0) {
|
||||
this.valueList.push(this.minValue)
|
||||
}
|
||||
result.push(this.valueList.join(','))
|
||||
break
|
||||
default:
|
||||
|
@ -96,7 +99,15 @@ export default {
|
|||
break
|
||||
}
|
||||
return result.length > 0 ? result.join('') : this.DEFAULT_VALUE
|
||||
}
|
||||
},
|
||||
// 指定值范围区间,介于最小值和最大值之间
|
||||
specifyRange() {
|
||||
let range = []
|
||||
for (let i = this.minValue; i <= this.maxValue; i++) {
|
||||
range.push(i)
|
||||
}
|
||||
return range
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
parseProp (value) {
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
<a-radio value="TYPE_SPECIFY" class="choice" :disabled="disabled">指定</a-radio>
|
||||
<div class="list">
|
||||
<a-checkbox-group v-model="valueList">
|
||||
<template v-for="i in maxValue+1">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i-1}`" :value="i-1" :disabled="type!==TYPE_SPECIFY || disabled">{{i-1}}</a-checkbox>
|
||||
<template v-for="i of specifyRange">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i}`" :value="i" :disabled="type!==TYPE_SPECIFY || disabled">{{i}}</a-checkbox>
|
||||
</template>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
<a-radio value="TYPE_SPECIFY" class="choice" :disabled="disabled">指定</a-radio>
|
||||
<div class="list">
|
||||
<a-checkbox-group v-model="valueList">
|
||||
<template v-for="i in maxValue+1">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i-1}`" :value="i-1" :disabled="type!==TYPE_SPECIFY || disabled">{{i-1}}</a-checkbox>
|
||||
<template v-for="i in specifyRange">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i}`" :value="i" :disabled="type!==TYPE_SPECIFY || disabled">{{i}}</a-checkbox>
|
||||
</template>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
|
|
|
@ -36,8 +36,8 @@
|
|||
<a-radio value="TYPE_SPECIFY" class="choice" :disabled="disableChoice">指定</a-radio>
|
||||
<div class="list">
|
||||
<a-checkbox-group v-model="valueList">
|
||||
<template v-for="i in maxValue+1">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i-1}`" :value="i-1" :disabled="type!==TYPE_SPECIFY || disabled">{{i-1}}</a-checkbox>
|
||||
<template v-for="i in specifyRange">
|
||||
<a-checkbox class="list-check-item" :key="`key-${i}`" :value="i" :disabled="type!==TYPE_SPECIFY || disabled">{{i}}</a-checkbox>
|
||||
</template>
|
||||
</a-checkbox-group>
|
||||
</div>
|
||||
|
@ -51,13 +51,14 @@ import mixin from './mixin'
|
|||
import { replaceWeekName, WEEK_MAP_EN } from './const.js'
|
||||
|
||||
const WEEK_MAP = {
|
||||
'周日': 0,
|
||||
'周一': 1,
|
||||
'周二': 2,
|
||||
'周三': 3,
|
||||
'周四': 4,
|
||||
'周五': 5,
|
||||
'周六': 6
|
||||
'周六': 6,
|
||||
// 按照国人习惯,将周日放到每周的最后一天
|
||||
'周日': 7,
|
||||
}
|
||||
|
||||
export default {
|
||||
|
@ -101,10 +102,10 @@ export default {
|
|||
created() {
|
||||
this.DEFAULT_VALUE = '*'
|
||||
// 0,7表示周日 1表示周一
|
||||
this.minValue = 0
|
||||
this.maxValue = 6
|
||||
this.valueRange.start = 0
|
||||
this.valueRange.end = 6
|
||||
this.minValue = 1
|
||||
this.maxValue = 7
|
||||
this.valueRange.start = 1
|
||||
this.valueRange.end = 7
|
||||
this.valueLoop.start = 2
|
||||
this.valueLoop.interval = 1
|
||||
this.parseProp(this.prop)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<!-- JEditableTable -->
|
||||
<!-- @version 1.6.1 -->
|
||||
<!-- @version 1.6.2 -->
|
||||
<!-- @author sjlei -->
|
||||
<template>
|
||||
<a-spin :spinning="loading">
|
||||
|
@ -11,7 +11,33 @@
|
|||
<a-col>
|
||||
<!-- 操作按钮 -->
|
||||
<div v-if="actionButton" class="action-button">
|
||||
<a-button v-if="buttonPermission('add')" type="primary" icon="plus" @click="handleClickAdd" :disabled="disabled">新增</a-button>
|
||||
<a-button-group v-if="buttonPermission('add')">
|
||||
<a-button type="primary" icon="plus" @click="handleClickAdd" :disabled="disabled">新增</a-button>
|
||||
<a-popover v-if="addButtonSettings" placement="right" overlayClassName="j-add-btn-settings">
|
||||
<a-row slot="title">
|
||||
<a-col :span="12">选项</a-col>
|
||||
<a-col :span="12" style="text-align: right;">
|
||||
<a-tooltip title="保存为默认值">
|
||||
<a-button type="link" icon="save" size="small" style="position: relative;left:4px;" @click="onAddButtonSettingsSave"/>
|
||||
</a-tooltip>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<template slot="content">
|
||||
<a-form-model layout="horizontal" :labelCol="{span:8}" :wrapperCol="{span:16}">
|
||||
<a-form-model-item label="添加行数">
|
||||
<a-input-number v-model="settings.addRowNum" :min="1"/>
|
||||
</a-form-model-item>
|
||||
<a-form-model-item label="添加位置">
|
||||
<a-input-number v-model="settings.addIndex" :min="0" :max="rows.length"/>
|
||||
<p style="font-size: 12px;color:#aaa;line-height: 14px;text-align: right;margin: 0;">0 = 最底部</p>
|
||||
</a-form-model-item>
|
||||
<a-divider style="margin: 8px 0;"/>
|
||||
<a-checkbox v-model="settings.addScrollToBottom">添加后滚动到底部</a-checkbox>
|
||||
</a-form-model>
|
||||
</template>
|
||||
<a-button icon="setting" type="primary"></a-button>
|
||||
</a-popover>
|
||||
</a-button-group>
|
||||
<span class="gap"></span>
|
||||
<template v-if="selectedRowIds.length>0">
|
||||
<a-popconfirm
|
||||
|
@ -318,7 +344,7 @@
|
|||
<a-tooltip v-else-if="file.status==='done'" title="上传完成">
|
||||
<a-icon type="check-circle" style="color:#00DB00;"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip v-else title="上传失败">
|
||||
<a-tooltip v-else :title="file.message||'上传失败'">
|
||||
<a-icon type="exclamation-circle" style="color:red;"/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
|
@ -409,9 +435,9 @@
|
|||
<span style="margin-left:5px">{{ getEllipsisWord(file.name,5) }}</span>
|
||||
</a-tooltip>
|
||||
|
||||
<a-tooltip v-else :title="file.name">
|
||||
<a-icon type="paper-clip" style="color:red;"/>
|
||||
<span style="color:red;margin-left:5px">{{ getEllipsisWord(file.name,5) }}</span>
|
||||
<a-tooltip v-else :title="file.message||'上传失败'">
|
||||
<a-icon type="exclamation-circle" style="color:red;"/>
|
||||
<span style="margin-left:5px">{{ getEllipsisWord(file.name,5) }}</span>
|
||||
</a-tooltip>
|
||||
|
||||
<template style="width: 30px">
|
||||
|
@ -464,20 +490,9 @@
|
|||
<template v-else-if="uploadValues[id]['path']">
|
||||
<img class="j-editable-image" :src="getCellImageView(id)" alt="无图片" @click="handleMoreOperation(id,'img',col)"/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a-icon type="exclamation-circle" style="color: red;" @click="handleClickShowImageError(id)"/>
|
||||
</template>
|
||||
<template slot="addonBefore" style="width: 30px">
|
||||
<a-tooltip v-if="file.status==='uploading'" :title="`上传中(${Math.floor(file.percent)}%)`">
|
||||
<a-icon type="loading"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip v-else-if="file.status==='done'" title="上传完成">
|
||||
<a-icon type="check-circle" style="color:#00DB00;"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip v-else title="上传失败">
|
||||
<a-icon type="exclamation-circle" style="color:red;"/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
<a-tooltip v-else :title="file.message||'上传失败'" @click="handleClickShowImageError(id)">
|
||||
<a-icon type="exclamation-circle" style="color:red;"/>
|
||||
</a-tooltip>
|
||||
|
||||
<template style="width: 30px">
|
||||
<a-dropdown :trigger="['click']" placement="bottomRight" :getPopupContainer="getParentContainer" style="margin-left: 10px;">
|
||||
|
@ -738,6 +753,11 @@
|
|||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示添加按钮选项
|
||||
addButtonSettings: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示行号
|
||||
rowNumber: {
|
||||
type: Boolean,
|
||||
|
@ -866,7 +886,16 @@
|
|||
lastPushTimeMap: new Map(),
|
||||
number:0,
|
||||
//不显示的按钮编码
|
||||
excludeCode:[]
|
||||
excludeCode:[],
|
||||
// 选项配置
|
||||
settings: {
|
||||
// 添加行数
|
||||
addRowNum: 1,
|
||||
// 添加位置(下标),0 = 最底部
|
||||
addIndex: 0,
|
||||
// 添加后滚动到底部
|
||||
addScrollToBottom: false,
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
@ -881,6 +910,7 @@
|
|||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
this.getSavedAddButtonSettings()
|
||||
},
|
||||
// 计算属性
|
||||
computed: {
|
||||
|
@ -1412,22 +1442,18 @@
|
|||
let tbody = this.getElement('tbody')
|
||||
let offsetHeight = tbody.offsetHeight
|
||||
let realScrollTop = tbody.scrollTop + offsetHeight
|
||||
if (forceScrollToBottom === false) {
|
||||
// 只有滚动条在底部的时候才自动滚动
|
||||
if (!((tbody.scrollHeight - realScrollTop) <= 10)) {
|
||||
return
|
||||
}
|
||||
if (forceScrollToBottom) {
|
||||
this.$nextTick(() => {
|
||||
this.resetScrollTop(this.$refs.scrollView.scrollHeight)
|
||||
})
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
tbody.scrollTop = tbody.scrollHeight
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 在指定位置添加一行
|
||||
* @param insertIndex 添加位置下标
|
||||
* @param num 添加的行数,默认1
|
||||
*/
|
||||
insert(insertIndex, num = 1) {
|
||||
insert(insertIndex, num = 1, forceScrollToBottom = false) {
|
||||
if (this.checkTooFastClick('insert', 1500)) {
|
||||
return
|
||||
}
|
||||
|
@ -1455,6 +1481,12 @@
|
|||
num, insertIndex,
|
||||
target: this
|
||||
})
|
||||
// 设置滚动条位置
|
||||
if (forceScrollToBottom) {
|
||||
this.$nextTick(() => {
|
||||
this.resetScrollTop(this.$refs.scrollView.scrollHeight)
|
||||
})
|
||||
}
|
||||
},
|
||||
/** 删除被选中的行 */
|
||||
removeSelectedRows() {
|
||||
|
@ -2095,7 +2127,12 @@
|
|||
|
||||
},
|
||||
handleClickAdd() {
|
||||
this.add()
|
||||
let {addRowNum, addIndex, addScrollToBottom} = this.settings
|
||||
if (addIndex <= 0) {
|
||||
this.add(addRowNum, addScrollToBottom)
|
||||
} else {
|
||||
this.insert(addIndex, addRowNum, addScrollToBottom)
|
||||
}
|
||||
},
|
||||
handleConfirmDelete() {
|
||||
this.removeSelectedRows()
|
||||
|
@ -2353,7 +2390,21 @@
|
|||
value['responseName'] = file.response[column.responseName]
|
||||
}
|
||||
if (file.status === 'done') {
|
||||
value['path'] = file.response[column.responseName]
|
||||
if (typeof file.response.success === 'boolean') {
|
||||
// 如果文件上传,被拦截器拦下,还会返回最外层的status = done
|
||||
// 但是内部的success会返回false并携带异常信息
|
||||
// 整个上传操作还是失败的
|
||||
// https://github.com/zhangdaiscott/jeecg-boot/issues/2691
|
||||
if (file.response.success) {
|
||||
value['path'] = file.response[column.responseName]
|
||||
} else {
|
||||
value['status'] = 'error'
|
||||
value['message'] = file.response.message || '未知错误'
|
||||
}
|
||||
} else {
|
||||
// 考虑到如果设置action上传路径为非jeecg-boot后台,可能不会返回 success 属性的情况,就默认为成功
|
||||
value['path'] = file.response[column.responseName]
|
||||
}
|
||||
} else if (file.status === 'error') {
|
||||
value['message'] = file.response.message || '未知错误'
|
||||
}
|
||||
|
@ -2415,6 +2466,25 @@
|
|||
})
|
||||
}
|
||||
},
|
||||
|
||||
/** 添加按钮设置保存为默认值 */
|
||||
onAddButtonSettingsSave() {
|
||||
let obj = {
|
||||
addRowNum: this.settings.addRowNum,
|
||||
addIndex: this.settings.addIndex,
|
||||
addScrollToBottom: this.settings.addScrollToBottom,
|
||||
}
|
||||
this.$ls.set('jet-add-btn-settings', obj)
|
||||
this.$message.success('保存成功')
|
||||
},
|
||||
/** 获取保存的添加按钮默认值 */
|
||||
getSavedAddButtonSettings() {
|
||||
let obj= this.$ls.get('jet-add-btn-settings')
|
||||
if (obj) {
|
||||
Object.assign(this.settings, obj)
|
||||
}
|
||||
},
|
||||
|
||||
/** 记录用到数据绑定的组件的值 */
|
||||
bindValuesChange(value, id, key) {
|
||||
this.$set(this[key], id, value)
|
||||
|
@ -3280,3 +3350,19 @@
|
|||
}
|
||||
|
||||
</style>
|
||||
<style lang="less">
|
||||
// 新增按钮配置气泡的样式
|
||||
.j-add-btn-settings {
|
||||
width: 240px;
|
||||
|
||||
.ant-form {
|
||||
.ant-form-item {
|
||||
margin-bottom: 0;
|
||||
|
||||
.ant-input-number {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -134,9 +134,17 @@
|
|||
}else{
|
||||
//update--begin--autor:wangshuai-----date:20200724------for:富文本编辑器切换tab无法修改------
|
||||
let tabLayout = getVmParentByName(this, 'TabLayout')
|
||||
tabLayout.excuteCallback(()=>{
|
||||
this.reload()
|
||||
})
|
||||
//update--begin--autor:liusq-----date:20210713------for:处理特殊情况excuteCallback不能使用------
|
||||
try {
|
||||
tabLayout.excuteCallback(() => {
|
||||
this.reload()
|
||||
})
|
||||
} catch (error) {
|
||||
if (tabLayout) {
|
||||
this.reload()
|
||||
}
|
||||
}
|
||||
//update--end--autor:liusq-----date:20210713------for:处理特殊情况excuteCallback不能使用------
|
||||
//update--begin--autor:wangshuai-----date:20200724------for:文本编辑器切换tab无法修改------
|
||||
}
|
||||
},
|
||||
|
|
|
@ -0,0 +1,242 @@
|
|||
<template>
|
||||
<a-modal
|
||||
ref="modal"
|
||||
:class="getClass(modalClass)"
|
||||
:style="getStyle(modalStyle)"
|
||||
:visible="visible"
|
||||
v-bind="_attrs"
|
||||
v-on="$listeners"
|
||||
@ok="handleOk"
|
||||
@cancel="handleCancel"
|
||||
destroyOnClose
|
||||
>
|
||||
|
||||
<slot></slot>
|
||||
<!--有设置标题-->
|
||||
<template v-if="!isNoTitle" slot="title">
|
||||
<a-row class="j-modal-title-row" type="flex">
|
||||
<a-col class="left">
|
||||
<slot name="title">{{ title }}</slot>
|
||||
</a-col>
|
||||
<a-col v-if="switchFullscreen" class="right" @click="toggleFullscreen">
|
||||
<a-button class="ant-modal-close ant-modal-close-x" ghost type="link" :icon="fullscreenButtonIcon"/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
<!--没有设置标题-->
|
||||
<template v-else slot="title">
|
||||
<a-row class="j-modal-title-row" type="flex">
|
||||
<a-col v-if="switchFullscreen" class="right" @click="toggleFullscreen">
|
||||
<a-button class="ant-modal-close ant-modal-close-x" ghost type="link" :icon="fullscreenButtonIcon"/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</template>
|
||||
|
||||
<!-- 处理 scopedSlots -->
|
||||
<template v-for="slotName of scopedSlotsKeys" :slot="slotName">
|
||||
<slot :name="slotName"></slot>
|
||||
</template>
|
||||
|
||||
<!-- 处理 slots -->
|
||||
<template v-for="slotName of slotsKeys" v-slot:[slotName]>
|
||||
<slot :name="slotName"></slot>
|
||||
</template>
|
||||
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import { getClass, getStyle } from '@/utils/props-util'
|
||||
import { triggerWindowResizeEvent } from '@/utils/util'
|
||||
|
||||
export default {
|
||||
name: 'JModal',
|
||||
props: {
|
||||
title: String,
|
||||
// 可使用 .sync 修饰符
|
||||
visible: Boolean,
|
||||
// 是否全屏弹窗,当全屏时无论如何都会禁止 body 滚动。可使用 .sync 修饰符
|
||||
fullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否允许切换全屏(允许后右上角会出现一个按钮)
|
||||
switchFullscreen: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 点击确定按钮的时候是否关闭弹窗
|
||||
okClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 内部使用的 slots ,不再处理
|
||||
usedSlots: ['title'],
|
||||
// 实际控制是否全屏的参数
|
||||
innerFullscreen: this.fullscreen,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 一些未处理的参数或特殊处理的参数绑定到 a-modal 上
|
||||
_attrs() {
|
||||
let attrs = { ...this.$attrs }
|
||||
// 如果全屏就将宽度设为 100%
|
||||
if (this.innerFullscreen) {
|
||||
attrs['width'] = '100%'
|
||||
}
|
||||
return attrs
|
||||
},
|
||||
modalClass() {
|
||||
return {
|
||||
'j-modal-box': true,
|
||||
'fullscreen': this.innerFullscreen,
|
||||
'no-title': this.isNoTitle,
|
||||
'no-footer': this.isNoFooter,
|
||||
}
|
||||
},
|
||||
modalStyle() {
|
||||
let style = {}
|
||||
// 如果全屏就将top设为 0
|
||||
if (this.innerFullscreen) {
|
||||
style['top'] = '0'
|
||||
}
|
||||
return style
|
||||
},
|
||||
isNoTitle() {
|
||||
return !this.title && !this.allSlotsKeys.includes('title')
|
||||
},
|
||||
isNoFooter() {
|
||||
return this._attrs['footer'] === null
|
||||
},
|
||||
slotsKeys() {
|
||||
return Object.keys(this.$slots).filter(key => !this.usedSlots.includes(key))
|
||||
},
|
||||
scopedSlotsKeys() {
|
||||
return Object.keys(this.$scopedSlots).filter(key => !this.usedSlots.includes(key))
|
||||
},
|
||||
allSlotsKeys() {
|
||||
return Object.keys(this.$slots).concat(Object.keys(this.$scopedSlots))
|
||||
},
|
||||
// 切换全屏的按钮图标
|
||||
fullscreenButtonIcon() {
|
||||
return this.innerFullscreen ? 'fullscreen-exit' : 'fullscreen'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
visible() {
|
||||
if (this.visible) {
|
||||
this.innerFullscreen = this.fullscreen
|
||||
}
|
||||
},
|
||||
innerFullscreen(val) {
|
||||
this.$emit('update:fullscreen', val)
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
getClass(clazz) {
|
||||
return { ...getClass(this), ...clazz }
|
||||
},
|
||||
getStyle(style) {
|
||||
return { ...getStyle(this), ...style }
|
||||
},
|
||||
|
||||
close() {
|
||||
this.$emit('update:visible', false)
|
||||
},
|
||||
|
||||
handleOk() {
|
||||
if (this.okClose) {
|
||||
this.close()
|
||||
}
|
||||
},
|
||||
handleCancel() {
|
||||
this.close()
|
||||
},
|
||||
|
||||
/** 切换全屏 */
|
||||
toggleFullscreen() {
|
||||
this.innerFullscreen = !this.innerFullscreen
|
||||
triggerWindowResizeEvent()
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
.j-modal-box {
|
||||
&.fullscreen {
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 0;
|
||||
|
||||
// 兼容1.6.2版本的antdv
|
||||
& .ant-modal {
|
||||
top: 0;
|
||||
padding: 0;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
& .ant-modal-content {
|
||||
height: 100vh;
|
||||
border-radius: 0;
|
||||
|
||||
& .ant-modal-body {
|
||||
/* title 和 footer 各占 55px */
|
||||
height: calc(100% - 55px - 55px);
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.no-title, &.no-footer {
|
||||
.ant-modal-body {
|
||||
height: calc(100% - 55px);
|
||||
}
|
||||
}
|
||||
&.no-title.no-footer {
|
||||
.ant-modal-body {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.j-modal-title-row {
|
||||
.left {
|
||||
width: calc(100% - 56px - 56px);
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 56px;
|
||||
position: inherit;
|
||||
|
||||
.ant-modal-close {
|
||||
right: 56px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
|
||||
&:hover {
|
||||
color: rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.no-title{
|
||||
.ant-modal-header {
|
||||
padding: 0px 24px;
|
||||
border-bottom: 0px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.j-modal-box.fullscreen {
|
||||
margin: 0;
|
||||
max-width: 100vw;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,124 @@
|
|||
<template>
|
||||
<j-modal :visible="visible" :confirmLoading="loading" :after-close="afterClose" v-bind="modalProps" @ok="onOk" @cancel="onCancel">
|
||||
<a-spin :spinning="loading">
|
||||
<div v-html="content"></div>
|
||||
<a-form-model ref="form" :model="model" :rules="rules">
|
||||
<a-form-model-item prop="input">
|
||||
<a-input ref="input" v-model="model.input" v-bind="inputProps" @pressEnter="onInputPressEnter"/>
|
||||
</a-form-model-item>
|
||||
</a-form-model>
|
||||
</a-spin>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pick from 'lodash.pick'
|
||||
|
||||
export default {
|
||||
name: 'JPrompt',
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
loading: false,
|
||||
content: '',
|
||||
// 弹窗参数
|
||||
modalProps: {
|
||||
title: '',
|
||||
},
|
||||
inputProps: {
|
||||
placeholder: '',
|
||||
},
|
||||
// form model
|
||||
model: {
|
||||
input: '',
|
||||
},
|
||||
// 校验
|
||||
rule: [],
|
||||
// 回调函数
|
||||
callback: {},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
rules() {
|
||||
return {
|
||||
input: this.rule
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
show(options) {
|
||||
this.content = options.content
|
||||
if (Array.isArray(options.rule)) {
|
||||
this.rule = options.rule
|
||||
}
|
||||
if (options.defaultValue != null) {
|
||||
this.model.input = options.defaultValue
|
||||
}
|
||||
// 取出常用的弹窗参数
|
||||
let pickModalProps = pick(options, 'title', 'centered', 'cancelText', 'closable', 'mask', 'maskClosable', 'okText', 'okType', 'okButtonProps', 'cancelButtonProps', 'width', 'wrapClassName', 'zIndex', 'dialogStyle', 'dialogClass')
|
||||
this.modalProps = Object.assign({}, pickModalProps, options.modalProps)
|
||||
// 取出常用的input参数
|
||||
let pickInputProps = pick(options, 'placeholder', 'allowClear')
|
||||
this.inputProps = Object.assign({}, pickInputProps, options.inputProps)
|
||||
// 回调函数
|
||||
this.callback = pick(options, 'onOk', 'onOkAsync', 'onCancel')
|
||||
this.visible = true
|
||||
this.$nextTick(() => this.$refs.input.focus())
|
||||
},
|
||||
|
||||
onOk() {
|
||||
this.$refs.form.validate((ok, err) => {
|
||||
if (ok) {
|
||||
let event = {value: this.model.input, target: this}
|
||||
// 异步方法优先级高于同步方法
|
||||
if (typeof this.callback.onOkAsync === 'function') {
|
||||
this.callback.onOkAsync(event)
|
||||
} else if (typeof this.callback.onOk === 'function') {
|
||||
this.callback.onOk(event)
|
||||
this.close()
|
||||
} else {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
onCancel() {
|
||||
if (typeof this.callback.onCancel === 'function') {
|
||||
this.callback.onCancel(this.model.input)
|
||||
}
|
||||
this.close()
|
||||
},
|
||||
|
||||
onInputPressEnter() {
|
||||
this.onOk()
|
||||
},
|
||||
|
||||
close() {
|
||||
this.visible = this.loading ? this.visible : false
|
||||
},
|
||||
|
||||
forceClose() {
|
||||
this.visible = false
|
||||
},
|
||||
|
||||
showLoading() {
|
||||
this.loading = true
|
||||
},
|
||||
hideLoading() {
|
||||
this.loading = false
|
||||
},
|
||||
|
||||
afterClose(e) {
|
||||
if (typeof this.modalProps.afterClose === 'function') {
|
||||
this.modalProps.afterClose(e)
|
||||
}
|
||||
this.$emit('after-close', e)
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -0,0 +1,18 @@
|
|||
import JModal from './JModal'
|
||||
import JPrompt from './JPrompt'
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.component(JModal.name, JModal)
|
||||
|
||||
const JPromptExtend = Vue.extend(JPrompt)
|
||||
Vue.prototype.$JPrompt = function (options = {}) {
|
||||
// 创建prompt实例
|
||||
const vm = new JPromptExtend().$mount()
|
||||
vm.show(options)
|
||||
// 关闭后销毁
|
||||
vm.$on('after-close', () => vm.$destroy())
|
||||
return vm
|
||||
}
|
||||
},
|
||||
}
|
|
@ -173,9 +173,11 @@
|
|||
let tempDestArr = []
|
||||
for(let rw of rows){
|
||||
let val = rw[orgFieldsArr[i]]
|
||||
if(!val){
|
||||
// update--begin--autor:liusq-----date:20210713------for:处理val等于0的情况issues/I3ZL4T------
|
||||
if(typeof val=='undefined'|| val==null || val.toString()==""){
|
||||
val = ""
|
||||
}
|
||||
// update--end--autor:liusq-----date:20210713------for:处理val等于0的情况issues/I3ZL4T------
|
||||
tempDestArr.push(val)
|
||||
}
|
||||
res[destFieldsArr[i]] = tempDestArr.join(",")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<a-select :value="arrayValue" @change="onChange" mode="multiple" :placeholder="placeholder">
|
||||
<a-select-option
|
||||
v-for="(item,index) in options"
|
||||
v-for="(item,index) in selectOptions"
|
||||
:key="index"
|
||||
:getPopupContainer="getParentContainer"
|
||||
:value="item.value">
|
||||
|
@ -12,6 +12,8 @@
|
|||
|
||||
<script>
|
||||
//option {label:,value:}
|
||||
import { getAction } from '@api/manage'
|
||||
|
||||
export default {
|
||||
name: 'JSelectMultiple',
|
||||
props: {
|
||||
|
@ -31,7 +33,8 @@
|
|||
},
|
||||
options:{
|
||||
type: Array,
|
||||
required: true
|
||||
default:()=>[],
|
||||
required: false
|
||||
},
|
||||
triggerChange:{
|
||||
type: Boolean,
|
||||
|
@ -48,12 +51,22 @@
|
|||
default:'',
|
||||
required:false
|
||||
},
|
||||
dictCode:{
|
||||
type:String,
|
||||
required:false
|
||||
},
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
arrayValue:!this.value?[]:this.value.split(this.spliter)
|
||||
arrayValue:!this.value?[]:this.value.split(this.spliter),
|
||||
dictOptions: [],
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
selectOptions(){
|
||||
return this.dictOptions.length > 0 ? this.dictOptions : this.options
|
||||
},
|
||||
},
|
||||
watch:{
|
||||
value (val) {
|
||||
if(!val){
|
||||
|
@ -63,6 +76,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
if (this.dictCode) {
|
||||
this.loadDictOptions()
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
onChange (selectedValue) {
|
||||
if(this.triggerChange){
|
||||
|
@ -77,7 +95,18 @@
|
|||
}else{
|
||||
return document.querySelector(this.popContainer)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 根据字典code查询字典项
|
||||
loadDictOptions(){
|
||||
getAction(`/sys/dict/getDictItems/${this.dictCode}`,{}).then(res=>{
|
||||
if (res.success) {
|
||||
this.dictOptions = res.result.map(item => ({value: item.value, label: item.text}))
|
||||
} else {
|
||||
console.error('getDictItems error: : ', res)
|
||||
this.dictOptions = []
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
|
|
|
@ -412,8 +412,9 @@
|
|||
this.queryParamsModel.splice(index, 1)
|
||||
},
|
||||
handleSelected(node, item) {
|
||||
let { type, options, dictCode, dictTable, dictText, customReturnField, popup } = node.dataRef
|
||||
let { type, dbType, options, dictCode, dictTable, dictText, customReturnField, popup } = node.dataRef
|
||||
item['type'] = type
|
||||
item['dbType'] = dbType
|
||||
item['options'] = options
|
||||
item['dictCode'] = dictCode
|
||||
item['dictTable'] = dictTable
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
:headers="headers"
|
||||
:data="{'biz':bizPath}"
|
||||
:fileList="fileList"
|
||||
:beforeUpload="beforeUpload"
|
||||
:beforeUpload="doBeforeUpload"
|
||||
@change="handleChange"
|
||||
:disabled="disabled"
|
||||
:returnUrl="returnUrl"
|
||||
|
@ -139,6 +139,9 @@
|
|||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
beforeUpload: {
|
||||
type: Function
|
||||
},
|
||||
},
|
||||
watch:{
|
||||
value:{
|
||||
|
@ -242,7 +245,7 @@
|
|||
}
|
||||
this.$emit('change', path);
|
||||
},
|
||||
beforeUpload(file){
|
||||
doBeforeUpload(file){
|
||||
this.uploadGoOn=true
|
||||
var fileType = file.type;
|
||||
if(this.fileType===FILE_TYPE_IMG){
|
||||
|
@ -252,7 +255,10 @@
|
|||
return false;
|
||||
}
|
||||
}
|
||||
//TODO 扩展功能验证文件大小
|
||||
// 扩展 beforeUpload 验证
|
||||
if (typeof this.beforeUpload === 'function') {
|
||||
return this.beforeUpload(file)
|
||||
}
|
||||
return true
|
||||
},
|
||||
handleChange(info) {
|
||||
|
|
|
@ -668,7 +668,11 @@ export default {
|
|||
async loadNewData(dataSource) {
|
||||
if (Array.isArray(dataSource)) {
|
||||
let {xTable} = this.$refs.vxe.$refs
|
||||
return await xTable.loadData(dataSource)
|
||||
// issues/2784
|
||||
// 先清空所有数据
|
||||
xTable.loadData([])
|
||||
// 再新增
|
||||
return xTable.insertAt(dataSource)
|
||||
}
|
||||
return []
|
||||
},
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<a-tooltip v-else-if="file.status === 'done'" title="上传完成">
|
||||
<a-icon type="check-circle" style="color:#00DB00;"/>
|
||||
</a-tooltip>
|
||||
<a-tooltip v-else title="上传失败">
|
||||
<a-tooltip v-else :title="file.message||'上传失败'">
|
||||
<a-icon type="exclamation-circle" style="color:red;"/>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
|
@ -118,8 +118,17 @@
|
|||
value['responseName'] = file.response[col.responseName]
|
||||
}
|
||||
if (file.status === 'done') {
|
||||
value['path'] = file.response[col.responseName]
|
||||
this.handleChangeCommon(value)
|
||||
if (typeof file.response.success === 'boolean') {
|
||||
if (file.response.success) {
|
||||
value['path'] = file.response[col.responseName]
|
||||
} else {
|
||||
value['status'] = 'error'
|
||||
value['message'] = file.response.message || '未知错误'
|
||||
}
|
||||
} else {
|
||||
// 考虑到如果设置action上传路径为非jeecg-boot后台,可能不会返回 success 属性的情况,就默认为成功
|
||||
value['path'] = file.response[col.responseName]
|
||||
}
|
||||
} else if (file.status === 'error') {
|
||||
value['message'] = file.response.message || '未知错误'
|
||||
}
|
||||
|
|
|
@ -26,19 +26,24 @@ import JSlider from './JSlider.vue'
|
|||
import JSwitch from './JSwitch.vue'
|
||||
import JTime from './JTime.vue'
|
||||
import JTreeTable from './JTreeTable.vue'
|
||||
import JEasyCron from "@/components/jeecg/JEasyCron";
|
||||
|
||||
import JEasyCron from '@/components/jeecg/JEasyCron'
|
||||
//jeecgbiz
|
||||
import JSelectDepart from '../jeecgbiz/JSelectDepart.vue'
|
||||
import JSelectMultiUser from '../jeecgbiz/JSelectMultiUser.vue'
|
||||
import JSelectPosition from '../jeecgbiz/JSelectPosition.vue'
|
||||
import JSelectRole from '../jeecgbiz/JSelectRole.vue'
|
||||
import JSelectUserByDep from '../jeecgbiz/JSelectUserByDep.vue'
|
||||
//引入需要全局注册的js函数和变量
|
||||
import { Modal, notification,message } from 'ant-design-vue'
|
||||
import lodash_object from 'lodash'
|
||||
import debounce from 'lodash/debounce'
|
||||
import pick from 'lodash.pick'
|
||||
import data from 'china-area-data'
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.use(JModal)
|
||||
Vue.component('JMarkdownEditor', JMarkdownEditor)
|
||||
Vue.component(JModal.name, JModal)
|
||||
Vue.component('JPopupOnlReport', JPopupOnlReport)
|
||||
Vue.component('JFilePop', JFilePop)
|
||||
Vue.component('JInputPop', JInputPop)
|
||||
|
@ -73,5 +78,14 @@ export default {
|
|||
Vue.component('JSelectRole', JSelectRole)
|
||||
Vue.component('JSelectUserByDep', JSelectUserByDep)
|
||||
Vue.component(JEasyCron.name, JEasyCron)
|
||||
|
||||
//注册全局js函数和变量
|
||||
Vue.prototype.$Jnotification = notification
|
||||
Vue.prototype.$Jmodal = Modal
|
||||
Vue.prototype.$Jmessage = message
|
||||
Vue.prototype.$Jlodash = lodash_object
|
||||
Vue.prototype.$Jdebounce= debounce
|
||||
Vue.prototype.$Jpick = pick
|
||||
Vue.prototype.$Jpcaa = data
|
||||
}
|
||||
}
|
|
@ -137,8 +137,12 @@
|
|||
param:{
|
||||
deep:true,
|
||||
handler(){
|
||||
this.dynamicParamHandler()
|
||||
this.loadData();
|
||||
// update--begin--autor:liusq-----date:20210706------for:JPopup组件在modal中使用报错#2729------
|
||||
if(this.visible){
|
||||
this.dynamicParamHandler()
|
||||
this.loadData();
|
||||
}
|
||||
// update--begin--autor:liusq-----date:20210706------for:JPopup组件在modal中使用报错#2729------
|
||||
},
|
||||
},
|
||||
sorter: {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div class="components-input-demo-presuffix">
|
||||
<!---->
|
||||
<a-input @click="openModal" placeholder="请点击选择部门" v-model="departNames" readOnly :disabled="disabled">
|
||||
<a-input @click="openModal" placeholder="请点击选择部门" v-model="textVals" readOnly :disabled="disabled">
|
||||
<a-icon slot="prefix" type="cluster" title="部门选择控件"/>
|
||||
<a-icon v-if="departIds" slot="suffix" type="close-circle" @click="handleEmpty" title="清空"/>
|
||||
<a-icon v-if="storeVals" slot="suffix" type="close-circle" @click="handleEmpty" title="清空"/>
|
||||
</a-input>
|
||||
|
||||
<j-select-depart-modal
|
||||
|
@ -11,7 +11,10 @@
|
|||
:modal-width="modalWidth"
|
||||
:multi="multi"
|
||||
:rootOpened="rootOpened"
|
||||
:depart-id="departIds"
|
||||
:depart-id="value"
|
||||
:store="storeField"
|
||||
:text="textField"
|
||||
:treeOpera="treeOpera"
|
||||
@ok="handleOK"
|
||||
@initComp="initComp"/>
|
||||
</div>
|
||||
|
@ -19,6 +22,7 @@
|
|||
|
||||
<script>
|
||||
import JSelectDepartModal from './modal/JSelectDepartModal'
|
||||
import { underLinetoHump } from '@/components/_util/StringUtil'
|
||||
export default {
|
||||
name: 'JSelectDepart',
|
||||
components:{
|
||||
|
@ -52,56 +56,70 @@
|
|||
// 自定义返回字段,默认返回 id
|
||||
customReturnField: {
|
||||
type: String,
|
||||
default: 'id'
|
||||
default: ''
|
||||
},
|
||||
backDepart: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false
|
||||
},
|
||||
// 存储字段 [key field]
|
||||
store: {
|
||||
type: String,
|
||||
default: 'id',
|
||||
required: false
|
||||
},
|
||||
// 显示字段 [label field]
|
||||
text: {
|
||||
type: String,
|
||||
default: 'departName',
|
||||
required: false
|
||||
},
|
||||
treeOpera: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: false
|
||||
}
|
||||
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
visible:false,
|
||||
confirmLoading:false,
|
||||
departNames:"",
|
||||
departIds:''
|
||||
storeVals: '', //[key values]
|
||||
textVals: '' //[label values]
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
storeField(){
|
||||
let field = this.customReturnField
|
||||
if(!field){
|
||||
field = this.store;
|
||||
}
|
||||
return underLinetoHump(field)
|
||||
},
|
||||
textField(){
|
||||
return underLinetoHump(this.text)
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
this.departIds = this.value
|
||||
this.storeVals = this.value
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
//update-begin-author:wangshuai date:20201124 for:组件 JSelectDepart.vue不是默认id时新内容编辑问题 gitee I247X2
|
||||
// if (this.customReturnField === 'id') {
|
||||
this.departIds = val
|
||||
// }
|
||||
//update-end-author:wangshuai date:20201124 for:组件 JSelectDepart.vue不是默认id时新内容编辑问题 gitee I247X2
|
||||
this.storeVals = val
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
initComp(departNames){
|
||||
this.departNames = departNames
|
||||
//update-begin-author:lvdandan date:20200513 for:TESTA-438 部门选择组件自定义返回值,数据无法回填
|
||||
//TODO 当返回字段为部门名称时会有问题,因为部门名称不唯一
|
||||
//返回字段不为id时,根据返回字段获取id
|
||||
if(this.customReturnField !== 'id' && this.value){
|
||||
const dataList = this.$refs.innerDepartSelectModal.dataList;
|
||||
console.log('this.value',this.value)
|
||||
this.departIds = this.value.split(',').map(item => {
|
||||
const data = dataList.filter(d=>d[this.customReturnField] === item)
|
||||
return data.length > 0 ? data[0].id : ''
|
||||
}).join(',')
|
||||
}
|
||||
//update-end-author:lvdandan date:20200513 for:TESTA-438 部门选择组件自定义返回值,数据无法回填
|
||||
initComp(textVals){
|
||||
this.textVals = textVals
|
||||
},
|
||||
//返回选中的部门信息
|
||||
backDeparInfo(){
|
||||
if(this.backDepart===true){
|
||||
if(this.departIds && this.departIds.length>0){
|
||||
let arr1 = this.departIds.split(',')
|
||||
let arr2 = this.departNames.split(',')
|
||||
let arr1 = this.storeVals.split(',')
|
||||
let arr2 = this.textVals.split(',')
|
||||
let info = []
|
||||
for(let i=0;i<arr1.length;i++){
|
||||
info.push({
|
||||
|
@ -116,17 +134,21 @@
|
|||
openModal(){
|
||||
this.$refs.innerDepartSelectModal.show()
|
||||
},
|
||||
handleOK(rows, idstr) {
|
||||
let value = ''
|
||||
handleOK(rows) {
|
||||
if (!rows && rows.length <= 0) {
|
||||
this.departNames = ''
|
||||
this.departIds = ''
|
||||
this.textVals = ''
|
||||
this.storeVals = ''
|
||||
} else {
|
||||
value = rows.map(row => row[this.customReturnField]).join(',')
|
||||
this.departNames = rows.map(row => row['departName']).join(',')
|
||||
this.departIds = idstr
|
||||
let arr1 = []
|
||||
let arr2 = []
|
||||
for(let dep of rows){
|
||||
arr1.push(dep[this.storeField])
|
||||
arr2.push(dep[this.textField])
|
||||
}
|
||||
this.storeVals = arr1.join(',')
|
||||
this.textVals = arr2.join(',')
|
||||
}
|
||||
this.$emit("change", value)
|
||||
this.$emit("change", this.storeVals)
|
||||
this.backDeparInfo()
|
||||
},
|
||||
getDepartNames(){
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
<template>
|
||||
<div>
|
||||
<a-input-search
|
||||
v-model="userNames"
|
||||
v-model="textVals"
|
||||
placeholder="请先选择用户"
|
||||
readOnly
|
||||
unselectable="on"
|
||||
@search="onSearchDepUser">
|
||||
<a-button slot="enterButton" :disabled="disabled">选择用户</a-button>
|
||||
</a-input-search>
|
||||
<j-select-user-by-dep-modal ref="selectModal" :modal-width="modalWidth" :multi="multi" @ok="selectOK" :user-ids="value" @initComp="initComp"/>
|
||||
<j-select-user-by-dep-modal
|
||||
ref="selectModal"
|
||||
:modal-width="modalWidth"
|
||||
:multi="multi"
|
||||
@ok="selectOK"
|
||||
:user-ids="value"
|
||||
:store="storeField"
|
||||
:text="textField"
|
||||
@initComp="initComp"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import JSelectUserByDepModal from './modal/JSelectUserByDepModal'
|
||||
import { underLinetoHump } from '@/components/_util/StringUtil'
|
||||
|
||||
export default {
|
||||
name: 'JSelectUserByDep',
|
||||
|
@ -42,20 +51,44 @@
|
|||
type: Boolean,
|
||||
default: false,
|
||||
required: false
|
||||
},
|
||||
// 存储字段 [key field]
|
||||
store: {
|
||||
type: String,
|
||||
default: 'username',
|
||||
required: false
|
||||
},
|
||||
// 显示字段 [label field]
|
||||
text: {
|
||||
type: String,
|
||||
default: 'realname',
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
userIds: "",
|
||||
userNames: ""
|
||||
storeVals: '', //[key values]
|
||||
textVals: '' //[label values]
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
storeField(){
|
||||
let field = this.customReturnField
|
||||
if(!field){
|
||||
field = this.store;
|
||||
}
|
||||
return underLinetoHump(field)
|
||||
},
|
||||
textField(){
|
||||
return underLinetoHump(this.text)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.userIds = this.value
|
||||
this.storeVals = this.value
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
this.userIds = val
|
||||
this.storeVals = val
|
||||
}
|
||||
},
|
||||
model: {
|
||||
|
@ -63,15 +96,15 @@
|
|||
event: 'change'
|
||||
},
|
||||
methods: {
|
||||
initComp(userNames) {
|
||||
this.userNames = userNames
|
||||
initComp(textVals) {
|
||||
this.textVals = textVals
|
||||
},
|
||||
//返回选中的用户信息
|
||||
backDeparInfo(){
|
||||
if(this.backUser===true){
|
||||
if(this.userIds && this.userIds.length>0){
|
||||
let arr1 = this.userIds.split(',')
|
||||
let arr2 = this.userNames.split(',')
|
||||
if(this.storeVals && this.storeVals.length>0){
|
||||
let arr1 = this.storeVals.split(',')
|
||||
let arr2 = this.textVals.split(',')
|
||||
let info = []
|
||||
for(let i=0;i<arr1.length;i++){
|
||||
info.push({
|
||||
|
@ -86,21 +119,22 @@
|
|||
onSearchDepUser() {
|
||||
this.$refs.selectModal.showModal()
|
||||
},
|
||||
selectOK(rows, idstr) {
|
||||
selectOK(rows) {
|
||||
console.log("当前选中用户", rows)
|
||||
console.log("当前选中用户ID", idstr)
|
||||
if (!rows) {
|
||||
this.userNames = ''
|
||||
this.userIds = ''
|
||||
this.storeVals = ''
|
||||
this.textVals = ''
|
||||
} else {
|
||||
let temp = ''
|
||||
let temp1 = []
|
||||
let temp2 = []
|
||||
for (let item of rows) {
|
||||
temp += ',' + item.realname
|
||||
temp1.push(item[this.storeField])
|
||||
temp2.push(item[this.textField])
|
||||
}
|
||||
this.userNames = temp.substring(1)
|
||||
this.userIds = idstr
|
||||
this.storeVals = temp1.join(',')
|
||||
this.textVals = temp2.join(',')
|
||||
}
|
||||
this.$emit("change", this.userIds)
|
||||
this.$emit("change", this.storeVals)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
:confirmLoading="confirmLoading"
|
||||
@ok="handleSubmit"
|
||||
@cancel="handleCancel"
|
||||
@update:fullscreen="isFullscreen"
|
||||
wrapClassName="j-depart-select-modal"
|
||||
switchFullscreen
|
||||
cancelText="关闭">
|
||||
|
@ -13,9 +14,9 @@
|
|||
<a-input-search style="margin-bottom: 1px" placeholder="请输入部门名称按回车进行搜索" @search="onSearch" />
|
||||
<a-tree
|
||||
checkable
|
||||
class="my-dept-select-tree"
|
||||
:class="treeScreenClass"
|
||||
:treeData="treeData"
|
||||
:checkStrictly="true"
|
||||
:checkStrictly="checkStrictly"
|
||||
@check="onCheck"
|
||||
@select="onSelect"
|
||||
@expand="onExpand"
|
||||
|
@ -32,8 +33,23 @@
|
|||
<span v-else>{{title}}</span>
|
||||
</template>
|
||||
</a-tree>
|
||||
|
||||
</a-spin>
|
||||
<!--底部父子关联操作和确认取消按钮-->
|
||||
<template slot="footer" v-if="treeOpera && multi">
|
||||
<div class="drawer-bootom-button">
|
||||
<a-dropdown style="float: left" :trigger="['click']" placement="topCenter">
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1" @click="switchCheckStrictly(1)">父子关联</a-menu-item>
|
||||
<a-menu-item key="2" @click="switchCheckStrictly(2)">取消关联</a-menu-item>
|
||||
</a-menu>
|
||||
<a-button>
|
||||
树操作 <a-icon type="up" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
<a-button @click="handleCancel" type="primary" style="margin-right: 0.8rem">关闭</a-button>
|
||||
<a-button @click="handleSubmit" type="primary" >确认</a-button>
|
||||
</div>
|
||||
</template>
|
||||
</j-modal>
|
||||
</template>
|
||||
|
||||
|
@ -41,7 +57,7 @@
|
|||
import { queryDepartTreeList } from '@/api/api'
|
||||
export default {
|
||||
name: 'JSelectDepartModal',
|
||||
props:['modalWidth','multi','rootOpened','departId'],
|
||||
props:['modalWidth','multi','rootOpened','departId', 'store', 'text','treeOpera'],
|
||||
data(){
|
||||
return {
|
||||
visible:false,
|
||||
|
@ -52,7 +68,9 @@
|
|||
dataList:[],
|
||||
checkedKeys:[],
|
||||
checkedRows:[],
|
||||
searchValue:""
|
||||
searchValue:"",
|
||||
checkStrictly: true,
|
||||
fullscreen:false
|
||||
}
|
||||
},
|
||||
created(){
|
||||
|
@ -64,15 +82,18 @@
|
|||
},
|
||||
visible: {
|
||||
handler() {
|
||||
if (this.departId) {
|
||||
this.checkedKeys = this.departId.split(",");
|
||||
// console.log('this.departId', this.departId)
|
||||
} else {
|
||||
this.checkedKeys = [];
|
||||
}
|
||||
this.initDepartComponent(true)
|
||||
}
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
treeScreenClass() {
|
||||
return {
|
||||
'my-dept-select-tree': true,
|
||||
'fullscreen': this.fullscreen,
|
||||
}
|
||||
},
|
||||
},
|
||||
methods:{
|
||||
show(){
|
||||
this.visible=true
|
||||
|
@ -80,6 +101,7 @@
|
|||
this.checkedKeys=[]
|
||||
},
|
||||
loadDepart(){
|
||||
// 这个方法是找到所有的部门信息
|
||||
queryDepartTreeList().then(res=>{
|
||||
if(res.success){
|
||||
let arr = [...res.result]
|
||||
|
@ -92,20 +114,23 @@
|
|||
}
|
||||
})
|
||||
},
|
||||
initDepartComponent(){
|
||||
let names = ''
|
||||
initDepartComponent(flag){
|
||||
let arr = []
|
||||
//该方法两个地方用 1.visible改变事件重新设置选中项 2.组件编辑页面回显
|
||||
let fieldName = flag==true?'key':this.text
|
||||
if(this.departId){
|
||||
let currDepartId = this.departId
|
||||
let arr2 = this.departId.split(',')
|
||||
for(let item of this.dataList){
|
||||
if(currDepartId.indexOf(item.key)>=0){
|
||||
names+=","+item.title
|
||||
if(arr2.indexOf(item[this.store])>=0){
|
||||
arr.push(item[fieldName])
|
||||
}
|
||||
}
|
||||
if(names){
|
||||
names = names.substring(1)
|
||||
}
|
||||
}
|
||||
this.$emit("initComp",names)
|
||||
if(flag==true){
|
||||
this.checkedKeys = [...arr]
|
||||
}else{
|
||||
this.$emit("initComp", arr.join(','))
|
||||
}
|
||||
},
|
||||
reWriterWithSlot(arr){
|
||||
for(let item of arr){
|
||||
|
@ -129,8 +154,11 @@
|
|||
}
|
||||
}
|
||||
this.expandedKeys=[...keys]
|
||||
//全部keys
|
||||
//this.allTreeKeys = [...keys]
|
||||
}else{
|
||||
this.expandedKeys=[]
|
||||
//this.allTreeKeys = []
|
||||
}
|
||||
},
|
||||
onCheck (checkedKeys,info) {
|
||||
|
@ -139,25 +167,32 @@
|
|||
this.checkedKeys = [...arr]
|
||||
this.checkedRows = (this.checkedKeys.length === 0) ? [] : [info.node.dataRef]
|
||||
}else{
|
||||
this.checkedKeys = checkedKeys.checked
|
||||
if(this.checkStrictly){
|
||||
this.checkedKeys = checkedKeys.checked
|
||||
}else{
|
||||
this.checkedKeys = checkedKeys
|
||||
}
|
||||
this.checkedRows = this.getCheckedRows(this.checkedKeys)
|
||||
}
|
||||
},
|
||||
onSelect(selectedKeys,info) {
|
||||
let keys = []
|
||||
keys.push(selectedKeys[0])
|
||||
if(!this.checkedKeys || this.checkedKeys.length===0 || !this.multi){
|
||||
this.checkedKeys = [...keys]
|
||||
this.checkedRows=[info.node.dataRef]
|
||||
}else{
|
||||
let currKey = info.node.dataRef.key
|
||||
if(this.checkedKeys.indexOf(currKey)>=0){
|
||||
this.checkedKeys = this.checkedKeys.filter(item=> item !==currKey)
|
||||
//取消关联的情况下才走onSelect的逻辑
|
||||
if(this.checkStrictly){
|
||||
let keys = []
|
||||
keys.push(selectedKeys[0])
|
||||
if(!this.checkedKeys || this.checkedKeys.length===0 || !this.multi){
|
||||
this.checkedKeys = [...keys]
|
||||
this.checkedRows=[info.node.dataRef]
|
||||
}else{
|
||||
this.checkedKeys.push(...keys)
|
||||
let currKey = info.node.dataRef.key
|
||||
if(this.checkedKeys.indexOf(currKey)>=0){
|
||||
this.checkedKeys = this.checkedKeys.filter(item=> item !==currKey)
|
||||
}else{
|
||||
this.checkedKeys.push(...keys)
|
||||
}
|
||||
}
|
||||
this.checkedRows = this.getCheckedRows(this.checkedKeys)
|
||||
}
|
||||
this.checkedRows = this.getCheckedRows(this.checkedKeys)
|
||||
},
|
||||
onExpand (expandedKeys) {
|
||||
this.expandedKeys = expandedKeys
|
||||
|
@ -235,6 +270,16 @@
|
|||
}
|
||||
}
|
||||
return rows
|
||||
},
|
||||
switchCheckStrictly (v) {
|
||||
if(v==1){
|
||||
this.checkStrictly = false
|
||||
}else if(v==2){
|
||||
this.checkStrictly = true
|
||||
}
|
||||
},
|
||||
isFullscreen(val){
|
||||
this.fullscreen=val
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -244,8 +289,22 @@
|
|||
<style lang="less" scoped>
|
||||
// 限制部门选择树高度,避免部门太多时点击确定不便
|
||||
.my-dept-select-tree{
|
||||
height: 350px;
|
||||
height:350px;
|
||||
|
||||
&.fullscreen{
|
||||
height: calc(100vh - 250px);
|
||||
}
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.drawer-bootom-button {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
padding: 10px 16px;
|
||||
text-align: right;
|
||||
left: 0;
|
||||
background: #fff;
|
||||
border-radius: 0 0 2px 2px;
|
||||
}
|
||||
</style>
|
|
@ -63,7 +63,7 @@
|
|||
export default {
|
||||
name: 'JSelectUserByDepModal',
|
||||
components: {},
|
||||
props: ['modalWidth', 'multi', 'userIds'],
|
||||
props: ['modalWidth', 'multi', 'userIds', 'store', 'text'],
|
||||
data() {
|
||||
return {
|
||||
queryParam: {
|
||||
|
@ -159,27 +159,27 @@
|
|||
if (this.userIds) {
|
||||
// 这里最后加一个 , 的原因是因为无论如何都要使用 in 查询,防止后台进行了模糊匹配,导致查询结果不准确
|
||||
let values = this.userIds.split(',') + ','
|
||||
getUserList({
|
||||
username: values,
|
||||
pageNo: 1,
|
||||
pageSize: values.length
|
||||
}).then((res) => {
|
||||
if (res.success) {
|
||||
this.selectionRows = []
|
||||
let selectedRowKeys = []
|
||||
let realNames = []
|
||||
res.result.records.forEach(user => {
|
||||
realNames.push(user['realname'])
|
||||
let param = {[this.store]: values}
|
||||
getAction('/sys/user/getMultiUser', param).then((list)=>{
|
||||
this.selectionRows = []
|
||||
let selectedRowKeys = []
|
||||
let textArray = []
|
||||
if(list && list.length>0){
|
||||
for(let user of list){
|
||||
textArray.push(user[this.text])
|
||||
selectedRowKeys.push(user['id'])
|
||||
this.selectionRows.push(user)
|
||||
})
|
||||
this.selectedRowKeys = selectedRowKeys
|
||||
this.$emit('initComp', realNames.join(','))
|
||||
}
|
||||
}
|
||||
this.selectedRowKeys = selectedRowKeys
|
||||
this.$emit('initComp', textArray.join(','))
|
||||
})
|
||||
|
||||
} else {
|
||||
// JSelectUserByDep组件bug issues/I16634
|
||||
this.$emit('initComp', '')
|
||||
// 前端用户选择单选无法置空的问题 #2610
|
||||
this.selectedRowKeys = []
|
||||
}
|
||||
},
|
||||
async loadData(arg) {
|
||||
|
@ -254,7 +254,7 @@
|
|||
handleSubmit() {
|
||||
let that = this;
|
||||
this.getSelectUserRows();
|
||||
that.$emit('ok', that.selectUserRows, that.selectUserIds);
|
||||
that.$emit('ok', that.selectUserRows);
|
||||
that.searchReset(0)
|
||||
that.close();
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="logo">
|
||||
<router-link :to="{name:'dashboard'}">
|
||||
<router-link :to="routerLinkTo">
|
||||
|
||||
<!-- update-begin- author:sunjianlei --- date:20190814 --- for: logo颜色根据主题颜色变化 -->
|
||||
<img v-if="navTheme === 'dark'" src="~@/assets/logo-white.png" alt="logo">
|
||||
|
@ -28,7 +28,12 @@
|
|||
type: Boolean,
|
||||
default: true,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
// 点击Logo跳转地址
|
||||
routerLinkTo: {
|
||||
type: Object,
|
||||
default: () => ({name: 'dashboard'}),
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -347,6 +347,21 @@ export const constantRouterMap = [
|
|||
// ]
|
||||
// },
|
||||
|
||||
{
|
||||
// OAuth2 APP页面路由
|
||||
path: '/oauth2-app',
|
||||
component: BlankLayout,
|
||||
redirect: '/oauth2-app/login',
|
||||
children: [
|
||||
{
|
||||
// OAuth2 登录路由
|
||||
path: 'login',
|
||||
name: 'login',
|
||||
component: () => import(/* webpackChunkName: "oauth2-app.login" */ '@/views/user/oauth2/OAuth2Login')
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
path: '/test',
|
||||
component: BlankLayout,
|
||||
|
|
|
@ -8,7 +8,6 @@ import { deleteAction, getAction,downFile,getFileAccessHttpUrl } from '@/api/man
|
|||
import Vue from 'vue'
|
||||
import { ACCESS_TOKEN, TENANT_ID } from "@/store/mutation-types"
|
||||
import store from '@/store'
|
||||
import {Modal} from 'ant-design-vue'
|
||||
|
||||
export const JeecgListMixin = {
|
||||
data(){
|
||||
|
@ -94,11 +93,11 @@ export const JeecgListMixin = {
|
|||
this.ipagination.total = 0;
|
||||
}
|
||||
//update-end---author:zhangyafei Date:20201118 for:适配不分页的数据列表------------
|
||||
}
|
||||
if(res.code===510){
|
||||
}else{
|
||||
this.$message.warning(res.message)
|
||||
}
|
||||
this.loading = false;
|
||||
}).finally(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
initDictConfig(){
|
||||
|
@ -296,10 +295,12 @@ export const JeecgListMixin = {
|
|||
},
|
||||
/* 导入 */
|
||||
handleImportExcel(info){
|
||||
this.loading = true;
|
||||
if (info.file.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList);
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
this.loading = false;
|
||||
if (info.file.response.success) {
|
||||
// this.$message.success(`${info.file.name} 文件上传成功`);
|
||||
if (info.file.response.code === 201) {
|
||||
|
@ -321,11 +322,12 @@ export const JeecgListMixin = {
|
|||
this.$message.error(`${info.file.name} ${info.file.response.message}.`);
|
||||
}
|
||||
} else if (info.file.status === 'error') {
|
||||
this.loading = false;
|
||||
if (info.file.response.status === 500) {
|
||||
let data = info.file.response
|
||||
const token = Vue.ls.get(ACCESS_TOKEN)
|
||||
if (token && data.message.includes("Token失效")) {
|
||||
Modal.error({
|
||||
this.$error({
|
||||
title: '登录已过期',
|
||||
content: '很抱歉,登录已过期,请重新登录',
|
||||
okText: '重新登录',
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import { formatDate } from '@/utils/util'
|
||||
import Area from '@/components/_util/Area'
|
||||
import { postAction } from '@/api/manage'
|
||||
|
||||
const onlUtil = {
|
||||
data(){
|
||||
return {
|
||||
mixin_pca:''
|
||||
mixin_pca:'',
|
||||
flowCodePre: 'onl_'
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.mixin_pca = new Area()
|
||||
this.mixin_pca = new Area(this.$Jpcaa)
|
||||
},
|
||||
methods:{
|
||||
simpleDateFormat(millisecond, format){
|
||||
|
|
|
@ -4,19 +4,20 @@ import store from './store'
|
|||
import NProgress from 'nprogress' // progress bar
|
||||
import 'nprogress/nprogress.css' // progress bar style
|
||||
import notification from 'ant-design-vue/es/notification'
|
||||
import { ACCESS_TOKEN,INDEX_MAIN_PAGE_PATH } from '@/store/mutation-types'
|
||||
import { generateIndexRouter } from "@/utils/util"
|
||||
import { ACCESS_TOKEN,INDEX_MAIN_PAGE_PATH, OAUTH2_LOGIN_PAGE_PATH } from '@/store/mutation-types'
|
||||
import { generateIndexRouter, isOAuth2AppEnv } from '@/utils/util'
|
||||
|
||||
NProgress.configure({ showSpinner: false }) // NProgress Configuration
|
||||
|
||||
const whiteList = ['/user/login', '/user/register', '/user/register-result','/user/alteration'] // no redirect whitelist
|
||||
whiteList.push(OAUTH2_LOGIN_PAGE_PATH)
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
NProgress.start() // start progress bar
|
||||
|
||||
if (Vue.ls.get(ACCESS_TOKEN)) {
|
||||
/* has token */
|
||||
if (to.path === '/user/login') {
|
||||
if (to.path === '/user/login' || to.path === OAUTH2_LOGIN_PAGE_PATH) {
|
||||
next({ path: INDEX_MAIN_PAGE_PATH })
|
||||
NProgress.done()
|
||||
} else {
|
||||
|
@ -59,10 +60,18 @@ router.beforeEach((to, from, next) => {
|
|||
}
|
||||
} else {
|
||||
if (whiteList.indexOf(to.path) !== -1) {
|
||||
// 在免登录白名单,直接进入
|
||||
next()
|
||||
// 在免登录白名单,如果进入的页面是login页面并且当前是OAuth2app环境,就进入OAuth2登录页面
|
||||
if (to.path === '/user/login' && isOAuth2AppEnv()) {
|
||||
next({path: OAUTH2_LOGIN_PAGE_PATH})
|
||||
} else {
|
||||
// 在免登录白名单,直接进入
|
||||
next()
|
||||
}
|
||||
NProgress.done()
|
||||
} else {
|
||||
next({ path: '/user/login', query: { redirect: to.fullPath } })
|
||||
// 如果当前是在OAuth2APP环境,就跳转到OAuth2登录页面
|
||||
let path = isOAuth2AppEnv() ? OAUTH2_LOGIN_PAGE_PATH : '/user/login'
|
||||
next({ path: path, query: { redirect: to.fullPath } })
|
||||
NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import Vuex from 'vuex'
|
|||
import app from './modules/app'
|
||||
import user from './modules/user'
|
||||
import permission from './modules/permission'
|
||||
import enhance from './modules/enhance'
|
||||
import online from './modules/online'
|
||||
import getters from './getters'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
@ -15,8 +13,6 @@ export default new Vuex.Store({
|
|||
app,
|
||||
user,
|
||||
permission,
|
||||
enhance,
|
||||
online
|
||||
},
|
||||
state: {
|
||||
|
||||
|
|
|
@ -159,6 +159,7 @@ const user = {
|
|||
Vue.ls.remove(USER_NAME)
|
||||
Vue.ls.remove(UI_CACHE_DB_DICT_DATA)
|
||||
Vue.ls.remove(CACHE_INCLUDED_ROUTES)
|
||||
Vue.ls.remove(TENANT_ID)
|
||||
//console.log('logoutToken: '+ logoutToken)
|
||||
logout(logoutToken).then(() => {
|
||||
if (process.env.VUE_APP_SSO == 'true') {
|
||||
|
|
|
@ -17,6 +17,7 @@ export const ENCRYPTED_STRING = 'ENCRYPTED_STRING'
|
|||
export const ENHANCE_PRE = 'enhance_'
|
||||
export const UI_CACHE_DB_DICT_DATA = 'UI_CACHE_DB_DICT_DATA'
|
||||
export const INDEX_MAIN_PAGE_PATH = '/dashboard/analysis'
|
||||
export const OAUTH2_LOGIN_PAGE_PATH = '/oauth2-app/login'
|
||||
export const TENANT_ID = 'TENANT_ID'
|
||||
export const ONL_AUTH_FIELDS = 'ONL_AUTH_FIELDS'
|
||||
//路由缓存问题,关闭了tab页时再打开就不刷新 #842
|
||||
|
|
|
@ -49,11 +49,13 @@ export default class signMd5Utils {
|
|||
result = {};
|
||||
|
||||
// 获取URL上最后带逗号的参数变量 sys/dict/getDictItems/sys_user,realname,username
|
||||
//【这边条件没有encode】带条件参数例子:/sys/dict/getDictItems/sys_user,realname,id,username!='admin'%20order%20by%20create_time
|
||||
let lastpathVariable = url.substring(url.lastIndexOf('/') + 1);
|
||||
if(lastpathVariable.includes(",")){
|
||||
if(lastpathVariable.includes("?")){
|
||||
lastpathVariable = lastpathVariable.substring(0, lastpathVariable.indexOf("?"));
|
||||
}
|
||||
//解决Sign 签名校验失败 #2728
|
||||
result["x-path-variable"] = decodeURI(lastpathVariable);
|
||||
}
|
||||
if (urlArray && urlArray[1]) {
|
||||
|
|
|
@ -2,7 +2,7 @@ import Vue from 'vue'
|
|||
import axios from 'axios'
|
||||
import store from '@/store'
|
||||
import { VueAxios } from './axios'
|
||||
import {Modal, notification} from 'ant-design-vue'
|
||||
import router from '@/router/index'
|
||||
import { ACCESS_TOKEN, TENANT_ID } from "@/store/mutation-types"
|
||||
|
||||
/**
|
||||
|
@ -28,7 +28,7 @@ const err = (error) => {
|
|||
console.log("------异常响应------",error.response.status)
|
||||
switch (error.response.status) {
|
||||
case 403:
|
||||
notification.error({ message: '系统提示', description: '拒绝访问',duration: 4})
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description: '拒绝访问',duration: 4})
|
||||
break
|
||||
case 500:
|
||||
console.log("------error.response------",error.response)
|
||||
|
@ -39,40 +39,43 @@ const err = (error) => {
|
|||
break;
|
||||
}
|
||||
// update-end- --- author:liusq ------ date:20200910 ---- for:处理Blob情况----
|
||||
//notification.error({ message: '系统提示', description:'Token失效,请重新登录!',duration: 4})
|
||||
if(token && data.message.includes("Token失效")){
|
||||
// update-begin- --- author:scott ------ date:20190225 ---- for:Token失效采用弹框模式,不直接跳转----
|
||||
Modal.error({
|
||||
title: '登录已过期',
|
||||
content: '很抱歉,登录已过期,请重新登录',
|
||||
okText: '重新登录',
|
||||
mask: false,
|
||||
onOk: () => {
|
||||
store.dispatch('Logout').then(() => {
|
||||
Vue.ls.remove(ACCESS_TOKEN)
|
||||
try {
|
||||
let path = window.document.location.pathname
|
||||
console.log("location pathname -> "+path)
|
||||
if(path!="/" && path.indexOf('/user/login')==-1){
|
||||
if (/wxwork|dingtalk/i.test(navigator.userAgent)) {
|
||||
Vue.prototype.$Jmessage.loading('登录已过期,正在重新登陆', 0)
|
||||
} else {
|
||||
Vue.prototype.$Jmodal.error({
|
||||
title: '登录已过期',
|
||||
content: '很抱歉,登录已过期,请重新登录',
|
||||
okText: '重新登录',
|
||||
mask: false,
|
||||
onOk: () => {
|
||||
store.dispatch('Logout').then(() => {
|
||||
Vue.ls.remove(ACCESS_TOKEN)
|
||||
try {
|
||||
let path = window.document.location.pathname
|
||||
console.log('location pathname -> ' + path)
|
||||
if (path != '/' && path.indexOf('/user/login') == -1) {
|
||||
window.location.reload()
|
||||
}
|
||||
} catch (e) {
|
||||
window.location.reload()
|
||||
}
|
||||
}catch (e) {
|
||||
window.location.reload()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
// update-end- --- author:scott ------ date:20190225 ---- for:Token失效采用弹框模式,不直接跳转----
|
||||
}
|
||||
break
|
||||
case 404:
|
||||
notification.error({ message: '系统提示', description:'很抱歉,资源未找到!',duration: 4})
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description:'很抱歉,资源未找到!',duration: 4})
|
||||
break
|
||||
case 504:
|
||||
notification.error({ message: '系统提示', description: '网络超时'})
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description: '网络超时'})
|
||||
break
|
||||
case 401:
|
||||
notification.error({ message: '系统提示', description:'未授权,请重新登录',duration: 4})
|
||||
Vue.prototype.$Jnotification.error({ message: '系统提示', description:'未授权,请重新登录',duration: 4})
|
||||
if (token) {
|
||||
store.dispatch('Logout').then(() => {
|
||||
setTimeout(() => {
|
||||
|
@ -82,13 +85,19 @@ const err = (error) => {
|
|||
}
|
||||
break
|
||||
default:
|
||||
notification.error({
|
||||
Vue.prototype.$Jnotification.error({
|
||||
message: '系统提示',
|
||||
description: data.message,
|
||||
duration: 4
|
||||
})
|
||||
break
|
||||
}
|
||||
} else if (error.message) {
|
||||
if (error.message.includes('timeout')) {
|
||||
Vue.prototype.$Jnotification.error({message: '系统提示', description: '网络超时'})
|
||||
} else {
|
||||
Vue.prototype.$Jnotification.error({message: '系统提示', description: error.message})
|
||||
}
|
||||
}
|
||||
return Promise.reject(error)
|
||||
};
|
||||
|
@ -99,6 +108,14 @@ service.interceptors.request.use(config => {
|
|||
if (token) {
|
||||
config.headers[ 'X-Access-Token' ] = token // 让每个请求携带自定义 token 请根据实际情况自行修改
|
||||
}
|
||||
|
||||
// update-begin--author:sunjianlei---date:20200723---for 如果当前在low-app环境,并且携带了appId,就向Header里传递appId
|
||||
const $route = router.currentRoute
|
||||
if ($route && $route.name && $route.name.startsWith('low-app') && $route.params.appId) {
|
||||
config.headers['X-Low-App-ID'] = $route.params.appId
|
||||
}
|
||||
// update-end--author:sunjianlei---date:20200723---for 如果当前在low-app环境,并且携带了appId,就向Header里传递appId
|
||||
|
||||
//update-begin-author:taoyan date:2020707 for:多租户
|
||||
let tenantid = Vue.ls.get(TENANT_ID)
|
||||
if (!tenantid) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import Vue from 'vue'
|
||||
import * as api from '@/api/api'
|
||||
import { isURL } from '@/utils/validate'
|
||||
import { ACCESS_TOKEN } from '@/store/mutation-types'
|
||||
import onlineCommons from '@jeecg/antd-online-mini'
|
||||
|
||||
export function timeFix() {
|
||||
|
@ -145,6 +147,7 @@ function generateChildRouters (data) {
|
|||
component: componentPath,
|
||||
//component: resolve => require(['@/' + component+'.vue'], resolve),
|
||||
hidden:item.hidden,
|
||||
//component:()=> import(`@/views/${item.component}.vue`),
|
||||
meta: {
|
||||
title:item.meta.title ,
|
||||
icon: item.meta.icon,
|
||||
|
@ -559,4 +562,32 @@ export function removeArrayElement(array, prod, value) {
|
|||
if(index>=0){
|
||||
array.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 判断是否是OAuth2APP环境 */
|
||||
export function isOAuth2AppEnv() {
|
||||
return /wxwork|dingtalk/i.test(navigator.userAgent)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取积木报表打印地址
|
||||
* @param url
|
||||
* @param id
|
||||
* @param open 是否自动打开
|
||||
* @returns {*}
|
||||
*/
|
||||
export function getReportPrintUrl(url, id, open) {
|
||||
// URL支持{{ window.xxx }}占位符变量
|
||||
url = url.replace(/{{([^}]+)?}}/g, (s1, s2) => eval(s2))
|
||||
if (url.includes('?')) {
|
||||
url += '&'
|
||||
} else {
|
||||
url += '?'
|
||||
}
|
||||
url += `id=${id}`
|
||||
url += `&token=${Vue.ls.get(ACCESS_TOKEN)}`
|
||||
if (open) {
|
||||
window.open(url)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<a-modal :visible="visible" title="修改头像" :maskClosable="false" :confirmLoading="confirmLoading" :width="800">
|
||||
<a-modal :visible="visible" title="修改头像" :maskClosable="false" :confirmLoading="confirmLoading" :width="800" @cancel="cancelHandel">
|
||||
<a-row>
|
||||
<a-col :xs="24" :md="12" :style="{height: '350px'}">
|
||||
<vue-cropper
|
||||
|
|
|
@ -305,7 +305,7 @@
|
|||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-model-item label="cron表达式" prop="cronExpression">
|
||||
<j-cron v-model="formData.cronExpression"></j-cron>
|
||||
<j-easy-cron v-model="formData.cronExpression"></j-easy-cron>
|
||||
</a-form-model-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
@ -457,6 +457,7 @@
|
|||
import JSelectMultiple from '@/components/jeecg/JSelectMultiple'
|
||||
import JTreeDict from "../../components/jeecg/JTreeDict.vue";
|
||||
import JCron from "@/components/jeecg/JCron.vue";
|
||||
import JEasyCron from "@/components/jeecg/JEasyCron";
|
||||
import JTreeSelect from '@/components/jeecg/JTreeSelect'
|
||||
import JSuperQuery from '@/components/jeecg/JSuperQuery'
|
||||
import JUpload from '@/components/jeecg/JUpload'
|
||||
|
@ -489,7 +490,7 @@
|
|||
JCheckbox,
|
||||
JCodeEditor,
|
||||
JDate, JEditor, JEllipsis, JSlider, JSelectMultiple,
|
||||
JCron, JTreeSelect, JSuperQuery, JMultiSelectTag,
|
||||
JCron, JEasyCron,JTreeSelect, JSuperQuery, JMultiSelectTag,
|
||||
JSearchSelectTag
|
||||
},
|
||||
data() {
|
||||
|
|
|
@ -214,7 +214,12 @@
|
|||
this.isorter.order = "ascend" == sorter.order ? "asc" : "desc"
|
||||
}
|
||||
//这种筛选方式只支持单选
|
||||
this.filters.status = filters.status[0];
|
||||
|
||||
// update-begin-author:liusq date:20210624 for:前台定时任务无法翻页 #2666
|
||||
if(filters && Object.keys(filters).length>0 && filters.status){
|
||||
this.filters.status = filters.status[0];
|
||||
}
|
||||
// update-end-author:liusq date:20210624 for:前台定时任务无法翻页 #2666
|
||||
this.ipagination = pagination;
|
||||
this.loadData();
|
||||
},
|
||||
|
|
|
@ -122,11 +122,6 @@
|
|||
align: 'center',
|
||||
customRender: (t, r, index) => index + 1
|
||||
},
|
||||
{
|
||||
title: '数据源编码',
|
||||
align: 'center',
|
||||
dataIndex: 'code'
|
||||
},
|
||||
{
|
||||
title: '数据源名称',
|
||||
align: 'center',
|
||||
|
@ -149,11 +144,6 @@
|
|||
dataIndex: 'dbUrl',
|
||||
customRender: (t) => ellipsis(t)
|
||||
},
|
||||
{
|
||||
title: '数据库名称',
|
||||
align: 'center',
|
||||
dataIndex: 'dbName'
|
||||
},
|
||||
{
|
||||
title: '用户名',
|
||||
align: 'center',
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
import {getFileAccessHttpUrl} from '@/api/manage';
|
||||
|
||||
export default {
|
||||
name: "SysOnlineList",
|
||||
name: "SysUserOnlineList",
|
||||
mixins:[JeecgListMixin, mixinDevice],
|
||||
components: {},
|
||||
data () {
|
|
@ -291,7 +291,7 @@
|
|||
superQueryFieldList: [
|
||||
{ type: 'input', value: 'username', text: '用户账号', },
|
||||
{ type: 'input', value: 'realname', text: '用户姓名', },
|
||||
{ type: 'select', value: 'sex', text: '性别', dictCode: 'sex' },
|
||||
{ type: 'select', value: 'sex', dbType: 'int', text: '性别', dictCode: 'sex' },
|
||||
],
|
||||
url: {
|
||||
syncUser: "/act/process/extActProcess/doSyncUser",
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
:disabled="disabled">
|
||||
</j-tree-select>
|
||||
</a-form-model-item>
|
||||
|
||||
|
||||
<a-form-model-item label="分类名称" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="name">
|
||||
<a-input v-model="model.name" placeholder="请输入分类名称"></a-input>
|
||||
</a-form-model-item>
|
||||
|
||||
|
||||
</a-form-model>
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
|
@ -36,10 +36,10 @@
|
|||
|
||||
import { httpAction,getAction } from '@/api/manage'
|
||||
import JTreeSelect from '@/components/jeecg/JTreeSelect'
|
||||
|
||||
|
||||
export default {
|
||||
name: "SysCategoryModal",
|
||||
components: {
|
||||
components: {
|
||||
JTreeSelect
|
||||
},
|
||||
data () {
|
||||
|
@ -70,7 +70,7 @@
|
|||
expandedRowKeys:[],
|
||||
pidField:"pid",
|
||||
subExpandedKeys:[]
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
@ -111,7 +111,8 @@
|
|||
httpAction(httpurl,this.model,method).then((res)=>{
|
||||
if(res.success){
|
||||
that.$message.success(res.message);
|
||||
that.submitSuccess(this.model)
|
||||
// close的时候清空了表单的值 导致model为空 修改值在列表页没有变 此处需要复制一下model
|
||||
that.submitSuccess({...this.model})
|
||||
}else{
|
||||
that.$message.warning(res.message);
|
||||
}
|
||||
|
@ -122,7 +123,7 @@
|
|||
}else{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
handleCancel () {
|
||||
|
|
|
@ -41,12 +41,12 @@
|
|||
label="数据源地址">
|
||||
<a-input placeholder="请输入数据源地址" v-decorator="['dbUrl', validatorRules.dbUrl]"/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
<!-- <a-form-item
|
||||
:labelCol="labelCol"
|
||||
:wrapperCol="wrapperCol"
|
||||
label="数据库名称">
|
||||
<a-input placeholder="请输入数据库名称" v-decorator="['dbName', validatorRules.dbName]"/>
|
||||
</a-form-item>
|
||||
</a-form-item>-->
|
||||
<a-form-item
|
||||
:labelCol="labelCol"
|
||||
:wrapperCol="wrapperCol"
|
||||
|
@ -124,7 +124,7 @@
|
|||
dbUrl: { rules: [{ required: true, message: '请输入数据源地址!' }] },
|
||||
dbName: { rules: [{ required: true, message: '请输入数据库名称!' }] },
|
||||
dbUsername: { rules: [{ required: true, message: '请输入用户名!' }] },
|
||||
dbPassword: { rules: [{ required: true, message: '请输入密码!' }] }
|
||||
dbPassword: { rules: [{ required: false, message: '请输入密码!' }] }
|
||||
},
|
||||
url: {
|
||||
add: '/sys/dataSource/add',
|
||||
|
@ -142,7 +142,25 @@
|
|||
// marialDB 数据库
|
||||
'5': { dbDriver: 'org.mariadb.jdbc.Driver' },
|
||||
// postgresql 数据库
|
||||
'6': { dbDriver: 'org.postgresql.Driver' }
|
||||
'6': { dbDriver: 'org.postgresql.Driver' },
|
||||
// 达梦 数据库
|
||||
'7': { dbDriver: 'dm.jdbc.driver.DmDriver' },
|
||||
// 人大金仓 数据库
|
||||
'8': { dbDriver: 'com.kingbase8.Driver' },
|
||||
// 神通 数据库
|
||||
'9': { dbDriver: 'com.oscar.Driver' },
|
||||
// SQLite 数据库
|
||||
'10': { dbDriver: 'org.sqlite.JDBC' },
|
||||
// DB2 数据库
|
||||
'11': { dbDriver: 'com.ibm.db2.jcc.DB2Driver' },
|
||||
// Hsqldb 数据库
|
||||
'12': { dbDriver: 'org.hsqldb.jdbc.JDBCDriver' },
|
||||
// Derby 数据库
|
||||
'13': { dbDriver: 'org.apache.derby.jdbc.ClientDriver' },
|
||||
// H2 数据库
|
||||
'14': { dbDriver: 'org.h2.Driver' },
|
||||
// 其他数据库
|
||||
'15': { dbDriver: '' }
|
||||
},
|
||||
dbUrlMap: {
|
||||
// MySQL 数据库
|
||||
|
@ -153,10 +171,28 @@
|
|||
'2': { dbUrl: 'jdbc:oracle:thin:@127.0.0.1:1521:ORCL' },
|
||||
// SQLServer 数据库
|
||||
'3': { dbUrl: 'jdbc:sqlserver://127.0.0.1:1433;SelectMethod=cursor;DatabaseName=jeecgboot' },
|
||||
// SQLServer 数据库
|
||||
// Mariadb 数据库
|
||||
'5': { dbUrl: 'jdbc:mariadb://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useSSL=false' },
|
||||
// SQLServer 数据库
|
||||
'6': { dbUrl: 'jdbc:postgresql://127.0.0.1:5432/jeecg-boot' }
|
||||
// Postgresql 数据库
|
||||
'6': { dbUrl: 'jdbc:postgresql://127.0.0.1:5432/jeecg-boot' },
|
||||
// 达梦 数据库
|
||||
'7': { dbUrl: 'jdbc:dm://127.0.0.1:5236/?jeecg-boot&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8' },
|
||||
// 人大金仓 数据库
|
||||
'8': { dbUrl: 'jdbc:kingbase8://127.0.0.1:54321/jeecg-boot' },
|
||||
// 神通 数据库
|
||||
'9': { dbUrl: 'jdbc:oscar://192.168.1.125:2003/jeecg-boot' },
|
||||
// SQLite 数据库
|
||||
'10': { dbUrl: 'jdbc:sqlite://opt/test.db' },
|
||||
// DB2 数据库
|
||||
'11': { dbUrl: 'jdbc:db2://127.0.0.1:50000/jeecg-boot' },
|
||||
// Hsqldb 数据库
|
||||
'12': { dbUrl: 'jdbc:hsqldb:hsql://127.0.0.1/jeecg-boot' },
|
||||
// Derby 数据库
|
||||
'13': { dbUrl: 'jdbc:derby://127.0.0.1:1527/jeecg-boot' },
|
||||
// H2 数据库
|
||||
'14': { dbUrl: 'jdbc:h2:tcp://127.0.0.1:8082/jeecg-boot' },
|
||||
// 其他数据库
|
||||
'15': { dbUrl: '' }
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
|
||||
<!--部门分配-->
|
||||
<a-form-model-item label="部门分配" :labelCol="labelCol" :wrapperCol="wrapperCol" v-show="!departDisabled">
|
||||
<j-select-depart v-model="model.selecteddeparts" :multi="true" @back="backDepartInfo" :backDepart="true"></j-select-depart>
|
||||
<j-select-depart v-model="model.selecteddeparts" :multi="true" @back="backDepartInfo" :backDepart="true" :treeOpera="true">></j-select-depart>
|
||||
</a-form-model-item>
|
||||
|
||||
<!--租户分配-->
|
||||
|
|
|
@ -35,18 +35,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import { ACCESS_TOKEN ,ENCRYPTED_STRING} from "@/store/mutation-types"
|
||||
import ThirdLogin from './third/ThirdLogin'
|
||||
import LoginSelectTenant from "./LoginSelectTenant"
|
||||
import TwoStepCaptcha from '@/components/tools/TwoStepCaptcha'
|
||||
import { encryption , getEncryptedString } from '@/utils/encryption/aesEncrypt'
|
||||
import { timeFix } from "@/utils/util"
|
||||
import Vue from 'vue'
|
||||
import { ACCESS_TOKEN, ENCRYPTED_STRING } from '@/store/mutation-types'
|
||||
import ThirdLogin from './third/ThirdLogin'
|
||||
import LoginSelectTenant from './LoginSelectTenant'
|
||||
import TwoStepCaptcha from '@/components/tools/TwoStepCaptcha'
|
||||
import { getEncryptedString } from '@/utils/encryption/aesEncrypt'
|
||||
import { timeFix } from '@/utils/util'
|
||||
|
||||
import LoginAccount from './LoginAccount'
|
||||
import LoginPhone from './LoginPhone'
|
||||
import LoginAccount from './LoginAccount'
|
||||
import LoginPhone from './LoginPhone'
|
||||
|
||||
export default {
|
||||
export default {
|
||||
components: {
|
||||
LoginSelectTenant,
|
||||
TwoStepCaptcha,
|
||||
|
|
|
@ -50,12 +50,11 @@
|
|||
|
||||
<script>
|
||||
|
||||
import Vue from 'vue'
|
||||
import { getAction,putAction } from '@/api/manage'
|
||||
import { USER_INFO } from "@/store/mutation-types"
|
||||
import store from './Login'
|
||||
import Vue from 'vue'
|
||||
import { putAction } from '@/api/manage'
|
||||
import { USER_INFO } from '@/store/mutation-types'
|
||||
|
||||
export default {
|
||||
export default {
|
||||
name: 'LoginSelectTenant',
|
||||
data(){
|
||||
return {
|
||||
|
@ -111,18 +110,19 @@
|
|||
this.isMultiDepart = false
|
||||
}
|
||||
},
|
||||
bizTenant(ids){
|
||||
if(!ids || ids.length==0){
|
||||
this.isMultiTenant = false
|
||||
} else if(ids.indexOf(',')<0){
|
||||
this.tenant_id = ids;
|
||||
this.isMultiTenant = false
|
||||
}else{
|
||||
this.visible = true
|
||||
this.isMultiTenant = true
|
||||
getAction('/sys/tenant/queryList', {ids: ids}).then(res=>{
|
||||
this.tenantList = res.result
|
||||
})
|
||||
bizTenantList(loginResult) {
|
||||
let tenantList = loginResult.tenantList
|
||||
if (Array.isArray(tenantList)) {
|
||||
if (tenantList.length === 0) {
|
||||
this.isMultiTenant = false
|
||||
} else if (tenantList.length === 1) {
|
||||
this.tenant_id = tenantList[0].id
|
||||
this.isMultiTenant = false
|
||||
} else {
|
||||
this.visible = true
|
||||
this.isMultiTenant = true
|
||||
this.tenantList = tenantList
|
||||
}
|
||||
}
|
||||
},
|
||||
show(loginResult){
|
||||
|
@ -131,8 +131,7 @@
|
|||
|
||||
let user = Vue.ls.get(USER_INFO)
|
||||
this.username = user.username
|
||||
let ids = user.relTenantIds
|
||||
this.bizTenant(ids);
|
||||
this.bizTenantList(loginResult);
|
||||
|
||||
if(this.visible===false){
|
||||
this.$store.dispatch('saveTenant', this.tenant_id);
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
<template>
|
||||
<div>
|
||||
<div id="loader-wrapper">
|
||||
<div id="loader"></div>
|
||||
<div class="loader-section section-left"></div>
|
||||
<div class="loader-section section-right"></div>
|
||||
<div class="load_title">正在登录 JeecgBoot 低代码平台,请耐心等待</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions } from 'vuex'
|
||||
import { isOAuth2AppEnv, timeFix } from '@/utils/util'
|
||||
import { INDEX_MAIN_PAGE_PATH } from '@/store/mutation-types'
|
||||
|
||||
export default {
|
||||
name: 'OAuth2Login',
|
||||
data() {
|
||||
return {
|
||||
env: {
|
||||
thirdApp: false,
|
||||
wxWork: false,
|
||||
dingtalk: false,
|
||||
},
|
||||
}
|
||||
},
|
||||
beforeCreate() {
|
||||
// 如果当前 不是 OAuth2APP环境,就重定向到 /user/login 页面
|
||||
if (!isOAuth2AppEnv()) {
|
||||
this.$router.replace({path: '/user/login'})
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.checkEnv()
|
||||
this.doOAuth2Login()
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['ThirdLogin']),
|
||||
|
||||
/** 检测当前的环境 */
|
||||
checkEnv() {
|
||||
// 判断当时是否是企业微信环境
|
||||
if (/wxwork/i.test(navigator.userAgent)) {
|
||||
this.env.thirdApp = true
|
||||
this.env.wxWork = true
|
||||
}
|
||||
// 判断当时是否是钉钉环境
|
||||
if (/dingtalk/i.test(navigator.userAgent)) {
|
||||
this.env.thirdApp = true
|
||||
this.env.dingtalk = true
|
||||
}
|
||||
},
|
||||
|
||||
/** 进行OAuth2登录操作 */
|
||||
doOAuth2Login() {
|
||||
if (this.env.thirdApp) {
|
||||
// 判断是否携带了Token,是就说明登录成功
|
||||
if (this.$route.query.oauth2LoginToken) {
|
||||
this.thirdType = this.$route.query.thirdType
|
||||
let token = this.$route.query.oauth2LoginToken
|
||||
this.doThirdLogin(token)
|
||||
} else if (this.env.wxWork) {
|
||||
this.doWechatEnterpriseOAuth2Login()
|
||||
} else if (this.env.dingtalk) {
|
||||
this.doDingTalkOAuth2Login()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 根据token执行登录
|
||||
doThirdLogin(token) {
|
||||
let param = {}
|
||||
param.thirdType = this.thirdType
|
||||
param.token = token
|
||||
this.ThirdLogin(param).then(res => {
|
||||
if (res.success) {
|
||||
this.loginSuccess()
|
||||
} else {
|
||||
this.requestFailed(res)
|
||||
}
|
||||
})
|
||||
},
|
||||
loginSuccess() {
|
||||
// 登陆成功,重定向到主页
|
||||
this.$router.replace({path: INDEX_MAIN_PAGE_PATH})
|
||||
// TODO 这个提示是否还需要?
|
||||
this.$notification.success({
|
||||
message: '欢迎',
|
||||
description: `${timeFix()},欢迎回来`,
|
||||
})
|
||||
},
|
||||
requestFailed(err) {
|
||||
this.$error({
|
||||
title: '登录失败',
|
||||
content: ((err.response || {}).data || {}).message || err.message || '请求出现错误,请稍后再试',
|
||||
okText: '重新登陆',
|
||||
onOk() {
|
||||
window.location.reload()
|
||||
},
|
||||
onCancel() {
|
||||
window.location.reload()
|
||||
},
|
||||
})
|
||||
},
|
||||
|
||||
/** 企业微信OAuth2登录 */
|
||||
doWechatEnterpriseOAuth2Login() {
|
||||
this.sysOAuth2Login('wechat_enterprise')
|
||||
},
|
||||
|
||||
/** 钉钉OAuth2登录 */
|
||||
doDingTalkOAuth2Login() {
|
||||
this.sysOAuth2Login('dingtalk')
|
||||
},
|
||||
|
||||
/** 后台构造oauth2登录地址 */
|
||||
sysOAuth2Login(source) {
|
||||
let url = `${window._CONFIG['domianURL']}/sys/thirdLogin/oauth2/${source}/login`
|
||||
url += `?state=${encodeURIComponent(window.location.origin)}`
|
||||
window.location.href = url
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
Loading…
Reference in New Issue