diff --git a/README.md b/README.md index 3c293c2ac4..7c521a4cd2 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ DataEase 是开源的数据可视化分析工具,帮助用户快速分析数 - MongoDB - Amazon Redshift - Hive +- DB2 > 更多数据源支持持续增加中... diff --git a/backend/src/main/java/io/dataease/controller/wizard/ReptileController.java b/backend/src/main/java/io/dataease/controller/wizard/ReptileController.java index 56f01e09b0..3fb4b2cd80 100644 --- a/backend/src/main/java/io/dataease/controller/wizard/ReptileController.java +++ b/backend/src/main/java/io/dataease/controller/wizard/ReptileController.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; +import java.util.List; import java.util.Map; @Api(tags = "首页") @@ -24,7 +25,7 @@ public class ReptileController { @GetMapping("lastActive") @ApiOperation("获取官方Blog最新动态") - public Map lastActive() { + public List lastActive() { return reptileService.lastActive(); } } diff --git a/backend/src/main/java/io/dataease/service/wizard/ReptileService.java b/backend/src/main/java/io/dataease/service/wizard/ReptileService.java index 2530f7d287..a8c8de74dc 100644 --- a/backend/src/main/java/io/dataease/service/wizard/ReptileService.java +++ b/backend/src/main/java/io/dataease/service/wizard/ReptileService.java @@ -7,8 +7,7 @@ import org.jsoup.nodes.Element; import org.jsoup.select.Elements; import org.springframework.stereotype.Service; -import java.util.HashMap; -import java.util.Map; +import java.util.*; /** * Author: wangjiahao @@ -18,27 +17,33 @@ import java.util.Map; @Service public class ReptileService { String blogUrl = "https://blog.fit2cloud.com/?cat=321"; + //获取最新的前几条数据 + private static int infoCount=1; - public Map lastActive() { - Map result = new HashMap(); + public List lastActive() { + List result = new ArrayList(); try { //爬取最新数据 Document doc = Jsoup.parse(HttpClientUtil.get(blogUrl, null)); Elements elementsContent = doc.getElementsByAttributeValue("rel", "bookmark"); Elements elementsTime = doc.getElementsByTag("time"); - Element lastInfo = elementsContent.get(0); - result.put("title",lastInfo.attr("title")); - result.put("href",lastInfo.attr("href")); - result.put("time",elementsTime.get(0).childNode(0).outerHtml()); + for(int i = 0;i infoMap = new HashMap(); + infoMap.put("title",info.attr("title")); + infoMap.put("href",info.attr("href")); + infoMap.put("time",elementsTime.get(i).childNode(0).outerHtml()); + result.add(infoMap); + } } catch (Exception e) { //ignore - result.put("title","支持移动端展示,数据源新增对DB2的支持,DataEase开源数据可视化分析平台v1.6.0发布"); - result.put("href","https://blog.fit2cloud.com/?p=3200"); - result.put("time","2022年1月10日"); + Map infoMap = new HashMap(); + infoMap.put("title","支持移动端展示,数据源新增对DB2的支持,DataEase开源数据可视化分析平台v1.6.0发布"); + infoMap.put("href","https://blog.fit2cloud.com/?p=3200"); + infoMap.put("time","2022年1月10日"); + result.add(infoMap); } - return result; - } diff --git a/frontend/src/assets/DataEase-0.jpg b/frontend/src/assets/DataEase-0.jpg new file mode 100644 index 0000000000..9e9795332e Binary files /dev/null and b/frontend/src/assets/DataEase-0.jpg differ diff --git a/frontend/src/assets/DataEase-1.jpg b/frontend/src/assets/DataEase-1.jpg new file mode 100644 index 0000000000..0cdc743d6b Binary files /dev/null and b/frontend/src/assets/DataEase-1.jpg differ diff --git a/frontend/src/assets/DataEase-2.jpg b/frontend/src/assets/DataEase-2.jpg new file mode 100644 index 0000000000..46c9ac5281 Binary files /dev/null and b/frontend/src/assets/DataEase-2.jpg differ diff --git a/frontend/src/assets/DataEase-3.jpg b/frontend/src/assets/DataEase-3.jpg new file mode 100644 index 0000000000..5a1078e153 Binary files /dev/null and b/frontend/src/assets/DataEase-3.jpg differ diff --git a/frontend/src/assets/DataEase-4.jpg b/frontend/src/assets/DataEase-4.jpg new file mode 100644 index 0000000000..55163d03f9 Binary files /dev/null and b/frontend/src/assets/DataEase-4.jpg differ diff --git a/frontend/src/assets/DataEase-5.jpg b/frontend/src/assets/DataEase-5.jpg new file mode 100644 index 0000000000..1fe04aa014 Binary files /dev/null and b/frontend/src/assets/DataEase-5.jpg differ diff --git a/frontend/src/assets/banner.png b/frontend/src/assets/banner.png new file mode 100644 index 0000000000..1dd1951cd2 Binary files /dev/null and b/frontend/src/assets/banner.png differ diff --git a/frontend/src/components/canvas/custom-component/UserView.vue b/frontend/src/components/canvas/custom-component/UserView.vue index 84f71aafa7..0ae214b946 100644 --- a/frontend/src/components/canvas/custom-component/UserView.vue +++ b/frontend/src/components/canvas/custom-component/UserView.vue @@ -118,9 +118,10 @@ export default { }, data() { return { + filterInit: false, // 标记是否已经通过watch.filters 进行初始化,如果filterInit=true 则create放弃数据初始化防止数据覆盖 refId: null, chart: BASE_CHART_STRING, - requestStatus: 'waiting', + requestStatus: 'success', message: null, drillClickDimensionList: [], drillFilters: [], @@ -242,7 +243,10 @@ export default { watch: { 'filters': function(val1, val2) { - isChange(val1, val2) && this.getData(this.element.propValue.viewId) + if (isChange(val1, val2)) { + this.filterInit = true + this.getData(this.element.propValue.viewId) + } }, linkageFilters: { handler(newVal, oldVal) { @@ -313,8 +317,8 @@ export default { created() { this.refId = uuid.v1 if (this.element && this.element.propValue && this.element.propValue.viewId) { - const hasFilter = this.componentData.filter(item => item.type === 'custom').some(item => item.options.value && !(item.options.value instanceof Object) || (item.options.attrs && item.options.attrs.default && item.options.attrs.default.isDynamic)) - if (!hasFilter || this.filters.length > 0) { this.getData(this.element.propValue.viewId, false) } + // 如果watch.filters 已经进行数据初始化时候,此处放弃数据初始化 + !this.filterInit && this.getData(this.element.propValue.viewId, false) } }, methods: { diff --git a/frontend/src/lang/en.js b/frontend/src/lang/en.js index fbe407abdf..74d9debbe4 100644 --- a/frontend/src/lang/en.js +++ b/frontend/src/lang/en.js @@ -1269,6 +1269,9 @@ export default { get_schema: 'Get Schema', schema: 'Database Schema', please_choose_schema: 'Please select Schema', + edit_datasource_msg: 'Modifying the data source information may make the data set under the modified data source unavailable. Confirm the modification?', + repeat_datasource_msg: 'Data source information with the same configuration already exists, ', + confirm_save: 'Confirm save?', in_valid: 'Invalid datasource', initial_pool_size: 'Initial connections', min_pool_size: 'Minimum of connections', @@ -1500,7 +1503,10 @@ export default { timeout_refresh: 'Timeout,Will Refresh...', mobile_layout: 'Mobile Layout', component_hidden: 'Component Hidden', - public_link_tips: 'New Is Public Link,The Target Panel Have Not Set Public Link,Can Not Jump' + public_link_tips: 'New Is Public Link,The Target Panel Have Not Set Public Link,Can Not Jump', + input_title: 'Input Title', + show_title: 'Show Title', + default_settings: 'Default Settings' }, plugin: { local_install: 'Local installation', @@ -1815,6 +1821,9 @@ export default { open_source_community: 'Open source community', click_show: 'Click To View', show_more: 'Show More', - click_inner: 'Click To Enter' + click_inner: 'Click To Enter', + email: 'Email:', + tel: 'Tel:', + web: 'Web:' } } diff --git a/frontend/src/lang/index.js b/frontend/src/lang/index.js index d77d9fa6ec..d7c16dfb3b 100644 --- a/frontend/src/lang/index.js +++ b/frontend/src/lang/index.js @@ -13,6 +13,8 @@ import fuZh from 'fit2cloud-ui/src/locale/lang/zh-CN' // 加载fit2cloud的内 import fuEn from 'fit2cloud-ui/src/locale/lang/en_US' // 加载fit2cloud的内容 +import fuTW from 'fit2cloud-ui/src/locale/lang/zh-TW' // 加载fit2cloud的内容 + Vue.use(VueI18n) const messages = { @@ -28,7 +30,8 @@ const messages = { }, zh_TW: { ...twLocale, - ...elementTWLocale + ...elementTWLocale, + ...fuTW } } export function getLanguage() { diff --git a/frontend/src/lang/tw.js b/frontend/src/lang/tw.js index 72e5569ddd..6844cb175d 100644 --- a/frontend/src/lang/tw.js +++ b/frontend/src/lang/tw.js @@ -1271,6 +1271,8 @@ export default { schema: '數據庫 Schema', please_choose_schema: '請選擇數據庫 Schema', edit_datasource_msg: '修改數據源信息,可能會導致改數據源下的數據集不可用,確認修改?', + repeat_datasource_msg: '已經存在相同配置的數據源信息,', + confirm_save: '確認保存?', in_valid: '無效數據源', initial_pool_size: '初始連接數', min_pool_size: '最小連接數', @@ -1502,7 +1504,10 @@ export default { timeout_refresh: '請求超時,稍後刷新...', mobile_layout: '移動端佈局', component_hidden: '隱藏的組件', - public_link_tips: '當前是公共鏈接模式,目標儀錶闆未設置公共鏈接,無法跳轉' + public_link_tips: '當前是公共鏈接模式,目標儀錶闆未設置公共鏈接,無法跳轉', + input_title: '請輸入標題', + show_title: '顯示標題', + default_settings: '默認值設置' }, plugin: { local_install: '本地安裝', @@ -1825,6 +1830,9 @@ export default { open_source_community: '開源社區', click_show: '點擊查看', show_more: '查看更多', - click_inner: '點擊進入' + click_inner: '點擊進入', + email: '邮箱:', + tel: '电话:', + web: '网址:' } } diff --git a/frontend/src/lang/zh.js b/frontend/src/lang/zh.js index a758f900f4..593f16ffec 100644 --- a/frontend/src/lang/zh.js +++ b/frontend/src/lang/zh.js @@ -1275,6 +1275,8 @@ export default { schema: '数据库 Schema', please_choose_schema: '请选择数据库 Schema', edit_datasource_msg: '修改数据源信息,可能会导致该数据源下的数据集不可用,确认修改?', + repeat_datasource_msg: '已经存在相同配置的数据源信息, ', + confirm_save: '确认保存?', in_valid: '无效数据源', initial_pool_size: '初始连接数', min_pool_size: '最小连接数', @@ -1511,7 +1513,10 @@ export default { timeout_refresh: '请求超时,稍后刷新...', mobile_layout: '移动端布局', component_hidden: '隐藏的组件', - public_link_tips: '当前是公共链接模式,目标仪表板未设置公共链接,无法跳转' + public_link_tips: '当前是公共链接模式,目标仪表板未设置公共链接,无法跳转', + input_title: '请输入标题', + show_title: '显示标题', + default_settings: '默认值设置' }, plugin: { local_install: '本地安装', @@ -1835,6 +1840,8 @@ export default { open_source_community: '开源社区', click_show: '点击查看', show_more: '查看更多', - click_inner: '点击进入' + email: '邮箱:', + tel: '电话:', + web: '网址:' } } diff --git a/frontend/src/views/panel/filter/filterMain/FilterControl.vue b/frontend/src/views/panel/filter/filterMain/FilterControl.vue index 0560e88138..3649a871ff 100644 --- a/frontend/src/views/panel/filter/filterMain/FilterControl.vue +++ b/frontend/src/views/panel/filter/filterMain/FilterControl.vue @@ -14,11 +14,11 @@
- 显示标题 + {{ $t('panel.show_title') }}
- +
- @@ -25,7 +25,8 @@ export default { return { component: DataHome, datasource: {}, - param: null + param: null, + tData: null } }, computed: {}, @@ -36,7 +37,8 @@ export default { methods: { // 切换main区内容 switchMain(param) { - const {component, componentParam} = param + console.log(param) + const {component, componentParam, tData} = param this.component = DataHome this.param = null this.$nextTick(() => { @@ -44,6 +46,7 @@ export default { case 'DsForm': this.component = DsForm this.param = componentParam + this.tData = tData break default: this.component = DataHome diff --git a/frontend/src/views/system/datasource/DsTree.vue b/frontend/src/views/system/datasource/DsTree.vue index 4ac6672f37..11151b86ff 100644 --- a/frontend/src/views/system/datasource/DsTree.vue +++ b/frontend/src/views/system/datasource/DsTree.vue @@ -216,10 +216,10 @@ export default { }, addFolder() { - this.switchMain('DsForm') + this.switchMain('DsForm', {}, this.tData) }, addFolderWithType(data) { - this.switchMain('DsForm', {type: data.id}) + this.switchMain('DsForm', {type: data.id}, this.tData) }, nodeClick(node, data) { if (node.type === 'folder') return @@ -243,11 +243,11 @@ export default { return {optType, data, node} }, edit(row) { - this.switchMain('DsForm', row) + this.switchMain('DsForm', row, this.tData) }, showInfo(row) { const param = {...row.data, ...{showModel: 'show'}} - this.switchMain('DsForm', param) + this.switchMain('DsForm', param, this.tData) }, _handleDelete(datasource) { this.$confirm(this.$t('datasource.delete_warning'), '', { @@ -257,7 +257,7 @@ export default { }).then(() => { delDs(datasource.id).then(res => { this.$success(this.$t('commons.delete_success')) - this.switchMain('DataHome') + this.switchMain('DataHome', {}, this.tData) this.refreshType(datasource) }) }).catch(() => { @@ -267,10 +267,12 @@ export default { }) }) }, - switchMain(component, componentParam) { + switchMain(component, componentParam, tData) { + console.log(tData) this.$emit('switch-main', { component, - componentParam + componentParam, + tData }) }, markInvalid(msgParam) { diff --git a/frontend/src/views/system/datasource/form.vue b/frontend/src/views/system/datasource/form.vue index 25564095dc..616a40343d 100644 --- a/frontend/src/views/system/datasource/form.vue +++ b/frontend/src/views/system/datasource/form.vue @@ -192,6 +192,10 @@ export default { params: { type: Object, default: null + }, + tData: { + type: Array, + default: null } }, data() { @@ -346,29 +350,81 @@ export default { this.$message.error(i18n.t('datasource.no_less_then_0')) return } + let repeat = false + let repeatDsName = '' + this.tData.forEach(item => { + if(item.id === this.form.type){ + item.children.forEach(child => { + let configuration = JSON.parse(child.configuration) + switch (this.form.type) { + case 'mysql': + case 'hive': + case 'mariadb': + case 'ds_doris': + case 'ck': + case 'mongo': + case 'mariadb': + if(configuration.host == this.form.configuration.host && configuration.dataBase == this.form.configuration.dataBase && configuration.port == this.form.configuration.port){ + repeat = true + repeatDsName = child.name + } + break + case 'pg': + case 'sqlServer': + case 'redshift': + case 'oracle': + case 'db2': + if(configuration.host == this.form.configuration.host && configuration.dataBase == this.form.configuration.dataBase && configuration.port == this.form.configuration.port && configuration.schema == this.form.configuration.schema){ + repeat = true + } + break + case 'es': + if(configuration.url == this.form.configuration.url){ + repeat = true + } + break + default: + break + } + }) + } + }) + this.$refs.dsForm.validate(valid => { - if (valid) { - const method = this.formType === 'add' ? addDs : editDs - const form = JSON.parse(JSON.stringify(this.form)) - form.configuration = JSON.stringify(form.configuration) - if (this.formType !== 'add' && this.originConfiguration !== form.configuration) { - $confirm(i18n.t('datasource.edit_datasource_msg'), () => { - method(form).then(res => { - this.$success(i18n.t('commons.save_success')) - this.refreshType(form) - this.backToList() - }) - }) - } else { - method(form).then(res => { - this.$success(i18n.t('commons.save_success')) - this.refreshType(form) - this.backToList() - }) - } - } else { + if (!valid) { return false } + const method = this.formType === 'add' ? addDs : editDs + const form = JSON.parse(JSON.stringify(this.form)) + form.configuration = JSON.stringify(form.configuration) + if (this.formType === 'modify' && this.originConfiguration !== form.configuration) { + if(repeat){ + $confirm(i18n.t('datasource.repeat_datasource_msg') + '[' + repeatDsName + '], ' + i18n.t('datasource.confirm_save'), () => { + $confirm(i18n.t('datasource.edit_datasource_msg'), () => { + this.method(method, form) + }) + }) + }else { + $confirm(i18n.t('datasource.edit_datasource_msg'), () => { + this.method(method, form) + }) + } + return + } + if(repeat){ + $confirm(i18n.t('datasource.repeat_datasource_msg') + '[' + repeatDsName + '], ' + i18n.t('datasource.confirm_save'), () => { + this.method(method, form) + }) + }else { + this.method(method, form) + } + }) + }, + method(method, form){ + method(form).then(res => { + this.$success(i18n.t('commons.save_success')) + this.refreshType(form) + this.backToList() }) }, getSchema() { diff --git a/frontend/src/views/wizard/card.vue b/frontend/src/views/wizard/card.vue index 1e1842a395..d5d81bd750 100644 --- a/frontend/src/views/wizard/card.vue +++ b/frontend/src/views/wizard/card.vue @@ -54,7 +54,7 @@ export default { border: lightgray solid 1px; border-radius: 0px 5px 5px 5px; height: 100%; - overflow: hidden; + overflow-y: auto; } diff --git a/frontend/src/views/wizard/details/CardDetail.vue b/frontend/src/views/wizard/details/CardDetail.vue new file mode 100644 index 0000000000..3e327642a5 --- /dev/null +++ b/frontend/src/views/wizard/details/CardDetail.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/frontend/src/views/wizard/details/LatestDevelopments.vue b/frontend/src/views/wizard/details/LatestDevelopments.vue index fb62518076..3e1d05d21d 100644 --- a/frontend/src/views/wizard/details/LatestDevelopments.vue +++ b/frontend/src/views/wizard/details/LatestDevelopments.vue @@ -1,13 +1,26 @@ @@ -16,13 +29,25 @@ import { blogLastActive } from '@/api/wizard/wizard' export default { - name: 'LatestDevelopments', + name: 'CardDetail', + props: { + imgIndex: { + type: Number, + required: true + }, + details: { + type: Object, + required: true + } + }, data() { return { - title: '', - href: '', - time: '' + blogsInfo: {}, + imgSrc: '../../../assets/DataEase-' + this.imgIndex + '.jpg' } + }, + computed: { + }, mounted() { this.init() @@ -30,9 +55,7 @@ export default { methods: { init() { blogLastActive().then(res => { - this.title = res.data.title - this.href = res.data.href - this.time = res.data.time + this.blogsInfo = res.data[0] }) } } @@ -43,23 +66,37 @@ export default { diff --git a/frontend/src/views/wizard/details/LatestDevelopmentsBack.vue b/frontend/src/views/wizard/details/LatestDevelopmentsBack.vue new file mode 100644 index 0000000000..1778310334 --- /dev/null +++ b/frontend/src/views/wizard/details/LatestDevelopmentsBack.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/frontend/src/views/wizard/index.vue b/frontend/src/views/wizard/index.vue index d2b00b6999..1a3824dfb6 100644 --- a/frontend/src/views/wizard/index.vue +++ b/frontend/src/views/wizard/index.vue @@ -5,9 +5,9 @@ {{ $t('wizard.welcome_hint') }} - - - + + + @@ -21,38 +21,72 @@ import LatestDevelopments from '@/views/wizard/details/LatestDevelopments' import TeachingVideo from '@/views/wizard/details/TeachingVideo' import EnterpriseEdition from '@/views/wizard/details/EnterpriseEdition' import ContactUs from '@/views/wizard/details/ContactUs' +import InfoCard from '@/views/wizard/infoCard' +import CardDetail from '@/views/wizard/details/CardDetail' +import { blogLastActive } from '@/api/wizard/wizard' + export default { name: 'Wizard', - components: { Card, DemoVideo, OnlineDocument, LatestDevelopments, TeachingVideo, EnterpriseEdition, ContactUs }, + components: { InfoCard, Card, DemoVideo, OnlineDocument, LatestDevelopments, TeachingVideo, EnterpriseEdition, ContactUs, CardDetail }, data() { return { cardList: [ { - headInfo: this.$t('wizard.demo_video'), - component: 'DemoVideo' + head: this.$t('wizard.demo_video'), + content: this.$t('wizard.demo_video_hint'), + bottom: '', + href: 'https://www.bilibili.com/video/BV1UB4y1K7jA', + component: 'CardDetail' }, { - headInfo: this.$t('wizard.online_document'), - component: 'OnlineDocument' + head: this.$t('wizard.online_document'), + content: this.$t('wizard.online_document_hint'), + bottom: '', + href: 'https://dataease.io/docs/dev_manual/dev_manual/', + component: 'CardDetail' }, { - headInfo: this.$t('wizard.latest_developments'), - component: 'LatestDevelopments' + head: this.$t('wizard.latest_developments'), + content: '', + bottom: '', + href: 'https://blog.fit2cloud.com/?cat=321', + component: 'CardDetail' }, { - headInfo: this.$t('wizard.teaching_video'), - component: 'TeachingVideo' + head: this.$t('wizard.teaching_video'), + content: '40分钟带你玩转 DataEase
用DataEase开源工具可视化 ClickHouse数据', + bottom: '', + href: 'https://e.vhall.com/v3/user/home/45637107', + component: 'CardDetail' }, { - headInfo: this.$t('wizard.enterprise_edition'), - component: 'EnterpriseEdition' + head: this.$t('wizard.enterprise_edition'), + content: this.$t('wizard.enterprise_edition_hint1') + '
' + this.$t('wizard.enterprise_edition_hint2') + '
' + this.$t('wizard.enterprise_edition_hint3'), + bottom: '', + href: 'https://jinshuju.net/f/TK5TTd', + component: 'CardDetail' }, { - headInfo: this.$t('wizard.contact_us'), - component: 'ContactUs' + head: this.$t('wizard.contact_us'), + content: this.$t('wizard.email') + 'dataease@fit2cloud.com
' + this.$t('wizard.tel') + '400-052-0755
' + this.$t('wizard.web') + 'www.dataease.io', + bottom: '', + href: 'https://www.dataease.io', + component: 'CardDetail' } ] } + }, + created() { + this.init() + }, + methods: { + init() { + blogLastActive().then(res => { + const blogsInfo = res.data[0] + this.cardList[2].content = blogsInfo.title + this.cardList[2].bottom = blogsInfo.time + }) + } } } @@ -62,23 +96,25 @@ export default { .main_container { } .head { - background-color: var(--MenuActiveBG, #409EFF); text-align: center; color: white; padding: 10px; - margin-top: 25px; + margin-top: 35px; + background-size: 100% 100% !important; + background-image: url('../../assets/banner.png'); } .hint_head { - line-height: 40px; + line-height: 50px; font-weight: bold; font-size: 25px; } .hint_content { - line-height: 40px; + line-height: 50px; font-size: 15px; } .card_container { + vertical-align: middle; } diff --git a/frontend/src/views/wizard/infoCard.vue b/frontend/src/views/wizard/infoCard.vue new file mode 100644 index 0000000000..ccecdbb681 --- /dev/null +++ b/frontend/src/views/wizard/infoCard.vue @@ -0,0 +1,36 @@ + + + + +