Files
continew-admin-ui/src/layout/components/HeaderRightBar/SettingDrawer.vue
kiki1373639299 704aacc38f feat: 增强布局组件(同步GI-DEMO),支持更多布局选项并优化布局切换功能
Co-authored-by: kiki1373639299<zkai0106@163.com>



# message auto-generated for no-merge-commit merge:
!11 merge dev into dev

feat: 增强布局组件(同步GI-DEMO),支持更多布局选项并优化布局切换功能

Created-by: kiki1373639299
Commit-by: kiki1373639299
Merged-by: Charles_7c
Description: <!--
  非常感谢您的 PR!在提交之前,请务必确保您 PR 的代码经过了完整测试,并且通过了代码规范检查。
-->

<!-- 在 [] 中输入 x 来勾选) -->

## PR 类型

<!-- 您的 PR 引入了哪种类型的变更? -->
<!-- 只支持选择一种类型,如果有多种类型,可以在更新日志中增加 “类型” 列。 -->

- [X] 新 feature
- [ ] Bug 修复
- [ ] 功能增强
- [ ] 文档变更
- [ ] 代码样式变更
- [ ] 重构
- [ ] 性能改进
- [ ] 单元测试
- [ ] CI/CD
- [ ] 其他

## PR 目的
同步GI-DEMO系统布局,并自定义样式增强
<!-- 描述一下您的 PR 解决了什么问题。如果可以,请链接到相关 issues。 -->

## 解决方案

<!-- 详细描述您是如何解决的问题 -->

## PR 测试

<!-- 如果可以,请为您的 PR 添加或更新单元测试。 -->
<!-- 请描述一下您是如何测试 PR 的。例如:创建/更新单元测试或添加相关的截图。 -->

## Changelog

| 模块  | Changelog | Related issues |
|-----|-----------| -------------- |
|     |           |                |

<!-- 如果有多种类型的变更,可以在变更日志表中增加 “类型” 列,该列的值与上方 “PR 类型” 相同。 -->
<!-- Related issues 格式为 Closes #<issue号>,或者 Fixes #<issue号>,或者 Resolves #<issue号>。 -->

## 其他信息

<!-- 请描述一下还有哪些注意事项。例如:如果引入了一个不向下兼容的变更,请描述其影响。 -->

## 提交前确认

- [X] PR 代码经过了完整测试,并且通过了代码规范检查
- [ ] 已经完整填写 Changelog,并链接到了相关 issues
- [X] PR 代码将要提交到 dev 分支

See merge request: continew/continew-admin-ui!11
2025-11-05 11:36:02 +08:00

