feat: 同步master
This commit is contained in:
parent
9eb1356c4e
commit
1af33d8a7e
30
package.json
30
package.json
|
@ -29,7 +29,7 @@
|
|||
"@faker-js/faker": "^8.3.1",
|
||||
"@iconify/iconify": "^3.1.1",
|
||||
"@iconify/vue": "^4.1.1",
|
||||
"@vueuse/core": "^10.7.1",
|
||||
"@vueuse/core": "^10.7.2",
|
||||
"@wangeditor/editor": "^5.1.23",
|
||||
"@wangeditor/editor-for-vue": "^5.1.10",
|
||||
"@zxcvbn-ts/core": "^3.0.4",
|
||||
|
@ -40,7 +40,7 @@
|
|||
"driver.js": "^1.3.1",
|
||||
"echarts": "^5.4.3",
|
||||
"echarts-wordcloud": "^2.1.0",
|
||||
"element-plus": "^2.4.4",
|
||||
"element-plus": "^2.5.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"mitt": "^3.0.1",
|
||||
"nprogress": "^0.2.0",
|
||||
|
@ -49,8 +49,8 @@
|
|||
"qrcode": "^1.5.3",
|
||||
"qs": "^6.11.2",
|
||||
"url": "^0.11.3",
|
||||
"vue": "3.4.6",
|
||||
"vue-draggable-plus": "^0.3.4",
|
||||
"vue": "3.4.14",
|
||||
"vue-draggable-plus": "^0.3.5",
|
||||
"vue-i18n": "9.9.0",
|
||||
"vue-json-pretty": "^2.3.0",
|
||||
"vue-router": "^4.2.5",
|
||||
|
@ -60,21 +60,21 @@
|
|||
"devDependencies": {
|
||||
"@commitlint/cli": "^18.4.4",
|
||||
"@commitlint/config-conventional": "^18.4.4",
|
||||
"@iconify/json": "^2.2.166",
|
||||
"@iconify/json": "^2.2.169",
|
||||
"@intlify/unplugin-vue-i18n": "^2.0.0",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/inquirer": "^9.0.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"@types/node": "^20.10.7",
|
||||
"@types/node": "^20.11.3",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@types/qs": "^6.9.11",
|
||||
"@types/sortablejs": "^1.15.7",
|
||||
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
||||
"@typescript-eslint/parser": "^6.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "^6.19.0",
|
||||
"@typescript-eslint/parser": "^6.19.0",
|
||||
"@unocss/transformer-variant-group": "^0.58.3",
|
||||
"@vitejs/plugin-legacy": "^5.2.0",
|
||||
"@vitejs/plugin-vue": "^5.0.2",
|
||||
"@vitejs/plugin-vue": "^5.0.3",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"autoprefixer": "^10.4.16",
|
||||
"chalk": "^5.3.0",
|
||||
|
@ -82,8 +82,8 @@
|
|||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-define-config": "^2.1.0",
|
||||
"eslint-plugin-prettier": "^5.1.2",
|
||||
"eslint-plugin-vue": "^9.19.2",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-vue": "^9.20.1",
|
||||
"esno": "^4.0.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"husky": "^8.0.3",
|
||||
|
@ -92,11 +92,11 @@
|
|||
"lint-staged": "^15.2.0",
|
||||
"plop": "^4.0.1",
|
||||
"postcss": "^8.4.33",
|
||||
"postcss-html": "^1.5.0",
|
||||
"postcss-html": "^1.6.0",
|
||||
"postcss-less": "^6.0.0",
|
||||
"prettier": "^3.1.1",
|
||||
"prettier": "^3.2.2",
|
||||
"rimraf": "^5.0.5",
|
||||
"rollup": "^4.9.4",
|
||||
"rollup": "^4.9.5",
|
||||
"rollup-plugin-visualizer": "^5.12.0",
|
||||
"stylelint": "^16.1.0",
|
||||
"stylelint-config-html": "^1.1.0",
|
||||
|
@ -109,7 +109,7 @@
|
|||
"vite": "5.0.11",
|
||||
"vite-plugin-ejs": "^1.7.0",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-mock": "^2.9.6",
|
||||
"vite-plugin-mock": "2.9.6",
|
||||
"vite-plugin-progress": "^0.0.7",
|
||||
"vite-plugin-purge-icons": "^0.10.0",
|
||||
"vite-plugin-style-import": "2.0.0",
|
||||
|
|
16
src/App.vue
16
src/App.vue
|
@ -2,9 +2,7 @@
|
|||
import { computed } from 'vue'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { ConfigGlobal } from '@/components/ConfigGlobal'
|
||||
import { isDark } from '@/utils/is'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { useStorage } from '@/hooks/web/useStorage'
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
|
@ -16,19 +14,7 @@ const currentSize = computed(() => appStore.getCurrentSize)
|
|||
|
||||
const greyMode = computed(() => appStore.getGreyMode)
|
||||
|
||||
const { getStorage } = useStorage()
|
||||
|
||||
// 根据浏览器当前主题设置系统主题色
|
||||
const setDefaultTheme = () => {
|
||||
if (getStorage('isDark') !== null) {
|
||||
appStore.setIsDark(getStorage('isDark'))
|
||||
return
|
||||
}
|
||||
const isDarkTheme = isDark()
|
||||
appStore.setIsDark(isDarkTheme)
|
||||
}
|
||||
|
||||
setDefaultTheme()
|
||||
appStore.initTheme()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { AxiosResponse, InternalAxiosRequestConfig } from './types'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import qs from 'qs'
|
||||
import { SUCCESS_CODE } from '@/constants'
|
||||
import { SUCCESS_CODE, TRANSFORM_REQUEST_DATA } from '@/constants'
|
||||
import { useUserStoreWithOut } from '@/store/modules/user'
|
||||
import { objToFormData } from '@/utils'
|
||||
|
||||
const defaultRequestInterceptors = (config: InternalAxiosRequestConfig) => {
|
||||
if (
|
||||
|
@ -10,6 +11,12 @@ const defaultRequestInterceptors = (config: InternalAxiosRequestConfig) => {
|
|||
config.headers['Content-Type'] === 'application/x-www-form-urlencoded'
|
||||
) {
|
||||
config.data = qs.stringify(config.data)
|
||||
} else if (
|
||||
TRANSFORM_REQUEST_DATA &&
|
||||
config.method === 'post' &&
|
||||
config.headers['Content-Type'] === 'multipart/form-data'
|
||||
) {
|
||||
config.data = objToFormData(config.data)
|
||||
}
|
||||
if (config.method === 'get' && config.params) {
|
||||
let url = config.url as string
|
||||
|
|
|
@ -230,7 +230,7 @@ export default defineComponent({
|
|||
const { schema = [], isCol } = unref(getProps)
|
||||
|
||||
return schema
|
||||
.filter((v) => !v.remove)
|
||||
.filter((v) => !v.remove && !v.hidden)
|
||||
.map((item) => {
|
||||
// 如果是 Divider 组件,需要自己占用一行
|
||||
const isDivider = item.component === 'Divider'
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import { ElDrawer, ElDivider, ElMessage } from 'element-plus'
|
||||
import { ref, unref, computed } from 'vue'
|
||||
import { ref, unref } from 'vue'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { ThemeSwitch } from '@/components/ThemeSwitch'
|
||||
import { colorIsDark, lighten, hexToRGB } from '@/utils/color'
|
||||
import { useCssVar } from '@vueuse/core'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { trim, setCssVar, getCssVar } from '@/utils'
|
||||
|
@ -24,8 +23,6 @@ const appStore = useAppStore()
|
|||
|
||||
const { t } = useI18n()
|
||||
|
||||
const layout = computed(() => appStore.getLayout)
|
||||
|
||||
const drawer = ref(false)
|
||||
|
||||
// 主题色相关
|
||||
|
@ -42,56 +39,14 @@ const setSystemTheme = (color: string) => {
|
|||
const headerTheme = ref(appStore.getTheme.topHeaderBgColor || '')
|
||||
|
||||
const setHeaderTheme = (color: string) => {
|
||||
const isDarkColor = colorIsDark(color)
|
||||
const textColor = isDarkColor ? '#fff' : 'inherit'
|
||||
const textHoverColor = isDarkColor ? lighten(color!, 6) : '#f6f6f6'
|
||||
const topToolBorderColor = isDarkColor ? color : '#eee'
|
||||
setCssVar('--top-header-bg-color', color)
|
||||
setCssVar('--top-header-text-color', textColor)
|
||||
setCssVar('--top-header-hover-color', textHoverColor)
|
||||
appStore.setTheme({
|
||||
topHeaderBgColor: color,
|
||||
topHeaderTextColor: textColor,
|
||||
topHeaderHoverColor: textHoverColor,
|
||||
topToolBorderColor
|
||||
})
|
||||
if (unref(layout) === 'top') {
|
||||
setMenuTheme(color)
|
||||
}
|
||||
appStore.setHeaderTheme(color)
|
||||
}
|
||||
|
||||
// 菜单主题相关
|
||||
const menuTheme = ref(appStore.getTheme.leftMenuBgColor || '')
|
||||
|
||||
const setMenuTheme = (color: string) => {
|
||||
const primaryColor = useCssVar('--el-color-primary', document.documentElement)
|
||||
const isDarkColor = colorIsDark(color)
|
||||
const theme: Recordable = {
|
||||
// 左侧菜单边框颜色
|
||||
leftMenuBorderColor: isDarkColor ? 'inherit' : '#eee',
|
||||
// 左侧菜单背景颜色
|
||||
leftMenuBgColor: color,
|
||||
// 左侧菜单浅色背景颜色
|
||||
leftMenuBgLightColor: isDarkColor ? lighten(color!, 6) : color,
|
||||
// 左侧菜单选中背景颜色
|
||||
leftMenuBgActiveColor: isDarkColor
|
||||
? 'var(--el-color-primary)'
|
||||
: hexToRGB(unref(primaryColor), 0.1),
|
||||
// 左侧菜单收起选中背景颜色
|
||||
leftMenuCollapseBgActiveColor: isDarkColor
|
||||
? 'var(--el-color-primary)'
|
||||
: hexToRGB(unref(primaryColor), 0.1),
|
||||
// 左侧菜单字体颜色
|
||||
leftMenuTextColor: isDarkColor ? '#bfcbd9' : '#333',
|
||||
// 左侧菜单选中字体颜色
|
||||
leftMenuTextActiveColor: isDarkColor ? '#fff' : 'var(--el-color-primary)',
|
||||
// logo字体颜色
|
||||
logoTitleTextColor: isDarkColor ? '#fff' : 'inherit',
|
||||
// logo边框颜色
|
||||
logoBorderColor: isDarkColor ? color : '#eee'
|
||||
}
|
||||
appStore.setTheme(theme)
|
||||
appStore.setCssVarTheme()
|
||||
appStore.setMenuTheme(color)
|
||||
}
|
||||
|
||||
// 监听layout变化,重置一些主题色
|
||||
|
@ -258,23 +213,21 @@ const themeChange = () => {
|
|||
/>
|
||||
|
||||
<!-- 菜单主题 -->
|
||||
<template v-if="layout !== 'top'">
|
||||
<ElDivider>{{ t('setting.menuTheme') }}</ElDivider>
|
||||
<ColorRadioPicker
|
||||
v-model="menuTheme"
|
||||
:schema="[
|
||||
'#fff',
|
||||
'#001529',
|
||||
'#212121',
|
||||
'#273352',
|
||||
'#191b24',
|
||||
'#383f45',
|
||||
'#001628',
|
||||
'#344058'
|
||||
]"
|
||||
@change="setMenuTheme"
|
||||
/>
|
||||
</template>
|
||||
<ElDivider>{{ t('setting.menuTheme') }}</ElDivider>
|
||||
<ColorRadioPicker
|
||||
v-model="menuTheme"
|
||||
:schema="[
|
||||
'#fff',
|
||||
'#001529',
|
||||
'#212121',
|
||||
'#273352',
|
||||
'#191b24',
|
||||
'#383f45',
|
||||
'#001628',
|
||||
'#344058'
|
||||
]"
|
||||
@change="setMenuTheme"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 界面显示 -->
|
||||
|
|
|
@ -69,7 +69,7 @@ const initColumns = (columns: TableColumn[], isReStore = false) => {
|
|||
}
|
||||
return (item.type && !DEFAULT_FILTER_COLUMN.includes(item.type)) || !item.type
|
||||
})
|
||||
if (!unref(oldColumns)) {
|
||||
if (!unref(oldColumns)?.length) {
|
||||
oldColumns.value = cloneDeep(newColumns)
|
||||
}
|
||||
settingColumns.value = cloneDeep(newColumns)
|
||||
|
@ -96,7 +96,8 @@ watch(
|
|||
initColumns(columns)
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
immediate: true,
|
||||
deep: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
|
|
@ -6,7 +6,7 @@ export const SUCCESS_CODE = 0
|
|||
/**
|
||||
* 请求contentType
|
||||
*/
|
||||
export const CONTENT_TYPE = 'application/json'
|
||||
export const CONTENT_TYPE: AxiosContentType = 'application/json'
|
||||
|
||||
/**
|
||||
* 请求超时时间
|
||||
|
@ -27,3 +27,8 @@ export const NO_RESET_WHITE_LIST = ['Redirect', 'Login', 'NoFind', 'Root']
|
|||
* 表格默认过滤列设置字段
|
||||
*/
|
||||
export const DEFAULT_FILTER_COLUMN = ['expand', 'selection']
|
||||
|
||||
/**
|
||||
* 是否根据headers->content-type自动转换数据格式
|
||||
*/
|
||||
export const TRANSFORM_REQUEST_DATA = true
|
||||
|
|
|
@ -78,17 +78,14 @@ const filterSearchSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
|
|||
|
||||
for (let i = 0; i < length; i++) {
|
||||
const schemaItem = crudSchema[i]
|
||||
// 判断是否隐藏
|
||||
if (!schemaItem?.search?.remove) {
|
||||
const searchSchemaItem = {
|
||||
component: schemaItem?.search?.component || 'Input',
|
||||
...schemaItem.search,
|
||||
field: schemaItem.field,
|
||||
label: schemaItem.label
|
||||
}
|
||||
|
||||
searchSchema.push(searchSchemaItem)
|
||||
const searchSchemaItem = {
|
||||
component: schemaItem?.search?.component || 'Input',
|
||||
...schemaItem.search,
|
||||
field: schemaItem.field,
|
||||
label: schemaItem.label
|
||||
}
|
||||
|
||||
searchSchema.push(searchSchemaItem)
|
||||
}
|
||||
|
||||
return searchSchema
|
||||
|
@ -124,16 +121,14 @@ const filterFormSchema = (crudSchema: CrudSchema[]): FormSchema[] => {
|
|||
for (let i = 0; i < length; i++) {
|
||||
const formItem = crudSchema[i]
|
||||
// 判断是否隐藏
|
||||
if (!formItem?.form?.remove) {
|
||||
const formSchemaItem = {
|
||||
component: formItem?.form?.component || 'Input',
|
||||
...formItem.form,
|
||||
field: formItem.field,
|
||||
label: formItem.label
|
||||
}
|
||||
|
||||
formSchema.push(formSchemaItem)
|
||||
const formSchemaItem = {
|
||||
component: formItem?.form?.component || 'Input',
|
||||
...formItem.form,
|
||||
field: formItem.field,
|
||||
label: formItem.label
|
||||
}
|
||||
|
||||
formSchema.push(formSchemaItem)
|
||||
}
|
||||
|
||||
return formSchema
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
import { defineStore } from 'pinia'
|
||||
import { store } from '../index'
|
||||
import { setCssVar, humpToUnderline } from '@/utils'
|
||||
import { mix } from '@/utils/color'
|
||||
import { ElMessage, ComponentSize } from 'element-plus'
|
||||
import { colorIsDark, hexToRGB, lighten, mix } from '@/utils/color'
|
||||
import { unref } from 'vue'
|
||||
import { useCssVar } from '@vueuse/core'
|
||||
import { useDark } from '@vueuse/core'
|
||||
|
||||
interface AppState {
|
||||
breadcrumb: boolean
|
||||
|
@ -270,6 +273,61 @@ export const useAppStore = defineStore('app', {
|
|||
})
|
||||
setCssVar(`--el-color-primary-dark-2`, mix(color, elColorPrimary, 0.2))
|
||||
}
|
||||
},
|
||||
setMenuTheme(color: string) {
|
||||
const primaryColor = useCssVar('--el-color-primary', document.documentElement)
|
||||
const isDarkColor = colorIsDark(color)
|
||||
const theme: Recordable = {
|
||||
// 左侧菜单边框颜色
|
||||
leftMenuBorderColor: isDarkColor ? 'inherit' : '#eee',
|
||||
// 左侧菜单背景颜色
|
||||
leftMenuBgColor: color,
|
||||
// 左侧菜单浅色背景颜色
|
||||
leftMenuBgLightColor: isDarkColor ? lighten(color!, 6) : color,
|
||||
// 左侧菜单选中背景颜色
|
||||
leftMenuBgActiveColor: isDarkColor
|
||||
? 'var(--el-color-primary)'
|
||||
: hexToRGB(unref(primaryColor), 0.1),
|
||||
// 左侧菜单收起选中背景颜色
|
||||
leftMenuCollapseBgActiveColor: isDarkColor
|
||||
? 'var(--el-color-primary)'
|
||||
: hexToRGB(unref(primaryColor), 0.1),
|
||||
// 左侧菜单字体颜色
|
||||
leftMenuTextColor: isDarkColor ? '#bfcbd9' : '#333',
|
||||
// 左侧菜单选中字体颜色
|
||||
leftMenuTextActiveColor: isDarkColor ? '#fff' : 'var(--el-color-primary)',
|
||||
// logo字体颜色
|
||||
logoTitleTextColor: isDarkColor ? '#fff' : 'inherit',
|
||||
// logo边框颜色
|
||||
logoBorderColor: isDarkColor ? color : '#eee'
|
||||
}
|
||||
this.setTheme(theme)
|
||||
this.setCssVarTheme()
|
||||
},
|
||||
setHeaderTheme(color: string) {
|
||||
const isDarkColor = colorIsDark(color)
|
||||
const textColor = isDarkColor ? '#fff' : 'inherit'
|
||||
const textHoverColor = isDarkColor ? lighten(color!, 6) : '#f6f6f6'
|
||||
const topToolBorderColor = isDarkColor ? color : '#eee'
|
||||
setCssVar('--top-header-bg-color', color)
|
||||
setCssVar('--top-header-text-color', textColor)
|
||||
setCssVar('--top-header-hover-color', textHoverColor)
|
||||
this.setTheme({
|
||||
topHeaderBgColor: color,
|
||||
topHeaderTextColor: textColor,
|
||||
topHeaderHoverColor: textHoverColor,
|
||||
topToolBorderColor
|
||||
})
|
||||
if (this.getLayout === 'top') {
|
||||
this.setMenuTheme(color)
|
||||
}
|
||||
},
|
||||
initTheme() {
|
||||
const isDark = useDark({
|
||||
valueDark: 'dark',
|
||||
valueLight: 'light'
|
||||
})
|
||||
isDark.value = this.getIsDark
|
||||
}
|
||||
},
|
||||
persist: true
|
||||
|
|
|
@ -126,3 +126,14 @@ export function toAnyString() {
|
|||
export function firstUpperCase(str: string) {
|
||||
return str.toLowerCase().replace(/( |^)[a-z]/g, (L) => L.toUpperCase())
|
||||
}
|
||||
|
||||
/**
|
||||
* 把对象转为formData
|
||||
*/
|
||||
export function objToFormData(obj: Recordable) {
|
||||
const formData = new FormData()
|
||||
Object.keys(obj).forEach((key) => {
|
||||
formData.append(key, obj[key])
|
||||
})
|
||||
return formData
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { LoginForm, RegisterForm } from './components'
|
|||
import { ThemeSwitch } from '@/components/ThemeSwitch'
|
||||
import { LocaleDropdown } from '@/components/LocaleDropdown'
|
||||
import { useI18n } from '@/hooks/web/useI18n'
|
||||
import { underlineToHump } from '@/utils'
|
||||
import { getCssVar, underlineToHump } from '@/utils'
|
||||
import { useAppStore } from '@/store/modules/app'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { ref } from 'vue'
|
||||
|
@ -26,6 +26,12 @@ const toRegister = () => {
|
|||
const toLogin = () => {
|
||||
isLogin.value = true
|
||||
}
|
||||
|
||||
const themeChange = () => {
|
||||
const color = getCssVar('--el-bg-color')
|
||||
appStore.setMenuTheme(color)
|
||||
appStore.setHeaderTheme(color)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -66,7 +72,7 @@ const toLogin = () => {
|
|||
</div>
|
||||
|
||||
<div class="flex justify-end items-center space-x-10px">
|
||||
<ThemeSwitch />
|
||||
<ThemeSwitch @change="themeChange" />
|
||||
<LocaleDropdown class="lt-xl:text-white dark:text-white" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,12 +20,8 @@ module.exports = {
|
|||
'function-no-unknown': null,
|
||||
'no-empty-source': null,
|
||||
'named-grid-areas-no-invalid': null,
|
||||
'unicode-bom': 'never',
|
||||
'no-descending-specificity': null,
|
||||
'font-family-no-missing-generic-family-keyword': null,
|
||||
'declaration-colon-space-after': 'always-single-line',
|
||||
'declaration-colon-space-before': 'never',
|
||||
'declaration-block-trailing-semicolon': null,
|
||||
'rule-empty-line-before': [
|
||||
'always',
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@ declare global {
|
|||
| 'application/json'
|
||||
| 'application/x-www-form-urlencoded'
|
||||
| 'multipart/form-data'
|
||||
| 'text/plain'
|
||||
|
||||
declare type AxiosMethod = 'get' | 'post' | 'delete' | 'put'
|
||||
|
||||
|
|
Loading…
Reference in New Issue