| // Licensed to the Apache Software Foundation (ASF) under one | |
| // or more contributor license agreements. See the NOTICE file | |
| // distributed with this work for additional information | |
| // regarding copyright ownership. The ASF licenses this file | |
| // to you under the Apache License, Version 2.0 (the | |
| // "License"); you may not use this file except in compliance | |
| // with the License. You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, | |
| // software distributed under the License is distributed on an | |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| // KIND, either express or implied. See the License for the | |
| // specific language governing permissions and limitations | |
| // under the License. | |
| <template> | |
| <div class="side-setting"> | |
| <setting-item :title="$t('label.theme.page.style.setting')" view-type="item"> | |
| <a-radio-group | |
| class="setting-group" | |
| name="themeGroup" | |
| v-model:value="layoutMode" | |
| @change="switchLayoutMode"> | |
| <setting-item | |
| view-type="radio-group" | |
| :items="pageStyles" | |
| :checked="layoutMode"></setting-item> | |
| </a-radio-group> | |
| </setting-item> | |
| <setting-item :title="$t('label.theme.color')" view-type="item" style="display: block;"> | |
| <a-radio-group | |
| class="setting-group" | |
| name="colorGroup" | |
| :default-value="colorPick" | |
| @change="switchColor"> | |
| <setting-item | |
| view-type="radio-group" | |
| :items="colors" | |
| :checked="colorPick"></setting-item> | |
| </a-radio-group> | |
| <a-divider style="margin-top: 45px;" /> | |
| </setting-item> | |
| <setting-item | |
| v-if="!projectView" | |
| :title="$t('label.theme.navigation.setting')" | |
| view-type="item"> | |
| <a-list :split="false"> | |
| <a-list-item> | |
| <div class="input-group"> | |
| <label>{{ $t('label.theme.navigation.bgColor') }}</label> | |
| <div class="color-picker" :style="{ backgroundColor: navBgColorPick }"> | |
| <a-input | |
| :disabled="layoutMode === 'dark'" | |
| type="color" | |
| v-model:value="navBgColorPick" | |
| @blur="(e) => updateSetting('@navigation-background-color', e.target.value)" /> | |
| </div> | |
| </div> | |
| </a-list-item> | |
| <a-list-item> | |
| <div class="input-group"> | |
| <label>{{ $t('label.theme.navigation.txtColor') }}</label> | |
| <div class="color-picker" :style="{ backgroundColor: navTextColorPick }"> | |
| <a-input | |
| :disabled="layoutMode === 'dark'" | |
| type="color" | |
| v-model:value="navTextColorPick" | |
| @blur="(e) => updateSetting('@navigation-text-color', e.target.value)" /> | |
| </div> | |
| </div> | |
| </a-list-item> | |
| </a-list> | |
| </setting-item> | |
| <setting-item | |
| v-if="projectView" | |
| :title="$t('label.theme.project.navigation.setting')" | |
| view-type="item"> | |
| <a-list :split="false"> | |
| <a-list-item> | |
| <div class="input-group"> | |
| <label>{{ $t('label.theme.navigation.bgColor') }}</label> | |
| <div class="color-picker" :style="{ backgroundColor: projectNavBgColorPick }"> | |
| <a-input | |
| type="color" | |
| v-model:value="projectNavBgColorPick" | |
| @blur="(e) => updateSetting('@project-nav-background-color', e.target.value)" /> | |
| </div> | |
| </div> | |
| </a-list-item> | |
| <a-list-item> | |
| <div class="input-group"> | |
| <label>{{ $t('label.theme.navigation.txtColor') }}</label> | |
| <div class="color-picker" :style="{ backgroundColor: projectNavTextColorPick }"> | |
| <a-input | |
| type="color" | |
| v-model:value="projectNavTextColorPick" | |
| @blur="(e) => updateSetting('@project-nav-text-color', e.target.value)" /> | |
| </div> | |
| </div> | |
| </a-list-item> | |
| </a-list> | |
| </setting-item> | |
| <div class="setting-action"> | |
| <a-divider style="margin: 15px 0;" /> | |
| <a-alert class="setting-action-alert" :message="$t('label.theme.alert')" type="warning" show-icon /> | |
| <a-button | |
| class="setting-action-btn" | |
| @click="downloadSetting"> | |
| <template #icon><download-outlined /></template> | |
| {{ $t('label.download.setting') }} | |
| </a-button> | |
| <a-button | |
| class="setting-action-btn" | |
| @click="resetSetting"> | |
| <template #icon><undo-outlined /></template> | |
| {{ $t('label.reset.to.default') }} | |
| </a-button> | |
| </div> | |
| </div> | |
| </template> | |
| <script> | |
| import SettingItem from '@/components/view/SettingItem' | |
| export default { | |
| name: 'Setting', | |
| components: { | |
| SettingItem | |
| }, | |
| props: { | |
| visible: { | |
| type: Boolean, | |
| default: false | |
| } | |
| }, | |
| data () { | |
| return { | |
| layoutMode: this.$config.theme['@layout-mode'] || 'light', | |
| colorPick: this.$config.theme['@primary-color'], | |
| navBgColorPick: this.$config.theme['@navigation-background-color'], | |
| navTextColorPick: this.$config.theme['@navigation-text-color'], | |
| projectNavBgColorPick: this.$config.theme['@project-nav-background-color'], | |
| projectNavTextColorPick: this.$config.theme['@project-nav-text-color'], | |
| uiSettings: {}, | |
| originalSetting: {} | |
| } | |
| }, | |
| computed: { | |
| projectView () { | |
| return Boolean(this.$store.getters.project && this.$store.getters.project.id) | |
| }, | |
| pageStyles () { | |
| const arrStyle = [ | |
| { | |
| name: 'light', | |
| type: 'image-checkbox', | |
| icon: 'light' | |
| }, | |
| { | |
| name: 'dark', | |
| type: 'image-checkbox', | |
| icon: 'dark' | |
| } | |
| ] | |
| return arrStyle | |
| }, | |
| colors () { | |
| return [ | |
| { | |
| name: 'daybreak.blue', | |
| type: 'color-checkbox', | |
| color: '#1890ff' | |
| }, | |
| { | |
| name: 'dust.red', | |
| type: 'color-checkbox', | |
| color: '#f5222d' | |
| }, | |
| { | |
| name: 'volcano', | |
| type: 'color-checkbox', | |
| color: '#fa541c' | |
| }, | |
| { | |
| name: 'sunset.orange', | |
| type: 'color-checkbox', | |
| color: '#faad14' | |
| }, | |
| { | |
| name: 'cyan', | |
| type: 'color-checkbox', | |
| color: '#13c2c2' | |
| }, | |
| { | |
| name: 'polar.green', | |
| type: 'color-checkbox', | |
| color: '#52c41a' | |
| }, | |
| { | |
| name: 'geek.blue', | |
| type: 'color-checkbox', | |
| color: '#2f54eb' | |
| }, | |
| { | |
| name: 'golden.purple', | |
| type: 'color-checkbox', | |
| color: '#722ed1' | |
| } | |
| ] | |
| } | |
| }, | |
| inject: ['parentToggleSetting'], | |
| watch: { | |
| projectView () { | |
| this.fetchData() | |
| } | |
| }, | |
| created () { | |
| this.fetchData() | |
| }, | |
| methods: { | |
| fetchData () { | |
| this.originalSetting = Object.assign({}, this.$config.theme) | |
| this.layoutMode = this.$config.theme['@layout-mode'] || 'light' | |
| this.uiSettings = this.$config.theme | |
| }, | |
| switchLayoutMode () { | |
| this.$store.dispatch('SetDarkMode', (this.layoutMode === 'dark')) | |
| this.updateSetting('@layout-mode', this.layoutMode) | |
| }, | |
| switchColor (e) { | |
| this.colorPick = e.target.value | |
| this.updateSetting('@primary-color', this.colorPick) | |
| }, | |
| updateSetting (name, value) { | |
| this.uiSettings[name] = value | |
| if (['@navigation-background-color'].includes(name)) { | |
| this.uiSettings['@logo-background-color'] = value | |
| } | |
| window.less.modifyVars(this.uiSettings) | |
| }, | |
| onClose () { | |
| this.parentToggleSetting(false) | |
| }, | |
| downloadSetting () { | |
| this.downloadObjectAsJson(this.$config.theme) | |
| }, | |
| resetSetting () { | |
| this.uiSettings = {} | |
| this.layoutMode = 'light' | |
| this.colorPick = this.originalSetting['@primary-color'] | |
| this.navBgColorPick = this.originalSetting['@navigation-background-color'] | |
| this.navTextColorPick = this.originalSetting['@navigation-text-color'] | |
| this.projectNavBgColorPick = this.originalSetting['@project-nav-background-color'] | |
| this.projectNavTextColorPick = this.originalSetting['@project-nav-text-color'] | |
| this.switchLayoutMode() | |
| this.$config.theme = this.originalSetting | |
| window.less.modifyVars(this.$config.theme) | |
| this.$message.success(this.$t('label.success')) | |
| }, | |
| downloadObjectAsJson (exportObj) { | |
| const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(exportObj, null, 2)) | |
| const downloadAnchorNode = document.createElement('a') | |
| downloadAnchorNode.setAttribute('href', dataStr) | |
| downloadAnchorNode.setAttribute('download', 'theme.json') | |
| document.body.appendChild(downloadAnchorNode) | |
| downloadAnchorNode.click() | |
| downloadAnchorNode.remove() | |
| } | |
| } | |
| } | |
| </script> | |
| <style lang="less" scoped> | |
| .side-setting { | |
| min-height: 100%; | |
| font-size: 14px; | |
| line-height: 1.5; | |
| word-wrap: break-word; | |
| position: relative; | |
| padding: 20px 0; | |
| .flex{ | |
| display: flex; | |
| } | |
| .select-item{ | |
| width: 80px; | |
| } | |
| } | |
| .setting-group { | |
| width: 100%; | |
| } | |
| .input-group { | |
| display: inline-flex; | |
| width: 100%; | |
| position: relative; | |
| .color-picker { | |
| position: absolute; | |
| width: 20px; | |
| height: 20px; | |
| overflow: hidden; | |
| top: 0; | |
| right: 0; | |
| border: 1px solid; | |
| cursor: pointer; | |
| .ant-input { | |
| opacity: 0; | |
| height: 20px; | |
| width: 20px; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| cursor: pointer; | |
| } | |
| } | |
| } | |
| .setting-action { | |
| width: 100%; | |
| padding: 0 24px; | |
| &-alert { | |
| display: flex; | |
| flex-direction: row; | |
| align-items: baseline; | |
| margin: 20px 0 8px; | |
| word-break: break-word; | |
| position: relative; | |
| :deep(.ant-alert-icon) { | |
| } | |
| } | |
| &-btn { | |
| width: 100%; | |
| margin-bottom: 5px; | |
| } | |
| } | |
| </style> |