diff --git a/core/core-frontend/src/components/rich-text/TinymceEditor.vue b/core/core-frontend/src/components/rich-text/TinymceEditor.vue
new file mode 100644
index 0000000000..a7d9374eb4
--- /dev/null
+++ b/core/core-frontend/src/components/rich-text/TinymceEditor.vue
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
diff --git a/core/core-frontend/src/locales/zh-CN.ts b/core/core-frontend/src/locales/zh-CN.ts
index 433fee8d76..ba15bcd79d 100644
--- a/core/core-frontend/src/locales/zh-CN.ts
+++ b/core/core-frontend/src/locales/zh-CN.ts
@@ -2136,7 +2136,9 @@ export default {
dsIntervalTime: '数据源检测时间间隔',
dsExecuteTime: '数据源检测频率',
frontTimeOut: '请求超时时间(秒)',
- logLiveTime: '日志保留时间(天)'
+ logLiveTime: '日志保留时间(天)',
+ platformOid: '第三方平台用户组织',
+ platformRid: '第三方平台用户角色'
},
template_manage: {
name_already_exists_type: '分类名称已存在',
diff --git a/core/core-frontend/src/store/modules/interactive.ts b/core/core-frontend/src/store/modules/interactive.ts
index c1ae8e9918..40d7392e98 100644
--- a/core/core-frontend/src/store/modules/interactive.ts
+++ b/core/core-frontend/src/store/modules/interactive.ts
@@ -6,6 +6,8 @@ import { listDatasources } from '@/api/datasource'
import type { BusiTreeRequest, BusiTreeNode } from '@/models/tree/TreeNode'
import { pathValid } from '@/store/modules/permission'
import { useCache } from '@/hooks/web/useCache'
+import { useAppStoreWithOut } from '@/store/modules/app'
+const appStore = useAppStoreWithOut()
const { wsCache } = useCache()
export interface InnerInteractive {
rootManage: boolean
@@ -47,7 +49,7 @@ export const interactiveStore = defineStore('interactive', {
actions: {
async setInteractive(param: BusiTreeRequest) {
const flag = busiFlagMap.findIndex(item => item === param.busiFlag)
- if (!hasMenuAuth(flag) && !window.DataEaseBi) {
+ if (!hasMenuAuth(flag) && !window.DataEaseBi && !appStore.getIsIframe) {
const tempData: InnerInteractive = {
rootManage: false,
anyManage: false,
diff --git a/core/core-frontend/src/views/mobile/home/index.vue b/core/core-frontend/src/views/mobile/home/index.vue
index c4d3b6aa7b..bbe989e7ca 100644
--- a/core/core-frontend/src/views/mobile/home/index.vue
+++ b/core/core-frontend/src/views/mobile/home/index.vue
@@ -6,6 +6,7 @@ import { shortcutOption } from '@/views/workbranch/ShortcutOption'
import { useRouter } from 'vue-router'
import Workbranch from '@/views/mobile/components/Workbranch.vue'
import request from '@/config/axios'
+import nothingNone from '@/assets/img/none.png'
import VanTabs from 'vant/es/tabs'
import VanNavBar from 'vant/es/nav-bar'
import VanTab from 'vant/es/tab'
@@ -19,6 +20,7 @@ const router = useRouter()
const { t } = useI18n()
const activeTab = ref('recent')
+const emptyTips = ref('')
const state = reactive({
tableData: [],
curTypeList: []
@@ -35,9 +37,22 @@ const loadTableData = () => {
})
.finally(() => {
emits('setLoading', false)
+ setEmptyTips()
})
}
+const setEmptyTips = () => {
+ emptyTips.value = state.tableData.length
+ ? ''
+ : `暂无${
+ {
+ recent: '数据',
+ store: '收藏',
+ share: '分享'
+ }[activeTab.value]
+ }`
+}
+
const loadShareTableData = () => {
emits('setLoading', true)
request
@@ -50,6 +65,7 @@ const loadShareTableData = () => {
})
.finally(() => {
emits('setLoading', false)
+ setEmptyTips()
})
}
@@ -133,6 +149,12 @@ const formatterTime = val => {
:time="formatterTime(ele.lastEditTime || ele.time)"
/>
+
+
![]()
+
+ {{ emptyTips }}
+
+
@@ -145,5 +167,23 @@ const formatterTime = val => {
height: calc(100vh - 142px);
margin-top: 8px;
}
+
+ .empty-img-mobile {
+ position: absolute;
+ top: 33%;
+ left: 0;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ font-size: 14px;
+ font-weight: 400;
+ line-height: 22px;
+
+ img {
+ margin-bottom: 8px;
+ }
+ }
}
diff --git a/core/core-frontend/src/views/mobile/panel/Mobile.vue b/core/core-frontend/src/views/mobile/panel/Mobile.vue
index 6b1f5407fb..351907078b 100644
--- a/core/core-frontend/src/views/mobile/panel/Mobile.vue
+++ b/core/core-frontend/src/views/mobile/panel/Mobile.vue
@@ -67,12 +67,7 @@ const onClickLeft = () => {
-
+
{
height: 100vh;
width: 100vw;
overflow-y: auto;
+ --van-nav-bar-height: 44px;
+ --van-nav-bar-arrow-size: 20px;
+ --van-nav-bar-icon-color: #1f2329;
+ --van-nav-bar-title-text-color: #1f2329;
+ --van-font-bold: 500;
+ --van-nav-bar-title-font-size: 17px;
}
diff --git a/core/core-frontend/src/views/system/parameter/basic/BasicEdit.vue b/core/core-frontend/src/views/system/parameter/basic/BasicEdit.vue
index fc31acf936..7563f3ef90 100644
--- a/core/core-frontend/src/views/system/parameter/basic/BasicEdit.vue
+++ b/core/core-frontend/src/views/system/parameter/basic/BasicEdit.vue
@@ -18,7 +18,9 @@ const state = reactive({
dsExecuteTime: 'minute',
frontTimeOut: '30'
}),
- settingList: []
+ settingList: [],
+ orgOptions: [],
+ roleOptions: []
})
const rule = reactive({
@@ -36,7 +38,10 @@ const buildSettingList = () => {
const pkey = item.pkey.startsWith('basic.') ? item.pkey : `basic.${item.pkey}`
const sort = item.sort
const type = item.type
- const pval = state.form[item.pkey]
+ let pval = state.form[item.pkey]
+ if (Array.isArray(pval)) {
+ pval = pval.join(',')
+ }
return { pkey, pval, type, sort }
})
}
@@ -99,7 +104,9 @@ const closeLoading = () => {
loadingInstance.value?.close()
}
-const edit = list => {
+const edit = (list, orgOptions, roleOptions) => {
+ state.orgOptions = orgOptions || []
+ state.roleOptions = roleOptions || []
state.settingList = list.map(item => {
const pkey = item.pkey
if (pkey === 'basic.logLiveTime') {
@@ -114,11 +121,62 @@ const edit = list => {
item['label'] = `setting_${pkey}`
item['pkey'] = pkey.split('.')[1]
let pval = item.pval
+ if (item.pkey.includes('platformRid') && pval?.length) {
+ pval = pval.split(',')
+ if (!rule['platformRid']) {
+ rule['platformRid'] = [
+ {
+ required: true,
+ message: t('common.require'),
+ trigger: ['blur', 'change']
+ }
+ ]
+ }
+ }
+ if (item.pkey.includes('platformOid')) {
+ if (!rule['platformOid']) {
+ rule['platformOid'] = [
+ {
+ required: true,
+ message: t('common.require'),
+ trigger: ['blur', 'change']
+ }
+ ]
+ }
+ }
state.form[item['pkey']] = pval || state.form[item['pkey']]
return item
})
dialogVisible.value = true
}
+const loadRoleOptions = async () => {
+ const oid = state.form['platformOid']
+ if (!oid) {
+ return
+ }
+ const res = await request.get({ url: `/role/queryWithOid/${oid}` })
+ const data = res.data
+ const map = groupBy(data)
+ state.roleOptions[0].children = map.get(false)
+ state.roleOptions[1].children = map.get(true)
+}
+const groupBy = list => {
+ const map = new Map()
+ list.forEach(item => {
+ const readonly = item.readonly
+ let arr = map.get(readonly)
+ if (!arr) {
+ arr = []
+ }
+ arr.push({ value: item.id, label: item.name, disabled: false })
+ map.set(readonly, arr)
+ })
+ return map
+}
+const oidChange = () => {
+ state.form['platformRid'] = []
+ loadRoleOptions()
+}
defineExpose({
edit
})
@@ -200,6 +258,29 @@ defineExpose({
type="number"
/>
+
+
+
+
+
+
diff --git a/core/core-frontend/src/views/system/parameter/basic/BasicInfo.vue b/core/core-frontend/src/views/system/parameter/basic/BasicInfo.vue
index 4c89aee153..6d16a75dda 100644
--- a/core/core-frontend/src/views/system/parameter/basic/BasicInfo.vue
+++ b/core/core-frontend/src/views/system/parameter/basic/BasicInfo.vue
@@ -18,29 +18,77 @@ import request from '@/config/axios'
import { SettingRecord } from '@/views/system/common/SettingTemplate'
import { reactive } from 'vue'
import { cloneDeep } from 'lodash-es'
+import { useI18n } from '@/hooks/web/useI18n'
+const { t } = useI18n()
const editor = ref()
const infoTemplate = ref()
const tooltips = [
{
key: 'setting_basic.frontTimeOut',
val: '请求超时时间(单位:秒,注意:保存后刷新浏览器生效)'
+ },
+ {
+ key: 'setting_basic.platformOid',
+ val: '作用域包括认证设置和平台对接'
+ },
+ {
+ key: 'setting_basic.platformRid',
+ val: '作用域包括认证设置和平台对接'
}
]
const state = reactive({
- templateList: [] as SettingRecord[]
+ templateList: [] as SettingRecord[],
+ orgOptions: [],
+ roleOptions: [
+ {
+ value: 'admin',
+ label: t('role.org_admin'),
+ children: null,
+ disabled: false
+ },
+ {
+ value: 'readonly',
+ label: t('role.average_role'),
+ children: null,
+ disabled: false
+ }
+ ]
})
let originData = []
+const selectedOid = ref('')
+const selectedOName = ref('')
+const selectedRid = ref([])
+const selectedRName = ref([])
const search = cb => {
const url = '/sysParameter/basic/query'
originData = []
state.templateList = []
- request.get({ url }).then(res => {
+ request.get({ url }).then(async res => {
originData = cloneDeep(res.data)
const data = res.data
for (let index = 0; index < data.length; index++) {
const item = data[index]
if (item.pkey === 'basic.autoCreateUser') {
item.pval = item.pval === 'true' ? '开启' : '未开启'
+ } else if (item.pkey === 'basic.platformOid') {
+ selectedOid.value = item.pval
+ await loadOrgOptions()
+ item.pval = selectedOName.value || '默认组织'
+ } else if (item.pkey === 'basic.platformRid') {
+ const pval = item.pval
+ if (pval?.length) {
+ const pvalArray = pval.split(',')
+ selectedRid.value = pvalArray
+ await loadRoleOptions()
+ if (selectedRName.value.length) {
+ item.pval = selectedRName.value.join(',')
+ } else {
+ item.pval = '普通角色'
+ }
+ } else {
+ selectedRid.value = []
+ item.pval = '普通角色'
+ }
} else {
item.pval = item.pval
}
@@ -58,6 +106,56 @@ const refresh = () => {
refresh()
const edit = () => {
- editor?.value.edit(cloneDeep(originData))
+ editor?.value.edit(
+ cloneDeep(originData),
+ cloneDeep(state.orgOptions),
+ cloneDeep(state.roleOptions)
+ )
+}
+const loadOrgOptions = async () => {
+ const res = await request.post({ url: '/org/mounted', data: {} })
+ const data = res.data
+ formatOrg(data)
+ state.orgOptions = data
+}
+const loadRoleOptions = async () => {
+ const res = await request.get({ url: `/role/queryWithOid/${selectedOid.value}` })
+ const data = res.data
+ const map = groupBy(data)
+ state.roleOptions[0].children = map.get(false)
+ state.roleOptions[1].children = map.get(true)
+}
+const formatOrg = list => {
+ const stack = [...list]
+ while (stack.length) {
+ const item = stack.pop()
+ if (item.id === selectedOid.value) {
+ selectedOName.value = item.name
+ }
+ item.value = item.id
+ item.label = item.name
+ item.disabled = item.readOnly
+ if (item.children?.length) {
+ item.children.forEach(kid => stack.push(kid))
+ }
+ }
+}
+
+const groupBy = list => {
+ const map = new Map()
+ selectedRName.value = []
+ list.forEach(item => {
+ if (selectedRid.value.includes(item.id)) {
+ selectedRName.value.push(item.name)
+ }
+ const readonly = item.readonly
+ let arr = map.get(readonly)
+ if (!arr) {
+ arr = []
+ }
+ arr.push({ value: item.id, label: item.name, disabled: false })
+ map.set(readonly, arr)
+ })
+ return map
}
diff --git a/de-xpack b/de-xpack
index d9d2d9a8a9..a1c4b52372 160000
--- a/de-xpack
+++ b/de-xpack
@@ -1 +1 @@
-Subproject commit d9d2d9a8a9eb67c4d3c68027d80fb4c5459c5c25
+Subproject commit a1c4b52372679fde98c2635264ef0b48ac64a50f
diff --git a/pom.xml b/pom.xml
index a8cbe273fe..b81857ec92 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
- 2.3.0
+ 2.4.0
17
UTF-8
2022.0.0.0
diff --git a/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/role/api/RoleApi.java b/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/role/api/RoleApi.java
index b4f497ab7b..34e7145209 100644
--- a/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/role/api/RoleApi.java
+++ b/sdk/api/api-permissions/src/main/java/io/dataease/api/permissions/role/api/RoleApi.java
@@ -8,6 +8,7 @@ import io.dataease.api.permissions.role.vo.RoleVO;
import io.dataease.auth.DeApiPath;
import io.dataease.auth.DePermit;
import io.dataease.model.KeywordRequest;
+import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
@@ -90,4 +91,8 @@ public interface RoleApi {
@Operation(summary = "查询组织内角色")
@PostMapping("/byCurOrg")
List byCurOrg(@RequestBody KeywordRequest request);
+
+ @Hidden
+ @GetMapping("/queryWithOid/{oid}")
+ List queryWithOid(@PathVariable("oid") Long oid);
}