203 lines
6.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<a-drawer v-model:visible="visible" title="项目配置" width="300px" unmount-on-close :footer="false">
<a-space :size="15" direction="vertical" fill>
<a-alert v-if="settingOpen" :show-icon="false" type="info">
复制配置按钮并将配置粘贴到 src/config/settings.ts 文件中
</a-alert>
<a-divider v-if="settingOpen" orientation="center">系统布局</a-divider>
<a-row v-if="settingOpen" :gutter="[8, 8]">
<a-col v-for="item in LAYOUT_OPTIONS" :key="item.value" :span="8">
<LayoutItem :mode="item.value" :name="item.label" @click="toggleLayout(item.value)" />
</a-col>
</a-row>
<a-divider orientation="center">系统主题</a-divider>
<a-row justify="center">
<ColorPicker
theme="dark" :color="appStore.themeColor" :sucker-hide="true" :colors-default="defaultColorList"
@change-color="changeColor"
></ColorPicker>
</a-row>
<a-divider v-if="settingOpen" orientation="center">界面显示</a-divider>
<a-descriptions v-if="settingOpen" :column="1" :align="{ value: 'right' }" :value-style="{ paddingRight: 0 }">
<a-descriptions-item label="页签显示">
<a-switch v-model="appStore.tab" />
</a-descriptions-item>
<a-descriptions-item label="页签风格">
<a-select
v-model="appStore.tabMode" placeholder="请选择" :options="tabModeList" :disabled="!appStore.tab"
:trigger-props="{ autoFitPopupMinWidth: true }" :style="{ width: '120px' }"
>
</a-select>
</a-descriptions-item>
<a-descriptions-item label="动画显示">
<a-switch v-model="appStore.animate" />
</a-descriptions-item>
<a-descriptions-item label="动画显示">
<a-select
v-model="appStore.animateMode" placeholder="请选择" :options="animateModeList"
:disabled="!appStore.animate" :style="{ width: '120px' }"
>
</a-select>
</a-descriptions-item>
<a-descriptions-item label="深色菜单">
<a-switch v-model="appStore.menuDark" />
</a-descriptions-item>
<a-descriptions-item label="手风琴效果">
<a-switch v-model="appStore.menuAccordion" />
</a-descriptions-item>
<a-descriptions-item label="版权显示">
<a-switch v-model="appStore.copyrightDisplay" />
</a-descriptions-item>
<a-descriptions-item label="水印">
<a-switch v-model="appStore.isOpenWatermark" />
</a-descriptions-item>
<a-descriptions-item label="水印信息">
<a-input v-model="appStore.watermark" placeholder="留空则显示用户名" />
</a-descriptions-item>
</a-descriptions>
<a-divider orientation="center">其它</a-divider>
<a-descriptions :column="1" :align="{ value: 'right' }" :value-style="{ paddingRight: 0 }">
<a-descriptions-item label="色弱模式">
<a-switch v-model="appStore.enableColorWeaknessMode" />
</a-descriptions-item>
<a-descriptions-item v-if="settingOpen" label="哀悼模式">
<a-switch v-model="appStore.enableMourningMode" />
</a-descriptions-item>
</a-descriptions>
<a-space v-if="settingOpen" direction="vertical" fill>
<a-button type="primary" long @click="copySettings">
<template #icon>
<icon-copy />
</template>
复制配置
</a-button>
</a-space>
</a-space>
</a-drawer>
</template>
<script setup lang="ts">
import { ColorPicker } from 'vue-color-kit'
import 'vue-color-kit/dist/vue-color-kit.css'
import { useClipboard } from '@vueuse/core'
import { Message } from '@arco-design/web-vue'
import LayoutItem from './components/LayoutItem.vue'
import { useAppStore } from '@/stores'
defineOptions({ name: 'SettingDrawer' })
const appStore = useAppStore()
const visible = ref(false)
const settingOpen = JSON.parse(import.meta.env.VITE_APP_SETTING)
interface LayoutItemProps { label: string, value: App.AppSettings['layout'] }
/** 布局选项 */
const LAYOUT_OPTIONS: LayoutItemProps[] = [
{ label: '默认布局', value: 'left' },
{ label: '混合布局', value: 'mix' },
{ label: '顶部布局', value: 'top' },
{ label: '双列布局', value: 'columns' },
]
const tabModeList: App.TabItem[] = [
{ label: '卡片', value: 'card' },
{ label: '间隔卡片', value: 'card-gutter' },
{ label: '圆角', value: 'rounded' },
]
const animateModeList: App.AnimateItem[] = [
{ label: '默认', value: 'zoom-fade' },
{ label: '滑动', value: 'fade-slide' },
{ label: '渐变', value: 'fade' },
{ label: '底部滑出', value: 'fade-bottom' },
{ label: '缩放消退', value: 'fade-scale' },
]
const open = () => {
visible.value = true
}
// 默认显示的主题色列表
const defaultColorList = [
'#165DFF',
'#409EFF',
'#18A058',
'#2d8cf0',
'#007AFF',
'#5ac8fa',
'#5856D6',
'#536dfe',
'#9c27b0',
'#AF52DE',
'#0096c7',
'#00C1D4',
'#43a047',
'#e53935',
'#f4511e',
'#6d4c41',
]
interface ColorObj {
hex: string
hsv: { h: number, s: number, v: number }
rgba: { r: number, g: number, b: number, a: number }
}
// 改变主题色
const changeColor = (colorObj: ColorObj) => {
if (!/^#[0-9A-Z]{6}/i.test(colorObj.hex)) return
appStore.setThemeColor(colorObj.hex)
}
// 复制配置
const copySettings = () => {
const settings: App.AppSettings = {
theme: 'light',
themeColor: appStore.themeColor,
tab: appStore.tab,
tabMode: appStore.tabMode,
animate: appStore.animate,
animateMode: appStore.animateMode,
menuCollapse: appStore.menuCollapse,
menuAccordion: appStore.menuAccordion,
menuDark: appStore.menuDark,
copyrightDisplay: appStore.copyrightDisplay,
layout: appStore.layout,
isOpenWatermark: appStore.isOpenWatermark,
watermark: appStore.watermark,
enableColorWeaknessMode: appStore.enableColorWeaknessMode,
enableMourningMode: appStore.enableMourningMode,
}
const settingJson = JSON.stringify(settings, null, 2)
const { isSupported, copy } = useClipboard({ source: settingJson })
if (isSupported) {
copy(settingJson)
Message.success({ content: '复制成功!' })
} else {
Message.error({ content: '请检查浏览器权限是否开启' })
}
}
/** 切换布局 */
const toggleLayout = (layout: App.AppSettings['layout']) => {
appStore.layout = layout
}
defineExpose({ open })
</script>
<style scoped lang="scss">
:deep(.arco-descriptions-item-label-block) {
color: var(--color-text-1);
}
.layout-text {
font-size: 12px;
text-align: center;
color: var(--color-text-2);
margin-top: 4px;
}
</style>