| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- <template>
- <div id="dashboard-header" class="wrap d-flex align-items-center">
- <draggable v-model="options" tag="ul" class="d-flex flex-fill flex-wrap list-unstyled m-0" handle=".handle">
- <li
- class="item"
- v-for="item in options"
- :key="item.id"
- :class="{ active: current.id === item.id }"
- @click.stop.prevent="$emit('select', item)">
- <icon type="move" class="handle" />
- <span>{{ item.name }}</span>
- </li>
- </draggable>
- <data-range v-if="(isAdminMode || isDomainMode) && $appConfig.isPrivate && !$store.getters.isSysCE" :dataRangeParams="dataRangeParams" @updateDataRange="updateDataRange" />
- <a-button @click="handleRefresh" type="link" class="action-btn">
- <icon type="refresh" />
- </a-button>
- <a-dropdown v-if="showActions.length" :trigger="['click']" slot="tabBarExtraContent" placement="bottomRight">
- <a class="ant-dropdown-link font-weight-bold pl-2 pr-2 h-100 d-block action-btn" @click="e => e.preventDefault()">
- <icon type="more" style="font-size: 18px;" />
- </a>
- <a-menu slot="overlay" @click="handleActionClick">
- <a-menu-item key="handleCreate" v-if="showActions.includes('create')"><a-icon type="plus" />{{$t('dashboard.text_103')}}</a-menu-item>
- <a-menu-item key="handleEdit" v-if="showActions.includes('edit')"><a-icon type="edit" />{{$t('dashboard.text_104')}}</a-menu-item>
- <a-menu-item key="handleDownload" v-if="showActions.includes('export')"><a-icon type="download" />{{$t('dashboard.text_105')}}</a-menu-item>
- <a-menu-item key="handleImport" v-if="showActions.includes('import')"><a-icon type="file" />{{$t('dashboard.text_106')}}</a-menu-item>
- <a-menu-item key="handleCopy" v-if="showActions.includes('clone')"><a-icon type="copy" />{{$t('dashboard.text_107')}}</a-menu-item>
- <a-menu-item key="handleShare" v-if="isAdminRole && isDefaultOption && showActions.includes('share')"><a-icon type="share-alt" />{{$t('common_104', [''])}}</a-menu-item>
- <a-menu-item key="handleDelete" v-if="showActions.includes('reset')"><a-icon type="delete" />{{deleteText}}</a-menu-item>
- </a-menu>
- </a-dropdown>
- </div>
- </template>
- <script>
- import * as R from 'ramda'
- import { mapGetters } from 'vuex'
- import { Base64 } from 'js-base64'
- import draggable from 'vuedraggable'
- import { download, uuid } from '@/utils/utils'
- import WindowsMixin from '@/mixins/windows'
- import DataRange from './DataRange.vue'
- export default {
- name: 'DashboardHeader',
- components: {
- draggable,
- DataRange,
- },
- mixins: [WindowsMixin],
- props: {
- tabs: {
- type: Array,
- required: true,
- },
- current: {
- type: Object,
- required: true,
- },
- // 当前卡片配置
- data: {
- type: [Array, Object],
- required: true,
- },
- // 检查options配置是否创建过
- checkOptionsCreated: {
- type: Function,
- required: true,
- },
- // 创建初始化配置
- initOptions: {
- type: Function,
- required: true,
- },
- // 是否为默认面板
- isDefaultOption: Boolean,
- dataRangeParams: {
- type: Object,
- },
- },
- data () {
- return {
- isPrivate: process.env.VUE_APP_IS_PRIVATE,
- }
- },
- computed: {
- ...mapGetters(['scope', 'userInfo', 'isAdminMode', 'isDomainMode']),
- options: {
- get () {
- return this.tabs
- },
- set (value) {
- this.$emit('update-options', value)
- },
- },
- // 是否只有一个标签
- isSingle () {
- return this.tabs.length === 1
- },
- deleteText () {
- if (this.isDefaultOption) {
- return this.$t('common.reset')
- } else {
- return this.$t('dashboard.text_108')
- }
- },
- showActions () {
- return (['create', 'edit', 'export', 'import', 'share', 'reset', 'clone']).filter(key => {
- return !this.$isScopedPolicyMenuHidden(`dashboard_hidden_actions.${key}`)
- })
- },
- isAdminRole () {
- const { projects = [] } = this.userInfo
- const systemProj = projects.find(o => o.name === 'system')
- return !!systemProj
- },
- },
- beforeDestroy () {
- this.pm = null
- },
- created () {
- this.pm = new this.$Manager('parameters', 'v1')
- },
- methods: {
- updateDataRange (params) {
- this.$emit('updateDataRange', params)
- },
- handleActionClick ({ key }) {
- if (this[key]) this[key]()
- },
- handleCreate () {
- this.$router.push({ name: 'DashboardEdit' })
- },
- handleEdit () {
- this.$router.push({ name: 'DashboardEdit', query: { id: this.current.id } })
- },
- handleDownload () {
- const name = `${this.$t(`policyScopeLabel.${this.scope}`)}_${this.current.name}.ocdb`
- const data = this.genExportData()
- download(data, name)
- },
- handleImport () {
- this.createDialog('DashboardImport', {
- title: this.$t('dashboard.text_106'),
- options: this.options,
- genName: name => this.genName(name),
- checkOptionsCreated: () => this.checkOptionsCreated(),
- initOptions: () => this.initOptions(),
- updateOptions: options => this.$emit('update-options', options),
- selectOption: item => {
- this.$emit('select', item)
- },
- })
- },
- handleDelete () {
- this.createDialog('CommonDialog', {
- header: this.deleteText,
- body: () => {
- let number
- if (R.is(Array, this.data)) {
- number = this.data.length
- } else {
- number = Object.keys(this.data).length
- }
- const data = [{
- ...this.current,
- number,
- }]
- return [
- <dialog-selected-tips count={1} action={this.deleteText} name={this.$t('dashboard.text_109')} />,
- <dialog-table
- vxeGridProps={{ showOverflow: 'title' }}
- data={ data }
- columns={
- [
- {
- field: 'name',
- title: this.$t('dashboard.text_110'),
- },
- {
- field: 'number',
- title: this.$t('dashboard.text_111'),
- },
- ]
- } />,
- ]
- },
- ok: async () => {
- try {
- const newOptions = [...this.options]
- const index = R.findIndex(R.propEq('id', this.current.id))(newOptions)
- if (index !== -1) {
- newOptions.splice(index, 1)
- }
- if (newOptions.length) {
- await this.$emit('update-options', newOptions)
- }
- await this.pm.delete({
- id: this.current.id,
- })
- // 使用删除后的列表首项,避免 update-options 尚未反映到 tabs 时仍用旧的 options[0]
- const next = newOptions.length ? newOptions[0] : this.options[0]
- this.$emit('select', next)
- } catch (error) {
- throw error
- }
- },
- })
- },
- async handleCopy () {
- try {
- // 检查是否已经创建了dashboard配置
- const optionsCreated = await this.checkOptionsCreated()
- if (!optionsCreated) {
- await this.initOptions()
- }
- // 更新options
- const newOptions = [...this.options]
- const id = `dashboard-${this.scope}-panel-${uuid(16)}`
- const item = {
- name: this.genName(this.current.name),
- id,
- }
- newOptions.push(item)
- await this.$emit('update-options', newOptions)
- // 创建panel数据配置
- const panelData = {}
- if (R.is(Array, this.data)) {
- for (let i = 0, len = this.data.length; i < len; i++) {
- panelData[`dashboard-item-${uuid(32)}`] = this.data[i]
- }
- } else {
- for (const key in this.data) {
- panelData[`dashboard-item-${uuid(32)}`] = this.data[key]
- }
- }
- await this.pm.create({
- data: {
- name: id,
- value: panelData,
- },
- })
- this.$emit('select', item)
- } catch (error) {
- throw error
- }
- },
- // 生成面板名称,如果已存在默认+1
- genName (name) {
- const existNames = this.options.map(item => item.name)
- let num = 1
- let newName = name
- while (existNames.includes(newName)) {
- newName = `${newName}-${num++}`
- }
- return newName
- },
- // 生成导出及克隆的数据
- genExportData () {
- const ret = {
- scope: this.scope,
- name: this.current.name,
- items: [],
- }
- R.forEachObjIndexed((value, key) => {
- ret.items.push(value)
- }, this.data)
- const data = Base64.encode(JSON.stringify(ret))
- return data
- },
- handleRefresh () {
- this.$emit('refresh')
- },
- handleShare () {
- this.createDialog('CommonDialog', {
- header: this.$t('common_104', ['']),
- body: () => {
- return [
- <a-alert class="mb-2" type="warning">
- <div slot="message">{ this.$t('dashbaord.panel_shared_tip') }</div>
- </a-alert>,
- <dialog-selected-tips count={1} action={this.$t('common_104', [''])} name={this.$t('dashboard.text_109')} />,
- ]
- },
- ok: async () => {
- await this.$store.dispatch('widgetSetting/putFetchWidgetSettingValue', {
- [`dashboard-${this.scope}`]: this.data,
- })
- this.$message.success(this.$t('compute.text_423'))
- },
- })
- },
- },
- }
- </script>
- <style lang="less" scoped>
- @import '~@/styles/less/theme';
- .wrap {
- border-bottom: 1px solid #EDEDED;
- }
- .item {
- padding: 12px 16px;
- margin: 0 32px 0 0;
- cursor: pointer;
- position: relative;
- color: rgba(0, 0, 0, 0.45);
- &:last-child {
- margin-right: 0;
- }
- &.active {
- border-bottom: 1px solid @primary-color;
- color: @primary-color;
- font-weight: bold;
- }
- &:hover {
- color: @primary-color;
- .handle {
- visibility: visible;
- }
- }
- .handle {
- cursor: move;
- visibility: hidden;
- position: absolute;
- left: 0;
- top: 4px;
- color: rgba(0, 0, 0, 0.65);
- }
- }
- .action-btn {
- color: rgba(0, 0, 0, 0.65);
- &:hover {
- color: #40a9ff;
- }
- }
- </style>
|