升级到2.4.6

This commit is contained in:
zer0Black
2022-04-05 23:25:02 +08:00
parent b3665a1a55
commit 7e45498fc2
45 changed files with 1490 additions and 597 deletions
@@ -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;">
@@ -68,175 +57,186 @@
</template>
<script>
import { getFileAccessHttpUrl } from '@api/manage'
import JVxeCellMixins from '@/components/jero/JVxeTable/mixins/JVxeCellMixins'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import JFilePop from '@/components/jero/minipop/JFilePop'
import { getFileAccessHttpUrl } from '@api/manage'
import JVxeCellMixins from '@/components/jero/JVxeTable/mixins/JVxeCellMixins'
import { ACCESS_TOKEN } from '@/store/mutation-types'
import JFilePop from '@/components/jero/minipop/JFilePop'
import JVxeUploadCell from '@/components/jero/JVxeTable/components/cells/JVxeUploadCell'
import JVxeUploadCell from '@/components/jero/JVxeTable/components/cells/JVxeUploadCell'
export default {
name: 'JVxeImageCell',
mixins: [JVxeCellMixins],
components: {JFilePop},
props: {},
data() {
return {
innerFile: null,
number:0
export default {
name: 'JVxeImageCell',
mixins: [JVxeCellMixins],
components: {JFilePop},
props: {},
data() {
return {
innerFile: null,
number:0
}
},
computed: {
/** upload headers */
uploadHeaders() {
let {originColumn: col} = this
let headers = {}
if (col.token === true) {
headers['X-Access-Token'] = this.$ls.get(ACCESS_TOKEN)
}
return headers
},
/** 上传请求地址 */
uploadAction() {
if (!this.originColumn.action) {
return window._CONFIG['domianURL'] + '/sys/common/upload'
} else {
return this.originColumn.action
}
},
computed: {
/** upload headers */
uploadHeaders() {
let {originColumn: col} = this
let headers = {}
if (col.token === true) {
headers['X-Access-Token'] = this.$ls.get(ACCESS_TOKEN)
}
return headers
},
/** 上传请求地址 */
uploadAction() {
if (!this.originColumn.action) {
return window._CONFIG['domianURL'] + '/sys/common/upload'
} else {
return this.originColumn.action
}
},
hasFile() {
return this.innerFile != null
},
/** 预览图片地址 */
imgSrc() {
if (this.innerFile) {
if (this.innerFile['url']) {
return this.innerFile['url']
} else if (this.innerFile['path']) {
let path = this.innerFile['path'].split(',')[0]
return getFileAccessHttpUrl(path)
}
}
return ''
},
responseName() {
if (this.originColumn.responseName) {
return this.originColumn.responseName
} else {
return 'message'
}
},
hasFile() {
return this.innerFile != null
},
watch: {
innerValue: {
immediate: true,
handler() {
if (this.innerValue) {
this.innerFile = this.innerValue
/** 预览图片地址 */
imgSrc() {
if (this.innerFile) {
if (this.innerFile['url']) {
return this.innerFile['url']
} else if (this.innerFile['path']) {
let path = this.innerFile['path'].split(',')[0]
return getFileAccessHttpUrl(path)
}
}
return ''
},
responseName() {
if (this.originColumn.responseName) {
return this.originColumn.responseName
} else {
return 'message'
}
},
},
watch: {
innerValue: {
immediate: true,
handler() {
if (this.innerValue) {
this.innerFile = this.innerValue
} else {
this.innerFile = null
}
},
},
},
methods: {
// 点击更多按钮
handleMoreOperation(originColumn) {
//update-begin-author:wangshuai date:20201021 for:LOWCOD-969 判断传过来的字段是否存在number,用于控制上传文件
if (originColumn.number) {
this.number = originColumn.number
} else {
this.number = 0
}
//update-end-author:wangshuai date:20201021 for:LOWCOD-969 判断传过来的字段是否存在number,用于控制上传文件
if(originColumn && originColumn.fieldExtendJson){
let json = JSON.parse(originColumn.fieldExtendJson);
this.number = json.uploadnum?json.uploadnum:0;
}
let path = ''
if (this.innerFile) {
path = this.innerFile.path
}
this.$refs.filePop.show('', path, 'img')
},
// 更多上传回调
handleFileSuccess(file) {
if (file) {
this.innerFile.path = file.path
this.handleChangeCommon(this.innerFile)
}
},
// 弹出上传出错详细信息
handleClickShowImageError() {
let file = this.innerFile || null
if (file && file['message']) {
this.$error({title: '上传出错', content: '错误信息:' + file['message'], maskClosable: true})
}
},
handleChangeUpload(info) {
let {originColumn: col} = this
let {file} = info
let value = {
name: file.name,
type: file.type,
size: file.size,
status: file.status,
percent: file.percent
}
if (file.response) {
value['responseName'] = file.response[this.responseName]
}
if (file.status === 'done') {
if (typeof file.response.success === 'boolean') {
if (file.response.success) {
value['path'] = file.response[this.responseName]
this.handleChangeCommon(value)
} else {
this.innerFile = null
value['status'] = 'error'
value['message'] = file.response.message || '未知错误'
}
},
},
},
methods: {
// 点击更多按钮
handleMoreOperation(originColumn) {
//update-begin-author:wangshuai date:20201021 for:LOWCOD-969 判断传过来的字段是否存在number,用于控制上传文件
if (originColumn.number) {
this.number = originColumn.number
} else {
this.number = 0
}
//update-end-author:wangshuai date:20201021 for:LOWCOD-969 判断传过来的字段是否存在number,用于控制上传文件
if(originColumn && originColumn.fieldExtendJson){
let json = JSON.parse(originColumn.fieldExtendJson);
this.number = json.uploadnum?json.uploadnum:0;
}
let path = ''
if (this.innerFile) {
path = this.innerFile.path
}
this.$refs.filePop.show('', path, 'img')
},
// 更多上传回调
handleFileSuccess(file) {
if (file) {
this.innerFile.path = file.path
this.handleChangeCommon(this.innerFile)
}
},
// 弹出上传出错详细信息
handleClickShowImageError() {
let file = this.innerFile || null
if (file && file['message']) {
this.$error({title: '上传出错', content: '错误信息:' + file['message'], maskClosable: true})
}
},
handleChangeUpload(info) {
let {originColumn: col} = this
let {file} = info
let value = {
name: file.name,
type: file.type,
size: file.size,
status: file.status,
percent: file.percent
}
if (file.response) {
value['responseName'] = file.response[this.responseName]
}
if (file.status === 'done') {
// 考虑到如果设置action上传路径为非jeecg-boot后台,可能不会返回 success 属性的情况,就默认为成功
value['path'] = file.response[this.responseName]
this.handleChangeCommon(value)
} else if (file.status === 'error') {
value['message'] = file.response.message || '未知错误'
}
this.innerFile = value
},
handleClickDownloadFile() {
if (this.imgSrc) {
window.open(this.imgSrc)
}
},
handleClickDeleteFile() {
this.handleChangeCommon(null)
},
} else if (file.status === 'error') {
value['message'] = file.response.message || '未知错误'
}
this.innerFile = value
},
// 【组件增强】注释详见:JVxeCellMixins.js
enhanced: {
switches: {visible: true},
getValue: value => JVxeUploadCell.enhanced.getValue(value),
setValue: value => JVxeUploadCell.enhanced.setValue(value),
}
handleClickDownloadFile() {
if (this.imgSrc) {
window.open(this.imgSrc)
}
},
handleClickDeleteFile() {
this.handleChangeCommon(null)
},
},
// 【组件增强】注释详见:JVxeCellMixins.js
enhanced: {
switches: {visible: true},
getValue: value => JVxeUploadCell.enhanced.getValue(value),
setValue: value => JVxeUploadCell.enhanced.setValue(value),
}
}
</script>
<style scoped lang="less">
.j-editable-image {
height: 32px;
max-width: 100px !important;
cursor: pointer;
&:hover {
opacity: 0.8;
}
&:active {
opacity: 0.6;
}
.j-editable-image {
height: 32px;
max-width: 100px !important;
cursor: pointer;
&:hover {
opacity: 0.8;
}
&:active {
opacity: 0.6;
}
}
</style>
+6 -4
View File
@@ -8,7 +8,7 @@ export default class Area {
* 构造器
* @param express
*/
constructor() {
constructor(pcaa) {
let arr = []
const province = pcaa['86']
Object.keys(province).map(key=>{
@@ -17,9 +17,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;
}
}
/* 全屏样式 */
+118 -31
View File
@@ -11,7 +11,34 @@
<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>
<div v-if="actionButton" class="action-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 +345,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 +436,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 +491,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 +754,11 @@
type: Boolean,
default: false
},
// 是否显示添加按钮选项
addButtonSettings: {
type: Boolean,
default: false
},
// 是否显示行号
rowNumber: {
type: Boolean,
@@ -866,7 +887,16 @@
lastPushTimeMap: new Map(),
number:0,
//不显示的按钮编码
excludeCode:[]
excludeCode:[],
// 选项配置
settings: {
// 添加行数
addRowNum: 1,
// 添加位置(下标),0 = 最底部
addIndex: 0,
// 添加后滚动到底部
addScrollToBottom: false,
},
}
},
created() {
@@ -881,6 +911,7 @@
event.stopPropagation()
}
}
this.getSavedAddButtonSettings()
},
// 计算属性
computed: {
@@ -1412,22 +1443,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
}
@@ -1456,6 +1483,12 @@
target: this
})
},
// 设置滚动条位置
if (forceScrollToBottom) {
this.$nextTick(() => {
this.resetScrollTop(this.$refs.scrollView.scrollHeight)
})
},
/** 删除被选中的行 */
removeSelectedRows() {
this.removeRows(this.selectedRowIds)
@@ -2095,7 +2128,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 +2391,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 +2467,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 +3351,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>
+11 -3
View File
@@ -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
}
},
}
@@ -23,7 +23,7 @@
</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">
@@ -198,7 +198,6 @@
height: calc(100% - 55px);
}
}
&.no-title.no-footer {
.ant-modal-body {
height: 100%;
@@ -225,14 +224,12 @@
}
}
}
&.no-title{
.ant-modal-header {
padding: 0px 24px;
border-bottom: 0px !important;
}
}
}
@media (max-width: 767px) {
+3 -1
View File
@@ -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(",")
+2 -1
View File
@@ -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
+9 -3
View File
@@ -7,7 +7,7 @@
:headers="headers"
:data="{'biz':bizPath}"
:fileList="fileList"
:beforeUpload="beforeUpload"
:beforeUpload="doBeforeUpload"
@change="handleChange"
:disabled="disabled"
:returnUrl="returnUrl"
@@ -111,6 +111,9 @@
type: Boolean,
default: true
},
beforeUpload: {
type: Function
},
},
watch:{
value:{
@@ -203,7 +206,7 @@
}
this.$emit('change', path);
},
beforeUpload(file){
doBeforeUpload(file){
this.uploadGoOn=true
var fileType = file.type;
if(this.fileType===FILE_TYPE_IMG){
@@ -213,7 +216,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 || '未知错误'
}
+17 -3
View File
@@ -26,18 +26,23 @@ 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"
//jerobiz
import JSelectDepart from '../jerobiz/JSelectDepart.vue'
import JSelectMultiUser from '../jerobiz/JSelectMultiUser.vue'
import JSelectRole from '../jerobiz/JSelectRole.vue'
import JSelectUserByDep from '../jerobiz/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)
@@ -71,5 +76,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------forJPopup组件在modal中使用报错#2729------
if(this.visible){
this.dynamicParamHandler()
this.loadData();
}
// update--begin--autor:liusq-----date:20210706------forJPopup组件在modal中使用报错#2729------
},
},
sorter: {
+152 -128
View File
@@ -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,147 +11,171 @@
:modal-width="modalWidth"
:multi="multi"
:rootOpened="rootOpened"
:depart-id="departIds"
:depart-id="value"
:store="storeField"
:text="textField"
:treeOpera="treeOpera"
@ok="handleOK"
@initComp="initComp"/>
</div>
</template>
<script>
import JSelectDepartModal from './modal/JSelectDepartModal'
export default {
name: 'JSelectDepart',
components:{
JSelectDepartModal
import JSelectDepartModal from './modal/JSelectDepartModal'
import { underLinetoHump } from '@/components/_util/StringUtil'
export default {
name: 'JSelectDepart',
components:{
JSelectDepartModal
},
props:{
modalWidth:{
type:Number,
default:500,
required:false
},
props:{
modalWidth:{
type:Number,
default:500,
required:false
},
multi:{
type:Boolean,
default:false,
required:false
},
rootOpened:{
type:Boolean,
default:true,
required:false
},
value:{
type:String,
required:false
},
disabled:{
type: Boolean,
required: false,
default: false
},
// 自定义返回字段,默认返回 id
customReturnField: {
type: String,
default: 'id'
},
backDepart: {
type: Boolean,
default: false,
required: false
}
multi:{
type:Boolean,
default:false,
required:false
},
data(){
return {
visible:false,
confirmLoading:false,
departNames:"",
departIds:''
}
rootOpened:{
type:Boolean,
default:true,
required:false
},
mounted(){
this.departIds = this.value
value:{
type:String,
required:false
},
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
}
disabled:{
type: Boolean,
required: false,
default: false
},
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;
this.departIds = this.value.split(',').map(item => {
const data = dataList.filter(d=>d[this.customReturnField] === item)
return data.length > 0 ? data[0].id : ''
}).join(',')
}
},
//返回选中的部门信息
backDeparInfo(){
if(this.backDepart===true){
if(this.departIds && this.departIds.length>0){
let arr1 = this.departIds.split(',')
let arr2 = this.departNames.split(',')
let info = []
for(let i=0;i<arr1.length;i++){
info.push({
value: arr1[i],
text: arr2[i]
})
}
this.$emit('back', info)
}
}
},
openModal(){
this.$refs.innerDepartSelectModal.show()
},
handleOK(rows, idstr) {
let value = ''
if (!rows && rows.length <= 0) {
this.departNames = ''
this.departIds = ''
} else {
value = rows.map(row => row[this.customReturnField]).join(',')
this.departNames = rows.map(row => row['departName']).join(',')
this.departIds = idstr
}
this.$emit("change", value)
this.backDeparInfo()
},
getDepartNames(){
return this.departNames
},
handleEmpty(){
this.handleOK('')
}
// 自定义返回字段,默认返回 id
customReturnField: {
type: String,
default: ''
},
model: {
prop: 'value',
event: 'change'
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,
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.storeVals = this.value
},
watch:{
value(val){
this.storeVals = val
}
},
methods:{
initComp(textVals){
this.textVals = textVals
},
//返回选中的部门信息
backDeparInfo(){
if(this.backDepart===true){
if(this.departIds && this.departIds.length>0){
let arr1 = this.storeVals.split(',')
let arr2 = this.textVals.split(',')
let info = []
for(let i=0;i<arr1.length;i++){
info.push({
value: arr1[i],
text: arr2[i]
})
}
this.$emit('back', info)
}
}
},
openModal(){
this.$refs.innerDepartSelectModal.show()
},
handleOK(rows) {
if (!rows && rows.length <= 0) {
this.textVals = ''
this.storeVals = ''
} else {
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", this.storeVals)
this.backDeparInfo()
},
getDepartNames(){
return this.departNames
},
handleEmpty(){
this.handleOK('')
}
},
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style scoped>
.components-input-demo-presuffix .anticon-close-circle {
cursor: pointer;
color: #ccc;
transition: color 0.3s;
font-size: 12px;
}
.components-input-demo-presuffix .anticon-close-circle:hover {
color: #f5222d;
}
.components-input-demo-presuffix .anticon-close-circle:active {
color: #666;
}
.components-input-demo-presuffix .anticon-close-circle {
cursor: pointer;
color: #ccc;
transition: color 0.3s;
font-size: 12px;
}
.components-input-demo-presuffix .anticon-close-circle:hover {
color: #f5222d;
}
.components-input-demo-presuffix .anticon-close-circle:active {
color: #666;
}
</style>
@@ -1,109 +1,143 @@
<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 JSelectUserByDepModal from './modal/JSelectUserByDepModal'
import { underLinetoHump } from '@/components/_util/StringUtil'
export default {
name: 'JSelectUserByDep',
components: {JSelectUserByDepModal},
props: {
modalWidth: {
type: Number,
default: 1250,
required: false
},
value: {
type: String,
required: false
},
disabled: {
type: Boolean,
required: false,
default: false
},
multi: {
type: Boolean,
default: true,
required: false
},
backUser: {
type: Boolean,
default: false,
required: false
export default {
name: 'JSelectUserByDep',
components: {JSelectUserByDepModal},
props: {
modalWidth: {
type: Number,
default: 1250,
required: false
},
value: {
type: String,
required: false
},
disabled: {
type: Boolean,
required: false,
default: false
},
multi: {
type: Boolean,
default: true,
required: false
},
backUser: {
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 {
storeVals: '', //[key values]
textVals: '' //[label values]
}
},
computed:{
storeField(){
let field = this.customReturnField
if(!field){
field = this.store;
}
return underLinetoHump(field)
},
data() {
return {
userIds: "",
userNames: ""
}
textField(){
return underLinetoHump(this.text)
}
},
mounted() {
this.storeVals = this.value
},
watch: {
value(val) {
this.storeVals = val
}
},
model: {
prop: 'value',
event: 'change'
},
methods: {
initComp(textVals) {
this.textVals = textVals
},
mounted() {
this.userIds = this.value
},
watch: {
value(val) {
this.userIds = val
}
},
model: {
prop: 'value',
event: 'change'
},
methods: {
initComp(userNames) {
this.userNames = userNames
},
//返回选中的用户信息
backDeparInfo(){
if(this.backUser===true){
if(this.userIds && this.userIds.length>0){
let arr1 = this.userIds.split(',')
let arr2 = this.userNames.split(',')
let info = []
for(let i=0;i<arr1.length;i++){
info.push({
value: arr1[i],
text: arr2[i]
})
}
this.$emit('back', info)
//返回选中的用户信息
backDeparInfo(){
if(this.backUser===true){
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({
value: arr1[i],
text: arr2[i]
})
}
this.$emit('back', info)
}
},
onSearchDepUser() {
this.$refs.selectModal.showModal()
},
selectOK(rows, idstr) {
console.log("当前选中用户", rows)
console.log("当前选中用户ID", idstr)
if (!rows) {
this.userNames = ''
this.userIds = ''
} else {
let temp = ''
for (let item of rows) {
temp += ',' + item.realname
}
this.userNames = temp.substring(1)
this.userIds = idstr
}
this.$emit("change", this.userIds)
}
},
onSearchDepUser() {
this.$refs.selectModal.showModal()
},
selectOK(rows) {
console.log("当前选中用户", rows)
if (!rows) {
this.storeVals = ''
this.textVals = ''
} else {
let temp1 = []
let temp2 = []
for (let item of rows) {
temp1.push(item[this.storeField])
temp2.push(item[this.textField])
}
this.storeVals = temp1.join(',')
this.textVals = temp2.join(',')
}
this.$emit("change", this.storeVals)
}
}
}
</script>
<style scoped>
@@ -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){
@@ -139,25 +164,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 +267,16 @@
}
}
return rows
},
switchCheckStrictly (v) {
if(v==1){
this.checkStrictly = false
}else if(v==2){
this.checkStrictly = true
}
},
isFullscreen(val){
this.fullscreen=val
}
}
}
@@ -242,10 +284,24 @@
</script>
<style lang="less" scoped>
// 限制部门选择树高度,避免部门太多时点击确定不便
.my-dept-select-tree{
height: 350px;
overflow-y: scroll;
}
// 限制部门选择树高度,避免部门太多时点击确定不便
.my-dept-select-tree{
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>
@@ -64,11 +64,12 @@
<script>
import {filterObj} from '@/utils/util'
import {queryDepartTreeList, getUserList, queryUserByDepId} from '@/api/api'
import { getAction } from '@/api/manage'
export default {
name: 'JSelectUserByDepModal',
components: {},
props: ['modalWidth', 'multi', 'userIds'],
props: ['modalWidth', 'multi', 'userIds', 'store', 'text'],
data() {
return {
queryParam: {
@@ -155,25 +156,27 @@
if (this.userIds) {
// 这里最后加一个 , 的原因是因为无论如何都要使用 in 查询,防止后台进行了模糊匹配,导致查询结果不准确
let values = this.userIds.split(',') + ','
getUserList({
username: values,
pageNo: 1,
pageSize: values.length
}).then((res) => {
if (res.success) {
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.selectedRowKeys = selectedRowKeys
this.$emit('initComp', realNames.join(','))
this.selectionRows.push(user)
}
}
this.selectedRowKeys = selectedRowKeys
this.$emit('initComp', textArray.join(','))
})
} else {
// JSelectUserByDep组件bug issues/I16634
this.$emit('initComp', '')
// 前端用户选择单选无法置空的问题 #2610
this.selectedRowKeys = []
}
},
async loadData(arg) {
@@ -251,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();
},
+7 -2
View File
@@ -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.png" alt="logo">
@@ -28,7 +28,12 @@
type: Boolean,
default: true,
required: false
}
},
// 点击Logo跳转地址
routerLinkTo: {
type: Object,
default: () => ({name: 'dashboard'}),
},
}
}
</script>