Merge branch 'dev' into pr@dev@refactor_filter_default_value

This commit is contained in:
fit2cloud-chenyw
2021-12-16 18:19:51 +08:00
committed by GitHub
75 changed files with 3386 additions and 1903 deletions

View File

@@ -173,4 +173,13 @@ export function datasetTaskList(page, size, data, loading) {
})
}
export function datasetRowPermissionsList(datasetId, page, size, data, loading) {
return request({
url: '/dataset/rowpermissions/pageList/' + datasetId + '/' + page + '/' + size,
method: 'post',
data,
loading: loading
})
}
export default { loadTable, getScene, addGroup, delGroup, addTable, delTable, groupTree }

View File

@@ -9,6 +9,7 @@
[classNameResizable]: resizable,
[classNameRotating]: rotating,
[classNameRotatable]: rotatable,
[classNameActive]: enabled ,
['linkageSetting']:linkageActive,
['positionChange']:!(dragging || resizing||rotating)
},
@@ -22,7 +23,7 @@
<div
:class="[
{
[classNameActive]: enabled ,
['de-drag-active-inner']:enabled,
[classNameMouseOn]: mouseOn || active
},
className
@@ -1809,7 +1810,10 @@ export default {
}
.de-drag-active{
outline: 1px solid #70c0ff;
user-select: none;
}
.de-drag-active-inner{
outline: 1px solid #70c0ff;
}
</style>

View File

@@ -0,0 +1,59 @@
<template>
<div class="bar-main">
<div style="margin-right: -1px;width: 18px">
<i class="icon iconfont icon-guanbi" @click.stop="closePreview" />
</div>
</div>
</template>
<script>
import { mapState } from 'vuex'
import bus from '@/utils/bus'
import SettingMenu from '@/components/canvas/components/Editor/SettingMenu'
import LinkageField from '@/components/canvas/components/Editor/LinkageField'
export default {
components: { },
props: {
},
data() {
return {
}
},
computed: {
},
mounted() {
},
beforeDestroy() {
},
methods: {
closePreview() {
this.$emit('closePreview')
}
}
}
</script>
<style lang="scss" scoped>
.bar-main{
position: absolute;
right: 0px;
float:right;
z-index: 2;
border-radius:2px;
padding-left: 5px;
padding-right: 2px;
cursor:pointer!important;
background-color: #0a7be0;
}
.bar-main i{
color: white;
float: right;
margin-right: 3px;
}
</style>

View File

