Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
df478e7779 | ||
![]() |
be6a1a7544 | ||
![]() |
b9dcb6821a | ||
![]() |
bb68975dc0 | ||
![]() |
2449f805ec | ||
![]() |
4112e58577 | ||
![]() |
0daa05e8d0 | ||
![]() |
7efc12fc65 | ||
![]() |
e9df85908a | ||
![]() |
41e48c5113 | ||
![]() |
9d1ade6336 | ||
![]() |
3818c31e55 | ||
![]() |
2ae47e898b | ||
![]() |
6d768d8320 | ||
![]() |
f48e1125d0 | ||
![]() |
ccbdd0cf6d | ||
![]() |
eae59a5501 | ||
![]() |
f9c999ae2f | ||
![]() |
f95e4521ad | ||
![]() |
0306b8669e | ||
![]() |
0b53292cfa | ||
![]() |
7bfd40ae04 | ||
![]() |
4c8f5c8afd | ||
![]() |
2b79265fd3 | ||
![]() |
e24ab230e7 |
18
LICENSE
18
LICENSE
@@ -22,15 +22,11 @@ SOFTWARE.
|
||||
|
||||
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>北京敲敲云科技有限公司</name>
|
||||
<email>jeecgos@163.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
开源协议补充
|
||||
JeecgBoot 是由 北京敲敲云科技有限公司 发行的软件。 总部位于北京,地址:中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱:jeecgos@163.com
|
||||
本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。
|
||||
|
||||
<scm>
|
||||
<connection>http://www.jeecg.com</connection>
|
||||
<developerConnection>https://qiaoqiaoyun.com</developerConnection>
|
||||
<url>http://www.jeecg.com/vip</url>
|
||||
</scm>
|
||||
1.允许基于本平台软件开展业务系统开发。
|
||||
2.不得基于该平台软件的基础,修改包装成一个与JeecgBoot平台软件功能类似的产品进行发布、销售,或与JeecgBoot参与同类软件产品市场的竞争。
|
||||
违反此条款属于侵权行为,须赔偿侵权经济损失,同时立即停止著作权侵权行为。
|
||||
解释权归:http://www.jeecg.com
|
112
README.md
112
README.md
@@ -1,11 +1,11 @@
|
||||
JEECG BOOT 低代码开发平台(Vue3前端)
|
||||
===============
|
||||
当前最新版本: 3.5.0(发布时间:2023-03-08)
|
||||
当前最新版本: 3.5.1(发布时间:2023-04-20)
|
||||
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
|
||||
[](http://www.jeecg.com)
|
||||
[](https://jeecg.blog.csdn.net)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
[](https://github.com/zhangdaiscott/jeecg-boot)
|
||||
|
||||
@@ -39,11 +39,11 @@ JeecgBoot-Vue3采用 Vue3.0、Vite、 Ant-Design-Vue3、TypeScript 等新技术
|
||||
|
||||
## 技术文档
|
||||
|
||||
- 官方文档:[http://vue3.jeecg.com](http://vue3.jeecg.com)
|
||||
- 官方文档:[http://help.jeecg.com](http://help.jeecg.com)
|
||||
- 官方网站: [http://www.jeecg.com](http://www.jeecg.com)
|
||||
- 在线演示:[低代码演示](http://boot3.jeecg.com) | [敲敲云零代码](https://www.qiaoqiaoyun.com)
|
||||
- 快速入门:[常见问题](http://vue3.jeecg.com/2426559) | [入门视频](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://vue3.jeecg.com/2677352)
|
||||
- QQ交流群:683903138
|
||||
- 快速入门:[常见问题](http://help.jeecg.com/qa.html) | [入门视频](https://www.bilibili.com/video/BV1V34y187Y9 "入门视频") | [ 代码生成](http://help.jeecg.com/vue3/codegen/online.html)
|
||||
- QQ交流群:⑦791696430、683903138
|
||||
|
||||
## 安装与使用
|
||||
|
||||
@@ -116,7 +116,7 @@ cd jeecgboot-vue3
|
||||
VITE_GLOB_API_URL=/jeecgboot
|
||||
VITE_GLOB_DOMAIN_URL=http://jeecg-boot-system:8080/jeecg-boot
|
||||
```
|
||||
后台单体启动 [见此文档](http://doc.jeecg.com/2043889)
|
||||
后台单体启动 [见此文档](https://help.jeecg.com/java/setup/docker/up.html)
|
||||
|
||||
- 编译项目
|
||||
|
||||
@@ -147,7 +147,7 @@ VITE_GLOB_API_URL=/jeecgboot
|
||||
VITE_GLOB_DOMAIN_URL=http://jeecg-boot-gateway:9999
|
||||
```
|
||||
|
||||
后台微服务启动 [见此文档](http://doc.jeecg.com/2656147)
|
||||
后台微服务启动 [见此文档](https://help.jeecg.com/java/springcloud/docker.html)
|
||||
|
||||
- 区别2. 修改Dockerfile文件
|
||||
|
||||
@@ -172,7 +172,7 @@ VITE_GLOB_DOMAIN_URL=http://jeecg-boot-gateway:9999
|
||||
|
||||
本项目需要一定前端基础知识,请确保掌握 Vue 的基础知识,以便能处理一些常见的问题。 建议在开发前先学一下以下内容,提前了解和学习这些知识,会对项目理解非常有帮助:
|
||||
|
||||
* [JeecgBoot-Vue3文档](http://vue3.jeecg.com)
|
||||
* [JeecgBoot-Vue3文档](http://help.jeecg.com)
|
||||
* [Vue3 文档](https://cn.vuejs.org/)
|
||||
* [Vben文档](https://doc.vvbin.cn)
|
||||
* [Ant-Design-Vue](https://www.antdv.com/docs/vue/introduce-cn/)
|
||||
@@ -334,25 +334,93 @@ VITE_GLOB_DOMAIN_URL=http://jeecg-boot-gateway:9999
|
||||
## 系统效果
|
||||
系统后台
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Online表单&Online报表&代码生成
|
||||
Online开发&代码生成
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
系统交互
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
流程设计
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
简版流程设计
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
仪表盘设计器
|
||||

|
||||
|
||||

|
||||
|
||||
报表设计器
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
表单设计器
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
大屏设计器
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
报表效果
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
接口文档
|
||||
@@ -360,22 +428,14 @@ Online表单&Online报表&代码生成
|
||||

|
||||
|
||||
|
||||
流程设计&表单设计
|
||||
手机端
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
大屏模板
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
PAD端
|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
|
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "jeecgboot-vue3",
|
||||
"version": "3.5.0",
|
||||
"version": "3.5.1",
|
||||
"author": {
|
||||
"name": "jeecg",
|
||||
"email": "jeecgos@163.com",
|
||||
@@ -81,7 +81,7 @@
|
||||
"vue-cropperjs": "^5.0.0",
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-infinite-scroll": "^2.0.2",
|
||||
"vue-print-nb-jeecg": "^1.0.10",
|
||||
"vue-print-nb-jeecg": "^1.0.12",
|
||||
"vue-router": "^4.0.14",
|
||||
"vue-types": "^4.1.1",
|
||||
"vuedraggable": "^4.1.0",
|
||||
@@ -125,12 +125,12 @@
|
||||
"cz-git": "^1.3.9",
|
||||
"czg": "^1.3.9",
|
||||
"dotenv": "^16.0.0",
|
||||
"eslint": "^8.13.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-define-config": "^1.1.1",
|
||||
"eslint-plugin-jest": "^25.2.2",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"eslint-plugin-vue": "^8.6.0",
|
||||
"eslint": "^8.22.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-define-config": "^1.14.0",
|
||||
"eslint-plugin-jest": "^27.2.1",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-vue": "^9.9.0",
|
||||
"esno": "^0.14.1",
|
||||
"fs-extra": "^10.1.0",
|
||||
"http-server": "^14.0.0",
|
||||
|
@@ -117,7 +117,15 @@
|
||||
const { defaultValue, component, componentProps } = schema;
|
||||
// handle date type
|
||||
if (defaultValue && dateItemType.includes(component)) {
|
||||
const { valueFormat } = componentProps
|
||||
//update-begin---author:wangshuai ---date:20230410 for:【issues/435】代码生成的日期控件赋默认值报错------------
|
||||
let valueFormat:string = "";
|
||||
if(componentProps){
|
||||
valueFormat = componentProps?.valueFormat;
|
||||
}
|
||||
if(!valueFormat){
|
||||
console.warn("未配置valueFormat,可能导致格式化错误!");
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20230410 for:【issues/435】代码生成的日期控件赋默认值报错------------
|
||||
if (!Array.isArray(defaultValue)) {
|
||||
//update-begin---author:wangshuai ---date:20221124 for:[issues/215]列表页查询框(日期选择框)设置初始时间,一进入页面时,后台报日期转换类型错误的------------
|
||||
if(valueFormat){
|
||||
|
@@ -81,7 +81,7 @@
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
emits: ['options-change', 'change'],
|
||||
emits: ['options-change', 'change','update:value'],
|
||||
setup(props, { emit, refs }) {
|
||||
const dictOptions = ref<any[]>([]);
|
||||
const attrs = useAttrs();
|
||||
@@ -164,6 +164,10 @@
|
||||
changeValue = e?.target?.value ?? e;
|
||||
}
|
||||
state.value = changeValue;
|
||||
|
||||
//update-begin---author:wangshuai ---date:20230403 for:【issues/4507】JDictSelectTag组件使用时,浏览器给出警告提示:Expected Function, got Array------------
|
||||
emit('update:value',changeValue)
|
||||
//update-end---author:wangshuai ---date:20230403 for:【issues/4507】JDictSelectTag组件使用时,浏览器给出警告提示:Expected Function, got Array述------------
|
||||
//update-end---author:wangshuai ---date:20230216 for:[QQYUN-4290]公文发文:选择机关代字报错,是因为值改变触发了change事件三次,导致数据发生改变------------
|
||||
|
||||
// nextTick(() => formItemContext.onFieldChange());
|
||||
|
@@ -2,6 +2,7 @@
|
||||
<div class="clearfix">
|
||||
<a-upload
|
||||
:listType="listType"
|
||||
accept="image/*"
|
||||
:multiple="multiple"
|
||||
:action="uploadUrl"
|
||||
:headers="headers"
|
||||
|
@@ -29,6 +29,7 @@
|
||||
:placeholder="placeholder"
|
||||
:filterOption="filterOption"
|
||||
:notFoundContent="loading ? undefined : null"
|
||||
:dropdownAlign="{overflow: {adjustY: adjustY }}"
|
||||
@change="handleChange"
|
||||
>
|
||||
<template #notFoundContent>
|
||||
@@ -64,6 +65,10 @@
|
||||
type: Function,
|
||||
default: (node) => node.parentNode,
|
||||
},
|
||||
//默认开启Y轴溢出位置调整,因此在可视空间不足时下拉框位置会自动上移,导致Select的输入框被遮挡。需要注意的是,默认情况是是可视空间,而不是所拥有的空间
|
||||
//update-begin-author:liusq date:2023-04-04 for:[issue/286]下拉搜索框遮挡问题
|
||||
adjustY:propTypes.bool.def(true),
|
||||
//update-end-author:liusq date:2023-04-04 for:[issue/286]下拉搜索框遮挡问题
|
||||
//是否在有值后立即触发change
|
||||
immediateChange: propTypes.bool.def(false),
|
||||
//update-begin-author:taoyan date:2022-8-15 for: VUEN-1971 【online 专项测试】关联记录和他表字段 1
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<!--部门选择组件-->
|
||||
<template>
|
||||
<div>
|
||||
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" />
|
||||
<JSelectBiz @handleOpen="handleOpen" :loading="loadingEcho" v-bind="attrs" @change="handleChange"/>
|
||||
<DeptSelectModal @register="regModal" @getSelectResult="setValue" v-bind="getBindValue" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -119,6 +119,17 @@
|
||||
emit('update:value', values.join(','));
|
||||
}
|
||||
const getBindValue = Object.assign({}, unref(props), unref(attrs));
|
||||
|
||||
//update-begin---author:wangshuai ---date:20230406 for:【issues/397】在表单中使用v-model:value绑定JSelectDept组件时无法清除已选择的数据------------
|
||||
/**
|
||||
* 值改变事件更新value值
|
||||
* @param values
|
||||
*/
|
||||
function handleChange(values) {
|
||||
emit('update:value', values);
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20230406 for:【issues/397】在表单中使用v-model:value绑定JSelectDept组件时无法清除已选择的数据------------
|
||||
|
||||
return {
|
||||
state,
|
||||
attrs,
|
||||
@@ -130,6 +141,7 @@
|
||||
regModal,
|
||||
setValue,
|
||||
handleOpen,
|
||||
handleChange
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@@ -26,7 +26,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, watch, nextTick, createApp } from 'vue';
|
||||
import { ref, reactive, computed, watch, nextTick, createApp,unref } from 'vue';
|
||||
import { Icon } from '/@/components/Icon';
|
||||
import { getToken } from '/@/utils/auth';
|
||||
import { uploadUrl } from '/@/api/common/api';
|
||||
@@ -82,7 +82,10 @@
|
||||
const isImageMode = computed(() => props.fileType === UploadTypeEnum.image);
|
||||
// 合并 props 和 attrs
|
||||
const bindProps = computed(() => {
|
||||
const bind: any = Object.assign({}, props, attrs);
|
||||
//update-begin-author:liusq date:20220411 for: [issue/455]上传组件传入accept限制上传文件类型无效
|
||||
const bind: any = Object.assign({}, props, unref(attrs));
|
||||
//update-end-author:liusq date:20220411 for: [issue/455]上传组件传入accept限制上传文件类型无效
|
||||
|
||||
bind.name = 'file';
|
||||
bind.listType = isImageMode.value ? 'picture-card' : 'text';
|
||||
bind.class = [bind.class, { 'upload-disabled': props.disabled }];
|
||||
|
@@ -129,7 +129,7 @@
|
||||
queryParam,
|
||||
dictOptions,
|
||||
},
|
||||
] = usePopBiz(getBindValue);
|
||||
] = usePopBiz(getBindValue,tableRef);
|
||||
|
||||
const showSearchFlag = computed(() => unref(queryInfo) && unref(queryInfo).length > 0);
|
||||
/**
|
||||
|
@@ -138,8 +138,10 @@ export function useSelectBiz(getList, props) {
|
||||
}
|
||||
//删除已选择的信息
|
||||
function handleDeleteSelected(record) {
|
||||
checkedKeys.value = checkedKeys.value.splice(checkedKeys.value.indexOf(record['id']), 1);
|
||||
selectRows.value = selectRows.value.filter((item) => item['id'] !== record['id']);
|
||||
//update-begin---author:wangshuai ---date:20230404 for:【issues/424】开启右侧列表后,在右侧列表中删除用户时,逻辑有问题------------
|
||||
checkedKeys.value = checkedKeys.value.filter((item) => item != record[props.rowKey]);
|
||||
selectRows.value = selectRows.value.filter((item) => item[props.rowKey] !== record[props.rowKey]);
|
||||
//update-end---author:wangshuai ---date:20230404 for:【issues/424】开启右侧列表后,在右侧列表中删除用户时,逻辑有问题------------
|
||||
}
|
||||
//清空选择项
|
||||
function reset() {
|
||||
|
@@ -115,8 +115,31 @@ export function useTreeBiz(treeRef, getList, props) {
|
||||
/**
|
||||
* 勾选全部
|
||||
*/
|
||||
function checkALL(checkAll) {
|
||||
async function checkALL(checkAll) {
|
||||
getTree().checkAll(checkAll);
|
||||
//update-begin---author:wangshuai ---date:20230403 for:【issues/394】所属部门树操作全部勾选不生效/【issues/4646】部门全部勾选后,点击确认按钮,部门信息丢失------------
|
||||
await nextTick();
|
||||
checkedKeys.value = getTree().getCheckedKeys();
|
||||
if(checkAll){
|
||||
getTreeRow();
|
||||
}else{
|
||||
selectRows.value = [];
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20230403 for:【issues/394】所属部门树操作全部勾选不生效/【issues/4646】部门全部勾选后,点击确认按钮,部门信息丢失------------
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取数列表
|
||||
* @param res
|
||||
*/
|
||||
function getTreeRow() {
|
||||
let ids = "";
|
||||
if(unref(checkedKeys).length>0){
|
||||
ids = checkedKeys.value.join(",");
|
||||
}
|
||||
getList({ids:ids}).then((res) =>{
|
||||
selectRows.value = res;
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -56,15 +56,17 @@ class Area {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getText(code) {
|
||||
|
||||
//update-begin-author:liusq---date:20230404--for: [issue/382]省市区组件JAreaLinkage数据不回显---
|
||||
getText(code,index=3) {
|
||||
if (!code || code.length == 0) {
|
||||
return '';
|
||||
}
|
||||
let arr = [];
|
||||
this.getAreaBycode(code, arr, 3);
|
||||
this.getAreaBycode(code, arr, index);
|
||||
return arr.join('/');
|
||||
}
|
||||
//update-end-author:liusq---date:20230404--for: [issue/382]省市区组件JAreaLinkage数据不回显---
|
||||
|
||||
getRealCode(code) {
|
||||
let arr = [];
|
||||
@@ -98,12 +100,14 @@ const jeecgAreaData = new Area();
|
||||
|
||||
// 根据code找文本
|
||||
const getAreaTextByCode = function (code) {
|
||||
let index = 3;
|
||||
//update-begin-author:liusq---date:20220531--for: 判断code是否是多code逗号分割的字符串,是的话,获取最后一位的code ---
|
||||
if (code && code.includes(',')) {
|
||||
index = code.split(",").length;
|
||||
code = code.substr(code.lastIndexOf(',') + 1);
|
||||
}
|
||||
//update-end-author:liusq---date:20220531--for: 判断code是否是多code逗号分割的字符串,是的话,获取最后一位的code ---
|
||||
return jeecgAreaData.getText(code);
|
||||
return jeecgAreaData.getText(code,index);
|
||||
};
|
||||
|
||||
export { getAreaTextByCode };
|
||||
|
@@ -36,7 +36,12 @@ export function useModalDragMove(context: UseModalDragMoveContext) {
|
||||
|
||||
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
|
||||
const minDragDomTop = dragDom.offsetTop;
|
||||
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
|
||||
let maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
|
||||
//update-begin-author:liusq---date:20230407--for: [issue/430]弹出页面出现自动吸顶,无法移动和显示头部---
|
||||
if(maxDragDomTop<0){
|
||||
maxDragDomTop = screenHeight - dragDom.offsetTop
|
||||
}
|
||||
//update-end-author:liusq---date:20230407--for: [issue/430]弹出页面出现自动吸顶,无法移动和显示头部---
|
||||
// 获取到的值带px 正则匹配替换
|
||||
const domLeft = getStyle(dragDom, 'left');
|
||||
const domTop = getStyle(dragDom, 'top');
|
||||
|
@@ -90,11 +90,13 @@
|
||||
onCheck: (v: CheckKeys, e) => {
|
||||
let currentValue = toRaw(state.checkedKeys) as KeyType[];
|
||||
if (isArray(currentValue) && searchState.startSearch) {
|
||||
const { key } = unref(getFieldNames);
|
||||
currentValue = difference(currentValue, getChildrenKeys(e.node.$attrs.node[key]));
|
||||
//update-begin-author:liusq---date:20230404--for: [issue/429]树搜索点击事件失效---
|
||||
const value = e.node.eventKey;
|
||||
currentValue = difference(currentValue, getChildrenKeys(value));
|
||||
if (e.checked) {
|
||||
currentValue.push(e.node.$attrs.node[key]);
|
||||
currentValue.push(value);
|
||||
}
|
||||
//update-begin-author:liusq---date:20230404--for: [issue/429]树搜索点击事件失效---
|
||||
state.checkedKeys = currentValue;
|
||||
} else {
|
||||
state.checkedKeys = v;
|
||||
|
@@ -17,10 +17,14 @@ export function useData(props: JVxeTableProps): JVxeDataProps {
|
||||
rowId: props.rowKey,
|
||||
// 高亮hover的行
|
||||
highlightHoverRow: true,
|
||||
|
||||
// --- 【issues/209】自带的tooltip会错位,所以替换成原生的title ---
|
||||
// 溢出隐藏并显示tooltip
|
||||
showOverflow: true,
|
||||
showOverflow: "title",
|
||||
// 表头溢出隐藏并显示tooltip
|
||||
showHeaderOverflow: true,
|
||||
showHeaderOverflow: "title",
|
||||
// --- 【issues/209】自带的tooltip会错位,所以替换成原生的title ---
|
||||
|
||||
showFooterOverflow: true,
|
||||
// 可编辑配置
|
||||
editConfig: {
|
||||
|
@@ -5,7 +5,7 @@ import { filterMultiDictText } from '/@/utils/dict/JDictSelectUtil.js';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { OnlineColumn } from '/@/components/jeecg/OnLine/types/onlineConfig';
|
||||
import { h } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { useMethods } from '/@/hooks/system/useMethods';
|
||||
import { importViewsFile } from '/@/utils';
|
||||
|
||||
@@ -33,6 +33,8 @@ export function usePopBiz(props, tableRef?) {
|
||||
const dataSource = ref<Array<object>>([]);
|
||||
//定义表格信息
|
||||
const columns = ref<Array<object>>([]);
|
||||
// 当前路由
|
||||
const route = useRoute();
|
||||
//定义请求url信息
|
||||
const configUrl = reactive({
|
||||
//列表页加载column和data
|
||||
@@ -533,6 +535,7 @@ export function usePopBiz(props, tableRef?) {
|
||||
pagination.current = 1;
|
||||
}
|
||||
let params = getQueryParams(); //查询条件
|
||||
params['onlRepUrlParamStr'] = getUrlParamString();
|
||||
console.log('params', params);
|
||||
loading.value = true;
|
||||
let url = `${configUrl.getData}${unref(cgRpConfigId)}`;
|
||||
@@ -546,6 +549,20 @@ export function usePopBiz(props, tableRef?) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取地址栏的参数
|
||||
*/
|
||||
function getUrlParamString() {
|
||||
let query = route.query;
|
||||
let arr:any[] = []
|
||||
if(query && Object.keys(query).length>0){
|
||||
Object.keys(query).map(k=>{
|
||||
arr.push(`${k}=${query[k]}`)
|
||||
})
|
||||
}
|
||||
return arr.join('&')
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置dataSource
|
||||
*/
|
||||
@@ -560,9 +577,11 @@ export function usePopBiz(props, tableRef?) {
|
||||
}
|
||||
dataSource.value = data.records;
|
||||
//update-begin-author:taoyan date:2023-2-11 for:issues/356 在线报表分页有问题
|
||||
tableRef.value && tableRef.value.setPagination({
|
||||
//update-begin-author:liusq date:2023-4-04 for:issues/426 修复356时候引入的回归错误 JPopupOnlReportModal.vue 中未修改
|
||||
tableRef?.value && tableRef?.value?.setPagination({
|
||||
total: Number(data.total)
|
||||
})
|
||||
//update-end-author:liusq date:2023-4-04 for:issues/426 修复356时候引入的回归错误 JPopupOnlReportModal.vue 中未修改
|
||||
//update-end-author:taoyan date:2023-2-11 for:issues/356 在线报表分页有问题
|
||||
} else {
|
||||
pagination.total = 0;
|
||||
|
@@ -69,13 +69,20 @@ export function useListPage(options: ListPageOptions) {
|
||||
if (realUrl) {
|
||||
let title = typeof name === 'function' ? name() : name;
|
||||
//update-begin-author:taoyan date:20220507 for: erp代码生成 子表 导出报错,原因未知-
|
||||
let paramsForm = {};
|
||||
let paramsForm:any = {};
|
||||
try {
|
||||
paramsForm = await getForm().validate();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
//update-end-author:taoyan date:20220507 for: erp代码生成 子表 导出报错,原因未知-
|
||||
|
||||
//update-begin-author:liusq date:20230410 for:[/issues/409]导出功能没有按排序结果导出,设置导出默认排序,创建时间倒序
|
||||
if(!paramsForm?.column){
|
||||
Object.assign(paramsForm,{column:'createTime',order:'desc'});
|
||||
}
|
||||
//update-begin-author:liusq date:20230410 for: [/issues/409]导出功能没有按排序结果导出,设置导出默认排序,创建时间倒序
|
||||
|
||||
//如果参数不为空,则整合到一起
|
||||
//update-begin-author:taoyan date:20220507 for: erp代码生成 子表 导出动态设置mainId
|
||||
if (params) {
|
||||
@@ -90,6 +97,7 @@ export function useListPage(options: ListPageOptions) {
|
||||
if (selectedRowKeys.value && selectedRowKeys.value.length > 0) {
|
||||
paramsForm['selections'] = selectedRowKeys.value.join(',');
|
||||
}
|
||||
console.log()
|
||||
return handleExportXls(title as string, realUrl, filterObj(paramsForm));
|
||||
//update-end---author:wangshuai ---date:20220411 for:导出新增自定义参数--------------
|
||||
} else {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
export const GITHUB_URL = 'https://github.com/jeecgboot/jeecgboot-vue3';
|
||||
|
||||
// vue-Jeecg-admin-next-doc
|
||||
export const DOC_URL = 'http://vue3.jeecg.com';
|
||||
export const DOC_URL = 'http://help.jeecg.com';
|
||||
|
||||
// site url
|
||||
export const SITE_URL = 'http://www.jeecg.com';
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<DepartLeftTree ref="leftTree" @select="onTreeSelect" />
|
||||
</a-col>
|
||||
<a-col :xl="18" :lg="24" :md="24" style="margin-bottom: 10px">
|
||||
<div style="height: 100%; background-color: white">
|
||||
<div style="height: 100%;" class="address-book">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable">
|
||||
<template #post="{ text }">
|
||||
@@ -86,4 +86,10 @@
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import './index.less';
|
||||
|
||||
/*begin 兼容暗夜模式*/
|
||||
.address-book{
|
||||
background-color: @component-background !important;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
</style>
|
||||
|
@@ -14,6 +14,7 @@
|
||||
const isUpdate = ref(true);
|
||||
const expandedRowKeys = ref([]);
|
||||
const treeData = ref([]);
|
||||
const isSubAdd = ref(false);
|
||||
//表单配置
|
||||
const [registerForm, { resetFields, setFieldsValue, validate, updateSchema }] = useForm({
|
||||
schemas: formSchema,
|
||||
@@ -34,6 +35,7 @@
|
||||
expandedRowKeys.value = [];
|
||||
setModalProps({ confirmLoading: false, minHeight: 80 });
|
||||
isUpdate.value = !!data?.isUpdate;
|
||||
isSubAdd.value = !!!data?.isUpdate && data.record.id;
|
||||
if (data?.record) {
|
||||
//表单赋值
|
||||
await setFieldsValue({
|
||||
@@ -79,7 +81,7 @@
|
||||
//展开的节点信息
|
||||
await getExpandKeysByPid(values['pid'], unref(treeData));
|
||||
//刷新列表(isUpdate:是否编辑;values:表单信息;expandedArr:展开的节点信息)
|
||||
emit('success', { isUpdate: unref(isUpdate), values: { ...values }, expandedArr: unref(expandedRowKeys).reverse() });
|
||||
emit('success', { isUpdate: unref(isUpdate), isSubAdd:unref(isSubAdd), values: { ...values }, expandedArr: unref(expandedRowKeys).reverse() });
|
||||
} finally {
|
||||
setModalProps({ confirmLoading: false });
|
||||
}
|
||||
|
@@ -145,7 +145,7 @@
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
async function handleSuccess({ isUpdate, values, expandedArr }) {
|
||||
async function handleSuccess({ isUpdate,isSubAdd, values, expandedArr }) {
|
||||
if (isUpdate) {
|
||||
//编辑回调
|
||||
updateTableDataRecord(values.id, values);
|
||||
@@ -155,9 +155,15 @@
|
||||
reload();
|
||||
} else {
|
||||
//新增子集
|
||||
expandedRowKeys.value = [];
|
||||
for (let key of unref(expandedArr)) {
|
||||
await expandTreeNode(key);
|
||||
//update-begin-author:liusq---date:20230411--for: [issue/4550]分类字典数据量过多会造成数据查询时间过长---
|
||||
if(isSubAdd){
|
||||
await expandTreeNode(values.pid);
|
||||
//update-end-author:liusq---date:20230411--for: [issue/4550]分类字典数据量过多会造成数据查询时间过长---
|
||||
}else{
|
||||
expandedRowKeys.value = [];
|
||||
for (let key of unref(expandedArr)) {
|
||||
await expandTreeNode(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,8 +253,12 @@
|
||||
*操作表格后处理树节点展开合并
|
||||
* */
|
||||
async function expandTreeNode(key) {
|
||||
let record = findTableDataRecord(key);
|
||||
expandedRowKeys.value.push(key);
|
||||
let record:any = findTableDataRecord(key);
|
||||
//update-begin-author:liusq---date:20230411--for: [issue/4550]分类字典数据量过多会造成数据查询时间过长,显示“接口请求超时,请刷新页面重试!”---
|
||||
if(!expandedRowKeys.value.includes(key)){
|
||||
expandedRowKeys.value.push(key);
|
||||
}
|
||||
//update-end-author:liusq---date:20230411--for: [issue/4550]分类字典数据量过多会造成数据查询时间过长,显示“接口请求超时,请刷新页面重试!”---
|
||||
let result = await getChildList({ pid: key });
|
||||
if (result && result.length > 0) {
|
||||
record.children = getDataByResult(result);
|
||||
|
@@ -112,3 +112,11 @@
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
/*begin 兼容暗夜模式*/
|
||||
.j-box-bottom-button-float{
|
||||
background-color: @component-background;
|
||||
border-top: 1px solid @border-color-base;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
</style>
|
||||
|
@@ -166,4 +166,11 @@
|
||||
.depart-rule-tree :deep(.scrollbar__bar) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/*begin 兼容暗夜模式*/
|
||||
.j-box-bottom-button-float{
|
||||
background-color: @component-background;
|
||||
border-top: 1px solid @border-color-base;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
</style>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<DepartLeftTree ref="leftTree" @select="onTreeSelect" @rootTreeData="onRootTreeData" />
|
||||
</a-col>
|
||||
<a-col :xl="12" :lg="24" :md="24" style="margin-bottom: 10px">
|
||||
<div style="height: 100%; background-color: white">
|
||||
<div style="height: 100%;" class="depart-manage">
|
||||
<a-tabs v-show="departData != null" defaultActiveKey="base-info">
|
||||
<a-tab-pane tab="基本信息" key="base-info" forceRender style="position: relative">
|
||||
<div style="padding: 20px">
|
||||
@@ -61,3 +61,10 @@
|
||||
<style lang="less">
|
||||
@import './index.less';
|
||||
</style>
|
||||
<style lang="less" scoped>
|
||||
/*begin 兼容暗夜模式*/
|
||||
.depart-manage{
|
||||
background-color: @component-background;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
</style>
|
||||
|
@@ -11,6 +11,7 @@
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import {getTenantId} from "/@/utils/auth";
|
||||
|
||||
const isOAuth = ref<boolean>(isOAuth2AppEnv());
|
||||
const env = ref<any>({ thirdApp: false, wxWork: false, dingtalk: false });
|
||||
@@ -50,7 +51,7 @@
|
||||
if (route.query.oauth2LoginToken) {
|
||||
let token = route.query.oauth2LoginToken;
|
||||
//执行登录操作
|
||||
thirdLogin({ token, thirdType: route.query.thirdType });
|
||||
thirdLogin({ token, thirdType: route.query.thirdType,tenantId: getTenantId });
|
||||
} else if (env.value.wxWork) {
|
||||
sysOAuth2Login('wechat_enterprise');
|
||||
} else if (env.value.dingtalk) {
|
||||
@@ -83,4 +84,4 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
|
@@ -41,7 +41,13 @@
|
||||
let values = await validate();
|
||||
setModalProps({ confirmLoading: true });
|
||||
//提交表单
|
||||
values.userIds += ',';
|
||||
//update-begin-author:liusq---date:20230404--for: [issue#429]新增通知公告提交指定用户参数有undefined ---
|
||||
if(values.msgType==='ALL'){
|
||||
values.userIds = '';
|
||||
}else{
|
||||
values.userIds += ',';
|
||||
}
|
||||
//update-end-author:liusq---date:20230404--for: [issue#429]新增通知公告提交指定用户参数有undefined ---
|
||||
await saveOrUpdate(values, isUpdate.value);
|
||||
//关闭弹窗
|
||||
closeModal();
|
||||
|
@@ -2,22 +2,22 @@ import { BasicColumn, FormSchema } from '/@/components/Table';
|
||||
import { rules } from '/@/utils/helper/validator';
|
||||
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '职务编码',
|
||||
dataIndex: 'code',
|
||||
width: 200,
|
||||
align: 'left',
|
||||
},
|
||||
// {
|
||||
// title: '职务编码',
|
||||
// dataIndex: 'code',
|
||||
// width: 200,
|
||||
// align: 'left',
|
||||
// },
|
||||
{
|
||||
title: '职务名称',
|
||||
dataIndex: 'name',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '职务等级',
|
||||
dataIndex: 'postRank_dictText',
|
||||
width: 100,
|
||||
},
|
||||
// {
|
||||
// title: '职务等级',
|
||||
// dataIndex: 'postRank_dictText',
|
||||
// width: 100,
|
||||
// },
|
||||
];
|
||||
|
||||
export const searchFormSchema: FormSchema[] = [
|
||||
@@ -36,35 +36,35 @@ export const formSchema: FormSchema[] = [
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
{
|
||||
label: '职级',
|
||||
field: 'postRank',
|
||||
component: 'JDictSelectTag',
|
||||
required: true,
|
||||
componentProps: {
|
||||
dictCode: 'position_rank',
|
||||
dropdownStyle: {
|
||||
maxHeight: '100vh',
|
||||
},
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
// {
|
||||
// label: '职级',
|
||||
// field: 'postRank',
|
||||
// component: 'JDictSelectTag',
|
||||
// required: true,
|
||||
// componentProps: {
|
||||
// dictCode: 'position_rank',
|
||||
// dropdownStyle: {
|
||||
// maxHeight: '100vh',
|
||||
// },
|
||||
// getPopupContainer: () => document.body,
|
||||
// },
|
||||
// },
|
||||
{
|
||||
field: 'name',
|
||||
label: '职务名称',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: 'code',
|
||||
label: '职务编码',
|
||||
component: 'Input',
|
||||
required: true,
|
||||
dynamicDisabled: ({ values }) => {
|
||||
return !!values.id;
|
||||
},
|
||||
dynamicRules: ({ model, schema }) => {
|
||||
return rules.duplicateCheckRule('sys_position', 'code', model, schema, true);
|
||||
},
|
||||
},
|
||||
// {
|
||||
// field: 'code',
|
||||
// label: '职务编码',
|
||||
// component: 'Input',
|
||||
// required: true,
|
||||
// dynamicDisabled: ({ values }) => {
|
||||
// return !!values.id;
|
||||
// },
|
||||
// dynamicRules: ({ model, schema }) => {
|
||||
// return rules.duplicateCheckRule('sys_position', 'code', model, schema, true);
|
||||
// },
|
||||
// },
|
||||
];
|
||||
|
@@ -42,6 +42,12 @@ export const searchFormSchema: FormSchema[] = [
|
||||
component: 'Input',
|
||||
colProps: { span: 6 },
|
||||
},
|
||||
{
|
||||
field: 'roleCode',
|
||||
label: '角色编码',
|
||||
component: 'Input',
|
||||
colProps: { span: 6 },
|
||||
},
|
||||
];
|
||||
/**
|
||||
* 角色用户搜索form
|
||||
|
63
src/views/system/tenant/TenantInviteUserModal.vue
Normal file
63
src/views/system/tenant/TenantInviteUserModal.vue
Normal file
@@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" :width="500" :title="title" @ok="handleSubmit">
|
||||
<BasicForm @register="registerForm" />
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { BasicModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
export default defineComponent({
|
||||
name: 'TenantInviteUserModal',
|
||||
components: {
|
||||
BasicModal,
|
||||
BasicForm,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const title = ref<string>('邀请成员');
|
||||
const [registerForm, { resetFields, validate }] = useForm({
|
||||
schemas: [
|
||||
{
|
||||
label: '手机号',
|
||||
field: 'phone',
|
||||
component: 'Input',
|
||||
dynamicRules: () => {
|
||||
return [
|
||||
{ required: true, message: '请填写手机号' },
|
||||
{ pattern: /^1[3456789]\d{9}$/, message: '手机号码格式有误' },
|
||||
];
|
||||
},
|
||||
},
|
||||
],
|
||||
showActionButtonGroup: false,
|
||||
labelCol: { span: 24 },
|
||||
wrapperCol: { span: 24 },
|
||||
});
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
//重置表单
|
||||
await resetFields();
|
||||
setModalProps({ minHeight: 100 });
|
||||
});
|
||||
|
||||
/**
|
||||
* 提交,返回给租户list页面
|
||||
*/
|
||||
async function handleSubmit() {
|
||||
let values = await validate();
|
||||
emit('inviteOk',values.phone);
|
||||
closeModal();
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
registerModal,
|
||||
registerForm,
|
||||
handleSubmit,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
@@ -18,9 +18,10 @@
|
||||
</BasicTable>
|
||||
</BasicModal>
|
||||
<TenantPackMenuModal @register="registerPackMenu" @success="success" />
|
||||
<TenantPackUserModal @register="registerPackUser" @success="success" />
|
||||
</template>
|
||||
<script lang="ts" setup name="tenant-pack-modal">
|
||||
import { ref, unref } from 'vue';
|
||||
import { reactive, ref, unref } from 'vue';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
import { packColumns, userColumns, packFormSchema } from './tenant.data';
|
||||
import { getTenantUserList, leaveTenant, packList, deletePackPermissions } from './tenant.api';
|
||||
@@ -28,8 +29,11 @@
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import TenantPackMenuModal from './TenantPackMenuModal.vue';
|
||||
import {Modal} from "ant-design-vue";
|
||||
import TenantPackUserModal from './TenantPackUserModal.vue';
|
||||
import {useMessage} from "/@/hooks/web/useMessage";
|
||||
|
||||
const [registerPackMenu, { openModal }] = useModal();
|
||||
const [registerPackUser, { openModal: packUserOpenModal }] = useModal();
|
||||
const tenantId = ref<number>(0);
|
||||
// 列表页面公共参数、方法
|
||||
const { prefixCls, tableContext } = useListPage({
|
||||
@@ -57,12 +61,14 @@
|
||||
},
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
|
||||
// Emits声明
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
const createBy = ref<string>('');
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
tenantId.value = data.tenantId;
|
||||
createBy.value = data.createBy;
|
||||
success();
|
||||
});
|
||||
//设置标题
|
||||
@@ -75,6 +81,10 @@
|
||||
|
||||
function getActions(record) {
|
||||
return [
|
||||
{
|
||||
label: '用户',
|
||||
onClick: seeTenantPackUser.bind(null, record),
|
||||
},
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
@@ -83,7 +93,7 @@
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除租户产品包',
|
||||
confirm: handleDelete.bind(null, record.id),
|
||||
confirm: handleDelete.bind(null, record),
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -108,18 +118,37 @@
|
||||
});
|
||||
}
|
||||
|
||||
//默认系统产品包不允许删除,包含(超级管理员、组织账户管理员、组织应用管理员)
|
||||
const packCode = reactive<any>(['superAdmin','accountAdmin','appAdmin']);
|
||||
const { createMessage } = useMessage();
|
||||
|
||||
/**
|
||||
* 删除产品包
|
||||
* @param 删除
|
||||
*/
|
||||
async function handleDelete(id) {
|
||||
await deletePackPermissions({ ids: id }, success);
|
||||
async function handleDelete(record) {
|
||||
//update-begin---author:wangshuai ---date:20230222 for:系统默认产品包不允许删除------------
|
||||
if(packCode.indexOf(record.packCode) != -1){
|
||||
createMessage.warning("默认系统产品包不允许删除");
|
||||
return;
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20230222 for:系统默认产品包不允许删除------------
|
||||
await deletePackPermissions({ ids: record.id }, success);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除产品包
|
||||
*/
|
||||
async function handlePackBatch() {
|
||||
let value = selectedRows.value;
|
||||
if(value && value.length>0){
|
||||
for (let i = 0; i < value.length; i++) {
|
||||
if(packCode.indexOf(value[i].packCode) != -1){
|
||||
createMessage.warning("默认系统产品包不允许删除");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Modal.confirm({
|
||||
title: '删除租户产品包',
|
||||
content: '是否删除租户产品包',
|
||||
@@ -141,4 +170,15 @@
|
||||
tenantId: unref(tenantId),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 产品包下面的用户
|
||||
* @param record
|
||||
*/
|
||||
function seeTenantPackUser(record) {
|
||||
record.createBy = unref(createBy);
|
||||
packUserOpenModal(true,{
|
||||
record:record
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
173
src/views/system/tenant/TenantPackUserModal.vue
Normal file
173
src/views/system/tenant/TenantPackUserModal.vue
Normal file
@@ -0,0 +1,173 @@
|
||||
<template>
|
||||
<BasicModal @register="registerModal" destroyOnClose :title="title" :width="1000" @ok="handleSubmit">
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<template #departNames="{ text, record }">
|
||||
<template v-if="text && text.length > 0">
|
||||
{{ getName(text) }}
|
||||
</template>
|
||||
</template>
|
||||
<template #positionNames="{ text, record }">
|
||||
<template v-if="text && text.length > 0">
|
||||
{{ getName(text) }}
|
||||
</template>
|
||||
</template>
|
||||
<template #tableTitle>
|
||||
<a-button preIcon="ant-design:usergroup-add-outlined" type="primary" @click="addUser">邀请成员</a-button>
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" />
|
||||
</template>
|
||||
</BasicTable>
|
||||
<user-select-modal :multi="true" @register="registerUserModal" @selected="onSelected"></user-select-modal>
|
||||
</BasicModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, ref } from 'vue';
|
||||
import { BasicModal, useModal, useModalInner } from '/@/components/Modal';
|
||||
import { BasicTable, TableAction } from '/@/components/Table';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { tenantPackUserColumns } from './tenant.data';
|
||||
import { queryTenantPackUserList, deleteTenantPackUser, addTenantPackUser } from './tenant.api';
|
||||
import UserSelectModal from '/@/components/Form/src/jeecg/components/userSelect/UserSelectModal.vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'TenantPackUserModal',
|
||||
components: { BasicModal, BasicTable, TableAction, UserSelectModal },
|
||||
setup() {
|
||||
//产品包信息
|
||||
const tenantPackData = reactive<any>({});
|
||||
//表单赋值
|
||||
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
|
||||
setModalProps({ confirmLoading: false, showCancelBtn: true, showOkBtn: false });
|
||||
Object.assign(tenantPackData, data.record);
|
||||
await reload();
|
||||
});
|
||||
const { createMessage } = useMessage();
|
||||
//设置标题
|
||||
const title = ref<string>('用户');
|
||||
//注册table数据
|
||||
const { tableContext } = useListPage({
|
||||
tableProps: {
|
||||
api: queryTenantPackUserList,
|
||||
immediate: false,
|
||||
columns: tenantPackUserColumns,
|
||||
canResize: false,
|
||||
useSearchForm: false,
|
||||
beforeFetch: (params) => {
|
||||
params.tenantId = tenantPackData.tenantId;
|
||||
params.packId = tenantPackData.id;
|
||||
params.status = 1;
|
||||
return params;
|
||||
},
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
},
|
||||
},
|
||||
});
|
||||
const [registerUserModal, { openModal: openUserModal, closeModal: closeUserModal }] = useModal();
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
/**
|
||||
* 获取部门/职务名称
|
||||
* @param value
|
||||
*/
|
||||
function getName(value) {
|
||||
return value.join(',');
|
||||
}
|
||||
|
||||
/**
|
||||
* 表格操作列
|
||||
* @param record
|
||||
*/
|
||||
function getTableAction(record) {
|
||||
const userStore = useUserStore();
|
||||
let username = userStore.getUserInfo.username;
|
||||
if (username != tenantPackData.createBy) {
|
||||
}
|
||||
return [
|
||||
{
|
||||
label: '移除',
|
||||
popConfirm: {
|
||||
title: '是否确认移除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
},
|
||||
ifShow: username == tenantPackData.createBy,
|
||||
},
|
||||
{
|
||||
label: '---',
|
||||
ifShow: username != tenantPackData.createBy,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
async function handleDelete(record) {
|
||||
let params = {
|
||||
packId: record.packId,
|
||||
packName: record.packName,
|
||||
tenantId: record.tenantId,
|
||||
userId: record.id,
|
||||
realname: record.realname,
|
||||
};
|
||||
await deleteTenantPackUser(params);
|
||||
await reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户弹窗
|
||||
*/
|
||||
function addUser() {
|
||||
openUserModal(true, {
|
||||
list: [],
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请人回调事件
|
||||
* @param arr
|
||||
*/
|
||||
async function onSelected(arr) {
|
||||
if (arr && arr.length > 0) {
|
||||
let names: any[] = [];
|
||||
let ids: any[] = [];
|
||||
for (let u of arr) {
|
||||
names.push(u.realname);
|
||||
ids.push(u.id);
|
||||
}
|
||||
console.log(tenantPackData);
|
||||
let params = {
|
||||
packId: tenantPackData.id,
|
||||
packName: tenantPackData.packName,
|
||||
tenantId: tenantPackData.tenantId,
|
||||
userId: ids.join(','),
|
||||
realname: names.join(','),
|
||||
};
|
||||
await addTenantPackUser(params);
|
||||
await reload();
|
||||
}
|
||||
closeUserModal();
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
registerModal,
|
||||
registerTable,
|
||||
rowSelection,
|
||||
getName,
|
||||
getTableAction,
|
||||
registerUserModal,
|
||||
addUser,
|
||||
onSelected,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
@@ -40,7 +40,7 @@
|
||||
</template>
|
||||
</BasicTable>
|
||||
<TenantModal @register="registerModal" @success="reload" />
|
||||
<UserSelectModal rowKey="id" @register="registerSelUserModal" @getSelectResult="onSelectOk" />
|
||||
<TenantInviteUserModal @register="registerSelUserModal" @inviteOk="handleInviteUserOk"/>
|
||||
<TenantUserModal @register="registerTenUserModal" />
|
||||
<!-- 产品包 -->
|
||||
<TenantPackModal @register="registerPackModal" />
|
||||
@@ -57,7 +57,7 @@
|
||||
import TenantModal from './TenantModal.vue';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import UserSelectModal from '/@/components/Form/src/jeecg/components/modal/UserSelectModal.vue';
|
||||
import TenantInviteUserModal from './TenantInviteUserModal.vue';
|
||||
import TenantUserModal from './TenantUserModal.vue';
|
||||
import TenantPackModal from './TenantPackModal.vue';
|
||||
import TenantRecycleBinModal from './TenantRecycleBinModal.vue';
|
||||
@@ -86,7 +86,7 @@
|
||||
}
|
||||
},
|
||||
});
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys, selectedRows }] = tableContext;
|
||||
|
||||
/**
|
||||
* 操作列定义
|
||||
@@ -156,14 +156,14 @@
|
||||
/**
|
||||
* 用户选择回调事件
|
||||
* @param options
|
||||
* @param values
|
||||
* @param value
|
||||
*/
|
||||
async function onSelectOk(options, values) {
|
||||
if (values && values.length > 0) {
|
||||
await invitationUserJoin({ ids: selectedRowKeys.value.join(','), userIds: values.join(',') });
|
||||
} else {
|
||||
createMessage.warn('请选择用户!');
|
||||
async function handleInviteUserOk(value) {
|
||||
//update-begin---author:wangshuai ---date:20230314 for:【QQYUN-4605】后台的邀请谁加入租户,没办法选不是租户下的用户------------
|
||||
if (value) {
|
||||
await invitationUserJoin({ ids: selectedRowKeys.value.join(','), phone: value });
|
||||
}
|
||||
//update-end---author:wangshuai ---date:20230314 for:【QQYUN-4605】后台的邀请谁加入租户,没办法选不是租户下的用户------------
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,6 +186,8 @@
|
||||
}
|
||||
packModal(true, {
|
||||
tenantId: unref(selectedRowKeys.value.join(',')),
|
||||
//将租户创建人(拥有者)传递过去,产品包下的用户不允许非拥有者删除
|
||||
createBy: selectedRows.value[0].createBy
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,10 @@ enum Api {
|
||||
recycleBinPageList = '/sys/tenant/recycleBinPageList',
|
||||
deleteLogicDeleted = '/sys/tenant/deleteLogicDeleted',
|
||||
revertTenantLogic = '/sys/tenant/revertTenantLogic',
|
||||
//用户产品包关系api
|
||||
queryTenantPackUserList = '/sys/tenant/queryTenantPackUserList',
|
||||
deleteTenantPackUser = '/sys/tenant/deleteTenantPackUser',
|
||||
addTenantPackUser = '/sys/tenant/addTenantPackUser',
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,3 +178,27 @@ export const revertTenantLogic = (params,handleSuccess) => {
|
||||
handleSuccess();
|
||||
})
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取租户产品包下面的用户
|
||||
* @param params
|
||||
*/
|
||||
export const queryTenantPackUserList = (params) => {
|
||||
return defHttp.get({ url: Api.queryTenantPackUserList, params });
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除用户和产品包的关系数据
|
||||
* @param params
|
||||
*/
|
||||
export const deleteTenantPackUser = (params)=>{
|
||||
return defHttp.put({ url: Api.deleteTenantPackUser, params });
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加用户和产品包的关系数据
|
||||
* @param params
|
||||
*/
|
||||
export const addTenantPackUser = (params)=>{
|
||||
return defHttp.post({ url: Api.addTenantPackUser, params });
|
||||
}
|
||||
|
@@ -49,6 +49,11 @@ export const columns: BasicColumn[] = [
|
||||
title: '部门',
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
dataIndex: 'createBy_dictText',
|
||||
title: '创建者(拥有者)',
|
||||
width: 150
|
||||
},
|
||||
/* {
|
||||
title: '开始时间',
|
||||
dataIndex: 'beginDate',
|
||||
@@ -300,6 +305,7 @@ export const packMenuFormSchema: FormSchema[] = [
|
||||
pidField: 'parent_id',
|
||||
multiple: true,
|
||||
treeCheckAble:true,
|
||||
treeCheckStrictly: true,
|
||||
getPopupContainer: () => document.body,
|
||||
},
|
||||
},
|
||||
@@ -372,3 +378,26 @@ export const searchRecycleFormSchema : FormSchema[] = [
|
||||
component: 'Input',
|
||||
},
|
||||
]
|
||||
|
||||
//产品包用户列表
|
||||
export const tenantPackUserColumns: BasicColumn[] = [
|
||||
{
|
||||
title: '用户',
|
||||
dataIndex: 'realname',
|
||||
width: 200,
|
||||
},
|
||||
{
|
||||
title: '部门',
|
||||
dataIndex: 'departNames',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
slots: { customRender: 'departNames' }
|
||||
},
|
||||
{
|
||||
title: '职位',
|
||||
dataIndex: 'positionNames',
|
||||
ellipsis: true,
|
||||
width: 200,
|
||||
slots: { customRender: 'positionNames' }
|
||||
}
|
||||
]
|
||||
|
@@ -284,7 +284,12 @@ export const formSchema: FormSchema[] = [
|
||||
label: '邮箱',
|
||||
field: 'email',
|
||||
component: 'Input',
|
||||
rules: rules.rule('email', false),
|
||||
dynamicRules: ({ model, schema }) => {
|
||||
return [
|
||||
{ ...rules.duplicateCheckRule('sys_user', 'email', model, schema, true)[0] },
|
||||
{ ...rules.rule('email', false)[0] },
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '手机号码',
|
||||
|
@@ -22,16 +22,6 @@
|
||||
<span class="pointer blue-e5" style="margin-left: 10px" @click="updatePassWord">修改</span>
|
||||
</div>
|
||||
|
||||
<div class="account-row-item">
|
||||
<div class="account-label gray-75">账号绑定</div>
|
||||
<span>
|
||||
<WechatFilled :style="!wechatData.bindWechat ? { color: '#9e9e9e' } : { color: '#1ec563' }" />
|
||||
<span class="gray-75" style="margin-left: 12px">微信</span>
|
||||
<span class="gray-75" style="margin-left: 8px" v-if="wechatData.bindWechat">{{ '已绑定:' + wechatData.name }}</span>
|
||||
<span class="blue-e5 pointer" style="margin-left: 24px" @click="wechatBind">{{ !wechatData.bindWechat ? '绑定' : '解绑' }}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="account-row-item clearfix">
|
||||
<div class="account-label gray-75">账户注销</div>
|
||||
<span style="color: red" class="pointer" @click="cancellation">注销</span>
|
||||
@@ -145,7 +135,9 @@ onMounted(() => {
|
||||
<style lang="less" scoped>
|
||||
.account-row-item {
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
/*begin 兼容暗夜模式*/
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
/*end 兼容暗夜模式*/
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
height: 71px;
|
||||
@@ -158,7 +150,9 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.gray-75 {
|
||||
color: #757575 !important;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color !important;
|
||||
/*end 兼容暗夜模式*/
|
||||
}
|
||||
|
||||
.pointer {
|
||||
@@ -188,7 +182,9 @@ onMounted(() => {
|
||||
.my-account{
|
||||
font-size: 17px;
|
||||
font-weight: 700!important;
|
||||
color: #333!important;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color;
|
||||
/*end 兼容暗夜模式*/
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
@@ -30,7 +30,7 @@
|
||||
<div class="account-data">
|
||||
<!-- 详细资料 -->
|
||||
<div class="account-detail">
|
||||
<div class="font-size-15 font-bold" style="color: #333!important;margin-bottom: 16px">详细资料</div>
|
||||
<div class="font-size-15 font-bold font-color-gray" style="margin-bottom: 16px">详细资料</div>
|
||||
<div class="margin-bottom-10 font-size-13">
|
||||
<span class="gray-75 item-label">生日</span>
|
||||
<span class="gray-3">{{ userInfo.birthday }}</span>
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
<!-- 联系信息 -->
|
||||
<div class="account-info">
|
||||
<div class="font-size-15 font-bold" style="color: #333!important;margin-bottom: 16px">联系信息</div>
|
||||
<div class="font-size-15 font-bold font-color-gray" style="margin-bottom: 16px">联系信息</div>
|
||||
<div class="margin-bottom-10 font-size-13">
|
||||
<span class="gray-75 item-label">邮箱</span>
|
||||
<span class="gray-3">{{ userInfo.email ? userInfo.email : "未填写" }}</span>
|
||||
@@ -219,7 +219,7 @@ onMounted(async () => {
|
||||
.user-setting-top {
|
||||
padding-top: 40px;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #eaeaea;
|
||||
border-bottom: 1px solid @border-color-base;
|
||||
display: flex;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
@@ -261,7 +261,9 @@ onMounted(async () => {
|
||||
width: 200px;
|
||||
text-overflow: ellipsis;
|
||||
line-height: 32px!important;
|
||||
color: #333;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color;
|
||||
/*end 兼容暗夜模式*/
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@@ -300,13 +302,15 @@ onMounted(async () => {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/*begin 兼容暗夜模式*/
|
||||
.gray-75 {
|
||||
color: #757575 !important;
|
||||
color: @text-color !important;
|
||||
}
|
||||
|
||||
.gray-3 {
|
||||
color: #333333;
|
||||
color: @text-color;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
|
||||
.account-info {
|
||||
width: 60%;
|
||||
@@ -335,7 +339,9 @@ onMounted(async () => {
|
||||
}
|
||||
|
||||
.use-day{
|
||||
color: #333;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color;
|
||||
/*end 兼容暗夜模式*/
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
span{
|
||||
@@ -346,4 +352,9 @@ onMounted(async () => {
|
||||
.font-size-13{
|
||||
font-size: 13px;
|
||||
}
|
||||
/*begin 兼容暗夜模式*/
|
||||
.font-color-gray{
|
||||
color: @text-color;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
</style>
|
||||
|
@@ -420,7 +420,9 @@ onMounted(() => {
|
||||
.my-tenant{
|
||||
font-size: 17px;
|
||||
font-weight: 700!important;
|
||||
color: #333!important;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color;
|
||||
/*end 兼容暗夜模式*/
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.tenant-list{
|
||||
@@ -430,7 +432,9 @@ onMounted(() => {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.tenant-list-item{
|
||||
border: 1px solid #eaeaea;
|
||||
/*begin 兼容暗夜模式*/
|
||||
border: 1px solid @border-color-base;
|
||||
/*end 兼容暗夜模式*/
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -446,7 +450,9 @@ onMounted(() => {
|
||||
padding: 14px 0;
|
||||
cursor: pointer;
|
||||
font-size:17px;
|
||||
color: #333!important;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color;
|
||||
/*end 兼容暗夜模式*/
|
||||
font-weight: 700!important;
|
||||
}
|
||||
}
|
||||
@@ -472,14 +478,18 @@ onMounted(() => {
|
||||
transition: ease-in 2s;
|
||||
|
||||
.content-box {
|
||||
border-top: 1px solid #eaeaea;
|
||||
/*begin 兼容暗夜模式*/
|
||||
border-top: 1px solid @border-color-base;
|
||||
/*end 兼容暗夜模式*/
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
padding: 24px 0;
|
||||
}
|
||||
|
||||
.content-name {
|
||||
color: #757575;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color;
|
||||
/*end 兼容暗夜模式*/
|
||||
text-align: center;
|
||||
width: 100px;
|
||||
font-size: 13px;
|
||||
@@ -491,7 +501,9 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.content-des-text {
|
||||
color: #757575;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color;
|
||||
/*end 兼容暗夜模式*/
|
||||
text-align: left;
|
||||
width: 76px;
|
||||
font-size: 13px;
|
||||
@@ -504,7 +516,9 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.footer-box {
|
||||
border-top: 1px solid #eaeaea;
|
||||
/*begin 兼容暗夜模式*/
|
||||
border-top: 1px solid @border-color-base;
|
||||
/*end 兼容暗夜模式*/
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
padding: 24px 0;
|
||||
@@ -515,18 +529,20 @@ onMounted(() => {
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
/*begin 兼容暗夜模式*/
|
||||
.font-color333 {
|
||||
color: #333333;
|
||||
color: @text-color;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.font-color9e {
|
||||
color: #9e9e9e;
|
||||
color: @text-color;
|
||||
}
|
||||
|
||||
.font-color75 {
|
||||
color: #757575;
|
||||
color: @text-color;
|
||||
}
|
||||
/*end 兼容暗夜模式*/
|
||||
|
||||
.font-size13 {
|
||||
font-size: 13px;
|
||||
|
@@ -74,14 +74,18 @@ export default defineComponent({
|
||||
}
|
||||
//tabs弹窗左边样式
|
||||
:deep(.ant-tabs-nav){
|
||||
background-color: #FFFFFF;
|
||||
/*begin 兼容暗夜模式*/
|
||||
background-color: @component-background;
|
||||
/*end 兼容暗夜模式*/
|
||||
height: 260px;
|
||||
}
|
||||
//tabs弹窗右边边样式
|
||||
:deep(.ant-tabs-content-holder){
|
||||
position: relative;
|
||||
left: 12px;
|
||||
background: #FFFFFF;
|
||||
/*begin 兼容暗夜模式*/
|
||||
background: @component-background;
|
||||
/*end 兼容暗夜模式*/
|
||||
height: auto !important;
|
||||
}
|
||||
}
|
||||
@@ -105,6 +109,8 @@ export default defineComponent({
|
||||
padding-right:14px;
|
||||
}
|
||||
.icon-font-color{
|
||||
color: #9e9e9e;
|
||||
/*begin 兼容暗夜模式*/
|
||||
color: @text-color;
|
||||
/*end 兼容暗夜模式*/
|
||||
}
|
||||
</style>
|
||||
|
Reference in New Issue
Block a user