Merge branch 'dev-v2' into pr@dev-v2_query_com

This commit is contained in:
dataeaseShu 2024-02-18 13:53:38 +08:00
commit 918da1e1ef
50 changed files with 689 additions and 154 deletions

View File

@ -43,10 +43,9 @@ public class SqlparserUtils {
}
SqlParser.Config config =
SqlParser.configBuilder()
.setLex(Lex.JAVA)
.setIdentifierMaxLength(256)
.build();
SqlParser.config()
.withLex(Lex.JAVA)
.withIdentifierMaxLength(256);
SqlParser sqlParser = SqlParser.create(tmpSql, config);
SqlNode sqlNode;
try {

View File

@ -21,10 +21,9 @@ public class SqlUtils {
}
SqlParser.Config config =
SqlParser.configBuilder()
.setLex(Lex.JAVA)
.setIdentifierMaxLength(256)
.build();
SqlParser.config()
.withLex(Lex.JAVA)
.withIdentifierMaxLength(256);
// 创建解析器
SqlParser sqlParser = SqlParser
.create(sql, config);

View File

@ -73,7 +73,7 @@ public class SQLConstants {
public static final String DEFAULT_INT_FORMAT = "DECIMAL(18,0)";
public static final String DEFAULT_FLOAT_FORMAT = "DECIMAL(27,8)";
public static final String DEFAULT_FLOAT_FORMAT = "DECIMAL(26,8)";
public static final String WHERE_VALUE_NULL = "(NULL,'')";

View File

@ -101,6 +101,7 @@ public class DataVisualizationServer implements DataVisualizationApi {
}
}
@DeLog(id = "#p0", ot = LogOT.READ, stExp = "#p1")
@Override
@XpackInteract(value = "dataVisualizationServer", original = true)
public DataVisualizationVO findById(Long dvId, String busiFlag) {

View File

@ -1,3 +1,3 @@
# 接口前缀
VITE_API_BASEPATH="/de2api"
VITE_API_BASEPATH="./de2api"
VITE_VERSION="0.0.0"

View File

@ -232,6 +232,7 @@ const {
} = toRefs(props)
const domId = ref('shape-id-' + element.value.id)
const pointList = ['lt', 't', 'rt', 'r', 'rb', 'b', 'lb', 'l']
const pointCorner = ['lt', 'rt', 'rb', 'lb']
const pointList2 = ['r', 'l']
const initialAngle = {
//
@ -608,6 +609,7 @@ const handleMouseDownOnPoint = (point, e) => {
let isFirst = true
const needLockProportion = isNeedLockProportion()
const originRadio = curComponent.value.style.width / curComponent.value.style.height
const move = moveEvent => {
// move
// move
@ -628,6 +630,27 @@ const handleMouseDownOnPoint = (point, e) => {
})
//Temp dataV
offsetDataVAdaptor(style, point)
//
if (curComponent.value.maintainRadio) {
//
const heightOffset = style.height - defaultStyle.value.height
//
const widthOffset = style.width - defaultStyle.value.width
//
const adaptorWidthOffset = heightOffset * originRadio
//
const adaptorHeightOffset = widthOffset / originRadio
if (pointCorner.includes(point)) {
style.height = defaultStyle.value.height + adaptorHeightOffset
} else if (Math.abs(widthOffset) > Math.abs(adaptorWidthOffset)) {
//
style.height = defaultStyle.value.height + adaptorHeightOffset
} else {
//
style.width = defaultStyle.value.width + adaptorWidthOffset
}
}
dvMainStore.setShapeStyle(style)
//
dashboardActive.value && emit('onResizing', moveEvent)

View File

@ -17,6 +17,17 @@
</el-form-item>
</el-col>
</el-row>
<el-form-item class="form-item" :class="'form-item-' + themes">
<el-checkbox
v-if="curComponent"
size="small"
:effect="themes"
v-model="curComponent['maintainRadio']"
@change="maintainRadioChange"
>
保持宽高比
</el-checkbox>
</el-form-item>
</el-form>
</template>
@ -71,9 +82,19 @@ const onPositionChange = key => {
if (!positionMounted.value[key]) {
positionMounted.value[key] = 0
}
const originRadio = curComponent.value.style.width / curComponent.value.style.height
curComponent.value.style[key] = Math.round(
(positionMounted.value[key] * canvasStyleData.value.scale) / 100
)
if (curComponent.value.maintainRadio) {
if (key === 'width') {
curComponent.value.style['height'] = curComponent.value.style['width'] / originRadio
positionMounted.value['height'] = Math.round(positionMounted.value['width'] / originRadio)
} else if (key === 'height') {
curComponent.value.style['width'] = curComponent.value.style['height'] * originRadio
positionMounted.value['width'] = Math.round(positionMounted.value['height'] * originRadio)
}
}
if (curComponent.value.component === 'Group') {
//Group
@ -84,6 +105,10 @@ const onPositionChange = key => {
snapshotStore.recordSnapshotCache()
}
const maintainRadioChange = () => {
snapshotStore.recordSnapshotCache()
}
const positionInit = () => {
if (curComponent.value) {
Object.keys(positionMounted.value).forEach(key => {

View File

@ -104,7 +104,7 @@ service.interceptors.request.use(
config.data = qs.stringify(config.data)
}
if (embeddedStore.baseUrl) {
config.baseURL = embeddedStore.baseUrl + 'de2api/'
config.baseURL = PATH_URL
}
if (linkStore.getLinkToken) {

View File

@ -58,6 +58,7 @@ export const commonAttr = {
events: {},
groupStyle: {}, // 当一个组件成为 Group 的子组件时使用
isLock: false, // 是否锁定组件
maintainRadio: false, // 布局时保持宽高比例
isShow: true, // 是否显示组件
collapseName: ['position', 'background', 'style', 'picture'], // 编辑组件时记录当前使用的是哪个折叠面板再次回来时恢复上次打开的折叠面板优化用户体验
linkage: {

View File

@ -12,6 +12,7 @@ import {
DEFAULT_INDICATOR_STYLE
} from '@/views/chart/components/editor/util/chart'
import { valueFormatter } from '@/views/chart/components/js/formatter'
import { hexColorToRGBA } from '@/views/chart/components/js/util'
const props = defineProps({
view: {
@ -222,15 +223,21 @@ const renderChart = async view => {
if (!view) {
return
}
const TEMP_DEFAULT_CHART = cloneDeep(BASE_VIEW_CONFIG)
delete TEMP_DEFAULT_CHART.customAttr.basicStyle.alpha
const chart = deepCopy({
...defaultsDeep(view, cloneDeep(BASE_VIEW_CONFIG)),
...defaultsDeep(view, TEMP_DEFAULT_CHART),
data: chartData.value
})
recursionTransObj(customAttrTrans, chart.customAttr, scale.value, terminal.value)
recursionTransObj(customStyleTrans, chart.customStyle, scale.value, terminal.value)
if (chart.customAttr) {
const customAttr = chart.customAttr
if (customAttr.indicator) {
switch (customAttr.indicator.hPosition) {
case 'left':
@ -254,6 +261,15 @@ const renderChart = async view => {
}
indicatorColor.value = customAttr.indicator.color
let suffixColor = customAttr.indicator.suffixColor
if (customAttr.basicStyle && customAttr.basicStyle.alpha !== undefined) {
indicatorColor.value = hexColorToRGBA(
customAttr.basicStyle.colors[0],
customAttr.basicStyle.alpha
)
suffixColor = hexColorToRGBA(customAttr.basicStyle.colors[1], customAttr.basicStyle.alpha)
}
indicatorClass.value = {
color: thresholdColor.value,
@ -270,7 +286,7 @@ const renderChart = async view => {
}
indicatorSuffixClass.value = {
color: customAttr.indicator.suffixColor,
color: suffixColor,
'font-size': customAttr.indicator.suffixFontSize + 'px',
'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[customAttr.indicator.suffixFontFamily],
@ -287,9 +303,15 @@ const renderChart = async view => {
suffixContent.value = defaultTo(customAttr.indicator.suffix, '')
}
if (customAttr.indicatorName && customAttr.indicatorName.show) {
let nameColor = customAttr.indicatorName.color
if (customAttr.basicStyle && customAttr.basicStyle.alpha !== undefined) {
nameColor = hexColorToRGBA(customAttr.basicStyle.colors[2], customAttr.basicStyle.alpha)
}
indicatorNameShow.value = true
indicatorNameClass.value = {
color: customAttr.indicatorName.color,
color: nameColor,
'font-size': customAttr.indicatorName.fontSize + 'px',
'font-family': defaultTo(
CHART_CONT_FAMILY_MAP[customAttr.indicatorName.fontFamily],

View File

@ -44,7 +44,7 @@ onMounted(() => {
popper-class="toolbox-top-popover"
placement="bottom-end"
width="208"
trigger="click"
trigger="hover"
>
<top-doc-card
:span="12"

View File

@ -2133,7 +2133,8 @@ export default {
autoCreateUser: '第三方自动创建用户',
dsIntervalTime: '数据源检测时间间隔',
dsExecuteTime: '数据源检测频率',
frontTimeOut: '请求超时时间'
frontTimeOut: '请求超时时间',
logLiveTime: '日志保留时间'
},
template_manage: {
name_already_exists_type: '分类名称已存在',

View File

@ -115,6 +115,7 @@ export function initCanvasDataPrepare(dvId, busiFlag, callBack) {
if (componentItem.component === 'Group') {
componentItem.expand = componentItem.expand || false
}
componentItem['maintainRadio'] = componentItem['maintainRadio'] || false
})
const curPreviewGap =
dvInfo.type === 'dashboard' && canvasStyleResult['dashboard'].gap === 'yes'

View File

@ -1,6 +1,6 @@
<script lang="ts" setup>
import { useI18n } from '@/hooks/web/useI18n'
import { PropType, toRefs, nextTick, watch } from 'vue'
import { PropType, toRefs, nextTick, watch, ref } from 'vue'
import MiscSelector from '@/views/chart/components/editor/editor-style/components/MiscSelector.vue'
import LabelSelector from '@/views/chart/components/editor/editor-style/components/LabelSelector.vue'
import TooltipSelector from '@/views/chart/components/editor/editor-style/components/TooltipSelector.vue'
@ -90,6 +90,9 @@ const emit = defineEmits([
'onIndicatorNameChange'
])
const indicatorValueRef = ref()
const indicatorNameRef = ref()
const showProperties = (property: EditorProperty) => properties.value?.includes(property)
const onMiscChange = (val, prop) => {
@ -117,11 +120,19 @@ const onTextChange = (val, prop) => {
}
const onIndicatorChange = (val, prop) => {
state.initReady && emit('onIndicatorChange', val, prop)
const value = { indicatorValue: val, indicatorName: undefined }
if (prop === 'color' || prop === 'suffixColor') {
value.indicatorName = indicatorNameRef.value?.getFormData()
}
state.initReady && emit('onIndicatorChange', value, prop)
}
const onIndicatorNameChange = (val, prop) => {
state.initReady && emit('onIndicatorNameChange', val, prop)
const value = { indicatorName: val, indicatorValue: undefined }
if (prop === 'color') {
value.indicatorValue = indicatorValueRef.value?.getFormData()
}
state.initReady && emit('onIndicatorNameChange', value, prop)
}
const onLegendChange = (val, prop) => {
@ -243,6 +254,7 @@ watch(
title="指标值"
>
<indicator-value-selector
ref="indicatorValueRef"
:property-inner="propertyInnerAll['indicator-value-selector']"
:themes="themes"
class="attr-selector"
@ -261,6 +273,7 @@ watch(
name="indicator-name"
>
<indicator-name-selector
ref="indicatorNameRef"
:property-inner="propertyInnerAll['indicator-name-selector']"
:themes="themes"
class="attr-selector"

View File

@ -5,13 +5,15 @@ import {
COLOR_PANEL,
CHART_FONT_FAMILY,
CHART_FONT_LETTER_SPACE,
DEFAULT_INDICATOR_NAME_STYLE
DEFAULT_INDICATOR_NAME_STYLE,
DEFAULT_BASIC_STYLE
} from '@/views/chart/components/editor/util/chart'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
import { cloneDeep, defaultsDeep } from 'lodash-es'
import { ElButton, ElIcon } from 'element-plus-secondary'
import Icon from '@/components/icon-custom/src/Icon.vue'
import { hexColorToRGBA } from '@/views/chart/components/js/util'
const dvMainStore = dvMainStoreWithOut()
const { batchOptStatus } = storeToRefs(dvMainStore)
@ -40,7 +42,8 @@ const fontFamily = CHART_FONT_FAMILY
const fontLetterSpace = CHART_FONT_LETTER_SPACE
const state = reactive({
indicatorNameForm: JSON.parse(JSON.stringify(DEFAULT_INDICATOR_NAME_STYLE))
indicatorNameForm: JSON.parse(JSON.stringify(DEFAULT_INDICATOR_NAME_STYLE)),
basicStyleForm: {} as ChartBasicStyle
})
const { chart } = toRefs(props)
@ -61,11 +64,25 @@ const changeTitleStyle = prop => {
}
const init = () => {
const TEMP_DEFAULT_BASIC_STYLE = cloneDeep(DEFAULT_BASIC_STYLE)
delete TEMP_DEFAULT_BASIC_STYLE.alpha
state.basicStyleForm = defaultsDeep(
cloneDeep(props.chart?.customAttr?.basicStyle),
cloneDeep(TEMP_DEFAULT_BASIC_STYLE)
)
const customText = defaultsDeep(
cloneDeep(props.chart?.customAttr?.indicatorName),
cloneDeep(DEFAULT_INDICATOR_NAME_STYLE)
)
if (state.basicStyleForm.alpha !== undefined) {
const color = hexColorToRGBA(state.basicStyleForm.colors[2], state.basicStyleForm.alpha)
customText.color = color
}
state.indicatorNameForm = cloneDeep(customText)
//
@ -85,6 +102,12 @@ watch(
},
{ deep: true }
)
function getFormData() {
return state.indicatorNameForm
}
defineExpose({ getFormData })
</script>
<template>
@ -125,6 +148,7 @@ watch(
:predefine="predefineColors"
@change="changeTitleStyle('color')"
is-custom
show-alpha
/>
</el-form-item>
<el-form-item class="form-item" :class="'form-item-' + themes" style="padding: 0 4px">

View File

@ -5,13 +5,15 @@ import {
COLOR_PANEL,
CHART_FONT_FAMILY,
CHART_FONT_LETTER_SPACE,
DEFAULT_INDICATOR_STYLE
DEFAULT_INDICATOR_STYLE,
DEFAULT_BASIC_STYLE
} from '@/views/chart/components/editor/util/chart'
import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain'
import { storeToRefs } from 'pinia'
import { cloneDeep, defaultsDeep } from 'lodash-es'
import { ElButton, ElIcon, ElInput } from 'element-plus-secondary'
import Icon from '@/components/icon-custom/src/Icon.vue'
import { hexColorToRGBA } from '@/views/chart/components/js/util'
const dvMainStore = dvMainStoreWithOut()
const { batchOptStatus } = storeToRefs(dvMainStore)
@ -31,7 +33,7 @@ const props = defineProps({
}
})
const emit = defineEmits(['onIndicatorChange'])
const emit = defineEmits(['onIndicatorChange', 'onBasicStyleChange'])
const toolTip = computed(() => {
return props.themes === 'dark' ? 'ndark' : 'dark'
})
@ -40,7 +42,8 @@ const fontFamily = CHART_FONT_FAMILY
const fontLetterSpace = CHART_FONT_LETTER_SPACE
const state = reactive({
indicatorValueForm: JSON.parse(JSON.stringify(DEFAULT_INDICATOR_STYLE))
indicatorValueForm: JSON.parse(JSON.stringify(DEFAULT_INDICATOR_STYLE)),
basicStyleForm: {} as ChartBasicStyle
})
const { chart } = toRefs(props)
@ -61,11 +64,27 @@ const changeTitleStyle = prop => {
}
const init = () => {
const TEMP_DEFAULT_BASIC_STYLE = cloneDeep(DEFAULT_BASIC_STYLE)
delete TEMP_DEFAULT_BASIC_STYLE.alpha
state.basicStyleForm = defaultsDeep(
cloneDeep(props.chart?.customAttr?.basicStyle),
cloneDeep(TEMP_DEFAULT_BASIC_STYLE)
)
const customText = defaultsDeep(
cloneDeep(props.chart?.customAttr?.indicator),
cloneDeep(DEFAULT_INDICATOR_STYLE)
)
if (state.basicStyleForm.alpha !== undefined) {
const color = hexColorToRGBA(state.basicStyleForm.colors[0], state.basicStyleForm.alpha)
const suffixColor = hexColorToRGBA(state.basicStyleForm.colors[1], state.basicStyleForm.alpha)
customText.color = color
customText.suffixColor = suffixColor
}
state.indicatorValueForm = cloneDeep(customText)
//
@ -86,6 +105,12 @@ watch(
},
{ deep: true }
)
function getFormData() {
return state.indicatorValueForm
}
defineExpose({ getFormData })
</script>
<template>
@ -125,6 +150,7 @@ watch(
class="color-picker-style"
:predefine="predefineColors"
@change="changeTitleStyle('color')"
show-alpha
is-custom
/>
</el-form-item>
@ -410,6 +436,7 @@ watch(
:predefine="predefineColors"
@change="changeTitleStyle('suffixColor')"
is-custom
show-alpha
/>
</el-form-item>
<el-form-item class="form-item" :class="'form-item-' + themes" style="padding: 0 4px">

View File

@ -691,13 +691,25 @@ const onLabelChange = val => {
renderChart(view.value)
}
const onIndicatorChange = val => {
view.value.customAttr.indicator = val
const onIndicatorChange = (val, prop) => {
if (prop === 'color' || prop === 'suffixColor') {
view.value.customAttr.basicStyle.alpha = undefined
if (val.indicatorName !== undefined) {
view.value.customAttr.indicatorName = val.indicatorName
}
}
view.value.customAttr.indicator = val.indicatorValue
renderChart(view.value)
}
const onIndicatorNameChange = val => {
view.value.customAttr.indicatorName = val
const onIndicatorNameChange = (val, prop) => {
if (prop === 'color') {
view.value.customAttr.basicStyle.alpha = undefined
if (val.indicatorValue !== undefined) {
view.value.customAttr.indicator = val.indicatorValue
}
}
view.value.customAttr.indicatorName = val.indicatorName
renderChart(view.value)
}

View File

@ -354,7 +354,7 @@ export const DEFAULT_TITLE_STYLE: ChartTextStyle = {
export const DEFAULT_INDICATOR_STYLE: ChartIndicatorStyle = {
show: true,
fontSize: '20',
color: '#5470C6',
color: '#5470C6ff',
hPosition: 'center',
vPosition: 'center',
isItalic: false,
@ -366,7 +366,7 @@ export const DEFAULT_INDICATOR_STYLE: ChartIndicatorStyle = {
suffixEnable: true,
suffix: '',
suffixFontSize: '14',
suffixColor: '#5470C6',
suffixColor: '#5470C6ff',
suffixIsItalic: false,
suffixIsBolder: true,
suffixFontFamily: 'Microsoft YaHei',
@ -376,7 +376,7 @@ export const DEFAULT_INDICATOR_STYLE: ChartIndicatorStyle = {
export const DEFAULT_INDICATOR_NAME_STYLE: ChartIndicatorNameStyle = {
show: true,
fontSize: '18',
color: '#ffffff',
color: '#ffffffff',
isItalic: false,
isBolder: true,
fontFamily: 'Microsoft YaHei',

View File

@ -319,13 +319,13 @@ function customCalcFunc(query, data, totalCfgMap) {
const result = minBy(data, n => {
return n[query[EXTRA_FIELD]]
})
return result[query[EXTRA_FIELD]]
return result?.[query[EXTRA_FIELD]]
}
case 'MAX': {
const result = maxBy(data, n => {
return n[query[EXTRA_FIELD]]
})
return result[query[EXTRA_FIELD]]
return result?.[query[EXTRA_FIELD]]
}
default: {
return data.reduce((p, n) => {

View File

@ -30,7 +30,7 @@
</div>
<div class="auth-root-class">
<el-button size="small" type="primary" @click="refresh">{{
<el-button size="small" type="primary" @click="refresh(pwdForm)">{{
t('pblink.sure_bt')
}}</el-button>
</div>
@ -71,20 +71,30 @@ const rule = reactive<FormRules>({
]
})
const refresh = () => {
const curLocation = window.location.href
const paramIndex = curLocation.indexOf('?')
const uuidIndex = curLocation.indexOf('de-link/') + 8
const uuid = curLocation.substring(uuidIndex, paramIndex !== -1 ? paramIndex : curLocation.length)
const pwd = form.value.password
const text = uuid + pwd
const ciphertext = rsaEncryp(text)
request.post({ url: '/share/validate', data: { ciphertext } }).then(res => {
if (res.data) {
wsCache.set(`link-${uuid}`, ciphertext)
window.location.reload()
const refresh = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
const curLocation = window.location.href
const paramIndex = curLocation.indexOf('?')
const uuidIndex = curLocation.indexOf('de-link/') + 8
const uuid = curLocation.substring(
uuidIndex,
paramIndex !== -1 ? paramIndex : curLocation.length
)
const pwd = form.value.password
const text = uuid + pwd
const ciphertext = rsaEncryp(text)
request.post({ url: '/share/validate', data: { ciphertext } }).then(res => {
if (res.data) {
wsCache.set(`link-${uuid}`, ciphertext)
window.location.reload()
} else {
msg.value = '密码错误'
}
})
} else {
msg.value = '密码错误'
console.error('error submit!', fields)
}
})
}

View File

@ -186,8 +186,13 @@ const enableSwitcher = () => {
}
const formatLinkAddr = () => {
const href = window.location.href
const prefix = href.substring(0, href.indexOf('#') + 1)
let prefix = '/'
if (window.DataEaseBi?.baseUrl) {
prefix = window.DataEaseBi.baseUrl + '#'
} else {
const href = window.location.href
prefix = href.substring(0, href.indexOf('#') + 1)
}
linkAddr.value = prefix + SHARE_BASE + state.detailInfo.uuid
}

View File

@ -190,8 +190,13 @@ const enableSwitcher = () => {
}
const formatLinkAddr = () => {
const href = window.location.href
const prefix = href.substring(0, href.indexOf('#') + 1)
let prefix = '/'
if (window.DataEaseBi?.baseUrl) {
prefix = window.DataEaseBi.baseUrl + '#'
} else {
const href = window.location.href
prefix = href.substring(0, href.indexOf('#') + 1)
}
linkAddr.value = prefix + SHARE_BASE + state.detailInfo.uuid
}

View File

@ -102,6 +102,15 @@ const closeLoading = () => {
const edit = list => {
state.settingList = list.map(item => {
const pkey = item.pkey
if (pkey === 'basic.logLiveTime') {
rule[pkey.split('.')[1]] = [
{
required: true,
message: t('common.require'),
trigger: ['blur', 'change']
}
]
}
item['label'] = `setting_${pkey}`
item['pkey'] = pkey.split('.')[1]
let pval = item.pval
@ -171,13 +180,26 @@ defineExpose({
v-model="state.form.frontTimeOut"
autocomplete="off"
step-strictly
class="text-left"
class="text-left edit-all-line"
:min="1"
:placeholder="t('common.inputText')"
controls-position="right"
type="number"
/>
</div>
<div v-else-if="item.pkey === 'logLiveTime'">
<el-input-number
v-model="state.form[item.pkey]"
autocomplete="off"
step-strictly
class="text-left edit-all-line"
:min="1"
:max="4000"
:placeholder="t('common.inputText')"
controls-position="right"
type="number"
/>
</div>
<v-else />
</el-form-item>
</el-form>
@ -215,6 +237,9 @@ defineExpose({
.is-error {
margin-bottom: 40px !important;
}
.edit-all-line {
width: 552px !important;
}
}
.setting-hidden-item {
display: none !important;

View File

@ -45,7 +45,6 @@ const search = cb => {
item.pval = item.pval
}
item.pkey = 'setting_' + item.pkey
console.log(item.pkey)
state.templateList.push(item)
}
cb && cb()

@ -1 +1 @@
Subproject commit 4889ffa0fcdfebe2755f5f1ce3b371e858abc981
Subproject commit 25c0bb1ec2569f54aed498da03732637cbdda727

View File

@ -1,43 +1,17 @@
#!/bin/bash
# chkconfig: 2345 10 90
# description: DATAEASE service
[Unit]
Description=DataEase Service
After=docker.service
Requires=docker.service
function startDATAEASE
{
dectl start
}
[Service]
User=root
Group=root
function stopDATAEASE
{
dectl stop
}
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/dectl start
ExecStop=/usr/bin/dectl stop
ExecReload=/usr/bin/dectl reload
function restartDATAEASE
{
stopDATAEASE
startDATAEASE
}
function statusDATAEASE
{
dectl status
}
export HOSTNAME=$HOSTNAME
case "$1" in
start)
startDATAEASE
;;
stop)
stopDATAEASE
;;
restart)
restartDATAEASE
;;
status)
statusDATAEASE
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
;;
esac
[Install]
WantedBy=multi-user.target

View File

@ -36,18 +36,20 @@ function usage() {
echo " ./dectl --help"
echo
echo "Commands: "
echo " status 查看 DATAEASE 服务运行状态"
echo " start 启动 DATAEASE 服务"
echo " stop 停止 DATAEASE 服务"
echo " restart 重启 DATAEASE 服务"
echo " reload 重新加载 DATAEASE 服务"
echo " upgrade 升级 DATAEASE 服务"
echo " clear-images 清理 DATAEASE 旧版本的相关镜像"
echo " version 查看 DATAEASE 版本"
echo " status 查看 DATAEASE 服务运行状态"
echo " start 启动 DATAEASE 服务"
echo " stop 停止 DATAEASE 服务"
echo " restart 重启 DATAEASE 服务"
echo " reload 重新加载 DATAEASE 服务"
echo " upgrade 升级 DATAEASE 服务"
echo " backup 备份 DATAEASE 服务"
echo " restore xxx.tar.gz 还原 DATAEASE 服务"
echo " clear-images 清理 DATAEASE 旧版本的相关镜像"
echo " version 查看 DATAEASE 版本"
}
function _generate_compose_file_args() {
if [[ $DE_INSTALL_MODE != "community" ]];then
compose_files="${compose_files} -f docker-compose-apisix.yml"
compose_files="${compose_files} -f docker-compose-apisix.yml -f docker-compose-task.yml"
fi
}
function _check_apisix_init() {
@ -55,14 +57,6 @@ function _check_apisix_init() {
_prepare_apisix
fi
}
function _check_task_init() {
if [[ $DE_INSTALL_MODE != "community" ]];then
_prepare_task
fi
}
function _prepare_task() {
compose_files="${compose_files} -f docker-compose-task.yml"
}
function _prepare_apisix() {
if [[ -z $DE_APISIX_KEY ]];then
need_init_apisix=true
@ -73,7 +67,6 @@ function _prepare_apisix() {
sed -i -e "s/DE_APISIX_KEY/${DE_APISIX_KEY}/g" $DE_RUNNING_BASE/apisix/apisix_conf/config.yaml
sed -i -e "s/DE_APISIX_KEY/${DE_APISIX_KEY}/g" $DE_RUNNING_BASE/conf/application.yml
fi
compose_files="${compose_files} -f docker-compose-apisix.yml"
}
function _init_apisix() {
DE_APISIX_KEY=$DE_APISIX_KEY sh $DE_RUNNING_BASE/bin/apisix/init.sh
@ -220,7 +213,7 @@ function status() {
function start() {
echo
_check_apisix_init
_check_task_init
_generate_compose_file_args
cd ${DE_RUNNING_BASE}
${compose_cmd} ${compose_files} up -d
_healthcheck
@ -284,7 +277,7 @@ function upgrade() {
exit 1
fi
tar zxvf $installer_file
tar zxf $installer_file
if [ $? != 0 ]; then
echo "下载在线安装包失败,请试试重新执行一次安装命令。"
rm -f $installer_file
@ -323,6 +316,33 @@ function clear_images() {
echo "清理完毕"
fi
}
function backup() {
backup_file_name=dataease-backup-$(date +%Y%m%d)_$(date +%H%M%S).tar.gz
tar --exclude=logs/dataease -zcf $backup_file_name -C $DE_RUNNING_BASE .
if [ $? -ne 0 ]; then
echo "备份失败"
exit 1
else
echo "备份成功,备份文件 : $backup_file_name"
fi
}
function restore() {
if [[ -z $target ]];then
echo "未指定需要恢复的备份文件!"
exit 1
elif [[ -f $target ]];then
service dataease stop
if [[ ! -d $DE_RUNNING_BASE ]];then
mkdir -p $DE_RUNNING_BASE
fi
echo "恢复备份 $target"
tar -zxf $target --directory=$DE_RUNNING_BASE
service dataease start
else
echo "未找到备份文件 $target"
exit 1
fi
}
function main() {
case "${action}" in
status)
@ -343,6 +363,12 @@ function main() {
upgrade)
upgrade
;;
backup)
backup
;;
restore)
restore $target
;;
clear-images)
clear_images
;;

View File

@ -5,6 +5,8 @@ CURRENT_DIR=$(
pwd
)
echo "$(date)" | tee -a ${CURRENT_DIR}/install.log
function log() {
message="[DATAEASE Log]: $1 "
echo -e "${message}" 2>&1 | tee -a ${CURRENT_DIR}/install.log
@ -28,7 +30,7 @@ if [ -f /usr/bin/dectl ]; then
fi
set -a
if [[ $DE_BASE ]] && [[ -f $DE_BASE/dataease2.0/.env ]]; then
if [[ -d $DE_BASE ]] && [[ -f $DE_BASE/dataease2.0/.env ]]; then
source $DE_BASE/dataease2.0/.env
INSTALL_TYPE='upgrade'
else
@ -48,7 +50,7 @@ DE_RUN_BASE=$DE_BASE/dataease2.0
conf_folder=${DE_RUN_BASE}/conf
templates_folder=${DE_RUN_BASE}/templates
if [[ $DE_RUN_BASE ]];then
if [[ -d $DE_RUN_BASE ]];then
for image in $(grep "image: " $DE_RUN_BASE/docker*.yml | awk -F 'image:' '{print $2}'); do
image_path=$(eval echo $image)
image_name=$(echo $image_path | awk -F "[/]" '{print $3}')
@ -102,9 +104,7 @@ if [ ! -f /usr/bin/dectl ]; then
ln -s /usr/local/bin/dectl /usr/bin/dectl 2>/dev/null
fi
echo "time: $(date)"
if which getenforce && [ $(getenforce) == "Enforcing" ];then
if which getenforce >/dev/null 2>&1 && [ $(getenforce) == "Enforcing" ];then
log "... 关闭 SELINUX"
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config
@ -115,14 +115,14 @@ fi
if which docker >/dev/null 2>&1; then
log "检测到 Docker 已安装,跳过安装步骤"
log "启动 Docker "
service docker start 2>&1 | tee -a ${CURRENT_DIR}/install.log
service docker start >/dev/null 2>&1 | tee -a ${CURRENT_DIR}/install.log
else
if [[ -d docker ]]; then
log "... 离线安装 docker"
cp docker/bin/* /usr/bin/
cp docker/service/docker.service /etc/systemd/system/
chmod +x /usr/bin/docker*
chmod 754 /etc/systemd/system/docker.service
chmod 644 /etc/systemd/system/docker.service
log "... 启动 docker"
systemctl enable docker; systemctl daemon-reload; service docker start 2>&1 | tee -a ${CURRENT_DIR}/install.log
else
@ -203,21 +203,20 @@ else
cd -
fi
log "配置 dataease Service"
cp ${DE_RUN_BASE}/bin/dataease/dataease.service /etc/init.d/dataease
chmod a+x /etc/init.d/dataease
if which chkconfig;then
chkconfig --add dataease
fi
if [ -f /etc/rc.d/rc.local ];then
dataeaseService=$(grep "service dataease start" /etc/rc.d/rc.local | wc -l)
if [ "$dataeaseService" -eq 0 ]; then
echo "sleep 10" >> /etc/rc.d/rc.local
echo "service dataease start" >> /etc/rc.d/rc.local
if which chkconfig >/dev/null 2>&1;then
chkconfig dataease >/dev/null
if [ $? -eq 0 ]; then
chkconfig --del dataease
fi
chmod +x /etc/rc.d/rc.local
fi
if [[ -f /etc/init.d/dataease ]];then
rm -f /etc/init.d/dataease
fi
log "配置 dataease Service"
cp ${DE_RUN_BASE}/bin/dataease/dataease.service /etc/systemd/system/
chmod 644 /etc/systemd/system/dataease.service
log "配置开机自启动"
systemctl enable dataease >/dev/null 2>&1; systemctl daemon-reload | tee -a ${CURRENT_DIR}/install.log
if [[ $(grep "vm.max_map_count" /etc/sysctl.conf | wc -l) -eq 0 ]];then
sysctl -w vm.max_map_count=2000000
@ -234,7 +233,7 @@ else
sed -i 's/^net\.ipv4\.ip_forward.*/net\.ipv4\.ip_forward=1/' /etc/sysctl.conf
fi
if which firewall-cmd >/dev/null; then
if which firewall-cmd >/dev/null 2>&1; then
if systemctl is-active firewalld &>/dev/null ;then
log "防火墙端口开放"
firewall-cmd --zone=public --add-port=${DE_PORT}/tcp --permanent
@ -251,12 +250,11 @@ if [[ $http_code == 200 ]];then
fi
log "启动服务"
dectl start | tee -a ${CURRENT_DIR}/install.log
dectl status 2>&1 | tee -a ${CURRENT_DIR}/install.log
systemctl start dataease 2>&1 | tee -a ${CURRENT_DIR}/install.log
access_port=$DE_PORT
if [[ $DE_INSTALL_MODE != "community" ]];then
access_port=9080
fi
echo -e "======================= 安装完成 =======================\n" 2>&1 | tee -a ${CURRENT_DIR}/install.log
echo -e "系统登录信息如下:\n 访问地址: http://服务器IP:$access_port\n 用户名: admin\n 初始密码: DataEase@123456" 2>&1 | tee -a ${CURRENT_DIR}/install.log
echo -e "系统登录信息如下:\n\t访问地址: http://服务器IP:$access_port\n\t用户名: admin\n\t初始密码: DataEase@123456" 2>&1 | tee -a ${CURRENT_DIR}/install.log

86
installer/quick_start.sh Normal file
View File

@ -0,0 +1,86 @@
if [[ -x "$(command -v python)" ]];then
py_cmd='python'
elif [[ -x "$(command -v python3)" ]]; then
py_cmd='python3'
fi
server_url="github.com"
echo -ne "检测 ${server_url} ... "
curl -m 5 -kIs https://${server_url} >/dev/null
if [ $? != 0 ];then
echo "failed"
echo "没有找到稳定的下载服务器,请稍候重试"
exit 1
else
echo "ok"
fi
rm -f /tmp/de_latest_release
$py_cmd - <<EOF
# -*- coding: UTF-8 -*-
import os
import json
import re
latest_release=""
release_pattern="v2\.\d+\.\d+$"
def get_releases(page):
try:
releases=os.popen("curl -s https://api.github.com/repos/dataease/dataease/releases?page=%d" % (page)).read()
releases=[ x["name"] for x in json.loads(releases) if x["prerelease"] == False ]
except Exception as e:
print(str(e))
print("Failed to obtain Release information, please check the network.")
exit(1)
else:
for release in releases:
if re.search(release_pattern,release) != None:
return release
page = 1
while (page <= 3):
latest_release = get_releases(page)
if (latest_release != "" and latest_release != None):
break
page += 1
if latest_release == None or latest_release == "":
print("Failed to obtain latest version, please try again.")
exit(1)
# 记录最新版本号
os.popen("echo "+latest_release+" > /tmp/de_latest_release")
EOF
if [ ! -f /tmp/de_latest_release ]; then
echo "获取最新版本失败,请检查网络连接是否正常"
exit 1
fi
latest_version=$(cat /tmp/de_latest_release)
echo "开始下载 DataEase ${latest_version} 版本在线安装包"
installer_file="dataease-online-installer-${latest_version}.tar.gz"
download_url="https://${server_url}/dataease/dataease/releases/download/${latest_version}/$installer_file"
echo "下载地址: ${download_url}"
curl -LOk -m 60 -o $installer_file $download_url
if [ ! -f ${installer_file} ];then
echo "下载在线安装包失败,请试试重新执行一次安装命令。"
exit 1
fi
tar zxvf ${installer_file}
if [ $? != 0 ];then
echo "下载在线安装包失败,请试试重新执行一次安装命令。"
rm -f ${installer_file}
exit 1
fi
cd ${installer_file%.tar.gz}
/bin/bash install.sh

View File

@ -2,6 +2,7 @@
DE_BASE=/opt
echo "如需备份 DataEase 数据,请执行 dectl backup 进行备份。如您的 dectl 命令不支持 backup 命令,请升级版本。"
read -r -p "即将卸载 DataEase 服务,包括删除运行目录、数据及相关镜像,是否继续? [Y/n] " input
case $input in
@ -18,14 +19,30 @@ case $input in
;;
esac
echo "停止 DataEase 服务"
service dataease stop >/dev/null 2>&1
echo "移除 DataEase 服务"
if which chkconfig >/dev/null 2>&1;then
chkconfig dataease >/dev/null
if [ $? -eq 0 ]; then
chkconfig --del dataease >/dev/null 2>&1
fi
fi
if [ -f /etc/systemd/system/dataease.service ];then
systemctl disable dataease >/dev/null 2>&1
rm -f /etc/systemd/system/dataease.service
systemctl daemon-reload
elif [[ -f /etc/init.d/dataease ]];then
rm -f /etc/init.d/dataease
fi
if [ -f /usr/bin/dectl ]; then
# 获取已安装的 DataEase 的运行目录
DE_BASE=$(grep "^DE_BASE=" /usr/bin/dectl | cut -d'=' -f2)
fi
echo "停止 DataEase 服务"
dectl stop
# 清理 DataEase 相关镜像
if test ! -z "$(docker images -f dangling=true -q)"; then
echo "清理虚悬镜像"
@ -38,4 +55,6 @@ if test -n "$(docker images | grep 'registry.cn-qingdao.aliyuncs.com/dataease')"
fi
# 清理 DataEase 运行目录及命令行工具 dectl
rm -rf ${DE_BASE}/dataease2.0 /usr/bin/dectl
rm -rf ${DE_BASE}/dataease2.0 /usr/bin/dectl
echo "DataEase 服务卸载完成"

View File

@ -25,7 +25,7 @@
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<h2.version>2.2.220</h2.version>
<knife4j.version>4.4.0</knife4j.version>
<calcite-core.version>1.35.2</calcite-core.version>
<calcite-core.version>1.35.3</calcite-core.version>
<commons-dbcp2.version>2.6.0</commons-dbcp2.version>
<antlr.version>3.5.2</antlr.version>
<java-jwt.version>3.12.1</java-jwt.version>

View File

@ -0,0 +1,37 @@
package io.dataease.api.dingtalk.api;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.api.dingtalk.dto.DingtalkEnableEditor;
import io.dataease.api.dingtalk.dto.DingtalkSettingCreator;
import io.dataease.api.dingtalk.dto.DingtalkTokenRequest;
import io.dataease.api.dingtalk.vo.DingtalkInfoVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@Tag(name = "钉钉设置")
@ApiSupport(order = 899)
public interface DingtalkApi {
@Operation(summary = "查询钉钉信息")
@GetMapping("/info")
DingtalkInfoVO info();
@Operation(summary = "保存")
@PostMapping("/create")
void save(@RequestBody DingtalkSettingCreator creator);
@Operation(summary = "钉钉token", hidden = true)
@PostMapping("/token")
String dingtalkToken(@RequestBody DingtalkTokenRequest request);
@Operation(summary = "切换开启状态")
@PostMapping("/switchEnable")
void switchEnable(@RequestBody DingtalkEnableEditor editor);
@Operation(summary = "验证可用性")
@PostMapping("/validate")
void validate(@RequestBody DingtalkSettingCreator creator);
}

View File

@ -0,0 +1,14 @@
package io.dataease.api.dingtalk.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Schema(description = "开启状态切换器")
@Data
public class DingtalkEnableEditor implements Serializable {
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
private boolean enable;
}

View File

@ -0,0 +1,23 @@
package io.dataease.api.dingtalk.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Schema(description = "钉钉设置构造器")
@Data
public class DingtalkSettingCreator implements Serializable {
@Schema(description = "agentId", requiredMode = Schema.RequiredMode.REQUIRED)
private String agentId;
@Schema(description = "appKey", requiredMode = Schema.RequiredMode.REQUIRED)
private String appKey;
@Schema(description = "appSecret", requiredMode = Schema.RequiredMode.REQUIRED)
private String appSecret;
@Schema(description = "回调域名", requiredMode = Schema.RequiredMode.REQUIRED)
private String callBack;
@Schema(description = "是否可用", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean enable;
@Schema(description = "是否有效")
private Boolean valid;
}

View File

@ -0,0 +1,13 @@
package io.dataease.api.dingtalk.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class DingtalkTokenRequest implements Serializable {
private String code;
private String state;
}

View File

@ -0,0 +1,24 @@
package io.dataease.api.dingtalk.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Schema(description = "钉钉信息")
@Data
public class DingtalkInfoVO implements Serializable {
@Schema(description = "agentId")
private String agentId;
@Schema(description = "appKey")
private String appKey;
@Schema(description = "appSecret")
private String appSecret;
@Schema(description = "回调域名")
private String callBack;
@Schema(description = "是否开启")
private Boolean enable = false;
@Schema(description = "是否可用")
private Boolean valid = false;
}

View File

@ -0,0 +1,37 @@
package io.dataease.api.wecom.api;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.api.wecom.dto.WecomCreator;
import io.dataease.api.wecom.dto.WecomEnableEditor;
import io.dataease.api.wecom.dto.WecomTokenRequest;
import io.dataease.api.wecom.vo.WecomInfoVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@Tag(name = "企微设置")
@ApiSupport(order = 899)
public interface WecomApi {
@Operation(summary = "查询企微信息")
@GetMapping("/info")
WecomInfoVO info();
@Operation(summary = "保存")
@PostMapping("/create")
void save(@RequestBody WecomCreator creator);
@Operation(summary = "企微token", hidden = true)
@PostMapping("/token")
String wecomToken(@RequestBody WecomTokenRequest request);
@Operation(summary = "切换开启状态")
@PostMapping("/switchEnable")
void switchEnable(@RequestBody WecomEnableEditor editor);
@Operation(summary = "验证可用性")
@PostMapping("/validate")
void validate(@RequestBody WecomCreator creator);
}

View File

@ -0,0 +1,22 @@
package io.dataease.api.wecom.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Data
public class WecomCreator implements Serializable {
@Schema(description = "corpId", requiredMode = Schema.RequiredMode.REQUIRED)
private String corpId;
@Schema(description = "agentId", requiredMode = Schema.RequiredMode.REQUIRED)
private String agentId;
@Schema(description = "appSecret", requiredMode = Schema.RequiredMode.REQUIRED)
private String appSecret;
@Schema(description = "回调域名", requiredMode = Schema.RequiredMode.REQUIRED)
private String callBack;
@Schema(description = "是否开启", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean enable = false;
@Schema(description = "是否可用", requiredMode = Schema.RequiredMode.REQUIRED)
private Boolean valid = false;
}

View File

@ -0,0 +1,14 @@
package io.dataease.api.wecom.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Schema(description = "开启状态切换器")
@Data
public class WecomEnableEditor implements Serializable {
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
private boolean enable;
}

View File

@ -0,0 +1,13 @@
package io.dataease.api.wecom.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class WecomTokenRequest implements Serializable {
private String code;
private String state;
}

View File

@ -0,0 +1,23 @@
package io.dataease.api.wecom.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
@Schema(description = "企微信息")
@Data
public class WecomInfoVO implements Serializable {
@Schema(description = "corpId")
private String corpId;
@Schema(description = "agentId")
private String agentId;
@Schema(description = "appSecret")
private String appSecret;
@Schema(description = "回调域名")
private String callBack;
@Schema(description = "是否开启")
private Boolean enable = false;
@Schema(description = "是否可用")
private Boolean valid = false;
}

View File

@ -12,6 +12,8 @@ public class OrgCreator implements Serializable {
@Serial
private static final long serialVersionUID = -4246980891732805368L;
private Long id;
@Schema(description = "组织名称")
private String name;
@Schema(description = "上级ID")

View File

@ -6,6 +6,7 @@ import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@ -22,4 +23,8 @@ public interface PerSettingApi {
@Operation(summary = "保存设置")
@PostMapping("/baisc/save")
void saveBasic(@RequestBody List<Object> settings);
@Hidden
@GetMapping("/baisc/single/{key}")
String singleValue(@PathVariable("key") String key);
}

View File

@ -26,11 +26,9 @@ import static io.dataease.constant.AuthResourceEnum.SYNC_DATASOURCE;
@DeApiPath(value = "/sync/datasource", rt = SYNC_DATASOURCE)
public interface SyncDatasourceApi {
@DePermit("m:read")
@PostMapping("/source/pager/{goPage}/{pageSize}")
IPage<SyncDatasourceVO> sourcePager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody BaseGridRequest request);
@DePermit("m:read")
@PostMapping("/target/pager/{goPage}/{pageSize}")
IPage<SyncDatasourceVO> targetPager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody BaseGridRequest request);
@ -52,7 +50,6 @@ public interface SyncDatasourceApi {
@PostMapping("/getSchema")
List<String> getSchema(@RequestBody SyncDatasourceDTO dataSourceDTO) throws DEException;
@DePermit({"#p0+':manage'"})
@GetMapping("/validate/{datasourceId}")
SyncDatasourceDTO validate(@PathVariable("datasourceId") String datasourceId) throws DEException;

View File

@ -17,9 +17,7 @@ public class GetDatasourceRequest extends SyncDatasourceDTO {
* 表格的抽取数据方式
*/
private boolean tableExtract;
/**
* 不为空时获取源数据库表字段将转换为doris的数据类型
*/
private String targetDbType;
private String targetDbId;
}

View File

@ -7,13 +7,13 @@ import io.dataease.auth.DeApiPath;
import io.dataease.request.BaseGridRequest;
import org.springframework.web.bind.annotation.*;
import static io.dataease.constant.AuthResourceEnum.TASK_LOG;
import static io.dataease.constant.AuthResourceEnum.TASK;
/**
* @author fit2cloud
* @date 2023/12/4 12:43
**/
@DeApiPath(value = "/sync/task/log", rt = TASK_LOG)
@DeApiPath(value = "/sync/task/log", rt = TASK)
public interface TaskLogApi {
@PostMapping("/pager/{goPage}/{pageSize}")
IPage<TaskLogVO> pager(@PathVariable("goPage") int goPage, @PathVariable("pageSize") int pageSize, @RequestBody BaseGridRequest request);

View File

@ -2,7 +2,7 @@ package io.dataease.constant;
public enum AuthResourceEnum {
PANEL(2, 1), SCREEN(3, 2), DATASET(5, 3), DATASOURCE(6, 4), SYSTEM(7, 0), USER(8, 5), ROLE(8, 6), ORG(9, 7), SYNC_DATASOURCE(10, 8), TASK(11, 9),TASK_LOG(12, 10), SUMMARY(13, 11);
PANEL(2, 1), SCREEN(3, 2), DATASET(5, 3), DATASOURCE(6, 4), SYSTEM(7, 0), USER(8, 5), ROLE(8, 6), ORG(9, 7), SYNC_DATASOURCE(23, 8), TASK(24, 9), SUMMARY(22, 10);
private long menuId;

View File

@ -3,5 +3,6 @@ package io.dataease.constant;
public class XpackSettingConstants {
public static final String AUTO_CREATE_USER = "basic.autoCreateUser";
public static final String LOG_LIVE_TIME = "basic.logLiveTime";
public static final String Front_Time_Out = "basic.frontTimeOut";
}

View File

@ -8,7 +8,7 @@ public class SystemSettingUtils {
public static boolean xpackSetting(String pkey) {
List<String> xpackSettingList = List.of(XpackSettingConstants.AUTO_CREATE_USER);
List<String> xpackSettingList = List.of(XpackSettingConstants.AUTO_CREATE_USER, XpackSettingConstants.LOG_LIVE_TIME);
return xpackSettingList.contains(pkey);
}
}

View File

@ -2,11 +2,23 @@ package io.dataease.utils;
import io.dataease.constant.AuthConstant;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;
import java.util.List;
import java.util.Objects;
public class WhitelistUtils {
private static String contextPath;
public static String getContextPath() {
if (StringUtils.isBlank(contextPath)) {
contextPath = Objects.requireNonNull(CommonBeanFactory.getBean(Environment.class)).getProperty("server.servlet.context-path", String.class);
}
return contextPath;
}
public static List<String> WHITE_PATH = List.of(
"/login/localLogin",
"/apisix/check",
@ -18,11 +30,16 @@ public class WhitelistUtils {
"/panel.html",
"/lark/info",
"/lark/token",
"/dingtalk/info",
"/dingtalk/token",
"/sysParameter/requestTimeOut",
"/setting/authentication/status",
"/");
public static boolean match(String requestURI) {
if (StringUtils.startsWith(requestURI, getContextPath())) {
requestURI = requestURI.replaceFirst(getContextPath(), "");
}
if (StringUtils.startsWith(requestURI, AuthConstant.DE_API_PREFIX)) {
requestURI = requestURI.replaceFirst(AuthConstant.DE_API_PREFIX, "");
}