feat: 添加深色模式和照片预览优化
- 新增全局深色模式切换功能,支持手动切换和跟随系统主题 - 优化照片墙预览,使用ElImageViewer组件支持左右切换 - 引入Element Plus深色模式相关样式文件 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
b68de2e9bf
commit
3ca39fc010
1
components.d.ts
vendored
1
components.d.ts
vendored
@ -23,6 +23,7 @@ declare module '@vue/runtime-core' {
|
|||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
ElHeader: typeof import('element-plus/es')['ElHeader']
|
ElHeader: typeof import('element-plus/es')['ElHeader']
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
ElMain: typeof import('element-plus/es')['ElMain']
|
ElMain: typeof import('element-plus/es')['ElMain']
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import type { RouteLocationNormalized, NavigationGuardNext } from 'vue-router'
|
|||||||
import { ElLoading } from 'element-plus'
|
import { ElLoading } from 'element-plus'
|
||||||
import 'element-plus/theme-chalk/el-message.css'
|
import 'element-plus/theme-chalk/el-message.css'
|
||||||
import 'element-plus/theme-chalk/el-message-box.css'
|
import 'element-plus/theme-chalk/el-message-box.css'
|
||||||
|
import 'element-plus/theme-chalk/el-image-viewer.css'
|
||||||
|
import 'element-plus/theme-chalk/dark/css-vars.css'
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
|
|
||||||
// 全局路由导航前置守卫
|
// 全局路由导航前置守卫
|
||||||
|
|||||||
@ -3,6 +3,10 @@
|
|||||||
<el-header class="layout-header">
|
<el-header class="layout-header">
|
||||||
<div class="main-title">博客管理后台</div>
|
<div class="main-title">博客管理后台</div>
|
||||||
<div class="nav-btns-right">
|
<div class="nav-btns-right">
|
||||||
|
<el-button link @click="toggleDarkMode" style="color: #fff; font-size: 18px; margin-right: 12px;">
|
||||||
|
<Moon v-if="!isDark" style="width: 18px" />
|
||||||
|
<Sunny v-else style="width: 18px" />
|
||||||
|
</el-button>
|
||||||
<el-dropdown @command="dropdownMenuCommand">
|
<el-dropdown @command="dropdownMenuCommand">
|
||||||
<el-button link type="primary">
|
<el-button link type="primary">
|
||||||
<UserFilled style="width: 18px" />
|
<UserFilled style="width: 18px" />
|
||||||
@ -92,6 +96,32 @@ const defaultActiveMenuKey = ref<string | null>(null)
|
|||||||
const openMenuNames = ref<string[]>([])
|
const openMenuNames = ref<string[]>([])
|
||||||
const mainViewReady = ref(false)
|
const mainViewReady = ref(false)
|
||||||
|
|
||||||
|
const isDark = ref(false)
|
||||||
|
function applyDarkMode(dark: boolean) {
|
||||||
|
isDark.value = dark
|
||||||
|
document.documentElement.classList.toggle('dark', dark)
|
||||||
|
}
|
||||||
|
function toggleDarkMode() {
|
||||||
|
const next = !isDark.value
|
||||||
|
applyDarkMode(next)
|
||||||
|
localStorage.setItem('theme_mode', next ? 'dark' : 'light')
|
||||||
|
}
|
||||||
|
// 初始化主题
|
||||||
|
;(() => {
|
||||||
|
const saved = localStorage.getItem('theme_mode')
|
||||||
|
if (saved) {
|
||||||
|
applyDarkMode(saved === 'dark')
|
||||||
|
} else {
|
||||||
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
||||||
|
applyDarkMode(prefersDark)
|
||||||
|
}
|
||||||
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
||||||
|
if (!localStorage.getItem('theme_mode')) {
|
||||||
|
applyDarkMode(e.matches)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})()
|
||||||
|
|
||||||
const changePwdModal = ref(false)
|
const changePwdModal = ref(false)
|
||||||
const changePwdLoading = ref(false)
|
const changePwdLoading = ref(false)
|
||||||
const changePwdForm = ref<VForm>()
|
const changePwdForm = ref<VForm>()
|
||||||
|
|||||||
@ -75,10 +75,16 @@
|
|||||||
@current-change="pageChange">
|
@current-change="pageChange">
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
</div>
|
</div>
|
||||||
|
<el-image-viewer
|
||||||
|
v-if="previewVisible"
|
||||||
|
:url-list="previewUrlList"
|
||||||
|
:initial-index="previewIndex"
|
||||||
|
@close="previewVisible = false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, h } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useStore } from 'vuex'
|
import { useStore } from 'vuex'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { MsgResult, Page } from '@/model/common.dto'
|
import { MsgResult, Page } from '@/model/common.dto'
|
||||||
@ -106,8 +112,11 @@ const store = useStore()
|
|||||||
const { loading, total, search, setLoadData, loadDataBase, reset, pageChange, pageSizeChange } = useBaseList(new PhotoWallPage())
|
const { loading, total, search, setLoadData, loadDataBase, reset, pageChange, pageSizeChange } = useBaseList(new PhotoWallPage())
|
||||||
|
|
||||||
const allowUploadExt = ['jpg', 'jpeg', 'png']
|
const allowUploadExt = ['jpg', 'jpeg', 'png']
|
||||||
const photowallData = ref([])
|
const photowallData = ref<PhotoWallModel[]>([])
|
||||||
const isUploading = ref(false)
|
const isUploading = ref(false)
|
||||||
|
const previewVisible = ref(false)
|
||||||
|
const previewUrlList = ref<string[]>([])
|
||||||
|
const previewIndex = ref(0)
|
||||||
|
|
||||||
let selectedData: string[] = []
|
let selectedData: string[] = []
|
||||||
|
|
||||||
@ -157,15 +166,11 @@ function uploadError(error: Error) {
|
|||||||
ElMessage.error(error.message)
|
ElMessage.error(error.message)
|
||||||
}
|
}
|
||||||
async function preview(row: PhotoWallModel) {
|
async function preview(row: PhotoWallModel) {
|
||||||
const previewHeight = Math.floor(row.height * (500 / row.width))
|
|
||||||
const pictureCdn = await http.get('/api/v2/common/config/picture_cdn')
|
const pictureCdn = await http.get('/api/v2/common/config/picture_cdn')
|
||||||
ElMessageBox({
|
const index = photowallData.value.findIndex(item => item._id === row._id)
|
||||||
title: '图片预览',
|
previewUrlList.value = photowallData.value.map(item => `${pictureCdn}/${item.name}`)
|
||||||
message: h('img', { style: `width:500px;height:${previewHeight}px;`, src: `${pictureCdn}/${row.name}` }, ''),
|
previewIndex.value = index >= 0 ? index : 0
|
||||||
showCancelButton: false,
|
previewVisible.value = true
|
||||||
confirmButtonText: '关闭',
|
|
||||||
customStyle: {width: '530px', maxWidth: 'unset'}
|
|
||||||
}).catch(() => {})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// created
|
// created
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user