@@ -5,7 +5,8 @@
@click="handleClick"
@mousedown="elementMouseDown"
>
<edit-bar v-if="editBarShow" :element="config" @showViewDetails="showViewDetails" />
<edit-bar v-if="componentActiveFlag" :element="config" @showViewDetails="showViewDetails" />
<close-bar v-if="previewVisible" @closePreview="closePreview" />
<de-out-widget
v-if="config.type==='custom'"
:id="'component' + config.id"
@@ -14,6 +15,7 @@
:out-style="config.style"
:element="config"
:in-screen="inScreen"
:h="config.style.height"
/>
<component
:is="config.component"
@@ -23,6 +25,7 @@
:style="getComponentStyleDefault(config.style)"
:prop-value="config.propValue"
:is-edit="false"
:active="componentActiveFlag"
:element="config"
:search-count="searchCount"
:h="config.style.height"
@@ -39,9 +42,10 @@ import { mapState } from 'vuex'
import DeOutWidget from '@/components/dataease/DeOutWidget'
import EditBar from '@/components/canvas/components/Editor/EditBar'
import MobileCheckBar from '@/components/canvas/components/Editor/MobileCheckBar'
import CloseBar from '@/components/canvas/components/Editor/CloseBar'
export default {
components: { MobileCheckBar, DeOutWidget, EditBar },
components: { CloseBar, MobileCheckBar, DeOutWidget, EditBar },
mixins: [mixins],
props: {
config: {
@@ -63,11 +67,20 @@ export default {
type: Boolean,
required: false,
default: true
},
terminal: {
type: String,
default: 'pc'
}
},
data() {
return {
previewVisible: false
}
},
computed: {
editBarShow() {
return this.curComponent && this.config === this.curComponent
componentActiveFlag() {
return (this.curComponent && this.config === this.curComponent) && !this.previewVisible
},
curGap() {
return this.config.auxiliaryMatrix ? this.componentGap : 0
@@ -155,7 +168,14 @@ export default {
this.$store.commit('setCurComponent', { component: this.config, index: this.index })
},
showViewDetails() {
this.$refs.wrapperChild.openChartDetailsDialog()
if (this.terminal === 'pc') {
this.$refs.wrapperChild.openChartDetailsDialog()
} else {
this.previewVisible = true
}
},
closePreview() {
this.previewVisible = false
}
}
}

View File

@@ -1,10 +1,10 @@
<template>
<div class="bar-main">
<div v-if="linkageSettingStatus&&element!==curLinkageView&&element.type==='view'" style="margin-right: -1px;width: 18px">
<div v-if="linkageAreaShow" style="margin-right: -1px;width: 18px">
<el-checkbox v-model="linkageInfo.linkageActive" />
<linkage-field v-if="linkageInfo.linkageActive" :element="element" />
</div>
<div v-else-if="!linkageSettingStatus">
<div v-if="normalAreaShow">
<setting-menu v-if="activeModel==='edit'" style="float: right;height: 24px!important;" @amRemoveItem="amRemoveItem" @linkJumpSet="linkJumpSet">
<span slot="icon" :title="$t('panel.setting')">
<i class="icon iconfont icon-shezhi" style="margin-top:2px" />
@@ -26,7 +26,6 @@
<i v-if="curComponent.type==='view'&&existLinkage" class="icon iconfont icon-quxiaoliandong" @click.stop="clearLinkage" />
</span>
</div>
</div>
</template>
@@ -54,6 +53,10 @@ export default {
type: String,
required: false,
default: 'preview'
},
previewVisible: {
type: Boolean,
default: false
}
},
data() {
@@ -70,6 +73,14 @@ export default {
mounted() {
},
computed: {
// 联动区域按钮显示
linkageAreaShow() {
return this.linkageSettingStatus && this.element !== this.curLinkageView && this.element.type === 'view'
},
// 编辑或预览区域显示
normalAreaShow() {
return !this.linkageSettingStatus
},
existLinkage() {
let linkageFiltersCount = 0
this.componentData.forEach(item => {
@@ -102,6 +113,9 @@ export default {
beforeDestroy() {
},
methods: {
closePreview() {
this.$emit('closePreview')
},
createTimer() {
if (!this.timer) {
this.timer = setInterval(() => {

View File

@@ -0,0 +1,92 @@
<template>
<div class="bar-main">
<div v-if="!linkageSettingStatus">
<span v-if="isEdit" :title="$t('panel.edit')">
<i class="icon iconfont icon-edit" @click.stop="edit" />
</span>
<span :title="$t('panel.details')">
<i class="icon iconfont icon-fangda" @click.stop="showViewDetails" />
</span>
</div>
</div>
</template>
<script>
import bus from '@/utils/bus'
import { mapState } from 'vuex'
export default {
props: {
viewId: {
type: String,
required: true
},
isEdit: {
type: Boolean,
required: false,
default: true
}
},
data() {
return {
componentType: null,
linkageActiveStatus: false,
editFilter: [
'view',
'custom'
],
timer: null
}
},
computed: {
...mapState([
'linkageSettingStatus',
'componentData',
'canvasStyleData'
])
},
mounted() {
},
beforeDestroy() {
},
methods: {
edit() {
// 编辑时临时保存 当前修改的画布
this.$store.dispatch('panel/setComponentDataTemp', JSON.stringify(this.componentData))
this.$store.dispatch('panel/setCanvasStyleDataTemp', JSON.stringify(this.canvasStyleData))
this.$store.dispatch('chart/setViewId', null)
this.$store.dispatch('chart/setViewId', this.viewId)
bus.$emit('PanelSwitchComponent', { name: 'ChartEdit', param: { 'id': this.viewId, 'optType': 'edit' }})
},
linkageEdit() {
},
amRemoveItem() {
this.$emit('amRemoveItem')
},
showViewDetails() {
this.$emit('showViewDetails')
}
}
}
</script>
<style lang="scss" scoped>
.bar-main{
position: absolute;
right: 0px;
float:right;
z-index: 2;
border-radius:2px;
padding-left: 5px;
padding-right: 2px;
cursor:pointer!important;
background-color: #0a7be0;
}
.bar-main i{
color: white;
float: right;
margin-right: 3px;
}
</style>

View File

@@ -51,7 +51,7 @@
<svg-icon v-if="item.deType === 2 || item.value === 3" icon-class="field_value" class="field-icon-value" />
<svg-icon v-if="item.deType === 5" icon-class="field_location" class="field-icon-location" />
</span>
<span style="float: left; color: #8492a6; font-size: 12px">{{ itemLinkage.targetField }}-{{ item.name }}</span>
<span style="float: left; color: #8492a6; font-size: 12px">{{ item.name }}</span>
</el-option>
</el-select>
</div>

View File

@@ -19,6 +19,7 @@
:config="item"
:search-count="searchCount"
:in-screen="inScreen"
:terminal="terminal"
/>
<!--视图详情-->
<el-dialog
@@ -36,6 +37,17 @@
</span>
<UserViewDialog ref="userViewDialog" :chart="showChartInfo" :chart-table="showChartTableInfo" />
</el-dialog>
<!--手机视图详情-->
<el-dialog
:title="'['+showChartInfo.name+']'+$t('chart.chart_details')"
:visible.sync="mobileChartDetailsVisible"
:fullscreen="true"
class="mobile-dialog-css"
:destroy-on-close="true"
>
<UserViewMobileDialog :chart="showChartInfo" :chart-table="showChartTableInfo" />
</el-dialog>
</div>
</div>
</div>
@@ -52,9 +64,10 @@ import eventBus from '@/components/canvas/utils/eventBus'
import elementResizeDetectorMaker from 'element-resize-detector'
import UserViewDialog from '@/components/canvas/custom-component/UserViewDialog'
import CanvasOptBar from '@/components/canvas/components/Editor/CanvasOptBar'
import UserViewMobileDialog from '@/components/canvas/custom-component/UserViewMobileDialog'
export default {
components: { ComponentWrapper, UserViewDialog, CanvasOptBar },
components: { UserViewMobileDialog, ComponentWrapper, UserViewDialog, CanvasOptBar },
model: {
prop: 'show',
event: 'change'
@@ -102,6 +115,7 @@ export default {
mainHeight: '100%',
searchCount: 0,
chartDetailsVisible: false,
mobileChartDetailsVisible: false,
showChartInfo: {},
showChartTableInfo: {},
// 布局展示 1.pc pc端布局 2.mobile 移动端布局
@@ -248,7 +262,11 @@ export default {
openChartDetailsDialog(chartInfo) {
this.showChartInfo = chartInfo.chart
this.showChartTableInfo = chartInfo.tableChart
this.chartDetailsVisible = true
if (this.terminal === 'pc') {
this.chartDetailsVisible = true
} else {
this.mobileChartDetailsVisible
}
},
exportExcel() {
this.$refs['userViewDialog'].exportExcel()
@@ -308,9 +326,16 @@ export default {
padding: 10px 20px 20px;
}
.mobile-dialog-css > > > .el-dialog__body {
padding: 0px;
}
::-webkit-scrollbar {
width: 0px!important;
height: 0px!important;
}
::v-deep .el-tabs__nav{
z-index: 0;
}
</style>

View File

@@ -13,7 +13,7 @@
<el-dropdown-item icon="el-icon-arrow-down" @click.native="downComponent">{{ $t('panel.downComponent') }}</el-dropdown-item>
<el-dropdown-item v-if="'view'===curComponent.type" icon="el-icon-link" @click.native="linkageSetting">{{ $t('panel.linkage_setting') }}</el-dropdown-item>
<el-dropdown-item v-if="'de-tabs'===curComponent.type" icon="el-icon-link" @click.native="addTab">{{ $t('panel.add_tab') }}</el-dropdown-item>
<el-dropdown-item v-if="'view'===curComponent.type" icon="el-icon-connection" @click.native="linkJumpSet">跳转设置</el-dropdown-item>
<el-dropdown-item v-if="'view'===curComponent.type" icon="el-icon-connection" @click.native="linkJumpSet">跳转设置</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>

View File

@@ -80,6 +80,7 @@
:element="item"
:out-style="getShapeStyleInt(item.style)"
:active="item === curComponent"
:h="getShapeStyleIntDeDrag(item.style,'height')"
/>
<component
:is="item.component"
@@ -1567,13 +1568,6 @@ export default {
padding:3px;
}
// 拖拽组件样式
.de-drag-active{
outline: 1px solid #70c0ff;
user-select: none;
}
.ref-line {
position: absolute;
background-color: #70c0ff;;

View File

@@ -8,6 +8,7 @@
'rect-shape'
]"
>
<EditBarView v-if="editBarViewShowFlag" :is-edit="isEdit" :view-id="element.propValue.viewId" @showViewDetails="openChartDetailsDialog" />
<div v-if="requestStatus==='error'" class="chart-error-class">
<div class="chart-error-message-class">
{{ message }},{{ $t('chart.chart_show_error') }}
@@ -67,10 +68,11 @@ import { getToken, getLinkToken } from '@/utils/auth'
import DrillPath from '@/views/chart/view/DrillPath'
import { areaMapping } from '@/api/map/map'
import ChartComponentG2 from '@/views/chart/components/ChartComponentG2'
import EditBarView from '@/components/canvas/components/Editor/EditBarView'
export default {
name: 'UserView',
components: { ChartComponent, TableNormal, LabelNormal, DrillPath, ChartComponentG2 },
components: { EditBarView, ChartComponent, TableNormal, LabelNormal, DrillPath, ChartComponentG2 },
props: {
element: {
type: Object,
@@ -93,10 +95,19 @@ export default {
required: false,
default: false
},
// eslint-disable-next-line vue/require-default-prop
componentIndex: {
type: Number,
required: false
},
inTab: {
type: Boolean,
required: false,
default: false
},
isEdit: {
type: Boolean,
require: false,
default: true
}
},
data() {
@@ -120,6 +131,9 @@ export default {
}
},
computed: {
editBarViewShowFlag() {
return this.active && this.inTab
},
charViewShowFlag() {
return this.httpRequest.status && this.chart.type && !this.chart.type.includes('table') && !this.chart.type.includes('text') && this.renderComponent() === 'echarts'
},
@@ -194,7 +208,8 @@ export default {
...mapState([
'canvasStyleData',
'nowPanelTrackInfo',
'nowPanelJumpInfo'
'nowPanelJumpInfo',
'publicLinkStatus'
])
},
@@ -385,9 +400,23 @@ export default {
// 内部仪表板跳转
if (jumpInfo.linkType === 'inner') {
if (jumpInfo.targetPanelId) {
const url = '#/preview/' + jumpInfo.targetPanelId
localStorage.setItem('jumpInfoParam', JSON.stringify(param))
window.open(url, jumpInfo.jumpType)
if (this.publicLinkStatus) {
// 判断是否有公共链接ID
if (jumpInfo.publicJumpId) {
const url = '/link/' + jumpInfo.publicJumpId
window.open(url, jumpInfo.jumpType)
} else {
this.$message({
type: 'warn',
message: this.$t('panel.public_link_tips'),
showClose: true
})
}
} else {
const url = '#/preview/' + jumpInfo.targetPanelId
window.open(url, jumpInfo.jumpType)
}
} else {
this.$message({
type: 'warn',
@@ -566,31 +595,31 @@ export default {
display: block !important;
}
.rect-shape > i {
right: 5px;
color: gray;
position: absolute;
}
/*.rect-shape > i {*/
/* right: 5px;*/
/* color: gray;*/
/* position: absolute;*/
/*}*/
.rect-shape > > > i:hover {
color: red;
}
/*.rect-shape > > > i:hover {*/
/* color: red;*/
/*}*/
.rect-shape:hover > > > .icon-fangda {
z-index: 2;
display: block;
}
/*.rect-shape:hover > > > .icon-fangda {*/
/* z-index: 2;*/
/* display: block;*/
/*}*/
.rect-shape > > > .icon-fangda {
display: none
}
/*.rect-shape > > > .icon-fangda {*/
/* display: none*/
/*}*/
.rect-shape:hover > > > .icon-shezhi {
z-index: 2;
display: block;
}
/*.rect-shape:hover > > > .icon-shezhi {*/
/* z-index: 2;*/
/* display: block;*/
/*}*/
.rect-shape > > > .icon-shezhi {
display: none
}
/*.rect-shape > > > .icon-shezhi {*/
/* display: none*/
/*}*/
</style>

View File

@@ -0,0 +1,90 @@
<template>
<de-container>
<de-main-container v-if="!chart.type.includes('table')" :style="customStyle" class="full-div">
<chart-component v-if="!chart.type.includes('text') && renderComponent() === 'echarts'" class="chart-class" :chart="chart" />
<chart-component-g2 v-if="!chart.type.includes('text') && renderComponent() === 'antv'" class="chart-class" :chart="chart" />
<label-normal v-if="chart.type.includes('text')" :chart="chart" class="table-class" />
</de-main-container>
<de-main-container v-else>
<table-normal :chart="chartTable" :show-summary="false" class="table-class" />
</de-main-container>
</de-container>
</template>
<script>
import ChartComponent from '@/views/chart/components/ChartComponent.vue'
import TableNormal from '@/views/chart/components/table/TableNormal'
import LabelNormal from '@/views/chart/components/normal/LabelNormal'
import { mapState } from 'vuex'
import ChartComponentG2 from '@/views/chart/components/ChartComponentG2'
import DeMainContainer from '@/components/dataease/DeMainContainer'
import DeContainer from '@/components/dataease/DeContainer'
export default {
name: 'UserViewMobileDialog',
components: { DeContainer, DeMainContainer, ChartComponentG2, ChartComponent, TableNormal, LabelNormal },
props: {
chart: {
type: Object,
default: null
},
chartTable: {
type: Object,
default: null
}
},
data() {
return {
refId: null
}
},
computed: {
customStyle() {
let style = {
}
if (this.canvasStyleData.openCommonStyle) {
if (this.canvasStyleData.panel.backgroundType === 'image' && this.canvasStyleData.panel.imageUrl) {
style = {
background: `url(${this.canvasStyleData.panel.imageUrl}) no-repeat`,
...style
}
} else if (this.canvasStyleData.panel.backgroundType === 'color') {
style = {
background: this.canvasStyleData.panel.color,
...style
}
}
}
if (!style.background) {
style.background = '#FFFFFF'
}
return style
},
...mapState([
'isClickComponent',
'curComponent',
'componentData',
'canvasStyleData'
])
},
methods: {
renderComponent() {
return this.chart.render
}
}
}
</script>
<style lang="scss" scoped>
.ms-main-container {
border: 0px;
}
.chart-class{
height: 100%;
}
.table-class{
height: 100%;
}
</style>

View File

@@ -85,7 +85,7 @@ export const assistList = [
component: 'rect-shape',
type: 'rect-shape',
label: '矩形',
icon: 'iconfont icon-juxing',
icon: 'iconfont icon-juxing1',
defaultClass: 'text-filter'
},
{

View File

@@ -51,7 +51,7 @@ export function mobile2MainCanvas(mainSource, mobileSource) {
top: mobileSource.style.top
}
mainSource.mobileStyle.x = mobileSource.x
mainSource.mobileStyle.y = mobileSource.x
mainSource.mobileStyle.y = mobileSource.y
mainSource.mobileStyle.sizex = mobileSource.sizex
mainSource.mobileStyle.sizey = mobileSource.sizey
}

View File

@@ -23,6 +23,7 @@
:element="element"
:in-draw="inDraw"
:in-screen="inScreen"
:size="sizeInfo"
/>
</div>
</div>
@@ -49,16 +50,37 @@ export default {
type: Boolean,
required: false,
default: true
},
h: {
type: Number,
default: 50
}
},
data() {
return {
inputMaxSize: 46,
inputLargeSize: 42,
inputSmallSize: 38,
inputMiniSize: 34,
options: null,
showNumber: false,
mainClass: ''
}
},
computed: {
sizeInfo() {
let size
if (this.h > this.inputMaxSize) {
} else if (this.h > this.inputLargeSize) {
size = 'medium'
} else if (this.h > this.inputSmallSize) {
size = 'small'
} else {
size = 'mini'
}
return size
}
},
mounted() {
this.watchSize()
},

View File

@@ -4,6 +4,7 @@
v-if="options!== null && options.attrs!==null"
:type="options.attrs.type"
:round="options.attrs.round"
:size="size"
>
{{ options.value }}
</el-button>
@@ -20,7 +21,8 @@ export default {
inDraw: {
type: Boolean,
default: true
}
},
size: String
},
data() {
return {

View File

@@ -9,8 +9,9 @@
:end-placeholder="$t(element.options.attrs.endPlaceholder)"
:placeholder="$t(element.options.attrs.placeholder)"
:append-to-body="inScreen"
style="min-height: 36px;"
value-format="timestamp"
:size="size"
:editable="false"
@change="dateChange"
/>
</template>
@@ -33,7 +34,8 @@ export default {
type: Boolean,
required: false,
default: true
}
},
size: String
},
data() {
return {

View File

@@ -8,6 +8,7 @@
@input="valueChange"
@keypress.enter.native="search"
@dblclick="setEdit"
:size="size"
>
<el-button slot="append" icon="el-icon-search" @click="search" />
@@ -26,7 +27,8 @@ export default {
inDraw: {
type: Boolean,
default: true
}
},
size: String
},
data() {
return {

View File

@@ -2,8 +2,9 @@
<el-quarter
v-if="options!== null && options.attrs!==null"
v-model="options.value"
:placeholder="options.attrs.placeholder"
:size="size"
:editable="false"
/>
</template>
@@ -18,7 +19,8 @@ export default {
inDraw: {
type: Boolean,
default: true
}
},
size: String
},
data() {
return {

View File

@@ -9,6 +9,7 @@
:multiple="element.options.attrs.multiple"
:placeholder="$t(element.options.attrs.placeholder)"
:popper-append-to-body="inScreen"
:size="size"
@change="changeValue"
@focus="setOptionWidth"
>
@@ -42,7 +43,8 @@ export default {
type: Boolean,
required: false,
default: true
}
},
size: String
},
data() {
return {

View File

@@ -35,7 +35,7 @@
</span>
<div v-if="activeTabName === item.name" class="de-tab-content">
<user-view v-if="item.content && item.content.propValue && item.content.propValue.viewId" :ref="item.name" :element="item.content" :out-style="outStyle" />
<user-view v-if="item.content && item.content.propValue && item.content.propValue.viewId" :ref="item.name" :in-tab="true" :is-edit="isEdit" :active="active" :element="item.content" :out-style="outStyle" />
</div>
</el-tab-pane>
@@ -94,6 +94,7 @@ import ViewSelect from '@/views/panel/ViewSelect'
import { uuid } from 'vue-uuid'
import bus from '@/utils/bus'
import componentList from '@/components/canvas/custom-component/component-list'
import { mapState } from 'vuex'
export default {
name: 'DeTabls',
@@ -107,6 +108,10 @@ export default {
type: Boolean,
default: true
},
active: {
type: Boolean,
default: false
},
outStyle: {
type: Object,
required: false,
@@ -129,11 +134,24 @@ export default {
tabList: []
}
},
watch: {
curComponent: {
handler(newVal, oldVla) {
console.log(newVal)
},
deep: true
}
},
created() {
bus.$on('add-new-tab', this.addNewTab)
this.tabList = this.element.options && this.element.options.tabList
this.activeTabName = this.tabList[0].name
},
computed: {
...mapState([
'curComponent'
])
},
methods: {
beforeHandleCommond(item, param) {
return {

View File

@@ -1,6 +1,6 @@
<template>
<el-select v-if="options!== null && options.attrs!==null" v-model="values" :multiple="options.attrs.multiple" :placeholder="options.attrs.placeholder" :popper-append-to-body="inScreen" @change="changeValue">
<el-select :size="size" v-if="options!== null && options.attrs!==null" v-model="values" :multiple="options.attrs.multiple" :placeholder="options.attrs.placeholder" :popper-append-to-body="inScreen" @change="changeValue">
<el-option
v-for="item in options.attrs.datas"
:key="item[options.attrs.key]"
@@ -28,7 +28,8 @@ export default {
type: Boolean,
required: false,
default: true
}
},
size: String
},
data() {
return {

View File

@@ -992,7 +992,9 @@ export default {
day_mom: 'Day mom',
data_sub: 'Sub',
data_percent: 'Percent',
compare_calc_expression: 'Expression'
compare_calc_expression: 'Expression',
and: 'And',
or: 'Or'
},
dataset: {
sheet_warn: 'There are multiple sheet pages, and the first one is extracted by default',
@@ -1173,6 +1175,16 @@ export default {
confirm_sync_field_tips: 'Sync field maybe change edit fieldplease confirm',
sync_success: 'Success',
sync_success_1: 'Successplease sync data again',
row_permission: {
type: 'Type',
name: 'Name',
condition: 'Conditions',
value: 'Value',
add: 'Add row permissions',
edit: 'Edit row permissions',
please_select_field: 'Please select a field'
},
row_permissions: 'Row Permissions',
union_data: 'Union Dataset',
add_union_table: 'Add Union Dataset',
edit_union: 'Edit Union Dataset',
@@ -1448,7 +1460,8 @@ export default {
panel_view_result_tips: 'Chose "Panel" Will Overwrite View`s Result,Range 1~10000',
timeout_refresh: 'TimeoutWill Refresh...',
mobile_layout: 'Mobile Layout',
component_hidden: 'Component Hidden'
component_hidden: 'Component Hidden',
public_link_tips: 'New Is Public Link,The Target Panel Have Not Set Public Link,Can Not Jump'
},
plugin: {
local_install: 'Local installation',

View File

@@ -992,7 +992,9 @@ export default {
day_mom: '日環比',
data_sub: '對比差值',
data_percent: '差值百分比',
compare_calc_expression: '計算公式'
compare_calc_expression: '計算公式',
and: '與',
or: '或'
},
dataset: {
sheet_warn: '有多個 Sheet 頁,默認抽取第一個',
@@ -1173,6 +1175,16 @@ export default {
confirm_sync_field_tips: '同步字段可能會導致已編輯字段發生變更,請確認',
sync_success: '同步成功',
sync_success_1: '同步成功,請對當前數據集重新執行數據同步操作',
row_permission: {
type: '類型',
name: '名稱',
condition: '條件',
value: '值',
add: '添加行權限',
edit: '編輯行權限',
please_select_field: '請選擇字段'
},
row_permissions: '行權限',
union_data: '關聯數據集',
add_union_table: '添加關聯數據集',
edit_union: '編輯關聯數據集',
@@ -1450,7 +1462,8 @@ export default {
panel_view_result_tips: '選擇儀表板會覆蓋視圖的結果展示數量取值範圍1~10000',
timeout_refresh: '请求超时,稍后刷新...',
mobile_layout: '移动端布局',
component_hidden: '隐藏的组件'
component_hidden: '隐藏的组件',
public_link_tips: '当前是公共链接模式,目标仪表板未设置公共链接,无法跳转'
},
plugin: {
local_install: '本地安裝',

View File

@@ -995,7 +995,9 @@ export default {
day_mom: '日环比',
data_sub: '对比差值',
data_percent: '差值百分比',
compare_calc_expression: '计算公式'
compare_calc_expression: '计算公式',
and: '与',
or: '或'
},
dataset: {
sheet_warn: '有多个 Sheet 页,默认抽取第一个',
@@ -1176,6 +1178,16 @@ export default {
confirm_sync_field_tips: '同步字段可能会导致已编辑字段发生变更,请确认',
sync_success: '同步成功',
sync_success_1: '同步成功,请对当前数据集重新执行数据同步操作',
row_permission: {
type: '类型',
name: '名称',
condition: '条件',
value: '值',
add: '添加行权限',
edit: '编辑行权限',
please_select_field: '请选择字段'
},
row_permissions: '行权限',
union_data: '关联数据集',
add_union_table: '添加关联数据集',
edit_union: '编辑关联数据集',
@@ -1459,7 +1471,8 @@ export default {
panel_view_result_tips: '选择仪表板会覆盖视图的结果展示数量取值范围1~10000',
timeout_refresh: '请求超时,稍后刷新...',
mobile_layout: '移动端布局',
component_hidden: '隐藏的组件'
component_hidden: '隐藏的组件',
public_link_tips: '当前是公共链接模式,目标仪表板未设置公共链接,无法跳转'
},
plugin: {
local_install: '本地安装',

View File

@@ -79,6 +79,8 @@ const data = {
componentGap: 5,
// 移动端布局状态
mobileLayoutStatus: false,
// 公共链接状态(当前是否是公共链接打开)
publicLinkStatus: false,
pcMatrixCount: {
x: 36,
y: 18
@@ -326,6 +328,9 @@ const data = {
setMobileLayoutStatus(state, status) {
state.mobileLayoutStatus = status
},
setPublicLinkStatus(state, status) {
state.publicLinkStatus = status
},
// 启用移动端布局
openMobileLayout(state) {
state.componentDataCache = JSON.stringify(state.componentData)

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2459092 */
src: url('iconfont.woff2?t=1636516993563') format('woff2'),
url('iconfont.woff?t=1636516993563') format('woff'),
url('iconfont.ttf?t=1636516993563') format('truetype');
src: url('iconfont.woff2?t=1639622225820') format('woff2'),
url('iconfont.woff?t=1639622225820') format('woff'),
url('iconfont.ttf?t=1639622225820') format('truetype');
}
.iconfont {
@@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-guanbi:before {
content: "\e60d";
}
.icon-juxing1:before {
content: "\e67e";
}
.icon-yidongduan:before {
content: "\e653";
}
@@ -37,10 +45,6 @@
content: "\e91b";
}
.icon-tabs:before {
content: "\e9a8";
}
.icon-shijian:before {
content: "\e665";
}
@@ -81,6 +85,10 @@
content: "\e8e6";
}
.icon-tabs:before {
content: "\e62a";
}
.icon-xiyu:before {
content: "\e619";
}

File diff suppressed because one or more lines are too long

View File

@@ -5,6 +5,20 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "1367318",
"name": "关闭",
"font_class": "guanbi",
"unicode": "e60d",
"unicode_decimal": 58893
},
{
"icon_id": "23446403",
"name": "矩形",
"font_class": "juxing1",
"unicode": "e67e",
"unicode_decimal": 59006
},
{
"icon_id": "11799014",
"name": "移动端",
@@ -47,13 +61,6 @@
"unicode": "e91b",
"unicode_decimal": 59675
},
{
"icon_id": "11982148",
"name": "tabs",
"font_class": "tabs",
"unicode": "e9a8",
"unicode_decimal": 59816
},
{
"icon_id": "658039",
"name": "时间",
@@ -124,6 +131,13 @@
"unicode": "e8e6",
"unicode_decimal": 59622
},
{
"icon_id": "15196968",
"name": "44.tabs",
"font_class": "tabs",
"unicode": "e62a",
"unicode_decimal": 58922
},
{
"icon_id": "23570269",
"name": "洗浴",

View File

@@ -14,7 +14,7 @@
</span>
<span class="item-span-style" :title="item.name">{{ item.name }}</span>
<span v-if="chart.type !== 'table-info' && item.summary" class="summary-span">
{{ $t('chart.' + item.summary) }}<span v-if="item.compareCalc.type && item.compareCalc.type !== '' && item.compareCalc.type !== 'none'">-{{ $t('chart.' + item.compareCalc.type) }}</span>
{{ $t('chart.' + item.summary) }}<span v-if="item.compareCalc && item.compareCalc.type && item.compareCalc.type !== '' && item.compareCalc.type !== 'none'">-{{ $t('chart.' + item.compareCalc.type) }}</span>
</span>
</el-tag>
<el-dropdown v-else trigger="click" size="mini" @command="clickItem">
@@ -33,7 +33,7 @@
</span>
<span class="item-span-style" :title="item.name">{{ item.name }}</span>
<span v-if="chart.type !== 'table-info' && item.summary" class="summary-span">
{{ $t('chart.' + item.summary) }}<span v-if="item.compareCalc.type && item.compareCalc.type !== '' && item.compareCalc.type !== 'none'">-{{ $t('chart.' + item.compareCalc.type) }}</span>
{{ $t('chart.' + item.summary) }}<span v-if="item.compareCalc && item.compareCalc.type && item.compareCalc.type !== '' && item.compareCalc.type !== 'none'">-{{ $t('chart.' + item.compareCalc.type) }}</span>
</span>
<i class="el-icon-arrow-down el-icon--right" style="position: absolute;top: 6px;right: 10px;" />
</el-tag>

View File

@@ -14,7 +14,7 @@
</span>
<span class="item-span-style" :title="item.name">{{ item.name }}</span>
<span v-if="chart.type !== 'table-info' && item.summary" class="summary-span">
{{ $t('chart.' + item.summary) }}<span v-if="item.compareCalc.type && item.compareCalc.type !== '' && item.compareCalc.type !== 'none'">-{{ $t('chart.' + item.compareCalc.type) }}</span>
{{ $t('chart.' + item.summary) }}<span v-if="item.compareCalc && item.compareCalc.type && item.compareCalc.type !== '' && item.compareCalc.type !== 'none'">-{{ $t('chart.' + item.compareCalc.type) }}</span>
</span>
</el-tag>
<el-dropdown v-else trigger="click" size="mini" @command="clickItem">
@@ -33,7 +33,7 @@
</span>
<span class="item-span-style" :title="item.name">{{ item.name }}</span>
<span v-if="chart.type !== 'table-info' && item.summary" class="summary-span">
{{ $t('chart.' + item.summary) }}<span v-if="item.compareCalc.type && item.compareCalc.type !== '' && item.compareCalc.type !== 'none'">-{{ $t('chart.' + item.compareCalc.type) }}</span>
{{ $t('chart.' + item.summary) }}<span v-if="item.compareCalc && item.compareCalc.type && item.compareCalc.type !== '' && item.compareCalc.type !== 'none'">-{{ $t('chart.' + item.compareCalc.type) }}</span>
</span>
<i class="el-icon-arrow-down el-icon--right" style="position: absolute;top: 6px;right: 10px;" />
</el-tag>

View File

@@ -1,6 +1,18 @@
<template>
<el-col>
<el-button icon="el-icon-plus" circle size="mini" style="margin-bottom: 10px;" @click="addFilter" />
<div style="display: inline-block;">
<el-button icon="el-icon-plus" circle size="mini" style="margin-bottom: 10px;" @click="addFilter" />
<el-radio-group
v-model="logic"
size="mini"
style="margin-left: 10px;"
@change="logicChange"
>
<el-radio-button label="and">{{ $t('chart.and') }}</el-radio-button>
<el-radio-button label="or">{{ $t('chart.or') }}</el-radio-button>
</el-radio-group>
</div>
<div style="max-height: 50vh;overflow-y: auto;">
<el-row v-for="(f,index) in item.filter" :key="index" class="filter-item">
<el-col :span="4">
@@ -54,16 +66,6 @@ export default {
label: this.$t('chart.filter_not_eq')
}]
},
// {
// label: '',
// options: [{
// value: 'like',
// label: this.$t('chart.filter_like')
// }, {
// value: 'not like',
// label: this.$t('chart.filter_not_like')
// }]
// },
{
label: '',
options: [{
@@ -83,12 +85,17 @@ export default {
value: 'ge',
label: this.$t('chart.filter_ge')
}]
}]
}],
logic: ''
}
},
mounted() {
this.init()
},
methods: {
init() {
this.logic = this.item.logic
},
addFilter() {
this.item.filter.push({
term: 'eq',
@@ -97,6 +104,9 @@ export default {
},
removeFilter(index) {
this.item.filter.splice(index, 1)
},
logicChange(val) {
this.item.logic = val
}
}
}

View File

@@ -1,6 +1,18 @@
<template>
<el-col>
<el-button icon="el-icon-plus" circle size="mini" style="margin-bottom: 10px;" @click="addFilter" />
<div style="display: inline-block;">
<el-button icon="el-icon-plus" circle size="mini" style="margin-bottom: 10px;" @click="addFilter" />
<el-radio-group
v-model="logic"
size="mini"
style="margin-left: 10px;"
@change="logicChange"
>
<el-radio-button label="and">{{ $t('chart.and') }}</el-radio-button>
<el-radio-button label="or">{{ $t('chart.or') }}</el-radio-button>
</el-radio-group>
</div>
<div style="max-height: 50vh;overflow-y: auto;">
<el-row v-for="(f,index) in item.filter" :key="index" class="filter-item">
<el-col :span="4">
@@ -156,7 +168,8 @@ export default {
}]
}
],
options: []
options: [],
logic: ''
}
},
watch: {
@@ -166,6 +179,7 @@ export default {
},
mounted() {
this.initOptions()
this.init()
},
methods: {
initOptions() {
@@ -179,6 +193,9 @@ export default {
}
}
},
init() {
this.logic = this.item.logic
},
addFilter() {
this.item.filter.push({
fieldId: this.item.id,
@@ -188,6 +205,9 @@ export default {
},
removeFilter(index) {
this.item.filter.splice(index, 1)
},
logicChange(val) {
this.item.logic = val
}
}
}

View File

@@ -804,6 +804,7 @@
<!--指标过滤器-->
<el-dialog
v-if="quotaFilterEdit"
v-dialogDrag
:title="$t('chart.add_filter')"
:visible="quotaFilterEdit"
@@ -818,6 +819,7 @@
</div>
</el-dialog>
<el-dialog
v-if="dimensionFilterEdit"
v-dialogDrag
:title="$t('chart.add_filter')"
:visible="dimensionFilterEdit"
@@ -832,6 +834,7 @@
</div>
</el-dialog>
<el-dialog
v-if="resultFilterEdit"
v-dialogDrag
:title="$t('chart.add_filter')"
:visible="resultFilterEdit"
@@ -1612,6 +1615,9 @@ export default {
showQuotaEditFilter(item) {
this.quotaItem = JSON.parse(JSON.stringify(item))
if (!this.quotaItem.logic) {
this.quotaItem.logic = 'and'
}
this.quotaFilterEdit = true
},
closeQuotaFilter() {
@@ -1631,8 +1637,10 @@ export default {
}
if (this.quotaItem.filterType === 'quota') {
this.view.yaxis[this.quotaItem.index].filter = this.quotaItem.filter
this.view.yaxis[this.quotaItem.index].logic = this.quotaItem.logic
} else if (this.quotaItem.filterType === 'quotaExt') {
this.view.yaxisExt[this.quotaItem.index].filter = this.quotaItem.filter
this.view.yaxisExt[this.quotaItem.index].logic = this.quotaItem.logic
}
this.calcData(true)
this.closeQuotaFilter()
@@ -1645,6 +1653,9 @@ export default {
showEditFilter(item) {
this.filterItem = JSON.parse(JSON.stringify(item))
this.chartForFilter = JSON.parse(JSON.stringify(this.view))
if (!this.filterItem.logic) {
this.filterItem.logic = 'and'
}
this.resultFilterEdit = true
},
closeResultFilter() {
@@ -1663,6 +1674,7 @@ export default {
}
}
this.view.customFilter[this.filterItem.index].filter = this.filterItem.filter
this.view.customFilter[this.filterItem.index].logic = this.filterItem.logic
this.calcData(true)
this.closeResultFilter()
},

View File

@@ -76,7 +76,7 @@ import FieldEdit from './FieldEdit'
export default {
name: 'ViewTable',
components: { FieldEdit, UnionView, DatasetChartDetail, UpdateInfo, TabDataPreview },
components: {FieldEdit, UnionView, DatasetChartDetail, UpdateInfo, TabDataPreview },
props: {
param: {
type: Object,

View File

@@ -0,0 +1,226 @@
<template>
<de-container style="height: auto">
<de-aside-container style="height: auto">
<el-button v-show="!showTargetSearchInput" class="de-icon" icon="el-icon-search" circle size="mini" @click="showTargetSearchWidget" />
<div v-show="showTargetSearchInput" class="de-input">
<el-input v-model="targetFilterText" class="main-area-input">
<el-button slot="append" icon="el-icon-close" @click="closeTargetSearchWidget" />
</el-input>
</div>
<el-tabs v-model="targetActiveName" :class="{'de-search-header': showTargetSearchInput}" @tab-click="handleClick">
<el-tab-pane v-for="(targetInfo, index) in targetInfoArray" :key="index" :lazy="true" :label="targetInfo.tabName" :name="targetInfo.authType">
<lazy-tree
v-if="targetActiveName===targetInfo.authType"
:active-name="targetActiveName"
:filter-text="targetFilterText"
:data-info="targetInfo"
highlight-current
@nodeClick="authNodeClick"
@execute-axios="executeAxios"
/>
</el-tab-pane>
</el-tabs>
</de-aside-container>
<de-main-container class="de-main-container-auth">
<el-button v-show="!showSourceSearchInput" class="de-icon" icon="el-icon-search" circle size="mini" @click="showSourceSearchWidget" />
<div v-show="showSourceSearchInput" class="de-input">
<el-input v-model="sourceFilterText" class="main-area-input">
<el-button slot="append" icon="el-icon-close" @click="closeSourceSearchWidget" />
</el-input>
</div>
<el-tabs v-model="sourceActiveName" :class="{'de-search-header': showSourceSearchInput}" @tab-click="handleClick">
<el-tab-pane v-for="(sourceInfo, index) in sourceInfoTabs" :key="index" :lazy="true" :label="sourceInfo.tabName" :name="sourceInfo.authType">
<lazy-tree
v-if="authCondition"
:active-name="sourceActiveName"
:filter-text="sourceFilterText"
:data-info="sourceInfo"
show-extent
:auth-condition="authCondition"
@execute-axios="executeAxios"
:attach-active-name="targetActiveName"
/>
</el-tab-pane>
</el-tabs>
</de-main-container>
</de-container>
</template>
<script>
import DeContainer from '@/components/dataease/DeContainer'
import DeAsideContainer from '@/components/dataease/DeAsideContainer'
import DeMainContainer from '@/components/dataease/DeMainContainer'
import LazyTree from './components/LazyTree'
export default {
name: 'Authority',
components: { LazyTree, DeMainContainer, DeAsideContainer, DeContainer },
props: {
resourceId: {
type: String,
default: null
}
},
data () {
return {
targetInfoArray:
[
{
tabName: this.$t('auth.dept'),
head: this.$t('auth.deptHead'),
direction: 'target',
authType: 'dept'
},
{
tabName: this.$t('auth.role'),
head: this.$t('auth.roleHead'),
direction: 'target',
authType: 'role'
},
{
tabName: this.$t('auth.user'),
head: this.$t('auth.userHead'),
direction: 'target',
authType: 'user'
}],
sourceInfoArray:
[
{
tabName: this.$t('auth.linkAuth'),
head: this.$t('auth.linkAuthHead'),
direction: 'source',
authType: 'link',
authTargets: 'dept,role,user'
},
{
tabName: this.$t('auth.datasetAuth'),
head: this.$t('auth.datasetAuthHead'),
direction: 'source',
authType: 'dataset',
authTargets: 'dept,role,user'
},
{
tabName: this.$t('auth.chartAuth'),
head: this.$t('auth.chartAuthHead'),
direction: 'source',
authType: 'chart',
authTargets: 'dept,role,user'
},
{
tabName: this.$t('auth.panelAuth'),
head: this.$t('auth.panelAuthHead'),
direction: 'source',
authType: 'panel',
authTargets: 'dept,role,user'
},
{
tabName: this.$t('auth.menuAuth'),
head: this.$t('auth.menuAuthHead'),
direction: 'source',
authType: 'menu',
authTargets: 'dept,role,user'
}
],
targetActiveName: null,
sourceActiveName: null,
showSourceSearchInput: false,
showTargetSearchInput: false,
sourceFilterText: '',
targetFilterText: '',
timeMachine: null,
authCondition: null
}
},
computed: {
sourceInfoTabs () {
const tabs = []
this.sourceInfoArray.forEach(item => {
if (item.authTargets.indexOf(this.targetActiveName) > -1) {
tabs.push(item)
}
})
return tabs
}
},
created () {
this.targetActiveName = this.targetInfoArray[0].authType
this.sourceActiveName = this.sourceInfoArray[0].authType
},
methods: {
executeAxios (param) {
this.$emit('execute-axios', param)
},
handleClick (tab, event) {
},
showSourceSearchWidget () {
this.showSourceSearchInput = true
},
closeSourceSearchWidget () {
this.sourceFilterText = ''
this.showSourceSearchInput = false
},
showTargetSearchWidget () {
this.showTargetSearchInput = true
},
closeTargetSearchWidget () {
this.targetFilterText = ''
this.showTargetSearchInput = false
},
save () {
this.$refs[this.activeName].save()
this.$emit('close-grant', 0)
},
cancel () {
this.$refs[this.activeName].cancel()
this.$emit('close-grant', 0)
},
authNodeClick (val) {
console.log('authNodeClick')
this.authCondition = val
},
clickAuth (auth) {
console.log('clickAuth')
}
}
}
</script>
<style lang="scss" scoped>
.de-tab {
border:1px solid #E6E6E6;
min-height:200px !important;
max-height:300px !important;
overflow:auto;
}
.de-icon {
position: absolute;
right: 10px;
top: 15px;
z-index: 99;
}
.el-input-group__append{
background-color: #ffffff;
}
.el-input__inner{
border-right: none;
}
.auth-root-class {
margin: 15px 0px 5px;
text-align: right;
}
.de-main-container-auth{
border: 1px solid #E6E6E6;
height: auto;
}
.blackTheme .de-main-container-auth {
border-color: #495865;
}
// ::-webkit-scrollbar {
// }
</style>

View File

@@ -0,0 +1,373 @@
<template xmlns:el-col="http://www.w3.org/1999/html">
<el-col v-loading="loading" class="tree-main">
<el-row v-if="showExtent" class="tree-head">
<span style="float: left;padding-left: 10px">{{ dataInfo.head }}</span>
<span v-for="auth in defaultAuthDetails" :key="auth.privilegeName" class="auth-span">
{{ auth.privilegeName }}
</span>
</el-row>
<el-row style="margin-top: 5px">
<el-tree
:props="defaultProps"
:load="loadNodes"
:data="treeData"
:node-key="defaultProps.id"
:highlight-current="highlightCurrent"
:default-expanded-keys="expandedKey"
lazy
@node-click="nodeClick"
>
<span slot-scope="{ node, data }" class="custom-tree-node">
<span>
<span style="margin-left: 6px" v-html="data.name" />
</span>
<span v-if="showExtent" @click.stop>
<div v-if="authDetails[data.id]">
<span v-for="auth in authDetails[data.id]" :key="auth.privilegeType" class="auth-span">
<!-- 1-{{ auth.privilegeType }}-{{ auth.privilegeValue }}-->
<a href="javascript:;" @click="clickAuth(data.id,auth)">
<svg-icon style="width: 25px;height: 25px" :icon-class="auth.privilegeValue===1?'lock_open':'lock_closed'" />
</a>
</span>
</div>
<div v-else>
<span v-for="auth in defaultAuthDetails" :key="auth.privilegeType" class="auth-span">
<!--2-{{ auth.privilegeType }}-{{ auth.privilegeValue }}-->
<a href="javascript:;" @click="clickAuth(data.id,auth)">
<svg-icon style="width: 25px;height: 25px" :icon-class="auth.privilegeValue===1?'lock_open':'lock_closed'" />
</a>
</span>
</div></span>
</span>
</el-tree>
</el-row>
</el-col>
</template>
<script>
// import { authChange, authDetails, authDetailsModel, authModel } from '@/api/system/sysAuth'
// import { execute } from '@/de-base/api/de-api'
export default {
name: 'LazyTree',
components: { },
props: {
filterText: {
type: String,
required: false,
default: ''
},
authCondition: {
type: Object,
required: false
},
dataInfo: {
type: Object,
required: true
},
activeName: {
type: String,
required: true
},
attachActiveName: String,
defaultProps: {
type: Object,
required: false,
default: function () {
return {
children: 'children',
label: 'name',
id: 'id',
parentId: 'pid',
isLeaf: 'leaf'
}
}
},
showExtent: Boolean,
highlightCurrent: Boolean
},
data () {
return {
loading: false,
treeData: [],
changeIndex: 0,
timeMachine: null,
expandedKey: [], // 展开节点 搜索时默认展开父级节点
defaultCondition: { // pid 是0的时候 查询的是顶级的节点
pid: '0'
},
authDetails: {},
defaultAuthDetails: [],
searchStatus: false, // 当前是否在搜索状态 (搜索状态 展开不加载子节点)
// 当前已经加载的节点ID 备用当前把当前authTarget的所有授权加载进来
loadedNodeIds: new Set()
}
},
computed: {
},
watch: {
filterText (val) {
this.expandedKey = []
if (val && val.length > 0) {
this.searchStatus = true
}
// 当组件名和 activeName 相等时 才进行查询
if (this.dataInfo.authType === this.activeName) {
this.destroyTimeMachine()
this.changeIndex++
this.filterNode(this.changeIndex)
}
},
authCondition: {
handler (newVal, oldVla) {
this.loadAuth()
},
deep: true
},
activeName: {
handler (newVal, oldVla) {
this.loadAuth()
},
deep: true
},
attachActiveName: {
handler (newVal, oldVla) {
this.authDetails = {}
},
deep: true
}
},
created () {
// 初始化授权模板
if (this.showExtent) {
this.executeAxios('/plugin/auth/authDetailsModel/' + this.dataInfo.authType, 'get', {}, res => {
this.defaultAuthDetails = res.data
})
// authDetailsModel(this.dataInfo.authType).then(res => {
// this.defaultAuthDetails = res.data
// })
this.loadAuth()
}
},
methods: {
executeAxios (url, type, data, callBack) {
const param = {
url: url,
type: type,
data: data,
callBack: callBack
}
this.$emit('execute-axios', param)
// if (process.env.NODE_ENV === 'development') {
// execute(param).then(res => {
// if (param.callBack) {
// param.callBack(res)
// }
// }).catch(e => {
// if (param.error) {
// param.error(e)
// }
// })
// }
},
loadAuth () {
if (this.authCondition && this.showExtent) {
let authQueryCondition = {}
if (this.dataInfo.direction === 'source') {
// 当前为授权数据 获取当前authTarget 的授权信息 authSource
authQueryCondition = {
authTarget: this.authCondition.id,
authTargetType: this.authCondition.type,
authSourceType: this.dataInfo.authType
}
} else {
authQueryCondition = {
authSource: this.authCondition.id,
authSourceType: this.authCondition.type
}
}
this.executeAxios('/plugin/auth/authDetails', 'post', authQueryCondition, res => {
this.authDetails = res.data
})
// authDetails(authQueryCondition).then(res => {
// this.authDetails = res.data
// })
}
},
loadNodes (node, resolve) {
if (!this.searchStatus) {
if (node.level === 0) {
const queryCondition = {
modelType: this.dataInfo.authType,
...this.defaultCondition
}
this.executeAxios('/plugin/auth/authModels', 'post', queryCondition, res => {
const data = res.data
resolve(data)
})
// authModel(queryCondition).then(res => {
// const data = res.data
// resolve(data)
// })
} else {
const queryCondition = {
modelType: this.dataInfo.authType
}
queryCondition[this.defaultProps.parentId] = node.data[this.defaultProps.id]
this.executeAxios('/plugin/auth/authModels', 'post', queryCondition, res => {
const data = res.data
resolve(data)
})
// authModel(queryCondition).then(res => {
// const data = res.data
// resolve(data)
// })
}
} else {
resolve(node.data.children)
}
},
filterNode (index) {
this.timeMachine = setTimeout(() => {
if (index === this.changeIndex) {
const queryCondition = {
withExtend: 'parent',
modelType: this.dataInfo.authType
}
queryCondition[this.defaultProps.label] = this.filterText
this.executeAxios('/plugin/auth/authModels', 'post', queryCondition, res => {
// 高亮显示
this.highlights(res.data)
this.treeData = this.buildTree(res.data)
// 恢复searchStatus 状态 可以允许继续展开父级
this.$nextTick(() => (this.searchStatus = false))
})
// authModel(queryCondition).then(res => {
// // 高亮显示
// this.highlights(res.data)
// this.treeData = this.buildTree(res.data)
// // 恢复searchStatus 状态 可以允许继续展开父级
// this.$nextTick(() => (this.searchStatus = false))
// })
}
this.destroyTimeMachine()
}, 1500)
},
nodeClick (data, node) {
this.$emit('nodeClick', { id: data.id, type: this.dataInfo.authType })
},
destroyTimeMachine () {
this.timeMachine && clearTimeout(this.timeMachine)
this.timeMachine = null
},
buildTree (arrs) {
const idMapping = arrs.reduce((acc, el, i) => {
acc[el[this.defaultProps.id]] = i
return acc
}, {})
const roots = []
arrs.forEach(el => {
// 判断根节点 ###
if (el[this.defaultProps.parentId] === null || el[this.defaultProps.parentId] === 0 || el[this.defaultProps.parentId] === '0') {
roots.push(el)
return
}
// 用映射表找到父元素
const parentEl = arrs[idMapping[el[this.defaultProps.parentId]]]
// 把当前元素添加到父元素的`children`数组中
parentEl.children = [...(parentEl.children || []), el]
// 设置展开节点 如果没有子节点则不进行展开
if (parentEl.children.length > 0) {
this.expandedKey.push(parentEl[this.defaultProps.id])
}
})
return roots
},
// 权限修改
clickAuth (dataId, auth) {
let authChangeCondition = {}
if (this.dataInfo.direction === 'source') { // 当前为授权数据
authChangeCondition = {
authSource: dataId,
authSourceType: this.dataInfo.authType,
authTarget: this.authCondition.id,
authTargetType: this.authCondition.type,
authDetail: auth
}
} else {
authChangeCondition = {
authTarget: dataId,
authTargetType: this.dataInfo.authType,
authSource: this.authCondition.id,
authSourceType: this.authCondition.type,
authDetail: auth
}
}
this.loading = true
this.executeAxios('/plugin/auth/authChange', 'post', authChangeCondition, res => {
// 重新加载权限
this.loadAuth()
this.loading = false
})
},
// 高亮显示搜索内容
highlights (data) {
if (data && this.filterText && this.filterText.length > 0) {
const replaceReg = new RegExp(this.filterText, 'g')// 匹配关键字正则
const replaceString = '<span style="color: #faaa39">' + this.filterText + '</span>' // 高亮替换v-html值
data.forEach(item => {
item.name = item.name.replace(replaceReg, replaceString) // 开始替换
})
}
}
}
}
</script>
<style scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-left: 8px;
}
.tree-main{
height: calc(100vh - 210px);
border: 1px solid #e6e6e6;
overflow-y: auto;
}
.blackTheme .tree-main {
border-color: var(--TableBorderColor) !important;
}
/* .tree-head{
height: 30px;
line-height: 30px;
border-bottom: 1px solid #e6e6e6;
background-color: #f7f8fa;
font-size: 12px;
color: #3d4d66 ;
} */
.tree-head{
height: 30px;
line-height: 30px;
border-bottom: 1px solid var(--TableBorderColor, #e6e6e6);
background-color: var(--SiderBG, #f7f8fa);
font-size: 12px;
color: var(--TableColor, #3d4d66) ;
}
.auth-span{
float: right;
width:50px;
margin-right: 30px
}
.highlights-text {
color: #faaa39 !important;
}
</style>

View File

@@ -32,6 +32,7 @@ export default {
methods: {
loadInit() {
this.$store.commit('setPublicLinkStatus', true)
debugger
// this.link = getQueryVariable(this.PARAMKEY)
this.link = this.$route.query.link

View File

@@ -9,7 +9,7 @@ import { loadResource } from '@/api/link'
import { uuid } from 'vue-uuid'
import Preview from '@/components/canvas/components/Editor/Preview'
import { getPanelAllLinkageInfo } from '@/api/panel/linkage'
import { queryPanelJumpInfo } from '@/api/panel/linkJump'
import { queryPanelJumpInfo, queryTargetPanelJumpInfo } from '@/api/panel/linkJump'
export default {
name: 'LinkView',
@@ -32,6 +32,10 @@ export default {
methods: {
setPanelInfo() {
loadResource(this.resourceId).then(res => {
this.$store.dispatch('panel/setPanelInfo', {
id: res.data.id,
name: res.data.name
})
// 刷新联动信息
getPanelAllLinkageInfo(this.resourceId).then(rsp => {
this.$store.commit('setNowPanelTrackInfo', rsp.data)
@@ -43,7 +47,27 @@ export default {
queryPanelJumpInfo(this.resourceId).then(rsp => {
this.$store.commit('setNowPanelJumpInfo', rsp.data)
})
this.show = true
// 如果含有跳转参数 进行触发
const tempParam = localStorage.getItem('jumpInfoParam')
if (tempParam) {
localStorage.removeItem('jumpInfoParam')
const jumpParam = JSON.parse(tempParam)
const jumpRequestParam = {
sourcePanelId: jumpParam.sourcePanelId,
sourceViewId: jumpParam.sourceViewId,
sourceFieldId: jumpParam.sourceFieldId,
targetPanelId: this.resourceId
}
this.show = false
// 刷新跳转目标仪表板联动信息
queryTargetPanelJumpInfo(jumpRequestParam).then(rsp => {
this.show = true
this.$store.commit('setNowTargetPanelJumpInfo', rsp.data)
this.$store.commit('addViewTrackFilter', jumpParam)
})
} else {
this.show = true
}
})
},
resetID(data) {

View File

@@ -82,7 +82,7 @@
<el-row v-for="(targetViewInfo,index) in linkJumpInfo.targetViewInfoList" :key="index">
<el-col :span="11">
<div class="select-filed">
<el-select v-model="targetViewInfo.targetViewId" style="width: 100%" size="mini" :placeholder="$t('panel.please_select')" @change="viewInfoOnChange(targetViewInfo)">
<el-select v-model="targetViewInfo.targetViewId" style="width: 100%" size="mini" :placeholder="$t('fu.search_bar.please_select')" @change="viewInfoOnChange(targetViewInfo)">
<el-option
v-for="item in currentLinkPanelViewArray"
:key="item.id"
@@ -99,7 +99,7 @@
</el-col>
<el-col :span="11">
<div class="select-filed">
<el-select v-model="targetViewInfo.targetFieldId" style="width: 100%" size="mini" :placeholder="$t('panel.please_select')">
<el-select v-model="targetViewInfo.targetFieldId" style="width: 100%" size="mini" :placeholder="$t('fu.search_bar.please_select')">
<el-option
v-for="viewField in viewIdFieldArrayMap[targetViewInfo.targetViewId]"
:key="viewField.id"

View File

@@ -11,6 +11,7 @@
:style="getComponentStyleDefault(config.style)"
:out-style="outStyle"
:element="config"
:in-screen="true"
/>
<component
:is="config.component"
@@ -30,10 +31,11 @@
import { mapState } from 'vuex'
import MobileCheckBar from '@/components/canvas/components/Editor/MobileCheckBar'
import { getStyle } from '@/components/canvas/utils/style'
import DeOutWidget from '@/components/dataease/DeOutWidget'
export default {
name: 'ComponentWaitItem',
components: { MobileCheckBar },
components: { DeOutWidget, MobileCheckBar },
props: {
config: {
type: Object,
@@ -87,6 +89,7 @@ export default {
<style scoped>
.component-custom {
position: relative!important;
outline: none;
width: 100% !important;
height: 100%;