mirror of
https://github.com/jeecgboot/JeecgBoot.git
synced 2025-12-08 17:12:28 +08:00
Compare commits
56 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 812cbce06b | |||
| 3b92086047 | |||
| 0fa24b8518 | |||
| 7e7ea37857 | |||
| e550843fd1 | |||
| 3cb20a6a43 | |||
| 0acea1abff | |||
| 9760185bf6 | |||
| 75be8dd5b1 | |||
| a7893c4941 | |||
| ef97f700ab | |||
| 6fb01abbc5 | |||
| fe1b58ade2 | |||
| 1998867ca6 | |||
| a351204865 | |||
| 4da1948cb0 | |||
| 55ebea88af | |||
| 4b830b37c9 | |||
| 537cc05601 | |||
| 8f9f27c550 | |||
| 57f72dd4d0 | |||
| e2e19fa456 | |||
| 98a5148e52 | |||
| c2ae049ad7 | |||
| b44acde9b5 | |||
| db467f22a7 | |||
| 53c91fc349 | |||
| 92028a7e44 | |||
| 8ce40fa3d4 | |||
| 05c7f76484 | |||
| 71a1e9a63b | |||
| 0606aa560a | |||
| 1bbca48ba8 | |||
| d0c15f2302 | |||
| c9ff5d51b4 | |||
| cce5d785e4 | |||
| 234022d905 | |||
| ab529aaf6c | |||
| 07c6d1a23d | |||
| 8f780e180e | |||
| 87f17b9fc5 | |||
| 5a93d001b4 | |||
| d822552e0c | |||
| 832fa30cc9 | |||
| 3af1b390f1 | |||
| a3695151dc | |||
| c269d7637f | |||
| 664413e5d7 | |||
| 986f909628 | |||
| 221940cc5f | |||
| 2a392fb738 | |||
| 2b47cd0c34 | |||
| 1900f3fe77 | |||
| 37fe6fea69 | |||
| 3fbb5ee4ad | |||
| b1958fd295 |
7
.github/ISSUE_TEMPLATE.md
vendored
7
.github/ISSUE_TEMPLATE.md
vendored
@ -9,4 +9,9 @@
|
||||
|
||||
|
||||
|
||||
友情提示: 未按格式要求发帖,会直接删掉。
|
||||
#### 友情提示(为了提高issue处理效率):
|
||||
- 未按格式要求发帖,会被直接删掉;
|
||||
- 请自己初判问题描述是否清楚,是否方便我们调查处理;
|
||||
- 针对问题请说明是Online在线功能(需说明用的主题模板),还是生成的代码功能;
|
||||
- 描述过于简单或模糊,导致无法处理的,会被直接删掉;
|
||||
|
||||
|
||||
51
README.md
51
README.md
@ -1,18 +1,19 @@
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
JEECG BOOT 低代码开发平台(前后端分离版本)
|
||||
===============
|
||||
|
||||
当前最新版本: 2.4.5(发布日期:2021-06-07)
|
||||
当前最新版本: 3.0(发布日期:2021-11-01)
|
||||
|
||||
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
|
||||
[](http://www.jeecg.com)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://jeecg.blog.csdn.net)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
|
||||
@ -44,14 +45,16 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中,
|
||||
|
||||
- 技术官网: [http://www.jeecg.com](http://www.jeecg.com)
|
||||
|
||||
- 开发文档: [http://doc.jeecg.com](http://doc.jeecg.com)
|
||||
|
||||
- 微服务启动: [单体升级为微服务启动文档2.4+](http://doc.jeecg.com/2043906)
|
||||
|
||||
- 在线演示 : [http://boot.jeecg.com](http://boot.jeecg.com)
|
||||
|
||||
- 在线演示(VUE3beta版):[http://boot3.jeecg.com](http://boot3.jeecg.com)
|
||||
|
||||
- 开发文档: [http://doc.jeecg.com](http://doc.jeecg.com)
|
||||
|
||||
- 视频教程 :[JeecgBoot入门视频](http://www.jeecg.com/doc/video)
|
||||
|
||||
- 微服务启动: [单体升级为微服务启动文档2.4+](http://doc.jeecg.com/2043906)
|
||||
|
||||
- 常见问题: [入门常见问题Q&A](http://jeecg.com/doc/qa)
|
||||
|
||||
- 更新日志: [版本日志](http://www.jeecg.com/doc/log)
|
||||
@ -61,13 +64,13 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中,
|
||||
交流互动
|
||||
-----------------------------------
|
||||
|
||||
- QQ交流群 : ④774126647、③816531124(满)、②769925425(满)、①284271917(满)
|
||||
- QQ交流群 : ⑤860162132、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
|
||||
|
||||
- 反馈问题: [反馈问题,请按格式发Issues](https://github.com/zhangdaiscott/jeecg-boot/issues/new)
|
||||
|
||||
- 参与开源: [欢迎加入JEECG开源团队,共同进步!!](http://www.jeecg.com/doc/join)
|
||||
|
||||
- Online一分钟: [1分钟快速学习](https://jeecg.blog.csdn.net/article/details/106078912)
|
||||
- Online一分钟: [1分钟快速学习](https://my.oschina.net/jeecg/blog/3083313)
|
||||
|
||||
|
||||
为什么选择JEECG-BOOT?
|
||||
@ -129,17 +132,33 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中,
|
||||
|
||||
- 依赖管理:Maven
|
||||
|
||||
- 数据库:MySQL5.7+ & Oracle 11g & Sqlserver2017
|
||||
|
||||
- 缓存:Redis
|
||||
|
||||
- 数据库脚本:MySQL5.7+ & Oracle 11g & Sqlserver2017(默认只提供这三个库脚本,其他库需要自己转)
|
||||
|
||||
| 数据库 | 支持 |
|
||||
| --- | --- |
|
||||
| MySQL | √ |
|
||||
| Oracle11g | √ |
|
||||
| Sqlserver2017 | √ |
|
||||
| PostgreSQL | √ |
|
||||
| DB2、Informix | √ |
|
||||
| MariaDB | √ |
|
||||
| SQLite、Hsqldb、Derby、H2 | √ |
|
||||
| 达梦、人大金仓、神通 | √ |
|
||||
| 华为高斯、虚谷、瀚高数据库 | √ |
|
||||
| 阿里云PolarDB、PPAS、HerdDB | √ |
|
||||
| Hive、HBase、CouchBase | √ |
|
||||
|
||||
|
||||
#### 后端
|
||||
- 基础框架:Spring Boot 2.3.5.RELEASE
|
||||
|
||||
- 微服务框架: Spring Cloud Alibaba 2.2.3.RELEASE
|
||||
|
||||
- 持久层框架:Mybatis-plus 3.4.1
|
||||
- 持久层框架:Mybatis-plus 3.4.3.1、Minidao
|
||||
|
||||
- 报表工具: jimureport 1.3.78
|
||||
|
||||
- 安全框架:Apache Shiro 1.7.0,Jwt 3.11.0
|
||||
|
||||
@ -382,11 +401,11 @@ Jeecg-Boot低代码开发平台,可以应用在任何J2EE项目的开发中,
|
||||
- 拉取项目代码
|
||||
```bash
|
||||
git clone https://github.com/zhangdaiscott/jeecg-boot.git
|
||||
cd jeecg-boot/ant-design-jeecg-vue
|
||||
cd jeecg-boot/ant-design-vue-jeecg
|
||||
```
|
||||
|
||||
1. 安装node.js
|
||||
2. 切换到ant-design-jeecg-vue文件夹下
|
||||
2. 切换到ant-design-vue-jeecg文件夹下
|
||||
```
|
||||
# 安装yarn
|
||||
npm install -g yarn
|
||||
@ -487,9 +506,9 @@ yarn run lint
|
||||
|
||||
- [Vue](https://cn.vuejs.org/v2/guide)
|
||||
|
||||
- [路由/菜单说明](https://gitee.com/jeecg/jeecg-boot/tree/v1.1/ant-design-jeecg-vue/src/router/README.md)
|
||||
- [路由/菜单说明](https://gitee.com/jeecg/jeecg-boot/tree/v1.1/ant-design-vue-jeecg/src/router/README.md)
|
||||
|
||||
- [ANTD 默认配置项](https://gitee.com/jeecg/jeecg-boot/blob/v1.1/ant-design-jeecg-vue/src/defaultSettings.js)
|
||||
- [ANTD 默认配置项](https://gitee.com/jeecg/jeecg-boot/blob/v1.1/ant-design-vue-jeecg/src/defaultSettings.js)
|
||||
|
||||
- 其他待补充...
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
Ant Design Jeecg Vue
|
||||
====
|
||||
|
||||
当前最新版本: 2.4.5(发布日期:20210607)
|
||||
当前最新版本: 3.0.0(发布日期:2021-11-01)
|
||||
|
||||
Overview
|
||||
----
|
||||
@ -33,7 +33,7 @@ Jeecg-boot 的前端UI框架,采用前后端分离方案,提供强大代码
|
||||
- 拉取项目代码
|
||||
```bash
|
||||
git clone https://github.com/zhangdaiscott/jeecg-boot.git
|
||||
cd jeecg-boot/ant-design-jeecg-vue
|
||||
cd jeecg-boot/ant-design-vue-jeecg
|
||||
```
|
||||
|
||||
- 安装依赖
|
||||
@ -93,9 +93,9 @@ yarn run lint
|
||||
|
||||
- [Vue](https://cn.vuejs.org/v2/guide)
|
||||
|
||||
- [路由/菜单说明](https://github.com/zhangdaiscott/jeecg-boot/tree/master/ant-design-jeecg-vue/src/router/README.md)
|
||||
- [路由/菜单说明](https://github.com/zhangdaiscott/jeecg-boot/tree/master/ant-design-vue-jeecg/src/router/README.md)
|
||||
|
||||
- [ANTD 默认配置项](https://github.com/zhangdaiscott/jeecg-boot/tree/master/ant-design-jeecg-vue/src/defaultSettings.js)
|
||||
- [ANTD 默认配置项](https://github.com/zhangdaiscott/jeecg-boot/tree/master/ant-design-vue-jeecg/src/defaultSettings.js)
|
||||
|
||||
- 其他待补充...
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "vue-antd-jeecg",
|
||||
"version": "2.4.5",
|
||||
"version": "3.0.0",
|
||||
"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": "3.0.0-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,4 @@
|
||||
import { pcaa } from 'area-data'
|
||||
|
||||
import Vue from 'vue'
|
||||
/**
|
||||
* 省市区
|
||||
*/
|
||||
@ -8,7 +7,10 @@ export default class Area {
|
||||
* 构造器
|
||||
* @param express
|
||||
*/
|
||||
constructor() {
|
||||
constructor(pcaa) {
|
||||
if(!pcaa){
|
||||
pcaa = Vue.prototype.$Jpcaa;
|
||||
}
|
||||
let arr = []
|
||||
const province = pcaa['86']
|
||||
Object.keys(province).map(key=>{
|
||||
@ -17,9 +19,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();
|
||||
}
|
||||
@ -48,7 +48,6 @@
|
||||
props:{
|
||||
disabled: Boolean,
|
||||
value: [String, Number],
|
||||
dict: String,
|
||||
dictOptions: Array,
|
||||
async: Boolean,
|
||||
placeholder:{
|
||||
@ -56,6 +55,11 @@
|
||||
default:"请选择",
|
||||
required:false
|
||||
},
|
||||
dict:{
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
},
|
||||
popContainer:{
|
||||
type:String,
|
||||
default:'',
|
||||
@ -186,16 +190,20 @@
|
||||
}
|
||||
}
|
||||
}else{
|
||||
//异步一开始也加载一点数据
|
||||
this.loading=true
|
||||
getAction(`/sys/dict/loadDict/${this.dict}`,{pageSize: this.pageSize, keyword:''}).then(res=>{
|
||||
this.loading=false
|
||||
if(res.success){
|
||||
this.options = res.result
|
||||
}else{
|
||||
this.$message.warning(res.message)
|
||||
}
|
||||
})
|
||||
if(!this.dict){
|
||||
console.error('搜索组件未配置字典项')
|
||||
}else{
|
||||
//异步一开始也加载一点数据
|
||||
this.loading=true
|
||||
getAction(`/sys/dict/loadDict/${this.dict}`,{pageSize: this.pageSize, keyword:''}).then(res=>{
|
||||
this.loading=false
|
||||
if(res.success){
|
||||
this.options = res.result
|
||||
}else{
|
||||
this.$message.warning(res.message)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
filterOption(input, option) {
|
||||
|
||||
@ -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
|
||||
@ -215,7 +241,7 @@
|
||||
:value="departCompValues[id]"
|
||||
:placeholder="replaceProps(col, col.placeholder)"
|
||||
:trigger-change="true"
|
||||
:multi="true"
|
||||
:multi="isMultipleSelect(col)"
|
||||
@change="(v)=>handleChangeDepartCommon(v,id,row,col)"
|
||||
/>
|
||||
<span
|
||||
@ -239,7 +265,7 @@
|
||||
:value="userCompValues[id]"
|
||||
:placeholder="replaceProps(col, col.placeholder)"
|
||||
:trigger-change="true"
|
||||
:multi="true"
|
||||
:multi="isMultipleSelect(col)"
|
||||
@change="(v)=>handleChangeUserCommon(v,id,row,col)"
|
||||
/>
|
||||
<span
|
||||
@ -277,8 +303,33 @@
|
||||
>{{ jdateValues[id] }}</span>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
|
||||
<!-- time -->
|
||||
<template v-else-if="col.type === formTypes.time">
|
||||
<a-tooltip v-bind="buildTooltipProps(row, col, id)">
|
||||
<j-time
|
||||
v-if="isEditRow(row, col)"
|
||||
:id="id"
|
||||
:key="i"
|
||||
v-bind="buildProps(row,col)"
|
||||
style="width: 100%;"
|
||||
:value="jdateValues[id]"
|
||||
:getCalendarContainer="getParentContainer"
|
||||
:placeholder="replaceProps(col, col.placeholder)"
|
||||
allowClear
|
||||
@change="(v)=>handleChangeJDateCommon(v,id,row,col)"
|
||||
/>
|
||||
<span
|
||||
v-else
|
||||
class="j-td-span no-edit"
|
||||
:class="{disabled: buildProps(row,col).disabled}"
|
||||
@click="handleEditRow(row, col)"
|
||||
>{{ jdateValues[id] }}</span>
|
||||
</a-tooltip>
|
||||
</template>
|
||||
|
||||
<!-- input_pop -->
|
||||
<template v-else-if="col.type === formTypes.input_pop">
|
||||
<template v-else-if="col.type === formTypes.input_pop||col.type === 'textarea'">
|
||||
<a-tooltip v-bind="buildTooltipProps(row, col, id)">
|
||||
<j-input-pop
|
||||
v-if="isEditRow(row, col)"
|
||||
@ -318,7 +369,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>
|
||||
@ -397,7 +448,7 @@
|
||||
|
||||
<!-- update-beign-author:taoyan date:0827 for:文件/图片逻辑新增 -->
|
||||
<div v-else-if="col.type === formTypes.file" :key="i">
|
||||
<template v-if="uploadValues[id] != null" v-for="(file,fileKey) of [(uploadValues[id]||{})]">
|
||||
<template v-if="hasUploadValue(id)" v-for="(file,fileKey) of [(uploadValues[id]||{})]">
|
||||
<div :key="fileKey" style="position: relative;">
|
||||
<a-tooltip v-if="file.status==='uploading'" :title="`上传中(${Math.floor(file.percent)}%)`">
|
||||
<a-icon type="loading" style="color:red;"/>
|
||||
@ -409,9 +460,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">
|
||||
@ -436,7 +487,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div :hidden="uploadValues[id] != null">
|
||||
<div :hidden="hasUploadValue(id)">
|
||||
<a-tooltip v-bind="buildTooltipProps(row, col, id)">
|
||||
<a-upload
|
||||
name="file"
|
||||
@ -456,7 +507,7 @@
|
||||
</div>
|
||||
|
||||
<div v-else-if="col.type === formTypes.image" :key="i">
|
||||
<template v-if="uploadValues[id] != null" v-for="(file,fileKey) of [(uploadValues[id]||{})]">
|
||||
<template v-if="hasUploadValue(id)" v-for="(file,fileKey) of [(uploadValues[id]||{})]">
|
||||
<div :key="fileKey" style="position: relative;">
|
||||
<template v-if="!uploadValues[id] || !(uploadValues[id]['url'] || uploadValues[id]['path'] || uploadValues[id]['message'])">
|
||||
<a-icon type="loading"/>
|
||||
@ -464,20 +515,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;">
|
||||
@ -505,7 +545,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div :hidden="uploadValues[id] != null">
|
||||
<div :hidden="hasUploadValue(id)">
|
||||
<a-tooltip v-bind="buildTooltipProps(row, col, id)">
|
||||
<a-upload
|
||||
name="file"
|
||||
@ -738,6 +778,11 @@
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示添加按钮选项
|
||||
addButtonSettings: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示行号
|
||||
rowNumber: {
|
||||
type: Boolean,
|
||||
@ -866,7 +911,16 @@
|
||||
lastPushTimeMap: new Map(),
|
||||
number:0,
|
||||
//不显示的按钮编码
|
||||
excludeCode:[]
|
||||
excludeCode:[],
|
||||
// 选项配置
|
||||
settings: {
|
||||
// 添加行数
|
||||
addRowNum: 1,
|
||||
// 添加位置(下标),0 = 最底部
|
||||
addIndex: 0,
|
||||
// 添加后滚动到底部
|
||||
addScrollToBottom: false,
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
@ -881,6 +935,7 @@
|
||||
event.stopPropagation()
|
||||
}
|
||||
}
|
||||
this.getSavedAddButtonSettings()
|
||||
},
|
||||
// 计算属性
|
||||
computed: {
|
||||
@ -1033,7 +1088,11 @@
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 判断文件/图片是否存在
|
||||
hasUploadValue(id){
|
||||
let flag = this.uploadValues[id] != null && this.uploadValues[id].toString().length>0
|
||||
return flag;
|
||||
},
|
||||
getElement(id, noCaseId = false) {
|
||||
if (!this.el[id]) {
|
||||
this.el[id] = document.getElementById((noCaseId ? '' : this.caseId) + id)
|
||||
@ -1244,7 +1303,7 @@
|
||||
selectValues[inputId] = undefined
|
||||
}
|
||||
|
||||
} else if (column.type === FormTypes.date || column.type === FormTypes.datetime) {
|
||||
} else if (column.type === FormTypes.date || column.type === FormTypes.datetime || column.type === FormTypes.time) {
|
||||
jdateValues[inputId] = sourceValue
|
||||
|
||||
} else if (column.type === FormTypes.slot) {
|
||||
@ -1256,7 +1315,7 @@
|
||||
departCompValues[inputId] = sourceValue
|
||||
} else if (column.type === FormTypes.sel_user) {
|
||||
userCompValues[inputId] = sourceValue
|
||||
} else if (column.type === FormTypes.input_pop) {
|
||||
} else if (column.type === FormTypes.input_pop || column.type === 'textarea') {
|
||||
jInputPopValues[inputId] = sourceValue
|
||||
} else if (column.type === FormTypes.radio) {
|
||||
radioValues[inputId] = sourceValue
|
||||
@ -1412,22 +1471,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 +1510,12 @@
|
||||
num, insertIndex,
|
||||
target: this
|
||||
})
|
||||
// 设置滚动条位置
|
||||
if (forceScrollToBottom) {
|
||||
this.$nextTick(() => {
|
||||
this.resetScrollTop(this.$refs.scrollView.scrollHeight)
|
||||
})
|
||||
}
|
||||
},
|
||||
/** 删除被选中的行 */
|
||||
removeSelectedRows() {
|
||||
@ -1556,7 +1617,7 @@
|
||||
value[column.key] = selected
|
||||
}
|
||||
|
||||
} else if (column.type === FormTypes.date || column.type === FormTypes.datetime) {
|
||||
} else if (column.type === FormTypes.date || column.type === FormTypes.datetime || column.type === FormTypes.time) {
|
||||
value[column.key] = this.jdateValues[inputId]
|
||||
|
||||
} else if (column.type === FormTypes.sel_depart) {
|
||||
@ -1565,7 +1626,7 @@
|
||||
} else if (column.type === FormTypes.sel_user) {
|
||||
value[column.key] = this.userCompValues[inputId]
|
||||
|
||||
} else if (column.type === FormTypes.input_pop) {
|
||||
} else if (column.type === FormTypes.input_pop || column.type === 'textarea') {
|
||||
value[column.key] = this.jInputPopValues[inputId]
|
||||
|
||||
} else if (column.type === FormTypes.upload) {
|
||||
@ -1761,13 +1822,13 @@
|
||||
}
|
||||
this.$set(this.checkboxValues, key, sourceValue)
|
||||
edited = true
|
||||
} else if (column.type === FormTypes.date || column.type === FormTypes.datetime) {
|
||||
} else if (column.type === FormTypes.date || column.type === FormTypes.datetime || column.type === FormTypes.time) {
|
||||
edited = this.setOneValue(this.jdateValues, modelKey, newValue)
|
||||
} else if (column.type === FormTypes.sel_depart) {
|
||||
edited = this.setOneValue(this.departCompValues, modelKey, newValue)
|
||||
} else if (column.type === FormTypes.sel_user) {
|
||||
edited = this.setOneValue(this.userCompValues, modelKey, newValue)
|
||||
} else if (column.type === FormTypes.input_pop) {
|
||||
} else if (column.type === FormTypes.input_pop || column.type === 'textarea') {
|
||||
edited = this.setOneValue(this.jInputPopValues, modelKey, newValue)
|
||||
} else if (column.type === FormTypes.slot) {
|
||||
edited = this.setOneValue(this.slotValues, modelKey, newValue)
|
||||
@ -2095,7 +2156,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()
|
||||
@ -2106,6 +2172,29 @@
|
||||
clearSelection() {
|
||||
this.selectedRowIds = []
|
||||
},
|
||||
// 获取当前选中的行
|
||||
getSelection() {
|
||||
return this.selectedRowIds.map(id => this.getCleanId(id))
|
||||
},
|
||||
// 设置当前选中的行
|
||||
async setSelection(selectedRowIds) {
|
||||
if (Array.isArray(selectedRowIds) && selectedRowIds.length > 0) {
|
||||
// 兼容IE
|
||||
await this.getElementPromise('tbody')
|
||||
await this.$nextTick()
|
||||
this.selectedRowIds = selectedRowIds.map(id => {
|
||||
let temp = id
|
||||
if (!this.hasCaseId(id)) {
|
||||
temp = this.caseId + id
|
||||
}
|
||||
return temp
|
||||
})
|
||||
}
|
||||
},
|
||||
// 切换全选状态
|
||||
toggleSelectionAll() {
|
||||
this.handleChangeCheckedAll()
|
||||
},
|
||||
/** 用于搜索下拉框中的内容 */
|
||||
handleSelectFilterOption(input, option, column) {
|
||||
if (column.allowSearch === true || column.allowInput === true) {
|
||||
@ -2313,11 +2402,7 @@
|
||||
this.validateOneInput(value, row, column, this.notPassedIds, true, 'change')
|
||||
|
||||
// 触发valueChange 事件
|
||||
if (showTime) {
|
||||
this.elemValueChange(FormTypes.datetime, row, column, value)
|
||||
} else {
|
||||
this.elemValueChange(FormTypes.date, row, column, value)
|
||||
}
|
||||
this.elemValueChange(column.type, row, column, value)
|
||||
},
|
||||
//部门组件值改变
|
||||
handleChangeDepartCommon(value, id, row, column){
|
||||
@ -2353,7 +2438,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 +2514,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)
|
||||
@ -2666,6 +2784,11 @@
|
||||
if (col.type === FormTypes.select && (col.allowInput === true || col.allowSearch === true)) {
|
||||
props['showSearch'] = true
|
||||
}
|
||||
if (col.type === FormTypes.sel_depart || col.type === FormTypes.sel_user) {
|
||||
let { storeField, textField } = this.getStoreAndTextField(col)
|
||||
props['store'] = storeField
|
||||
props['text'] = textField
|
||||
}
|
||||
|
||||
// 判断是否是禁用的列
|
||||
props['disabled'] = (typeof col['disabled'] === 'boolean' ? col['disabled'] : props['disabled'])
|
||||
@ -2683,6 +2806,42 @@
|
||||
return props
|
||||
},
|
||||
|
||||
/**获取部门选择 、用户选择的存储字段、展示字段*/
|
||||
getStoreAndTextField(col){
|
||||
let storeField = '', textField = ''
|
||||
if(col.type === FormTypes.sel_depart){
|
||||
storeField = 'id'
|
||||
textField = 'departName'
|
||||
}else if(col.type === FormTypes.sel_user){
|
||||
storeField = 'username'
|
||||
textField = 'realname'
|
||||
}
|
||||
if(col.fieldExtendJson){
|
||||
// online逻辑
|
||||
let tempJson = JSON.parse(col.fieldExtendJson)
|
||||
if(tempJson){
|
||||
if(tempJson.store){
|
||||
storeField = tempJson.store
|
||||
}
|
||||
if(tempJson.text){
|
||||
textField = tempJson.text
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// 实际开发逻辑
|
||||
if(col.store){
|
||||
storeField = col.store
|
||||
}
|
||||
if(col.text){
|
||||
textField = col.text
|
||||
}
|
||||
}
|
||||
return {
|
||||
storeField,
|
||||
textField
|
||||
}
|
||||
},
|
||||
|
||||
/** 辅助方法:防止过快点击,如果点击过快的话就返回 true */
|
||||
checkTooFastClick(key = 'default', ms = 300) {
|
||||
let nowTime = Date.now()
|
||||
@ -2896,6 +3055,21 @@
|
||||
}else{
|
||||
return this.excludeCode.indexOf(code)<0
|
||||
}
|
||||
},
|
||||
// 判断用户、部门组件是否多选
|
||||
isMultipleSelect(column){
|
||||
let jsonStr = column.fieldExtendJson
|
||||
if(jsonStr){
|
||||
// online
|
||||
let config = JSON.parse(jsonStr)
|
||||
if(config && config['multiSelect']==false){
|
||||
return false
|
||||
}
|
||||
}else if(column.multi==false){
|
||||
// 实际开发
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
},
|
||||
@ -3280,3 +3454,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无法修改------
|
||||
}
|
||||
},
|
||||
|
||||
@ -47,10 +47,10 @@
|
||||
|
||||
<script>
|
||||
|
||||
import { getClass, getStyle } from '@/utils/props-util'
|
||||
import { triggerWindowResizeEvent } from '@/utils/util'
|
||||
import { getClass, getStyle } from '@/utils/props-util'
|
||||
import { triggerWindowResizeEvent } from '@/utils/util'
|
||||
|
||||
export default {
|
||||
export default {
|
||||
name: 'JModal',
|
||||
props: {
|
||||
title: String,
|
||||
@ -169,6 +169,7 @@
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
.j-modal-box {
|
||||
&.fullscreen {
|
||||
top: 0;
|
||||
124
ant-design-vue-jeecg/src/components/jeecg/JModal/JPrompt.vue
Normal file
124
ant-design-vue-jeecg/src/components/jeecg/JModal/JPrompt.vue
Normal file
@ -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>
|
||||
18
ant-design-vue-jeecg/src/components/jeecg/JModal/index.js
Normal file
18
ant-design-vue-jeecg/src/components/jeecg/JModal/index.js
Normal file
@ -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 :value="arrayValue" @change="onChange" mode="multiple" :placeholder="placeholder" allowClear>
|
||||
<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 = []
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@ -379,7 +379,7 @@
|
||||
this.$message.warn("不能查询空条件")
|
||||
}
|
||||
},
|
||||
emitCallback(event = {}) {
|
||||
emitCallback(event = {}, loadStatus = true) {
|
||||
let { params = [], matchType = this.matchType } = event
|
||||
this.superQueryFlag = (params && params.length > 0)
|
||||
for (let param of params) {
|
||||
@ -388,7 +388,7 @@
|
||||
}
|
||||
}
|
||||
console.debug('---高级查询参数--->', { params, matchType })
|
||||
this.$emit(this.callback, params, matchType)
|
||||
this.$emit(this.callback, params, matchType, loadStatus)
|
||||
},
|
||||
handleCancel() {
|
||||
this.close()
|
||||
@ -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
|
||||
@ -427,9 +428,13 @@
|
||||
handleOpen() {
|
||||
this.show()
|
||||
},
|
||||
handleOutReset(loadStaus=true) {
|
||||
this.resetLine()
|
||||
this.emitCallback({}, loadStaus)
|
||||
},
|
||||
handleReset() {
|
||||
this.resetLine()
|
||||
this.emitCallback()
|
||||
this.emitCallback({}, true)
|
||||
},
|
||||
handleSave() {
|
||||
let queryParams = this.removeEmptyObject(this.queryParamsModel)
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -98,6 +98,8 @@ export default {
|
||||
// 是否一直显示组件,如果为false则只有点击的时候才出现组件
|
||||
// 注:该参数不能动态修改;如果行、列字段多的情况下,会根据机器性能造成不同程度的卡顿。
|
||||
alwaysEdit: PropTypes.bool.def(false),
|
||||
// 联动配置,数组,详情配置见文档
|
||||
linkageConfig: PropTypes.array.def(() => []),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -151,7 +153,10 @@ export default {
|
||||
// 允许执行刷新特效的行ID
|
||||
reloadEffectRowKeysMap: {},
|
||||
//配置了但是没有授权的按钮和列 集合
|
||||
excludeCode:[]
|
||||
excludeCode:[],
|
||||
// 联动下拉选项(用于隔离不同的下拉选项)
|
||||
// 内部联动配置,map
|
||||
_innerLinkageConfig: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -178,6 +183,18 @@ export default {
|
||||
renderOptions.target = this
|
||||
}
|
||||
}
|
||||
// 处理联动列,联动列只能作用于 select 组件
|
||||
if (column.$type === JVXETypes.select && this._innerLinkageConfig != null) {
|
||||
// 判断当前列是否是联动列
|
||||
if (this._innerLinkageConfig.has(column.key)) {
|
||||
renderOptions.linkage = {
|
||||
config: this._innerLinkageConfig.get(column.key),
|
||||
getLinkageOptionsSibling: this.getLinkageOptionsSibling,
|
||||
getLinkageOptionsAsync: this.getLinkageOptionsAsync,
|
||||
linkageSelectChange: this.linkageSelectChange,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (column.editRender) {
|
||||
Object.assign(column.editRender, renderOptions)
|
||||
}
|
||||
@ -278,15 +295,21 @@ export default {
|
||||
immediate: true,
|
||||
async handler() {
|
||||
let vxe = await getRefPromise(this, 'vxe')
|
||||
// 阻断vue监听大数据,提高性能
|
||||
|
||||
// 开启了排序就自动计算排序值
|
||||
if (this.dragSort) {
|
||||
this.dataSource.forEach((data, idx) => {
|
||||
this.dataSource.forEach((data, idx) => {
|
||||
// 开启了排序就自动计算排序值
|
||||
if (this.dragSort) {
|
||||
this.$set(data, this.dragSortKey, idx + 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
// 处理联动回显数据
|
||||
if (this._innerLinkageConfig != null) {
|
||||
for (let configItem of this._innerLinkageConfig.values()) {
|
||||
this.autoSetLinkageOptionsByData(data, '', configItem, 0)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// 阻断vue监听大数据,提高性能
|
||||
vxe.loadData(this.dataSource)
|
||||
|
||||
// TODO 解析disabledRows
|
||||
@ -469,7 +492,40 @@ export default {
|
||||
this._innerColumns = _innerColumns
|
||||
this._innerEditRules = _innerEditRules
|
||||
}
|
||||
}
|
||||
},
|
||||
// watch linkageConfig
|
||||
// 整理多级联动配置
|
||||
linkageConfig: {
|
||||
immediate: true,
|
||||
handler() {
|
||||
if (Array.isArray(this.linkageConfig) && this.linkageConfig.length > 0) {
|
||||
// 获取联动的key顺序
|
||||
let getLcKeys = (key, arr) => {
|
||||
let col = this._innerColumns.find(col => col.key === key)
|
||||
if (col) {
|
||||
arr.push(col.key)
|
||||
if (col.linkageKey) {
|
||||
return getLcKeys(col.linkageKey, arr)
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
let configMap = new Map()
|
||||
this.linkageConfig.forEach(lc => {
|
||||
let keys = getLcKeys(lc.key, [])
|
||||
// 多个key共享一个,引用地址
|
||||
let configItem = {
|
||||
...lc, keys,
|
||||
optionsMap: new Map()
|
||||
}
|
||||
keys.forEach(k => configMap.set(k, configItem))
|
||||
})
|
||||
this._innerLinkageConfig = configMap
|
||||
} else {
|
||||
this._innerLinkageConfig = null
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
},
|
||||
@ -668,7 +724,24 @@ export default {
|
||||
async loadNewData(dataSource) {
|
||||
if (Array.isArray(dataSource)) {
|
||||
let {xTable} = this.$refs.vxe.$refs
|
||||
return await xTable.loadData(dataSource)
|
||||
// issues/2784
|
||||
// 先清空所有数据
|
||||
xTable.loadData([])
|
||||
|
||||
dataSource.forEach((data, idx) => {
|
||||
// 开启了排序就自动计算排序值
|
||||
if (this.dragSort) {
|
||||
this.$set(data, this.dragSortKey, idx + 1)
|
||||
}
|
||||
// 处理联动回显数据
|
||||
if (this._innerLinkageConfig != null) {
|
||||
for (let configItem of this._innerLinkageConfig.values()) {
|
||||
this.autoSetLinkageOptionsByData(data, '', configItem, 0)
|
||||
}
|
||||
}
|
||||
})
|
||||
// 再新增
|
||||
return xTable.insertAt(dataSource)
|
||||
}
|
||||
return []
|
||||
},
|
||||
@ -793,6 +866,7 @@ export default {
|
||||
* 添加一行或多行
|
||||
*
|
||||
* @param rows
|
||||
* @param isOnlJs 是否是onlineJS增强触发的
|
||||
* @return
|
||||
*/
|
||||
async addRows(rows = {}, isOnlJs) {
|
||||
@ -892,6 +966,89 @@ export default {
|
||||
this.$emit(name, event)
|
||||
},
|
||||
|
||||
/** 【多级联动】获取同级联动下拉选项 */
|
||||
getLinkageOptionsSibling(row, col, config, request) {
|
||||
// 如果当前列不是顶级列
|
||||
let key = ''
|
||||
if (col.key !== config.key) {
|
||||
// 就找出联动上级列
|
||||
let idx = config.keys.findIndex(k => col.key === k)
|
||||
let parentKey = config.keys[idx - 1]
|
||||
key = row[parentKey]
|
||||
// 如果联动上级列没有选择数据,就直接返回空数组
|
||||
if (key === '' || key == null) {
|
||||
return []
|
||||
}
|
||||
} else {
|
||||
key = 'root'
|
||||
}
|
||||
let options = config.optionsMap.get(key)
|
||||
if (!Array.isArray(options)) {
|
||||
if (request) {
|
||||
let parent = key === 'root' ? '' : key
|
||||
return this.getLinkageOptionsAsync(config, parent)
|
||||
} else {
|
||||
options = []
|
||||
}
|
||||
}
|
||||
return options
|
||||
},
|
||||
/** 【多级联动】获取联动下拉选项(异步) */
|
||||
getLinkageOptionsAsync(config, parent) {
|
||||
return new Promise(resolve => {
|
||||
let key = parent ? parent : 'root'
|
||||
let options
|
||||
if (config.optionsMap.has(key)) {
|
||||
options = config.optionsMap.get(key)
|
||||
if (options instanceof Promise) {
|
||||
options.then(opt => {
|
||||
config.optionsMap.set(key, opt)
|
||||
resolve(opt)
|
||||
})
|
||||
} else {
|
||||
resolve(options)
|
||||
}
|
||||
} else if (typeof config.requestData === 'function') {
|
||||
// 调用requestData方法,通过传入parent来获取子级
|
||||
let promise = config.requestData(parent)
|
||||
config.optionsMap.set(key, promise)
|
||||
promise.then(opt => {
|
||||
config.optionsMap.set(key, opt)
|
||||
resolve(opt)
|
||||
})
|
||||
} else {
|
||||
resolve([])
|
||||
}
|
||||
})
|
||||
},
|
||||
// 【多级联动】 用于回显数据,自动填充 optionsMap
|
||||
autoSetLinkageOptionsByData(data, parent, config, level) {
|
||||
if (level === 0) {
|
||||
this.getLinkageOptionsAsync(config, '')
|
||||
} else {
|
||||
this.getLinkageOptionsAsync(config, parent)
|
||||
}
|
||||
if (config.keys.length - 1 > level) {
|
||||
let value = data[config.keys[level]]
|
||||
if (value) {
|
||||
this.autoSetLinkageOptionsByData(data, value, config, level + 1)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 【多级联动】联动组件change时,清空下级组件
|
||||
linkageSelectChange(row, col, config, value) {
|
||||
if (col.linkageKey) {
|
||||
this.getLinkageOptionsAsync(config, value)
|
||||
let idx = config.keys.findIndex(k => k === col.key)
|
||||
let values = {}
|
||||
for (let i = idx; i < config.keys.length; i++) {
|
||||
values[config.keys[i]] = ''
|
||||
}
|
||||
// 清空后几列的数据
|
||||
this.setValues([{rowKey: row.id, values}])
|
||||
}
|
||||
},
|
||||
|
||||
/** 加载数据字典并合并到 options */
|
||||
_loadDictConcatToOptions(column) {
|
||||
initDictOptions(column.dictCode).then((res) => {
|
||||
@ -1084,6 +1241,15 @@ export default {
|
||||
let createValue = getEnhancedMixins(col.$type || col.type, 'createValue')
|
||||
record[col.key] = createValue({row: record, column, $table: xTable})
|
||||
}
|
||||
// update-begin--author:sunjianlei---date:20210819------for: 处理联动列,联动列只能作用于 select 组件
|
||||
if (col.$type === JVXETypes.select && this._innerLinkageConfig != null) {
|
||||
// 判断当前列是否是联动列
|
||||
if (this._innerLinkageConfig.has(col.key)) {
|
||||
let configItem = this._innerLinkageConfig.get(col.key)
|
||||
this.getLinkageOptionsAsync(configItem, '')
|
||||
}
|
||||
}
|
||||
// update-end--author:sunjianlei---date:20210819------for: 处理联动列,联动列只能作用于 select 组件
|
||||
})
|
||||
return record
|
||||
},
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
:multi="multi"
|
||||
:rootOpened="rootOpened"
|
||||
:depart-id="departIds"
|
||||
:store="storeField()"
|
||||
:text="textField()"
|
||||
@ok="handleOK"
|
||||
@initComp="initComp"/>
|
||||
<span style="display: inline-block;height:100%;padding-left:14px" v-if="departIds" >
|
||||
@ -68,7 +70,7 @@
|
||||
}
|
||||
},
|
||||
multi(){
|
||||
if(this.cellProps.multi==false){
|
||||
if(this.cellProps.multi==false || this.originColumn.multi===false){
|
||||
return false
|
||||
}else{
|
||||
return true
|
||||
@ -101,15 +103,17 @@
|
||||
handleEmpty(){
|
||||
this.handleOK('')
|
||||
},
|
||||
handleOK(rows, idstr) {
|
||||
handleOK(rows) {
|
||||
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
|
||||
let storeField = this.storeField();
|
||||
let textField = this.textField();
|
||||
value = rows.map(row => row[storeField]).join(',')
|
||||
this.departNames = rows.map(row => row[textField]).join(',')
|
||||
this.departIds = value
|
||||
}
|
||||
this.handleChangeCommon(this.departIds)
|
||||
},
|
||||
@ -118,6 +122,34 @@
|
||||
},
|
||||
handleChange(value) {
|
||||
this.handleChangeCommon(value)
|
||||
},
|
||||
storeField(){
|
||||
if(this.originColumn){
|
||||
const str = this.originColumn.fieldExtendJson
|
||||
if(str){
|
||||
let json = JSON.parse(str)
|
||||
if(json && json.store){
|
||||
return json.store
|
||||
}
|
||||
}else if(this.originColumn.store){
|
||||
return this.originColumn.store
|
||||
}
|
||||
}
|
||||
return 'id'
|
||||
},
|
||||
textField(){
|
||||
if(this.originColumn){
|
||||
const str = this.originColumn.fieldExtendJson
|
||||
if(str){
|
||||
let json = JSON.parse(str)
|
||||
if(json && json.text){
|
||||
return json.text
|
||||
}
|
||||
}else if(this.originColumn.text){
|
||||
return this.originColumn.text
|
||||
}
|
||||
}
|
||||
return 'departName'
|
||||
}
|
||||
},
|
||||
enhanced: {
|
||||
|
||||
@ -7,11 +7,16 @@
|
||||
v-bind="selectProps"
|
||||
style="width: 100%;"
|
||||
@blur="handleBlur"
|
||||
@change="handleChangeCommon"
|
||||
@change="handleChange"
|
||||
@search="handleSearchSelect"
|
||||
>
|
||||
|
||||
<template v-for="option of originColumn.options">
|
||||
<div v-if="loading" slot="notFoundContent">
|
||||
<a-icon type="loading" />
|
||||
<span> 加载中…</span>
|
||||
</div>
|
||||
|
||||
<template v-for="option of selectOptions">
|
||||
<a-select-option :key="option.value" :value="option.value" :disabled="option.disabled">
|
||||
<span>{{option.text || option.label || option.title|| option.value}}</span>
|
||||
</a-select-option>
|
||||
@ -23,10 +28,18 @@
|
||||
<script>
|
||||
import JVxeCellMixins, { dispatchEvent } from '@/components/jeecg/JVxeTable/mixins/JVxeCellMixins'
|
||||
import { JVXETypes } from '@comp/jeecg/JVxeTable/index'
|
||||
import { filterDictText } from '@comp/dict/JDictSelectUtil'
|
||||
|
||||
export default {
|
||||
name: 'JVxeSelectCell',
|
||||
mixins: [JVxeCellMixins],
|
||||
data(){
|
||||
return {
|
||||
loading: false,
|
||||
// 异步加载的options(用于多级联动)
|
||||
asyncOptions: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
selectProps() {
|
||||
let props = {...this.cellProps}
|
||||
@ -37,6 +50,32 @@
|
||||
}
|
||||
return props
|
||||
},
|
||||
// 下拉选项
|
||||
selectOptions() {
|
||||
if (this.asyncOptions) {
|
||||
return this.asyncOptions
|
||||
}
|
||||
let {linkage} = this.renderOptions
|
||||
if (linkage) {
|
||||
let {getLinkageOptionsSibling, config} = linkage
|
||||
let res = getLinkageOptionsSibling(this.row, this.originColumn, config, true)
|
||||
// 当返回Promise时,说明是多级联动
|
||||
if (res instanceof Promise) {
|
||||
this.loading = true
|
||||
res.then(opt => {
|
||||
this.asyncOptions = opt
|
||||
this.loading = false
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
this.loading = false
|
||||
})
|
||||
} else {
|
||||
this.asyncOptions = null
|
||||
return res
|
||||
}
|
||||
}
|
||||
return this.originColumn.options
|
||||
},
|
||||
},
|
||||
created() {
|
||||
let multiple = [JVXETypes.selectMultiple, JVXETypes.list_multi]
|
||||
@ -54,6 +93,15 @@
|
||||
},
|
||||
methods: {
|
||||
|
||||
handleChange(value) {
|
||||
// 处理下级联动
|
||||
let linkage = this.renderOptions.linkage
|
||||
if (linkage) {
|
||||
linkage.linkageSelectChange(this.row, this.originColumn, linkage.config, value)
|
||||
}
|
||||
this.handleChangeCommon(value)
|
||||
},
|
||||
|
||||
/** 处理blur失去焦点事件 */
|
||||
handleBlur(value) {
|
||||
let {allowInput, options} = this.originColumn
|
||||
@ -120,7 +168,28 @@
|
||||
dispatchEvent.call(this, event, 'ant-select')
|
||||
},
|
||||
},
|
||||
translate: {enabled: true},
|
||||
translate: {
|
||||
enabled: true,
|
||||
async handler(value,) {
|
||||
let options
|
||||
let {linkage} = this.renderOptions
|
||||
// 判断是否是多级联动,如果是就通过接口异步翻译
|
||||
if (linkage) {
|
||||
let {getLinkageOptionsSibling, config} = linkage
|
||||
options = getLinkageOptionsSibling(this.row, this.originColumn, config, true)
|
||||
if (options instanceof Promise) {
|
||||
return new Promise(resolve => {
|
||||
options.then(opt => {
|
||||
resolve(filterDictText(opt, value))
|
||||
})
|
||||
})
|
||||
}
|
||||
} else {
|
||||
options = this.column.own.options
|
||||
}
|
||||
return filterDictText(options, value)
|
||||
},
|
||||
},
|
||||
getValue(value) {
|
||||
if (Array.isArray(value)) {
|
||||
return value.join(',')
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
<template>
|
||||
<a-time-picker
|
||||
ref="timePicker"
|
||||
:value="innerDateValue"
|
||||
allowClear
|
||||
dropdownClassName="j-vxe-date-picker"
|
||||
style="min-width: 0;"
|
||||
v-bind="cellProps"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
import JVxeCellMixins, { dispatchEvent } from '@/components/jeecg/JVxeTable/mixins/JVxeCellMixins'
|
||||
|
||||
export default {
|
||||
name: 'JVxeTimeCell',
|
||||
mixins: [JVxeCellMixins],
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
innerDateValue: null,
|
||||
dateFormat: 'HH:mm:ss'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
innerValue: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (val == null || val === '') {
|
||||
this.innerDateValue = null
|
||||
} else {
|
||||
this.innerDateValue = moment(val, this.dateFormat)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange(mom, dateStr) {
|
||||
this.handleChangeCommon(dateStr)
|
||||
}
|
||||
},
|
||||
// 【组件增强】注释详见:JVxeCellMixins.js
|
||||
enhanced: {
|
||||
aopEvents: {
|
||||
editActived(event) {
|
||||
dispatchEvent.call(this, event, 'ant-calendar-picker', el => el.children[0].dispatchEvent(event.$event))
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -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 || '未知错误'
|
||||
}
|
||||
|
||||
@ -16,6 +16,8 @@
|
||||
:multi="multi"
|
||||
:user-ids="userIds"
|
||||
@ok="selectOK"
|
||||
:store="storeField"
|
||||
:text="textField"
|
||||
@initComp="initComp"/>
|
||||
<span style="display: inline-block;height:100%;padding-left:14px" v-if="userIds" >
|
||||
<span @click="openSelect" style="display: inline-block;vertical-align: middle">{{ userNames }}</span>
|
||||
@ -77,6 +79,30 @@
|
||||
}else{
|
||||
return true
|
||||
}
|
||||
},
|
||||
storeField(){
|
||||
if(this.originColumn){
|
||||
const str = this.originColumn.fieldExtendJson
|
||||
if(str){
|
||||
let json = JSON.parse(str)
|
||||
if(json && json.store){
|
||||
return json.store
|
||||
}
|
||||
}
|
||||
}
|
||||
return 'username'
|
||||
},
|
||||
textField(){
|
||||
if(this.originColumn){
|
||||
const str = this.originColumn.fieldExtendJson
|
||||
if(str){
|
||||
let json = JSON.parse(str)
|
||||
if(json && json.text){
|
||||
return json.text
|
||||
}
|
||||
}
|
||||
}
|
||||
return 'realname'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@ -102,12 +128,8 @@
|
||||
this.userNames = ''
|
||||
this.userIds = ''
|
||||
} else {
|
||||
let temp = ''
|
||||
for (let item of rows) {
|
||||
temp += ',' + item.realname
|
||||
}
|
||||
this.userNames = temp.substring(1)
|
||||
this.userIds = idstr
|
||||
this.userIds = rows.map(row => row[this.storeField]).join(',')
|
||||
this.userNames = rows.map(row => row[this.textField]).join(',')
|
||||
}
|
||||
this.handleChangeCommon(this.userIds)
|
||||
},
|
||||
|
||||
@ -6,6 +6,7 @@ import JVxeSlotCell from './components/cells/JVxeSlotCell'
|
||||
import JVxeNormalCell from './components/cells/JVxeNormalCell'
|
||||
import JVxeInputCell from './components/cells/JVxeInputCell'
|
||||
import JVxeDateCell from './components/cells/JVxeDateCell'
|
||||
import JVxeTimeCell from './components/cells/JVxeTimeCell'
|
||||
import JVxeSelectCell from './components/cells/JVxeSelectCell'
|
||||
import JVxeCheckboxCell from './components/cells/JVxeCheckboxCell'
|
||||
import JVxeUploadCell from './components/cells/JVxeUploadCell'
|
||||
@ -32,6 +33,7 @@ export const AllCells = {
|
||||
...mapCell(JVXETypes.selectMultiple, JVxeSelectCell), // 下拉多选
|
||||
...mapCell(JVXETypes.date, JVxeDateCell),
|
||||
...mapCell(JVXETypes.datetime, JVxeDateCell),
|
||||
...mapCell(JVXETypes.time, JVxeTimeCell),
|
||||
...mapCell(JVXETypes.upload, JVxeUploadCell),
|
||||
...mapCell(JVXETypes.textarea, JVxeTextareaCell),
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ export const JVXETypes = {
|
||||
select: 'select',
|
||||
date: 'date',
|
||||
datetime: 'datetime',
|
||||
time: 'time',
|
||||
checkbox: 'checkbox',
|
||||
upload: 'upload',
|
||||
// 下拉搜索
|
||||
|
||||
@ -73,6 +73,16 @@ export default {
|
||||
props['disabled'] = true
|
||||
}
|
||||
|
||||
// update-begin-author:taoyan date:20211011 for: online表单,附表用户选择器{"multiSelect":false}不生效,单表可以生效 #3036
|
||||
let jsonStr = col['fieldExtendJson']
|
||||
if(jsonStr){
|
||||
let fieldExtendJson = JSON.parse(jsonStr)
|
||||
if(fieldExtendJson && fieldExtendJson['multiSelect']==false){
|
||||
props['multi'] = false
|
||||
}
|
||||
}
|
||||
// update-end-author:taoyan date:20211011 for: online表单,附表用户选择器{"multiSelect":false}不生效,单表可以生效 #3036
|
||||
|
||||
return props
|
||||
},
|
||||
},
|
||||
@ -102,7 +112,13 @@ export default {
|
||||
|
||||
// 判断是否启用翻译
|
||||
if (this.renderType === JVXERenderType.spaner && this.enhanced.translate.enabled) {
|
||||
this.innerValue = this.enhanced.translate.handler.call(this, value)
|
||||
let res = this.enhanced.translate.handler.call(this, value)
|
||||
// 异步翻译,目前仅【多级联动】使用
|
||||
if (res instanceof Promise) {
|
||||
res.then(value => this.innerValue = value)
|
||||
} else {
|
||||
this.innerValue = res
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,7 @@
|
||||
<a-icon type="close" @click="visible=false"/>
|
||||
</span>
|
||||
</div>
|
||||
<a-input :value="inputContent" :disabled="disabled" @change="handleInputChange">
|
||||
<a-input :value="inputContent" :disabled="disabled" @change="handleInputChange" :placeholder="placeholder">
|
||||
<a-icon slot="suffix" type="fullscreen" @click.stop="pop" />
|
||||
</a-input>
|
||||
<div slot="content">
|
||||
@ -53,6 +53,10 @@
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
placeholder:{
|
||||
type:String,
|
||||
required:false
|
||||
}
|
||||
|
||||
},
|
||||
data(){
|
||||
|
||||
@ -74,6 +74,7 @@
|
||||
import {filterObj} from '@/utils/util'
|
||||
import { filterMultiDictText } from '@/components/dict/JDictSelectUtil'
|
||||
import { httpGroupRequest } from '@/api/GroupRequest.js'
|
||||
import md5 from 'md5'
|
||||
|
||||
const MODAL_WIDTH = 1200;
|
||||
export default {
|
||||
@ -137,8 +138,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: {
|
||||
@ -386,9 +391,12 @@
|
||||
}
|
||||
//update-end---author:liusq Date:20210203 for:pop选择器列主键问题 issues/I29P9Q------------
|
||||
})
|
||||
if(res.length>50){
|
||||
// update-begin---author:taoyan Date:20211025 for:jpopup 表格key重复BUG /issues/3121
|
||||
res = md5(res)
|
||||
/*if(res.length>50){
|
||||
res = res.substring(0,50)
|
||||
}
|
||||
}*/
|
||||
// update-end---author:taoyan Date:20211025 for:jpopup 表格key重复BUG /issues/3121
|
||||
return res
|
||||
},
|
||||
|
||||
|
||||
@ -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();
|
||||
},
|
||||
|
||||
@ -219,10 +219,20 @@
|
||||
cacheRouterArray.splice(cacheRouterArray.findIndex(item => item === componentName), 1)
|
||||
Vue.ls.set(CACHE_INCLUDED_ROUTES, cacheRouterArray)
|
||||
}
|
||||
this.emitPageClosed(removeRoute[0])
|
||||
}
|
||||
//update-end--Author:scott Date:20201015 for:路由缓存问题,关闭了tab页时再打开就不刷新 #842
|
||||
|
||||
},
|
||||
// 触发 page-closed (页面关闭)全局事件
|
||||
emitPageClosed(closedRoute) {
|
||||
this.$root.$emit('page-closed', {
|
||||
closedRoute,
|
||||
pageList: this.pageList,
|
||||
linkList: this.linkList,
|
||||
activePage: this.activePage
|
||||
})
|
||||
},
|
||||
onContextmenu(e) {
|
||||
const pagekey = this.getPageKey(e.target)
|
||||
if (pagekey !== null) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -20,6 +20,7 @@ import 'ant-design-vue/dist/antd.less'; // or 'ant-design-vue/dist/antd.less'
|
||||
import '@/permission' // permission control
|
||||
import '@/utils/filter' // base filter
|
||||
import Print from 'vue-print-nb-jeecg'
|
||||
/*import '@babel/polyfill'*/
|
||||
import preview from 'vue-photo-preview'
|
||||
import 'vue-photo-preview/dist/skin.css'
|
||||
import SSO from '@/cas/sso.js'
|
||||
|
||||
@ -53,6 +53,7 @@ export const JEditableTableMixin = {
|
||||
this.tableReset();
|
||||
resolve();
|
||||
}).then(() => {
|
||||
if (typeof this.addBefore === 'function') this.addBefore()
|
||||
// 默认新增空数据
|
||||
let rowNum = this.addDefaultRowNum
|
||||
if (typeof rowNum !== 'number') {
|
||||
|
||||
@ -51,6 +51,7 @@ export const JEditableTableModelMixin = {
|
||||
this.tableReset();
|
||||
resolve();
|
||||
}).then(() => {
|
||||
if (typeof this.addBefore === 'function') this.addBefore()
|
||||
// 默认新增空数据
|
||||
let rowNum = this.addDefaultRowNum
|
||||
if (typeof rowNum !== 'number') {
|
||||
|
||||
@ -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,10 +1,12 @@
|
||||
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(){
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,8 @@ const getters = {
|
||||
enhanceJs:(state) => (code) => {
|
||||
state.enhance.enhanceJs[code] = Vue.ls.get(ENHANCE_PRE+code);
|
||||
return state.enhance.enhanceJs[code]
|
||||
}
|
||||
},
|
||||
sysSafeMode: state => state.user.sysSafeMode,
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -3,9 +3,9 @@ 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 permission from './modules/permission'
|
||||
import getters from './getters'
|
||||
|
||||
Vue.use(Vuex)
|
||||
@ -16,7 +16,7 @@ export default new Vuex.Store({
|
||||
user,
|
||||
permission,
|
||||
enhance,
|
||||
online
|
||||
online,
|
||||
},
|
||||
state: {
|
||||
|
||||
|
||||
@ -14,7 +14,9 @@ const user = {
|
||||
welcome: '',
|
||||
avatar: '',
|
||||
permissionList: [],
|
||||
info: {}
|
||||
info: {},
|
||||
// 系统安全模式
|
||||
sysSafeMode: null,
|
||||
},
|
||||
|
||||
mutations: {
|
||||
@ -38,6 +40,13 @@ const user = {
|
||||
SET_TENANT: (state, id) => {
|
||||
state.tenantid = id
|
||||
},
|
||||
SET_SYS_SAFE_MODE: (state, sysSafeMode) => {
|
||||
if (typeof sysSafeMode === 'boolean') {
|
||||
state.sysSafeMode = sysSafeMode
|
||||
} else {
|
||||
state.sysSafeMode = false
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
@ -124,20 +133,22 @@ const user = {
|
||||
sessionStorage.setItem(USER_AUTH,JSON.stringify(authData));
|
||||
sessionStorage.setItem(SYS_BUTTON_AUTH,JSON.stringify(allAuthData));
|
||||
if (menuData && menuData.length > 0) {
|
||||
//update--begin--autor:qinfeng-----date:20200109------for:JEECG-63 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
|
||||
menuData.forEach((item, index) => {
|
||||
if (item["children"]) {
|
||||
let hasChildrenMenu = item["children"].filter((i) => {
|
||||
return !i.hidden || i.hidden == false
|
||||
})
|
||||
if (hasChildrenMenu == null || hasChildrenMenu.length == 0) {
|
||||
item["hidden"] = true
|
||||
}
|
||||
}
|
||||
})
|
||||
//console.log(" menu show json ", menuData)
|
||||
//update--end--autor:qinfeng-----date:20200109------for:JEECG-63 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
|
||||
// //update--begin--autor:qinfeng-----date:20200109------for:JEECG-63 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
|
||||
// menuData.forEach((item, index) => {
|
||||
// if (item["children"]) {
|
||||
// let hasChildrenMenu = item["children"].filter((i) => {
|
||||
// return !i.hidden || i.hidden == false
|
||||
// })
|
||||
// if (hasChildrenMenu == null || hasChildrenMenu.length == 0) {
|
||||
// item["hidden"] = true
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
// //console.log(" menu show json ", menuData)
|
||||
// //update--end--autor:qinfeng-----date:20200109------for:JEECG-63 一级菜单的子菜单全部是隐藏路由,则一级菜单不显示------
|
||||
commit('SET_PERMISSIONLIST', menuData)
|
||||
// 设置系统安全模式
|
||||
commit('SET_SYS_SAFE_MODE', response.result.sysSafeMode)
|
||||
} else {
|
||||
reject('getPermissionList: permissions must be a non-null array !')
|
||||
}
|
||||
@ -159,6 +170,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
|
||||
|
||||
@ -8,6 +8,7 @@ const FormTypes = {
|
||||
select: 'select',
|
||||
date: 'date',
|
||||
datetime: 'datetime',
|
||||
time: 'time',
|
||||
upload: 'upload',
|
||||
file: 'file',
|
||||
image: 'image',
|
||||
|
||||
@ -49,12 +49,14 @@ 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("?"));
|
||||
}
|
||||
result["x-path-variable"] = lastpathVariable;
|
||||
//解决Sign 签名校验失败 #2728
|
||||
result["x-path-variable"] = decodeURIComponent(lastpathVariable);
|
||||
}
|
||||
if (urlArray && urlArray[1]) {
|
||||
let paramString = urlArray[1], paramResult;
|
||||
|
||||
@ -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,68 @@ 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
|
||||
}
|
||||
|
||||
/**
|
||||
* JS实现AOP切面
|
||||
*
|
||||
* @param obj 包含函数的对象
|
||||
* @param funcName 要切面的函数名
|
||||
* @param callback 执行方法前的回调,用于切面,callback的返回值就是funcName最终的返回值
|
||||
*/
|
||||
export function aspectAroundFunction(obj, funcName, callback) {
|
||||
if (typeof callback !== 'function' || !obj) {
|
||||
console.warn('【aspectAroundFunction】obj或callback格式不正确')
|
||||
return
|
||||
}
|
||||
// 保存原来的函数
|
||||
let func = obj[funcName]
|
||||
if (typeof func !== 'function') {
|
||||
console.warn('【aspectAroundFunction】' + funcName + '不是一个方法')
|
||||
return
|
||||
}
|
||||
// 赋值新方法
|
||||
// 实现当外部调用 funcName 时,首先调用我定义的新方法
|
||||
// 然后调用传入的callback方法,以决定是否执行 funcName,以及更改参数、返回值
|
||||
obj[funcName] = function (...args) {
|
||||
return callback({
|
||||
args,
|
||||
// 只有执行 proceed 才会真正执行给定的 funcName 方法
|
||||
proceed() {
|
||||
try {
|
||||
return func.apply(obj, args)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -8,123 +8,155 @@
|
||||
:height="484"
|
||||
:dataSource="dataSource"
|
||||
:columns="columns"
|
||||
@valueChange="handleValueChange"
|
||||
:linkage-config="linkageConfig"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
import { randomNumber, randomUUID } from '@/utils/util'
|
||||
import { JVXETypes } from '@/components/jeecg/JVxeTable'
|
||||
import { JVXETypes } from '@/components/jeecg/JVxeTable'
|
||||
import { getAction } from '@api/manage'
|
||||
|
||||
export default {
|
||||
name: 'JVxeDemo2',
|
||||
data() {
|
||||
return {
|
||||
columns: [
|
||||
{
|
||||
title: '省/直辖市/自治区',
|
||||
key: 's1',
|
||||
type: JVXETypes.select,
|
||||
width: '240px',
|
||||
options: [],
|
||||
placeholder: '请选择${title}'
|
||||
},
|
||||
{
|
||||
title: '市',
|
||||
key: 's2',
|
||||
type: JVXETypes.select,
|
||||
width: '240px',
|
||||
options: [],
|
||||
placeholder: '请选择${title}'
|
||||
},
|
||||
{
|
||||
title: '县/区',
|
||||
key: 's3',
|
||||
type: JVXETypes.select,
|
||||
width: '240px',
|
||||
options: [],
|
||||
placeholder: '请选择${title}'
|
||||
}
|
||||
],
|
||||
dataSource: [],
|
||||
|
||||
mockData: [
|
||||
{ text: '北京市', value: '110000', parent: null },
|
||||
{ text: '天津市', value: '120000', parent: null },
|
||||
{ text: '河北省', value: '130000', parent: null },
|
||||
{ text: '上海市', value: '310000', parent: null },
|
||||
|
||||
{ text: '北京市', value: '110100', parent: '110000' },
|
||||
{ text: '天津市市', value: '120100', parent: '120000' },
|
||||
{ text: '石家庄市', value: '130100', parent: '130000' },
|
||||
{ text: '唐山市', value: '130200', parent: '130000' },
|
||||
{ text: '秦皇岛市', value: '130300', parent: '130000' },
|
||||
{ text: '上海市', value: '310100', parent: '310000' },
|
||||
|
||||
{ text: '东城区', value: '110101', parent: '110100' },
|
||||
{ text: '西城区', value: '110102', parent: '110100' },
|
||||
{ text: '朝阳区', value: '110105', parent: '110100' },
|
||||
{ text: '和平区', value: '120101', parent: '120100' },
|
||||
{ text: '河东区', value: '120102', parent: '120100' },
|
||||
{ text: '河西区', value: '120103', parent: '120100' },
|
||||
{ text: '黄浦区', value: '310101', parent: '310100' },
|
||||
{ text: '徐汇区', value: '310104', parent: '310100' },
|
||||
{ text: '长宁区', value: '310105', parent: '310100' },
|
||||
{ text: '长安区', value: '130102', parent: '130100' },
|
||||
{ text: '桥西区', value: '130104', parent: '130100' },
|
||||
{ text: '新华区', value: '130105', parent: '130100' },
|
||||
{ text: '路南区', value: '130202', parent: '130200' },
|
||||
{ text: '路北区', value: '130203', parent: '130200' },
|
||||
{ text: '古冶区', value: '130204', parent: '130200' },
|
||||
{ text: '海港区', value: '130302', parent: '130300' },
|
||||
{ text: '山海关区', value: '130303', parent: '130300' },
|
||||
{ text: '北戴河区', value: '130304', parent: '130300' },
|
||||
]
|
||||
}
|
||||
|
||||
},
|
||||
created() {
|
||||
// 初始化数据
|
||||
this.columns[0].options = this.request(null)
|
||||
},
|
||||
methods: {
|
||||
|
||||
request(parentId) {
|
||||
return this.mockData.filter(i => i.parent === parentId)
|
||||
},
|
||||
|
||||
/** 当选项被改变时,联动其他组件 */
|
||||
handleValueChange(event) {
|
||||
const { type, row, column, value, target } = event
|
||||
console.log("event",event)
|
||||
if (type === JVXETypes.select) {
|
||||
|
||||
// 第一列
|
||||
if (column.key === 's1') {
|
||||
// 设置第二列的 options
|
||||
console.log('this.request(value)::',this.request(value))
|
||||
target.$refs.vxe.columns[3].options = this.request(value)
|
||||
// 清空后两列的数据
|
||||
target.setValues([{
|
||||
rowKey: row.id,
|
||||
values: { s2: '', s3: '' }
|
||||
}])
|
||||
target.$refs.vxe.columns[4].options = []
|
||||
} else
|
||||
// 第二列
|
||||
if (column.key === 's2') {
|
||||
target.$refs.vxe.columns[4].options = this.request(value)
|
||||
target.setValues([{
|
||||
rowKey: row.id,
|
||||
values: { s3: '' }
|
||||
}])
|
||||
}
|
||||
export default {
|
||||
name: 'JVxeDemo2',
|
||||
data() {
|
||||
return {
|
||||
// 联动配置
|
||||
linkageConfig: [
|
||||
{requestData: this.requestData, key: 's1'},
|
||||
// 可配置多个联动
|
||||
{requestData: this.loadMenu, key: 'menu1',},
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
title: '性别',
|
||||
key: 'sex',
|
||||
type: JVXETypes.select,
|
||||
dictCode: 'sex',
|
||||
width: '180px',
|
||||
placeholder: '请选择${title}',
|
||||
},
|
||||
{
|
||||
title: '省/直辖市/自治区',
|
||||
key: 's1',
|
||||
type: JVXETypes.select,
|
||||
width: '180px',
|
||||
placeholder: '请选择${title}',
|
||||
// 联动字段(即下一级的字段)
|
||||
linkageKey: 's2',
|
||||
},
|
||||
{
|
||||
title: '市',
|
||||
key: 's2',
|
||||
type: JVXETypes.select,
|
||||
width: '180px',
|
||||
placeholder: '请选择${title}',
|
||||
// 联动字段(即下一级的字段)
|
||||
linkageKey: 's3',
|
||||
},
|
||||
{
|
||||
title: '县/区',
|
||||
key: 's3',
|
||||
type: JVXETypes.select,
|
||||
width: '180px',
|
||||
options: [],
|
||||
placeholder: '请选择${title}',
|
||||
},
|
||||
{
|
||||
title: '一级菜单',
|
||||
key: 'menu1',
|
||||
type: JVXETypes.select,
|
||||
width: '180px',
|
||||
placeholder: '请选择${title}',
|
||||
// 联动字段(即下一级的字段)
|
||||
linkageKey: 'menu2',
|
||||
},
|
||||
{
|
||||
title: '二级菜单',
|
||||
key: 'menu2',
|
||||
type: JVXETypes.select,
|
||||
width: '180px',
|
||||
placeholder: '请选择${title}',
|
||||
// 联动字段(即下一级的字段)
|
||||
linkageKey: 'menu3',
|
||||
},
|
||||
{
|
||||
title: '三级菜单',
|
||||
key: 'menu3',
|
||||
type: JVXETypes.select,
|
||||
width: '180px',
|
||||
placeholder: '请选择${title}',
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
dataSource: [
|
||||
{sex: '1', s1: '110000', s2: '110100', s3: '110101'},
|
||||
{sex: '2', s1: '130000', s2: '130300', s3: '130303'},
|
||||
],
|
||||
// 模拟数据
|
||||
mockData: [
|
||||
{text: '北京市', value: '110000', parent: ''},
|
||||
{text: '天津市', value: '120000', parent: ''},
|
||||
{text: '河北省', value: '130000', parent: ''},
|
||||
{text: '上海市', value: '310000', parent: ''},
|
||||
|
||||
{text: '北京市', value: '110100', parent: '110000'},
|
||||
{text: '天津市市', value: '120100', parent: '120000'},
|
||||
{text: '石家庄市', value: '130100', parent: '130000'},
|
||||
{text: '唐山市', value: '130200', parent: '130000'},
|
||||
{text: '秦皇岛市', value: '130300', parent: '130000'},
|
||||
{text: '上海市', value: '310100', parent: '310000'},
|
||||
|
||||
{text: '东城区', value: '110101', parent: '110100'},
|
||||
{text: '西城区', value: '110102', parent: '110100'},
|
||||
{text: '朝阳区', value: '110105', parent: '110100'},
|
||||
{text: '和平区', value: '120101', parent: '120100'},
|
||||
{text: '河东区', value: '120102', parent: '120100'},
|
||||
{text: '河西区', value: '120103', parent: '120100'},
|
||||
{text: '黄浦区', value: '310101', parent: '310100'},
|
||||
{text: '徐汇区', value: '310104', parent: '310100'},
|
||||
{text: '长宁区', value: '310105', parent: '310100'},
|
||||
{text: '长安区', value: '130102', parent: '130100'},
|
||||
{text: '桥西区', value: '130104', parent: '130100'},
|
||||
{text: '新华区', value: '130105', parent: '130100'},
|
||||
{text: '路南区', value: '130202', parent: '130200'},
|
||||
{text: '路北区', value: '130203', parent: '130200'},
|
||||
{text: '古冶区', value: '130204', parent: '130200'},
|
||||
{text: '海港区', value: '130302', parent: '130300'},
|
||||
{text: '山海关区', value: '130303', parent: '130300'},
|
||||
{text: '北戴河区', value: '130304', parent: '130300'},
|
||||
],
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 模拟从后台查询数据
|
||||
*/
|
||||
requestData(parent) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let data = this.mockData.filter(i => i.parent === parent)
|
||||
setTimeout(() => {
|
||||
resolve(data)
|
||||
}, 500)
|
||||
})
|
||||
},
|
||||
|
||||
async loadMenu(parent) {
|
||||
let res
|
||||
// 如果parent为空,则查询第一级菜单
|
||||
if (parent === '') {
|
||||
res = await getAction('/sys/permission/getSystemMenuList')
|
||||
} else {
|
||||
res = await getAction('/sys/permission/getSystemSubmenu', {parentId: parent})
|
||||
}
|
||||
if (res.success) {
|
||||
// 返回的数据里必须包含 value 和 text 字段
|
||||
return res.result.map(item => ({value: item.id, text: item.name}))
|
||||
}
|
||||
this.$message.warning('loadMenu失败:' + res.message)
|
||||
return []
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -268,6 +268,7 @@
|
||||
placeholder="请选择菜单"
|
||||
dict="sys_permission,name,id"
|
||||
pidField="parent_id"
|
||||
hasChildField="is_leaf"
|
||||
pidValue=""
|
||||
/>
|
||||
</a-form-model-item>
|
||||
@ -283,6 +284,7 @@
|
||||
placeholder="请选择菜单"
|
||||
dict="sys_permission,name,id"
|
||||
pidField="parent_id"
|
||||
hasChildField="is_leaf"
|
||||
pidValue=""
|
||||
multiple
|
||||
/>
|
||||
@ -305,7 +307,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 +459,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 +492,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 () {
|
||||
@ -156,10 +156,6 @@
|
||||
</a-popconfirm>
|
||||
</a-menu-item>
|
||||
|
||||
<a-menu-item>
|
||||
<a href="javascript:;" @click="handleAgentSettings(record.username)">代理人</a>
|
||||
</a-menu-item>
|
||||
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</span>
|
||||
@ -291,7 +287,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",
|
||||
@ -378,10 +374,6 @@
|
||||
handleChangePassword(username) {
|
||||
this.$refs.passwordmodal.show(username);
|
||||
},
|
||||
handleAgentSettings(username){
|
||||
this.$refs.sysUserAgentModal.agentSettings(username);
|
||||
this.$refs.sysUserAgentModal.title = "用户代理人设置";
|
||||
},
|
||||
passwordModalOk() {
|
||||
//TODO 密码修改完成 不需要刷新页面,可以把datasource中的数据更新一下
|
||||
},
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<a-form-model ref="form" :model="model" :rules="validatorRules">
|
||||
<a-form-model-item required prop="username">
|
||||
<a-input v-model="model.username" size="large" placeholder="请输入帐户名 / jeecg">
|
||||
<a-input v-model="model.username" size="large" placeholder="请输入帐户名 / admin">
|
||||
<a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }"/>
|
||||
</a-input>
|
||||
</a-form-model-item>
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -1,183 +0,0 @@
|
||||
<template>
|
||||
<div class="main">
|
||||
|
||||
<a-form style="max-width: 500px; margin: 40px auto 0;" :form="form" @keyup.enter.native="nextStep">
|
||||
<a-form-item>
|
||||
<a-input
|
||||
v-decorator="['username',validatorRules.username]"
|
||||
size="large"
|
||||
type="text"
|
||||
autocomplete="false"
|
||||
placeholder="请输入用户账号或手机号">
|
||||
<a-icon slot="prefix" type="lock" :style="{ color: 'rgba(0,0,0,.25)' }"/>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
<a-row :gutter="0">
|
||||
<a-col :span="14">
|
||||
<a-form-item>
|
||||
<a-input
|
||||
v-decorator="['inputCode',validatorRules.inputCode]"
|
||||
size="large"
|
||||
type="text"
|
||||
@change="inputCodeChange"
|
||||
placeholder="请输入验证码">
|
||||
<a-icon slot="prefix" v-if=" inputCodeContent==verifiedCode " type="smile"
|
||||
:style="{ color: 'rgba(0,0,0,.25)' }"/>
|
||||
<a-icon slot="prefix" v-else type="frown" :style="{ color: 'rgba(0,0,0,.25)' }"/>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="10" style="text-align: right">
|
||||
<img v-if="requestCodeSuccess" style="margin-top: 2px;" :src="randCodeImage" @click="handleChangeCheckCode"/>
|
||||
<img v-else style="margin-top: 2px;" src="../../../assets/checkcode.png" @click="handleChangeCheckCode"/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-form-item :wrapperCol="{span: 19, offset: 5}">
|
||||
<router-link style="float: left;line-height: 40px;" :to="{ name: 'login' }">使用已有账户登录</router-link>
|
||||
<a-button type="primary" @click="nextStep">下一步</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getAction,postAction } from '@/api/manage'
|
||||
import { checkOnlyUser } from '@/api/api'
|
||||
|
||||
export default {
|
||||
name: "Step1",
|
||||
data() {
|
||||
return {
|
||||
form: this.$form.createForm(this),
|
||||
inputCodeContent: "",
|
||||
inputCodeNull: true,
|
||||
verifiedCode: "",
|
||||
validatorRules: {
|
||||
username: {rules: [{required: false}, {validator: this.validateInputUsername}]},
|
||||
inputCode: {rules: [{required: true, message: '请输入验证码!'}]},
|
||||
},
|
||||
randCodeImage:'',
|
||||
requestCodeSuccess:true,
|
||||
currdatetime:''
|
||||
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.handleChangeCheckCode();
|
||||
},
|
||||
methods: {
|
||||
handleChangeCheckCode(){
|
||||
this.currdatetime = new Date().getTime();
|
||||
getAction(`/sys/randomImage/${this.currdatetime}`).then(res=>{
|
||||
if(res.success){
|
||||
this.randCodeImage = res.result
|
||||
this.requestCodeSuccess=true
|
||||
}else{
|
||||
this.$message.error(res.message)
|
||||
this.requestCodeSuccess=false
|
||||
}
|
||||
}).catch(()=>{
|
||||
this.requestCodeSuccess=false
|
||||
})
|
||||
},
|
||||
nextStep() {
|
||||
let that = this
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
let isPhone = false;
|
||||
var params = {}
|
||||
var reg = /^[1-9]\d*$|^0$/;
|
||||
var username = values.username;
|
||||
if (reg.test(username) == true) {
|
||||
params.phone = username;
|
||||
isPhone = true
|
||||
} else {
|
||||
params.username = username;
|
||||
}
|
||||
that.validateInputCode().then(()=>{
|
||||
getAction("/sys/user/querySysUser", params).then((res) => {
|
||||
if (res.success) {
|
||||
var userList = {
|
||||
username: res.result.username,
|
||||
phone: res.result.phone,
|
||||
isPhone: isPhone
|
||||
};
|
||||
setTimeout(function () {
|
||||
that.$emit('nextStep', userList)
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
},
|
||||
validateInputCode() {
|
||||
return new Promise((resolve,reject)=>{
|
||||
postAction("/sys/checkCaptcha",{
|
||||
captcha:this.inputCodeContent,
|
||||
checkKey:this.currdatetime
|
||||
}).then(res=>{
|
||||
if(res.success){
|
||||
resolve();
|
||||
}else{
|
||||
this.$message.error(res.message)
|
||||
reject();
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
inputCodeChange(e) {
|
||||
this.inputCodeContent = e.target.value;
|
||||
console.log(this.inputCodeContent)
|
||||
if (!e.target.value || 0 == e.target.value) {
|
||||
this.inputCodeNull = true
|
||||
} else {
|
||||
this.inputCodeContent = this.inputCodeContent.toLowerCase()
|
||||
this.inputCodeNull = false
|
||||
}
|
||||
},
|
||||
generateCode(value) {
|
||||
this.verifiedCode = value.toLowerCase();
|
||||
console.log(this.verifiedCode);
|
||||
},
|
||||
validateInputUsername(rule, value, callback) {
|
||||
console.log(value);
|
||||
var reg = /^[0-9]+.?[0-9]*/;
|
||||
if (!value) {
|
||||
callback("请输入用户名和手机号!");
|
||||
}
|
||||
|
||||
//判断用户输入账号还是手机号码
|
||||
if (reg.test(value)) {
|
||||
var params = {
|
||||
phone: value,
|
||||
};
|
||||
checkOnlyUser(params).then((res) => {
|
||||
if (res.success) {
|
||||
callback("用户名不存在!")
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
var params = {
|
||||
username: value,
|
||||
};
|
||||
checkOnlyUser(params).then((res) => {
|
||||
if (res.success) {
|
||||
callback("用户名不存在!")
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
130
ant-design-vue-jeecg/src/views/user/oauth2/OAuth2Login.vue
Normal file
130
ant-design-vue-jeecg/src/views/user/oauth2/OAuth2Login.vue
Normal file
@ -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>
|
||||
@ -14,6 +14,14 @@ module.exports = {
|
||||
*/
|
||||
// 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
|
||||
productionSourceMap: false,
|
||||
// 多入口配置
|
||||
// pages: {
|
||||
// index: {
|
||||
// entry: 'src/main.js',
|
||||
// template: 'public/index.html',
|
||||
// filename: 'index.html',
|
||||
// }
|
||||
// },
|
||||
//打包app时放开该配置
|
||||
//publicPath:'./',
|
||||
configureWebpack: config => {
|
||||
|
||||
@ -888,10 +888,10 @@
|
||||
cssnano-preset-default "^4.0.0"
|
||||
postcss "^7.0.0"
|
||||
|
||||
"@jeecg/antd-online-mini@2.4.5-RC":
|
||||
version "2.4.5-RC"
|
||||
resolved "https://registry.npmjs.org/@jeecg/antd-online-mini/-/antd-online-mini-2.4.5-RC.tgz#88740572f352a8baae694a83305f289b54e603c4"
|
||||
integrity sha512-2Wxj7wr+j3YGU5W1NtOWGM/qv1bd28UVBAxMCIZ/vY12w8+qnaNK9IKri6oJmqYiB40UA9EUqsxE9iMlRfv3Ww==
|
||||
"@jeecg/antd-online-mini@3.0.0-beta":
|
||||
version "3.0.0-beta"
|
||||
resolved "https://registry.npmjs.org/@jeecg/antd-online-mini/-/antd-online-mini-3.0.0-beta.tgz#bd7cbbd30c7c2cdee9d816ad996cd9a58378dc95"
|
||||
integrity sha512-V2JwKeBy8WinDrIcGaZyr+FwmF63aItR8dEO570qVhw+Gfz+E9p+fE7SNmSDdbjNu4yiKfsavzdl2JvG4pwgXA==
|
||||
|
||||
"@mrmlnc/readdir-enhanced@^2.2.1":
|
||||
version "2.2.1"
|
||||
@ -1659,9 +1659,9 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
ant-design-vue@^1.7.2:
|
||||
version "1.7.5"
|
||||
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-1.7.5.tgz#e7ed04cb358adc56be02c7453d2db026d2c405e3"
|
||||
integrity sha512-QVrirCz6eetzui+Dv/ujMqUwIr8e/2H+pKr4VC3mpc+cHkw6L9cBRJK7DhfO7GTyK4EWKkEH3lfLWlD/XjUoQQ==
|
||||
version "1.7.8"
|
||||
resolved "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-1.7.8.tgz#1abbf86b68a4f5b1000bea0487b8031dc0001661"
|
||||
integrity sha512-F1hmiS9vwbyfuFvlamdW5l9bHKqRlj9wHaGDIE41NZMWXyWy8qL0UFa/+I0Wl8gQWZCqODW5pN6Yfoyn85At3A==
|
||||
dependencies:
|
||||
"@ant-design/icons" "^2.1.1"
|
||||
"@ant-design/icons-vue" "^2.0.0"
|
||||
@ -1725,11 +1725,6 @@ arch@^2.1.1:
|
||||
resolved "https://registry.npmjs.org/arch/-/arch-2.1.2.tgz#0c52bbe7344bb4fa260c443d2cbad9c00ff2f0bf"
|
||||
integrity sha512-NTBIIbAfkJeIletyABbVtdPgeKfDafR+1mZV/AyyfC1UkVkp9iUjV+wwmqtUgphHYajbI86jejBJp5e+jkGTiQ==
|
||||
|
||||
area-data@^5.0.6:
|
||||
version "5.0.6"
|
||||
resolved "https://registry.npmjs.org/area-data/-/area-data-5.0.6.tgz#c381c3f88ff9e1050accd07549d206fce2a28d13"
|
||||
integrity sha512-QxLoA+823xXKyhw5S3750I9TToki0OS42HU9ol3rCOsCXfkjtl8RtQ/eoj0cK0Levn4//oEM05FmMumfw/HIlg==
|
||||
|
||||
argparse@^1.0.7:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||
@ -3089,6 +3084,11 @@ check-types@^8.0.3:
|
||||
resolved "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552"
|
||||
integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==
|
||||
|
||||
china-area-data@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmjs.org/china-area-data/-/china-area-data-5.0.1.tgz#7943b83a0619f033bb5893da80cb46e52e44be66"
|
||||
integrity sha512-BQDPpiv5Nn+018ekcJK2oSD9PAD+E1bvXB0wgabc//dFVS/KvRqCgg0QOEUt3vBkx9XzB5a9BmkJCEZDBxVjVw==
|
||||
|
||||
chokidar@^2.1.2, chokidar@^2.1.8:
|
||||
version "2.1.8"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
|
||||
@ -7679,7 +7679,7 @@ moment-timezone@^0.5.31:
|
||||
|
||||
"moment@>= 2.9.0":
|
||||
version "2.29.1"
|
||||
resolved "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||
|
||||
moment@^2.21.0:
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
Jeecg-Boot 低代码开发平台
|
||||
===============
|
||||
|
||||
当前最新版本: 2.4.5(发布日期:20210607)
|
||||
当前最新版本: 3.0(发布日期:2021-11-01)
|
||||
|
||||
|
||||
## 后端技术架构
|
||||
- 基础框架:Spring Boot 2.3.5.RELEASE
|
||||
|
||||
- 持久层框架:Mybatis-plus 3.4.1
|
||||
- 持久层框架:Mybatis-plus 3.4.3.1
|
||||
|
||||
- 安全框架:Apache Shiro 1.7.0,Jwt 3.11.0
|
||||
|
||||
@ -29,7 +29,7 @@ Jeecg-Boot 低代码开发平台
|
||||
|
||||
- 依赖管理:Maven
|
||||
|
||||
- 数据库:MySQL5.7+ & Oracle 11g
|
||||
- 数据库:MySQL5.7+ & Oracle 11g & SqlServer & postgresql & 国产等更多数据库
|
||||
|
||||
- 缓存:Redis
|
||||
|
||||
@ -43,7 +43,7 @@ Jeecg-Boot 低代码开发平台
|
||||
|
||||
- 常见问题: [http://jeecg.com/doc/qa](http://jeecg.com/doc/qa)
|
||||
|
||||
- QQ交流群 : ③816531124、①284271917、②769925425
|
||||
- QQ交流群 : ⑤860162132、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
|
||||
|
||||
|
||||
## 专项文档
|
||||
@ -159,31 +159,37 @@ code: {
|
||||
|
||||
|
||||
## docker镜像用法
|
||||
文档: http://doc.jeecg.com/2043889
|
||||
|
||||
```
|
||||
注意: 如果本地安装了mysql和redis,启动容器前先停掉本地服务,不然会端口冲突。
|
||||
net stop redis
|
||||
net stop mysql
|
||||
|
||||
# 1.修改项目配置文件 application.yml
|
||||
active: docker
|
||||
|
||||
# 2.先进JAVA项目根路径 maven打包
|
||||
mvn clean package
|
||||
|
||||
|
||||
# 3.构建镜像__容器组(当你改变本地代码,也可重新构建镜像)
|
||||
docker-compose build
|
||||
|
||||
# 4.配置host
|
||||
# 1.配置host
|
||||
|
||||
# jeecgboot
|
||||
127.0.0.1 jeecg-boot-redis
|
||||
127.0.0.1 jeecg-boot-mysql
|
||||
127.0.0.1 jeecg-boot-system
|
||||
|
||||
# 2.修改项目配置文件 application.yml
|
||||
active: dev
|
||||
|
||||
# 3.修改application-dev.yml文件的数据库和redis链接
|
||||
修改数据库连接和redis连接,将连接改成host方式
|
||||
|
||||
# 5.启动镜像__容器组(也可取代运行中的镜像)
|
||||
# 4.先进JAVA项目jeecg-boot根路径 maven打包
|
||||
mvn clean package
|
||||
|
||||
|
||||
# 5.构建镜像__容器组(当你改变本地代码,也可重新构建镜像)
|
||||
docker-compose build
|
||||
|
||||
|
||||
# 6.启动镜像__容器组(也可取代运行中的镜像)
|
||||
docker-compose up -d
|
||||
|
||||
# 6.访问后台项目(注意要开启swagger)
|
||||
# 7.访问后台项目(注意要开启swagger)
|
||||
http://localhost:8080/jeecg-boot/doc.html
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,5 +1,6 @@
|
||||
CREATE database if NOT EXISTS `nacos` default character set utf8mb4 collate utf8mb4_unicode_ci;
|
||||
CREATE database if NOT EXISTS `nacos` default character set utf8mb4 collate utf8mb4_general_ci;
|
||||
use `nacos`;
|
||||
|
||||
/*
|
||||
Navicat Premium Data Transfer
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
# XXL-JOB v2.2.0
|
||||
# Copyright (c) 2015-present, xuxueli.
|
||||
|
||||
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_unicode_ci;
|
||||
CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_general_ci;
|
||||
use `xxl_job`;
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
-- online 新增部门授权 扩展字段
|
||||
ALTER TABLE `onl_auth_relation`
|
||||
ADD COLUMN `auth_mode` varchar(50) NULL COMMENT '授权方式role角色,depart部门,user人' AFTER `cgform_id`;
|
||||
update onl_auth_relation set auth_mode = 'role';
|
||||
|
||||
-- 部门表新增 qywx_identifier 字段
|
||||
ALTER TABLE `sys_depart`
|
||||
ADD COLUMN `qywx_identifier` varchar(100) NULL COMMENT '对接企业微信的ID' AFTER `del_flag`;
|
||||
|
||||
-- sys_third_account 表新增 third_user_id 字段
|
||||
ALTER TABLE `sys_third_account`
|
||||
ADD COLUMN `third_user_id` varchar(100) NULL COMMENT '第三方app用户账号' AFTER `third_user_uuid`;
|
||||
|
||||
-- 新增第三方APP消息测试菜单
|
||||
INSERT INTO `sys_permission` (`id`, `parent_id`, `name`, `url`, `component`, `is_route`, `component_name`, `redirect`, `menu_type`, `perms`, `perms_type`, `sort_no`, `always_show`, `icon`, `is_leaf`, `keep_alive`, `hidden`, `description`, `create_by`, `create_time`, `update_by`, `update_time`, `del_flag`, `rule_flag`, `status`, `internal_or_external`) VALUES ('1387612436586065922', '2a470fc0c3954d9dbb61de6d80846549', '第三方APP消息测试', '/jeecg/ThirdAppMessageTest', 'jeecg/ThirdAppMessageTest', '1', NULL, NULL, '1', NULL, '1', '3', '0', NULL, '1', '0', '0', NULL, 'admin', '2021-04-29 11:39:20', 'admin', '2021-04-29 11:39:27', '0', '0', '1', '0');
|
||||
|
||||
-- 定时任务:一个类允许配置多个调度
|
||||
-- 删除定时任务表唯一索引
|
||||
ALTER TABLE `sys_quartz_job`
|
||||
DROP INDEX `uniq_job_class_name`;
|
||||
|
||||
-- 停止所有的定时任务,用于旧数据,只执行一次即可,【执行完毕后需要重启后台项目,并[手动]再次打开定时任务】!
|
||||
DELETE FROM `qrtz_cron_triggers`;
|
||||
DELETE FROM `qrtz_fired_triggers`;
|
||||
DELETE FROM `qrtz_triggers`;
|
||||
DELETE FROM `qrtz_job_details`;
|
||||
UPDATE `sys_quartz_job` SET `status` = '-1';
|
||||
|
||||
-- 不支持mariaDB数据库处理 issues/I3QID1
|
||||
update sys_dict_item set item_text = 'MariaDB' where id ='1349250340104474626';
|
||||
update sys_dict_item set item_text = 'Postgresql' where id ='1349254569766457345';
|
||||
|
||||
-- sys_announcement新增dt_task_id字段
|
||||
ALTER TABLE `sys_announcement`
|
||||
ADD COLUMN `dt_task_id` varchar(100) NULL COMMENT '钉钉task_id,用于撤回消息' AFTER `msg_abstract`;
|
||||
|
||||
|
||||
-- 模板类型注释错误
|
||||
ALTER TABLE `jimu_report`
|
||||
MODIFY COLUMN `template` tinyint(1) NULL DEFAULT NULL COMMENT '是否是模板 0不是,1是' AFTER `api_code`;
|
||||
|
||||
-- 查询支持默认值
|
||||
ALTER TABLE `jimu_report_db_field`
|
||||
ADD COLUMN `search_value` varchar(100) NULL COMMENT '查询默认值' AFTER `dict_code`;
|
||||
|
||||
-- jimu_report_db增加JSON数据字段
|
||||
ALTER TABLE `jimu_report_db`
|
||||
ADD COLUMN `json_data` text NULL COMMENT 'json数据,直接解析json内容' AFTER `db_source_type`;
|
||||
|
||||
-- 连接失败次数
|
||||
ALTER TABLE `jimu_report_data_source`
|
||||
ADD COLUMN `connect_times` int(1) NULL COMMENT '连接失败次数' AFTER `update_time`;
|
||||
|
||||
-- 联动图表ID
|
||||
ALTER TABLE `jimu_report_link`
|
||||
ADD COLUMN `link_chart_id` varchar(50) NULL COMMENT '联动图表的ID' AFTER `api_url`;
|
||||
|
||||
-- 类转换器字段添加
|
||||
ALTER TABLE `jimu_report_db`
|
||||
ADD COLUMN `api_convert` varchar(255) NULL COMMENT 'api转换器' AFTER `json_data`;
|
||||
|
||||
|
||||
-- 修复脚本的一些问题---
|
||||
update sys_permission set url="{{ window._CONFIG['domianURL'] }}/jmreport/view/1352160857479581696?token=${token}" where id ='1352200630711652354';
|
||||
UPDATE `jimu_report_db` SET `jimu_report_id` = '1352160857479581696', `create_by` = 'admin', `update_by` = 'admin', `create_time` = '2021-05-19 19:20:44', `update_time` = '2021-05-19 19:20:44', `db_code` = 'infoForReport', `db_ch_name` = '信息', `db_type` = '1', `db_table_name` = NULL, `db_dyn_sql` = NULL, `db_key` = NULL, `tb_db_key` = NULL, `tb_db_table_name` = NULL, `java_type` = NULL, `java_value` = NULL, `api_url` = '{{ domainURL }}/sys/actuator/redis/infoForReport', `api_method` = '0', `is_list` = 1, `is_page` = '1', `db_source` = '', `db_source_type` = NULL, `json_data` = NULL WHERE `id` = '60b3feffadc55eb49baa5a48fdf1ff0e';
|
||||
UPDATE `jimu_report_db` SET `jimu_report_id` = '1352160857479581696', `create_by` = 'admin', `update_by` = 'admin', `create_time` = '2021-05-19 19:20:50', `update_time` = '2021-05-19 19:20:50', `db_code` = 'memoryForReport', `db_ch_name` = '内存', `db_type` = '1', `db_table_name` = NULL, `db_dyn_sql` = NULL, `db_key` = NULL, `tb_db_key` = NULL, `tb_db_table_name` = NULL, `java_type` = NULL, `java_value` = NULL, `api_url` = '{{ domainURL }}/sys/actuator/redis/memoryForReport', `api_method` = '0', `is_list` = 1, `is_page` = '0', `db_source` = '', `db_source_type` = NULL, `json_data` = NULL WHERE `id` = '6a1d22ca4c95e8fab655d3ceed43a84d';
|
||||
UPDATE `jimu_report_db` SET `jimu_report_id` = '1352160857479581696', `create_by` = 'admin', `update_by` = 'admin', `create_time` = '2021-05-19 19:21:03', `update_time` = '2021-05-19 19:21:03', `db_code` = 'keysSizeForReport', `db_ch_name` = '数量', `db_type` = '1', `db_table_name` = NULL, `db_dyn_sql` = NULL, `db_key` = NULL, `tb_db_key` = NULL, `tb_db_table_name` = NULL, `java_type` = NULL, `java_value` = NULL, `api_url` = '{{ domainURL }}/sys/actuator/redis/keysSizeForReport', `api_method` = '0', `is_list` = 1, `is_page` = '0', `db_source` = '', `db_source_type` = NULL, `json_data` = NULL WHERE `id` = 'd4a29dfda94357308faf62be2b94db08';
|
||||
63
jeecg-boot/db/增量SQL/2.4.6升级到3.0增量脚本sql
Normal file
63
jeecg-boot/db/增量SQL/2.4.6升级到3.0增量脚本sql
Normal file
@ -0,0 +1,63 @@
|
||||
-- 字段长度不规范,导致转库错误Specified key was too long; max key length is 767 bytes
|
||||
ALTER TABLE `rep_demo_dxtj`
|
||||
MODIFY COLUMN `id` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '主键' FIRST;
|
||||
|
||||
ALTER TABLE `sys_third_account`
|
||||
MODIFY COLUMN `third_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录来源' AFTER `third_user_id`;
|
||||
|
||||
|
||||
-- 数据源字典sql整理
|
||||
DELETE FROM `sys_dict_item` WHERE dict_id ='1209733563293962241';
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1209733775114702850', '1209733563293962241', 'MySQL5.5', '1', '', 1, 1, 'admin', '2019-12-25 15:13:02', NULL, NULL);
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1334440962954936321', '1209733563293962241', 'MYSQL5.7+', '4', '', 2, 1, 'admin', '2020-12-03 18:16:02', 'admin', '2021-07-15 13:44:29');
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1209733839933476865', '1209733563293962241', 'Oracle', '2', '', 3, 1, 'admin', '2019-12-25 15:13:18', 'admin', '2021-07-15 13:44:08');
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1209733903020003330', '1209733563293962241', 'SQLServer', '3', '', 4, 1, 'admin', '2019-12-25 15:13:33', 'admin', '2021-07-15 13:44:11');
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1414837074500976641', '1209733563293962241', 'postgresql', '6', '', 5, 1, 'admin', '2021-07-13 14:40:20', 'admin', '2021-07-15 13:44:15');
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1415547541091504129', '1209733563293962241', 'marialDB', '5', '', 6, 1, 'admin', '2021-07-15 13:43:28', 'admin', '2021-07-15 13:44:23');
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418049969003089922', '1209733563293962241', '达梦', '7', '', 7, 1, 'admin', '2021-07-22 11:27:13', 'admin', '2021-07-22 11:27:30');
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050017053036545', '1209733563293962241', '人大金仓', '8', '', 8, 1, 'admin', '2021-07-22 11:27:25', NULL, NULL);
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050075555188737', '1209733563293962241', '神通', '9', '', 9, 1, 'admin', '2021-07-22 11:27:39', NULL, NULL);
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050110669901826', '1209733563293962241', 'SQLite', '10', '', 10, 1, 'admin', '2021-07-22 11:27:47', NULL, NULL);
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050149475602434', '1209733563293962241', 'DB2', '11', '', 11, 1, 'admin', '2021-07-22 11:27:56', NULL, NULL);
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050209823248385', '1209733563293962241', 'Hsqldb', '12', '', 12, 1, 'admin', '2021-07-22 11:28:11', 'admin', '2021-07-22 11:28:27');
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418050323111399425', '1209733563293962241', 'Derby', '13', '', 13, 1, 'admin', '2021-07-22 11:28:38', NULL, NULL);
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418117316707590146', '1209733563293962241', 'H2', '14', '', 14, 1, 'admin', '2021-07-22 15:54:50', NULL, NULL);
|
||||
INSERT INTO `sys_dict_item` (`id`, `dict_id`, `item_text`, `item_value`, `description`, `sort_order`, `status`, `create_by`, `create_time`, `update_by`, `update_time`) VALUES ('1418491604048449537', '1209733563293962241', '其他数据库', '15', '', 15, 1, 'admin', '2021-07-23 16:42:07', NULL, NULL);
|
||||
|
||||
|
||||
-- 新增 hideTab 字段
|
||||
ALTER TABLE `sys_permission`
|
||||
ADD COLUMN `hide_tab` int(2) NULL COMMENT '是否隐藏tab: 0否,1是' AFTER `hidden`;
|
||||
|
||||
|
||||
|
||||
-- 【online表单】新增 low_app_id 字段
|
||||
ALTER TABLE `onl_cgform_head`
|
||||
ADD COLUMN `low_app_id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '关联的应用ID' AFTER `des_form_code`;
|
||||
|
||||
|
||||
|
||||
-- online老数据,存在字符串类型key值不一致的情况,String改为string
|
||||
UPDATE onl_cgform_field SET db_type = 'string' where binary db_type = 'String';
|
||||
|
||||
-- 积木报表升级
|
||||
ALTER TABLE `jimu_report`
|
||||
MODIFY COLUMN `view_count` bigint(15) NULL DEFAULT 0 COMMENT '浏览次数' AFTER `template`;
|
||||
ALTER TABLE `jimu_report`
|
||||
MODIFY COLUMN `json_str` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'json字符串' AFTER `type`;
|
||||
ALTER TABLE `jimu_report_db_field`
|
||||
ADD COLUMN `search_format` varchar(50) NULL COMMENT '查询时间格式化表达式' AFTER `search_value`;
|
||||
ALTER TABLE `jimu_report_db_param`
|
||||
ADD COLUMN `search_format` varchar(50) NULL COMMENT '查询时间格式化表达式' AFTER `dict_code`;
|
||||
UPDATE jimu_report SET json_str=replace(json_str,'"subtotal":"totalField"','"funcname":"SUM"');
|
||||
ALTER TABLE `jimu_report`
|
||||
ADD COLUMN `css_str` text NULL COMMENT 'css增强' AFTER `view_count`,
|
||||
ADD COLUMN `js_str` text NULL COMMENT 'js增强' AFTER `css_str`;
|
||||
ALTER TABLE `jimu_report_link`
|
||||
CHANGE COLUMN `expression` `requirement` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '条件' AFTER `link_chart_id`;
|
||||
ALTER TABLE `jimu_report_db_field`
|
||||
ADD COLUMN `ext_json` text NULL COMMENT '参数配置' AFTER `search_format`;
|
||||
ALTER TABLE `jimu_report_db_param`
|
||||
ADD COLUMN `ext_json` text NULL COMMENT '参数配置' AFTER `search_format`;
|
||||
ALTER TABLE `jimu_report_db`
|
||||
MODIFY COLUMN `is_list` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '0' COMMENT '是否是列表0否1是 默认0' AFTER `api_method`;
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-boot-base-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>2.4.5</version>
|
||||
<version>3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
package org.jeecg.common.bpm.api;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.constant.ServiceNameConstants;
|
||||
import org.jeecg.common.online.api.factory.OnlineBaseExtAPIFallbackFactory;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/**
|
||||
* 流程接口
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
@Component
|
||||
@FeignClient(contextId = "bpmBaseRemoteApi", value = ServiceNameConstants.SYSTEM_SERVICE,
|
||||
fallbackFactory = OnlineBaseExtAPIFallbackFactory.class)
|
||||
public interface IBpmBaseExtAPI {
|
||||
/**
|
||||
* 23. 流程提交接口(online,自定义开发)
|
||||
*
|
||||
* @param flowCode
|
||||
* 流程业务关联 例如:joa_leave_01
|
||||
* @param id
|
||||
* 表单业务数据data id
|
||||
* @param formUrl
|
||||
* 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile
|
||||
* 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username
|
||||
* 流程发起人账号
|
||||
* @param jsonData
|
||||
* Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostMapping(value = "/act/process/extActProcess/startMutilProcess")
|
||||
Result<String> startMutilProcess(@RequestParam("flowCode") String flowCode, @RequestParam("id") String id,
|
||||
@RequestParam("formUrl") String formUrl, @RequestParam("formUrlMobile") String formUrlMobile,
|
||||
@RequestParam("username") String username, @RequestParam("jsonData") String jsonData) throws Exception;
|
||||
|
||||
/**
|
||||
* 24. 流程提交接口(自定义表单设计器)
|
||||
*
|
||||
* @param flowCode
|
||||
* 流程业务关联 例如:joa_leave_01
|
||||
* @param id
|
||||
* 表单业务数据data id
|
||||
* @param formUrl
|
||||
* 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile
|
||||
* 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username
|
||||
* 流程发起人账号
|
||||
* @param jsonData
|
||||
* Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostMapping(value = "/act/process/extActProcess/startDesFormMutilProcess")
|
||||
Result<String> startDesFormMutilProcess(@RequestParam("flowCode") String flowCode, @RequestParam("id") String id,
|
||||
@RequestParam("formUrl") String formUrl, @RequestParam("formUrlMobile") String formUrlMobile,
|
||||
@RequestParam("username") String username, @RequestParam("jsonData") String jsonData) throws Exception;
|
||||
|
||||
/**
|
||||
* 25. 保存流程草稿箱接口(自定义开发表单、online表单)
|
||||
*
|
||||
* @param flowCode
|
||||
* 流程业务关联 例如:joa_leave_01
|
||||
* @param id
|
||||
* 表单业务数据data id
|
||||
* @param formUrl
|
||||
* 流程审批时附件页面默认展示的PC端表单组件(地址) 【非必填】
|
||||
* @param formUrlMobile
|
||||
* 流程审批时附件页面默认展示的移动端表单组件(地址) 【非必填】
|
||||
* @param username
|
||||
* 流程发起人账号
|
||||
* @param jsonData
|
||||
* Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@PostMapping(value = "/act/process/extActProcess/saveMutilProcessDraft")
|
||||
Result<String> saveMutilProcessDraft(@RequestParam("flowCode") String flowCode, @RequestParam("id") String id,
|
||||
@RequestParam("formUrl") String formUrl, @RequestParam("formUrlMobile") String formUrlMobile,
|
||||
@RequestParam("username") String username, @RequestParam("jsonData") String jsonData) throws Exception;
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
package org.jeecg.common.bpm.api.factory;
|
||||
|
||||
import org.jeecg.common.bpm.api.IBpmBaseExtAPI;
|
||||
import org.jeecg.common.bpm.api.fallback.BpmBaseExtAPIFallback;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import feign.hystrix.FallbackFactory;
|
||||
|
||||
@Component
|
||||
public class BpmBaseExtAPIFallbackFactory implements FallbackFactory<IBpmBaseExtAPI> {
|
||||
|
||||
@Override
|
||||
public IBpmBaseExtAPI create(Throwable throwable) {
|
||||
BpmBaseExtAPIFallback fallback = new BpmBaseExtAPIFallback();
|
||||
fallback.setCause(throwable);
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
package org.jeecg.common.bpm.api.fallback;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.bpm.api.IBpmBaseExtAPI;
|
||||
import org.jeecg.common.online.api.IOnlineBaseExtAPI;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* 进入fallback的方法 检查是否token未设置
|
||||
*/
|
||||
@Slf4j
|
||||
public class BpmBaseExtAPIFallback implements IBpmBaseExtAPI {
|
||||
|
||||
@Setter
|
||||
private Throwable cause;
|
||||
|
||||
@Override
|
||||
public Result<String> startMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,
|
||||
String username, String jsonData) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> startDesFormMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,
|
||||
String username, String jsonData) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<String> saveMutilProcessDraft(String flowCode, String id, String formUrl, String formUrlMobile,
|
||||
String username, String jsonData) throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package org.jeecg.common.online.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.common.constant.ServiceNameConstants;
|
||||
import org.jeecg.common.online.api.factory.OnlineBaseExtAPIFallbackFactory;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 【Online】Feign API接口
|
||||
*/
|
||||
@Component
|
||||
@FeignClient(contextId = "onlineBaseRemoteApi", value = ServiceNameConstants.SYSTEM_ONLINE, fallbackFactory = OnlineBaseExtAPIFallbackFactory.class)
|
||||
public interface IOnlineBaseExtAPI {
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步新增
|
||||
*/
|
||||
@PostMapping(value = "/online/api/cgform/crazyForm/{name}")
|
||||
String cgformPostCrazyForm(@PathVariable("name") String tableName, @RequestBody JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步编辑
|
||||
*/
|
||||
@PutMapping(value = "/online/api/cgform/crazyForm/{name}")
|
||||
String cgformPutCrazyForm(@PathVariable("name") String tableName, @RequestBody JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* 通过online表名查询数据,同时查询出子表的数据
|
||||
*
|
||||
* @param tableName online表名
|
||||
* @param dataIds online数据ID
|
||||
* @return
|
||||
*/
|
||||
@GetMapping(value = "/online/api/cgform/queryAllDataByTableName")
|
||||
JSONObject cgformQueryAllDataByTableName(@RequestParam("tableName") String tableName, @RequestParam("dataIds") String dataIds);
|
||||
|
||||
/**
|
||||
* online表单删除数据
|
||||
*
|
||||
* @param cgformCode Online表单code
|
||||
* @param dataIds 数据ID,可逗号分割
|
||||
* @return
|
||||
*/
|
||||
@DeleteMapping("/online/api/cgform/cgformDeleteDataByCode")
|
||||
String cgformDeleteDataByCode(@RequestParam("cgformCode") String cgformCode, @RequestParam("dataIds") String dataIds);
|
||||
|
||||
/**
|
||||
* 【cgreport】通过 head code 获取 sql语句,并执行该语句返回查询数据
|
||||
*
|
||||
* @param code 报表Code,如果没传ID就通过code查
|
||||
* @param forceKey
|
||||
* @param dataList
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/online/api/cgreportGetData")
|
||||
Map<String, Object> cgreportGetData(@RequestParam("code") String code, @RequestParam("forceKey") String forceKey, @RequestParam("dataList") String dataList);
|
||||
|
||||
/**
|
||||
* 【cgreport】对 cgreportGetData 的返回值做优化,封装 DictModel 集合
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/online/api/cgreportGetDataPackage")
|
||||
List<DictModel> cgreportGetDataPackage(@RequestParam("code") String code, @RequestParam("dictText") String dictText, @RequestParam("dictCode") String dictCode, @RequestParam("dataList") String dataList);
|
||||
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package org.jeecg.common.online.api.factory;
|
||||
|
||||
import feign.hystrix.FallbackFactory;
|
||||
import org.jeecg.common.online.api.IOnlineBaseExtAPI;
|
||||
import org.jeecg.common.online.api.fallback.OnlineBaseExtAPIFallback;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class OnlineBaseExtAPIFallbackFactory implements FallbackFactory<IOnlineBaseExtAPI> {
|
||||
|
||||
@Override
|
||||
public IOnlineBaseExtAPI create(Throwable throwable) {
|
||||
OnlineBaseExtAPIFallback fallback = new OnlineBaseExtAPIFallback();
|
||||
fallback.setCause(throwable);
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
package org.jeecg.common.online.api.fallback;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jeecg.common.online.api.IOnlineBaseExtAPI;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 进入fallback的方法 检查是否token未设置
|
||||
*/
|
||||
@Slf4j
|
||||
public class OnlineBaseExtAPIFallback implements IOnlineBaseExtAPI {
|
||||
|
||||
@Setter
|
||||
private Throwable cause;
|
||||
|
||||
@Override
|
||||
public String cgformPostCrazyForm(String tableName, JSONObject jsonObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cgformPutCrazyForm(String tableName, JSONObject jsonObject) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSONObject cgformQueryAllDataByTableName(String tableName, String dataIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cgformDeleteDataByCode(String cgformCode, String dataIds) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> cgreportGetData(String code, String forceKey, String dataList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> cgreportGetDataPackage(String code, String dictText, String dictCode, String dataList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,10 +9,7 @@ import org.jeecg.common.system.api.factory.SysBaseAPIFallbackFactory;
|
||||
import org.jeecg.common.system.vo.*;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -109,6 +106,14 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
@GetMapping("/sys/api/queryDictItemsByCode")
|
||||
List<DictModel> queryDictItemsByCode(@RequestParam("code") String code);
|
||||
|
||||
/**
|
||||
* 获取有效的数据字典项
|
||||
* @param code
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryEnableDictItemsByCode")
|
||||
public List<DictModel> queryEnableDictItemsByCode(@RequestParam("code") String code);
|
||||
|
||||
/** 11查询所有的父级字典,按照create_time排序 */
|
||||
@GetMapping("/sys/api/queryAllDict")
|
||||
List<DictModel> queryAllDict();
|
||||
@ -385,30 +390,31 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryUsersByUsernames")
|
||||
List<JSONObject> queryUsersByUsernames(String usernames);
|
||||
List<JSONObject> queryUsersByUsernames(@RequestParam("usernames") String usernames);
|
||||
|
||||
/**
|
||||
* 37根据多个用户ID(逗号分隔),查询返回多个用户信息
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryUsersByIds")
|
||||
List<JSONObject> queryUsersByIds(String ids);
|
||||
@RequestMapping("/sys/api/queryUsersByIds")
|
||||
List<JSONObject> queryUsersByIds(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 38根据多个部门编码(逗号分隔),查询返回多个部门信息
|
||||
* @param orgCodes
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryDepartsByOrgcodes")
|
||||
List<JSONObject> queryDepartsByOrgcodes(String orgCodes);
|
||||
@RequestMapping("/sys/api/queryDepartsByOrgcodes")
|
||||
List<JSONObject> queryDepartsByOrgcodes(@RequestParam("orgCodes") String orgCodes);
|
||||
|
||||
/**
|
||||
* 39根据多个部门编码(逗号分隔),查询返回多个部门信息
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryDepartsByOrgIds")
|
||||
List<JSONObject> queryDepartsByOrgIds(String ids);
|
||||
List<JSONObject> queryDepartsByOrgIds(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 40发送邮件消息
|
||||
@ -424,4 +430,81 @@ public interface ISysBaseAPI extends CommonAPI {
|
||||
*/
|
||||
@GetMapping("/sys/api/getDeptUserByOrgCode")
|
||||
List<Map> getDeptUserByOrgCode(@RequestParam("orgCode")String orgCode);
|
||||
|
||||
/**
|
||||
* 42 查询分类字典翻译
|
||||
*/
|
||||
@GetMapping("/sys/api/loadCategoryDictItem")
|
||||
List<String> loadCategoryDictItem(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 43 根据字典code加载字典text
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param keys 要查询的key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/loadDictItem")
|
||||
List<String> loadDictItem(@RequestParam("dictCode") String dictCode, @RequestParam("keys") String keys);
|
||||
|
||||
/**
|
||||
* 44 根据字典code查询字典项
|
||||
*
|
||||
* @param dictCode 顺序:tableName,text,code
|
||||
* @param dictCode 要查询的key
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/getDictItems")
|
||||
List<DictModel> getDictItems(@RequestParam("dictCode") String dictCode);
|
||||
|
||||
/**
|
||||
* 45 根据多个字典code查询多个字典项
|
||||
*
|
||||
* @param dictCodeList
|
||||
* @return key = dictCode ; value=对应的字典项
|
||||
*/
|
||||
@RequestMapping("/sys/api/getManyDictItems")
|
||||
Map<String, List<DictModel>> getManyDictItems(@RequestParam("dictCodeList") List<String> dictCodeList);
|
||||
|
||||
/**
|
||||
* 46 【JSearchSelectTag下拉搜索组件专用接口】
|
||||
* 大数据量的字典表 走异步加载 即前端输入内容过滤数据
|
||||
*
|
||||
* @param dictCode 字典code格式:table,text,code
|
||||
* @param keyword 过滤关键字
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/loadDictItemByKeyword")
|
||||
List<DictModel> loadDictItemByKeyword(@RequestParam("dictCode") String dictCode, @RequestParam("keyword") String keyword, @RequestParam(value = "pageSize", required = false) Integer pageSize);
|
||||
|
||||
/**
|
||||
* 47 根据多个部门id(逗号分隔),查询返回多个部门信息
|
||||
* @param ids
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/sys/api/queryDepartsByIds")
|
||||
List<JSONObject> queryDepartsByIds(@RequestParam("ids") String ids);
|
||||
|
||||
/**
|
||||
* 48 普通字典的翻译,根据多个dictCode和多条数据,多个以逗号分割
|
||||
* @param dictCodes
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/sys/api/translateManyDict")
|
||||
Map<String, List<DictModel>> translateManyDict(@RequestParam("dictCodes") String dictCodes, @RequestParam("keys") String keys);
|
||||
|
||||
/**
|
||||
* 49 字典表的 翻译,可批量
|
||||
* @param table
|
||||
* @param text
|
||||
* @param code
|
||||
* @param keys 多个用逗号分割
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@GetMapping("/sys/api/translateDictFromTableByKeys")
|
||||
List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys);
|
||||
|
||||
}
|
||||
|
||||
@ -72,6 +72,11 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> queryEnableDictItemsByCode(String code) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> queryAllDict() {
|
||||
return null;
|
||||
@ -255,6 +260,22 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
public List<JSONObject> queryDepartsByOrgcodes(String orgCodes) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JSONObject> queryDepartsByIds(String ids) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendEmailMsg(String email,String title,String content) {
|
||||
|
||||
@ -269,4 +290,29 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
|
||||
public List<JSONObject> queryDepartsByOrgIds(String ids) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> loadCategoryDictItem(String ids) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> loadDictItem(String dictCode, String keys) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> getDictItems(String dictCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<DictModel>> getManyDictItems(List<String> dictCodeList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DictModel> loadDictItemByKeyword(String dictCode, String keyword, Integer pageSize) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,26 +1,48 @@
|
||||
package org.jeecg.config;
|
||||
|
||||
import feign.Feign;
|
||||
import feign.Logger;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.codec.Encoder;
|
||||
import feign.form.spring.SpringFormEncoder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.jeecg.common.config.mqtoken.UserTokenContext;
|
||||
import org.jeecg.common.constant.CommonConstant;
|
||||
import org.jeecg.common.util.DateUtils;
|
||||
import org.jeecg.common.util.PathMatcherUtil;
|
||||
import org.jeecg.config.sign.interceptor.SignAuthConfiguration;
|
||||
import org.jeecg.config.sign.util.HttpUtils;
|
||||
import org.jeecg.config.sign.util.SignUtil;
|
||||
import org.springframework.beans.factory.ObjectFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
|
||||
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
|
||||
import org.springframework.cloud.openfeign.support.SpringDecoder;
|
||||
import org.springframework.cloud.openfeign.support.SpringEncoder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer;
|
||||
|
||||
import feign.Feign;
|
||||
import feign.Logger;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.codec.Decoder;
|
||||
import feign.codec.Encoder;
|
||||
import feign.form.spring.SpringFormEncoder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ConditionalOnClass(Feign.class)
|
||||
@AutoConfigureBefore(FeignAutoConfiguration.class)
|
||||
@ -34,13 +56,42 @@ public class FeignConfig {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (null != attributes) {
|
||||
HttpServletRequest request = attributes.getRequest();
|
||||
log.info("Feign request: {}", request.getRequestURI());
|
||||
log.debug("Feign request: {}", request.getRequestURI());
|
||||
// 将token信息放入header中
|
||||
String token = request.getHeader(CommonConstant.X_ACCESS_TOKEN);
|
||||
if(token==null){
|
||||
if(token==null || "".equals(token)){
|
||||
token = request.getParameter("token");
|
||||
}
|
||||
log.info("Feign request token: {}", token);
|
||||
log.debug("Feign request token: {}", token);
|
||||
requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
|
||||
|
||||
//根据URL地址过滤请求 【字典表参数签名验证】
|
||||
if (PathMatcherUtil.matches(Arrays.asList(SignAuthConfiguration.urlList),requestTemplate.path())) {
|
||||
try {
|
||||
log.info("============================ [begin] fegin api url ============================");
|
||||
log.info(requestTemplate.path());
|
||||
log.info(requestTemplate.method());
|
||||
String queryLine = requestTemplate.queryLine();
|
||||
if(queryLine!=null && queryLine.startsWith("?")){
|
||||
queryLine = queryLine.substring(1);
|
||||
}
|
||||
log.info(queryLine);
|
||||
if(requestTemplate.body()!=null){
|
||||
log.info(new String(requestTemplate.body()));
|
||||
}
|
||||
SortedMap<String, String> allParams = HttpUtils.getAllParams(requestTemplate.path(),queryLine,requestTemplate.body(),requestTemplate.method());
|
||||
String sign = SignUtil.getParamsSign(allParams);
|
||||
log.info(" Feign request params sign: {}",sign);
|
||||
log.info("============================ [end] fegin api url ============================");
|
||||
requestTemplate.header(CommonConstant.X_SIGN, sign);
|
||||
requestTemplate.header(CommonConstant.X_TIMESTAMP, DateUtils.getCurrentTimestamp().toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}else{
|
||||
String token = UserTokenContext.getToken();
|
||||
log.debug("Feign request token: {}", token);
|
||||
requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
|
||||
}
|
||||
};
|
||||
@ -72,4 +123,42 @@ public class FeignConfig {
|
||||
public Encoder multipartFormEncoder(ObjectFactory<HttpMessageConverters> messageConverters) {
|
||||
return new SpringFormEncoder(new SpringEncoder(messageConverters));
|
||||
}
|
||||
|
||||
// update-begin--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ----------
|
||||
@Bean
|
||||
public Encoder feignEncoder() {
|
||||
return new SpringEncoder(feignHttpMessageConverter());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Decoder feignDecoder() {
|
||||
return new SpringDecoder(feignHttpMessageConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置解码器为fastjson
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private ObjectFactory<HttpMessageConverters> feignHttpMessageConverter() {
|
||||
final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter());
|
||||
return () -> httpMessageConverters;
|
||||
}
|
||||
|
||||
private FastJsonHttpMessageConverter getFastJsonConverter() {
|
||||
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
|
||||
|
||||
List<MediaType> supportedMediaTypes = new ArrayList<>();
|
||||
MediaType mediaTypeJson = MediaType.valueOf(MediaType.APPLICATION_JSON_VALUE);
|
||||
supportedMediaTypes.add(mediaTypeJson);
|
||||
converter.setSupportedMediaTypes(supportedMediaTypes);
|
||||
FastJsonConfig config = new FastJsonConfig();
|
||||
config.getSerializeConfig().put(JSON.class, new SwaggerJsonSerializer());
|
||||
config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
|
||||
converter.setFastJsonConfig(config);
|
||||
|
||||
return converter;
|
||||
}
|
||||
// update-end--Author:sunjianlei Date:20210604 for: 给 Feign 添加 FastJson 的解析支持 ----------
|
||||
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>jeecg-boot-base-api</artifactId>
|
||||
<groupId>org.jeecgframework.boot</groupId>
|
||||
<version>2.4.5</version>
|
||||
<version>3.0</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
package org.jeecg.common.bpm.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jeecg.common.api.vo.Result;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
/**
|
||||
* 流程接口
|
||||
*
|
||||
* @author scott
|
||||
*/
|
||||
public interface IBpmBaseExtAPI {
|
||||
/**
|
||||
* 23. 流程提交接口(online,自定义开发)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> startMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,String username, String jsonData) throws Exception;
|
||||
|
||||
/**
|
||||
* 24. 流程提交接口(自定义表单设计器)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址)
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址)
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> startDesFormMutilProcess(String flowCode, String id, String formUrl, String formUrlMobile,String username,String jsonData) throws Exception;
|
||||
/**
|
||||
* 25. 保存流程草稿箱接口(自定义开发表单、online表单)
|
||||
* @param flowCode 流程业务关联 例如:joa_leave_01
|
||||
* @param id 表单业务数据data id
|
||||
* @param formUrl 流程审批时附件页面默认展示的PC端表单组件(地址) 【非必填】
|
||||
* @param formUrlMobile 流程审批时附件页面默认展示的移动端表单组件(地址) 【非必填】
|
||||
* @param username 流程发起人账号
|
||||
* @param jsonData Json串,额外扩展的流程变量值 【非必填】
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
Result<String> saveMutilProcessDraft(String flowCode, String id, String formUrl, String formUrlMobile,String username,String jsonData) throws Exception;
|
||||
|
||||
}
|
||||
@ -0,0 +1,61 @@
|
||||
package org.jeecg.common.online.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.jeecg.common.system.vo.DictModel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 表单设计器【Online】翻译API接口
|
||||
*
|
||||
* @author sunjianlei
|
||||
*/
|
||||
public interface IOnlineBaseExtAPI {
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步新增
|
||||
*/
|
||||
String cgformPostCrazyForm(String tableName, JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* 【Online】 表单设计器专用:同步编辑
|
||||
*/
|
||||
String cgformPutCrazyForm(String tableName, JSONObject jsonObject) throws Exception;
|
||||
|
||||
/**
|
||||
* online表单删除数据
|
||||
*
|
||||
* @param cgformCode Online表单code
|
||||
* @param dataIds 数据ID,可逗号分割
|
||||
* @return
|
||||
*/
|
||||
String cgformDeleteDataByCode(String cgformCode, String dataIds);
|
||||
|
||||
/**
|
||||
* 通过online表名查询数据,同时查询出子表的数据
|
||||
*
|
||||
* @param tableName online表名
|
||||
* @param dataIds online数据ID
|
||||
* @return
|
||||
*/
|
||||
JSONObject cgformQueryAllDataByTableName(String tableName, String dataIds);
|
||||
|
||||
/**
|
||||
* 对 cgreportGetData 的返回值做优化,封装 DictModel 集合
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
List<DictModel> cgreportGetDataPackage(String code, String dictText, String dictCode, String dataList);
|
||||
|
||||
/**
|
||||
* 【cgreport】通过 head code 获取 sql语句,并执行该语句返回查询数据
|
||||
*
|
||||
* @param code 报表Code,如果没传ID就通过code查
|
||||
* @param forceKey
|
||||
* @param dataList
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> cgreportGetData(String code, String forceKey, String dataList);
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user