style(web): 统一后台图标与全局视觉
This commit is contained in:
1 parent
5c087f4db9
commit
97fbeda508
67 files changed
+737
-744
No files matched your search
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
export type UserLoginType = {
|
export type UserLoginType = {
|
||||||
username: string
|
username: string
|
||||||
password: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserType = {
|
export type UserType = {
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.9 KiB |
@@ -0,0 +1,5 @@
|
|||||||
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
|
import AppIcon from './src/AppIcon.vue'
|
||||||
|
|
||||||
|
export { AppIcon }
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { Icon } from '@/components/Icon'
|
||||||
|
import { normalizeAppIcon } from '@/constants/icons'
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台统一图标入口:默认使用 Material Symbols Rounded。
|
||||||
|
*/
|
||||||
|
const props = defineProps({
|
||||||
|
icon: propTypes.string,
|
||||||
|
color: propTypes.string,
|
||||||
|
size: propTypes.number.def(18),
|
||||||
|
hoverColor: propTypes.string
|
||||||
|
})
|
||||||
|
|
||||||
|
const resolvedIcon = computed(() => normalizeAppIcon(props.icon))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Icon
|
||||||
|
:icon="resolvedIcon"
|
||||||
|
:color="color"
|
||||||
|
:size="size"
|
||||||
|
:hover-color="hoverColor"
|
||||||
|
class="app-icon"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.app-icon {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
line-height: 1;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -9,7 +9,7 @@ import { filterBreadcrumb } from './helper'
|
|||||||
import { filter, treeToList } from '@/utils/tree'
|
import { filter, treeToList } from '@/utils/tree'
|
||||||
import type { RouteLocationNormalizedLoaded, RouteMeta } from 'vue-router'
|
import type { RouteLocationNormalizedLoaded, RouteMeta } from 'vue-router'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store/modules/app'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ export default defineComponent({
|
|||||||
<ElBreadcrumbItem to={{ path: disabled ? '' : v.path }} key={v.name}>
|
<ElBreadcrumbItem to={{ path: disabled ? '' : v.path }} key={v.name}>
|
||||||
{meta?.icon && breadcrumbIcon.value ? (
|
{meta?.icon && breadcrumbIcon.value ? (
|
||||||
<>
|
<>
|
||||||
<Icon icon={meta.icon} class="mr-[5px]"></Icon> {t(v?.meta?.title)}
|
<AppIcon icon={meta.icon} class="mr-[5px]"></AppIcon> {t(v?.meta?.title)}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
t(v?.meta?.title)
|
t(v?.meta?.title)
|
||||||
@@ -117,10 +117,10 @@ export default defineComponent({
|
|||||||
|
|
||||||
:deep(&__item):last-child {
|
:deep(&__item):last-child {
|
||||||
.@{prefix-cls}__inner {
|
.@{prefix-cls}__inner {
|
||||||
color: var(--el-text-color-placeholder);
|
color: var(--el-text-color-regular);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--el-text-color-placeholder);
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { computed, unref } from 'vue'
|
|||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store/modules/app'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -26,9 +27,9 @@ const toggleCollapse = () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="prefixCls" @click="toggleCollapse">
|
<div :class="prefixCls" @click="toggleCollapse">
|
||||||
<Icon
|
<AppIcon
|
||||||
:size="18"
|
:size="18"
|
||||||
:icon="collapse ? 'ant-design:menu-unfold-outlined' : 'ant-design:menu-fold-outlined'"
|
:icon="collapse ? AppIcons.menuOpen : AppIcons.menu"
|
||||||
:color="color"
|
:color="color"
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import { ElCard, ElTooltip } from 'element-plus'
|
import { ElCard, ElTooltip } from 'element-plus'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -24,7 +25,7 @@ defineProps({
|
|||||||
<template #content>
|
<template #content>
|
||||||
<div class="max-w-200px">{{ message }}</div>
|
<div class="max-w-200px">{{ message }}</div>
|
||||||
</template>
|
</template>
|
||||||
<Icon class="ml-5px" icon="bi:question-circle-fill" :size="14" />
|
<AppIcon class="ml-5px" :icon="AppIcons.help" :size="14" />
|
||||||
</ElTooltip>
|
</ElTooltip>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ defineExpose({
|
|||||||
:disabled="item.disabled"
|
:disabled="item.disabled"
|
||||||
:command="item"
|
:command="item"
|
||||||
>
|
>
|
||||||
<Icon :icon="item.icon" /> {{ t(item.label) }}
|
<AppIcon :icon="item.icon" /> {{ t(item.label) }}
|
||||||
</ElDropdownItem>
|
</ElDropdownItem>
|
||||||
</ElDropdownMenu>
|
</ElDropdownMenu>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import { propTypes } from '@/utils/propTypes'
|
|||||||
import { ref, unref, PropType, computed, defineComponent } from 'vue'
|
import { ref, unref, PropType, computed, defineComponent } from 'vue'
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store/modules/app'
|
||||||
import { DescriptionsSchema } from './types'
|
import { DescriptionsSchema } from './types'
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
import { get } from 'lodash-es'
|
import { get } from 'lodash-es'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
|
||||||
@@ -94,12 +95,14 @@ export default defineComponent({
|
|||||||
{props.title}
|
{props.title}
|
||||||
{props.message ? (
|
{props.message ? (
|
||||||
<ElTooltip content={props.message} placement="right">
|
<ElTooltip content={props.message} placement="right">
|
||||||
<Icon icon="bi:question-circle-fill" class="ml-5px" size={14} />
|
<AppIcon icon={AppIcons.help} class="ml-5px" size={14} />
|
||||||
</ElTooltip>
|
</ElTooltip>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{props.collapse ? <Icon icon={show.value ? 'ep:arrow-down' : 'ep:arrow-up'} /> : null}
|
{props.collapse ? (
|
||||||
|
<AppIcon icon={show.value ? AppIcons.chevronDown : AppIcons.chevronUp} />
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { ElDialog, ElScrollbar } from 'element-plus'
|
|||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { computed, useAttrs, ref, unref, useSlots, watch, nextTick } from 'vue'
|
import { computed, useAttrs, ref, unref, useSlots, watch, nextTick } from 'vue'
|
||||||
import { isNumber } from '@/utils/is'
|
import { isNumber } from '@/utils/is'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const slots = useSlots()
|
const slots = useSlots()
|
||||||
|
|
||||||
@@ -77,17 +78,17 @@ const dialogStyle = computed(() => {
|
|||||||
<div
|
<div
|
||||||
class="h-54px flex justify-between items-center absolute top-[50%] right-15px translate-y-[-50%]"
|
class="h-54px flex justify-between items-center absolute top-[50%] right-15px translate-y-[-50%]"
|
||||||
>
|
>
|
||||||
<Icon
|
<AppIcon
|
||||||
v-if="fullscreen"
|
v-if="fullscreen"
|
||||||
class="cursor-pointer is-hover !h-54px mr-10px"
|
class="cursor-pointer is-hover !h-54px mr-10px"
|
||||||
:icon="isFullscreen ? 'radix-icons:exit-full-screen' : 'radix-icons:enter-full-screen'"
|
:icon="isFullscreen ? AppIcons.fullscreenExit : AppIcons.fullscreen"
|
||||||
color="var(--el-color-info)"
|
color="var(--el-color-info)"
|
||||||
hover-color="var(--el-color-primary)"
|
hover-color="var(--el-color-primary)"
|
||||||
@click="toggleFull"
|
@click="toggleFull"
|
||||||
/>
|
/>
|
||||||
<Icon
|
<AppIcon
|
||||||
class="cursor-pointer is-hover !h-54px"
|
class="cursor-pointer is-hover !h-54px"
|
||||||
icon="ep:close"
|
:icon="AppIcons.close"
|
||||||
hover-color="var(--el-color-primary)"
|
hover-color="var(--el-color-primary)"
|
||||||
color="var(--el-color-info)"
|
color="var(--el-color-info)"
|
||||||
@click="close"
|
@click="close"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { ElIcon } from 'element-plus'
|
|||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
import { Icon } from '@iconify/vue'
|
import { Icon } from '@iconify/vue'
|
||||||
|
import { normalizeAppIcon } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -22,9 +23,10 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const isLocal = computed(() => props.icon.startsWith('svg-icon:'))
|
const isLocal = computed(() => props.icon.startsWith('svg-icon:'))
|
||||||
|
const normalizedIcon = computed(() => normalizeAppIcon(props.icon))
|
||||||
|
|
||||||
const symbolId = computed(() => {
|
const symbolId = computed(() => {
|
||||||
return unref(isLocal) ? `#icon-${props.icon.split('svg-icon:')[1]}` : props.icon
|
return unref(isLocal) ? `#icon-${props.icon.split('svg-icon:')[1]}` : unref(normalizedIcon)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 是否使用在线图标
|
// 是否使用在线图标
|
||||||
@@ -48,8 +50,8 @@ const getIconifyStyle = computed(() => {
|
|||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<Icon v-if="isUseOnline" :icon="icon" :style="getIconifyStyle" />
|
<Icon v-if="isUseOnline" :icon="normalizedIcon" :style="getIconifyStyle" />
|
||||||
<div v-else :class="`${icon} iconify`" :style="getIconifyStyle"></div>
|
<div v-else :class="`${normalizedIcon} iconify`" :style="getIconifyStyle"></div>
|
||||||
</template>
|
</template>
|
||||||
</ElIcon>
|
</ElIcon>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { useLocaleStore } from '@/store/modules/locale'
|
|||||||
import { useLocale } from '@/hooks/web/useLocale'
|
import { useLocale } from '@/hooks/web/useLocale'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -36,9 +37,9 @@ const setLang = (lang: LocaleType) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ElDropdown :class="prefixCls" trigger="click" @command="setLang">
|
<ElDropdown :class="prefixCls" trigger="click" @command="setLang">
|
||||||
<Icon
|
<AppIcon
|
||||||
:size="18"
|
:size="18"
|
||||||
icon="ion:language-sharp"
|
:icon="AppIcons.language"
|
||||||
class="cursor-pointer !p-0"
|
class="cursor-pointer !p-0"
|
||||||
:class="$attrs.class"
|
:class="$attrs.class"
|
||||||
:color="color"
|
:color="color"
|
||||||
|
|||||||
@@ -67,8 +67,8 @@ watch(
|
|||||||
to="/"
|
to="/"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src="@/assets/imgs/logo.png"
|
src="@/assets/imgs/brand-mark.png"
|
||||||
class="w-[calc(var(--logo-height)-10px)] h-[calc(var(--logo-height)-10px)]"
|
class="w-[var(--brand-mark-size)] h-[var(--brand-mark-size)] rounded-[var(--brand-mark-radius)] object-cover"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
v-if="show"
|
v-if="show"
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
import type { RouteMeta } from 'vue-router'
|
import type { RouteMeta } from 'vue-router'
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
|
||||||
export const useRenderMenuTitle = () => {
|
export const useRenderMenuTitle = () => {
|
||||||
@@ -9,7 +11,7 @@ export const useRenderMenuTitle = () => {
|
|||||||
|
|
||||||
return icon ? (
|
return icon ? (
|
||||||
<>
|
<>
|
||||||
<Icon icon={meta.icon}></Icon>
|
<AppIcon icon={meta.icon}></AppIcon>
|
||||||
<span class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap">
|
<span class="v-menu__title overflow-hidden overflow-ellipsis whitespace-nowrap">
|
||||||
{t(title as string)}
|
{t(title as string)}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
import { useFullscreen } from '@vueuse/core'
|
import { useFullscreen } from '@vueuse/core'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -23,9 +24,9 @@ const toggleFullscreen = () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="prefixCls" @click="toggleFullscreen">
|
<div :class="prefixCls" @click="toggleFullscreen">
|
||||||
<Icon
|
<AppIcon
|
||||||
:size="18"
|
:size="18"
|
||||||
:icon="isFullscreen ? 'zmdi:fullscreen-exit' : 'zmdi:fullscreen'"
|
:icon="isFullscreen ? AppIcons.fullscreenExit : AppIcons.fullscreen"
|
||||||
:color="color"
|
:color="color"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { ElButton } from 'element-plus'
|
|||||||
import { useIcon } from '@/hooks/web/useIcon'
|
import { useIcon } from '@/hooks/web/useIcon'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const emit = defineEmits(['search', 'reset', 'expand'])
|
const emit = defineEmits(['search', 'reset', 'expand'])
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ const onExpand = () => {
|
|||||||
v-if="showSearch"
|
v-if="showSearch"
|
||||||
type="primary"
|
type="primary"
|
||||||
:loading="searchLoading"
|
:loading="searchLoading"
|
||||||
:icon="useIcon({ icon: 'ep:search' })"
|
:icon="useIcon({ icon: AppIcons.search })"
|
||||||
@click="onSearch"
|
@click="onSearch"
|
||||||
>
|
>
|
||||||
{{ t('common.query') }}
|
{{ t('common.query') }}
|
||||||
@@ -45,14 +46,14 @@ const onExpand = () => {
|
|||||||
<ElButton
|
<ElButton
|
||||||
v-if="showReset"
|
v-if="showReset"
|
||||||
:loading="resetLoading"
|
:loading="resetLoading"
|
||||||
:icon="useIcon({ icon: 'ep:refresh-right' })"
|
:icon="useIcon({ icon: AppIcons.refresh })"
|
||||||
@click="onReset"
|
@click="onReset"
|
||||||
>
|
>
|
||||||
{{ t('common.reset') }}
|
{{ t('common.reset') }}
|
||||||
</ElButton>
|
</ElButton>
|
||||||
<ElButton
|
<ElButton
|
||||||
v-if="showExpand"
|
v-if="showExpand"
|
||||||
:icon="useIcon({ icon: visible ? 'ep:arrow-down' : 'ep:arrow-up' })"
|
:icon="useIcon({ icon: visible ? AppIcons.chevronDown : AppIcons.chevronUp })"
|
||||||
text
|
text
|
||||||
@click="onExpand"
|
@click="onExpand"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ElDrawer, ElDivider, ElMessage } from 'element-plus'
|
import { ElDrawer, ElDivider, ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { ref, unref } from 'vue'
|
import { ref, unref } from 'vue'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { ThemeSwitch } from '@/components/ThemeSwitch'
|
import { ThemeSwitch } from '@/components/ThemeSwitch'
|
||||||
@@ -14,6 +14,7 @@ import LayoutRadioPicker from './components/LayoutRadioPicker.vue'
|
|||||||
import { useStorage } from '@/hooks/web/useStorage'
|
import { useStorage } from '@/hooks/web/useStorage'
|
||||||
import { useClipboard } from '@vueuse/core'
|
import { useClipboard } from '@vueuse/core'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { clear: storageClear } = useStorage('localStorage')
|
const { clear: storageClear } = useStorage('localStorage')
|
||||||
|
|
||||||
@@ -145,9 +146,18 @@ const copyConfig = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 清空缓存
|
// 清空缓存
|
||||||
const clear = () => {
|
const clear = async () => {
|
||||||
storageClear()
|
try {
|
||||||
window.location.reload()
|
await ElMessageBox.confirm(t('setting.clearCacheMessage'), t('setting.clearAndReset'), {
|
||||||
|
confirmButtonText: t('common.ok'),
|
||||||
|
cancelButtonText: t('common.cancel'),
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
storageClear()
|
||||||
|
window.location.reload()
|
||||||
|
} catch {
|
||||||
|
// 取消清除时保持当前状态
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const themeChange = () => {
|
const themeChange = () => {
|
||||||
@@ -163,7 +173,7 @@ const themeChange = () => {
|
|||||||
class="fixed top-[45%] right-0 w-40px h-40px flex items-center justify-center bg-[var(--el-color-primary)] cursor-pointer z-10"
|
class="fixed top-[45%] right-0 w-40px h-40px flex items-center justify-center bg-[var(--el-color-primary)] cursor-pointer z-10"
|
||||||
@click="drawer = true"
|
@click="drawer = true"
|
||||||
>
|
>
|
||||||
<Icon icon="ant-design:setting-outlined" color="#fff" />
|
<AppIcon :icon="AppIcons.settings" color="#fff" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ElDrawer v-model="drawer" direction="rtl" size="350px" :z-index="4000">
|
<ElDrawer v-model="drawer" direction="rtl" size="350px" :z-index="4000">
|
||||||
@@ -254,6 +264,6 @@ const themeChange = () => {
|
|||||||
@prefix-cls: ~'@{namespace}-setting';
|
@prefix-cls: ~'@{namespace}-setting';
|
||||||
|
|
||||||
.@{prefix-cls} {
|
.@{prefix-cls} {
|
||||||
border-radius: 6px 0 0 6px;
|
border-radius: var(--app-radius-md) 0 0 6px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
import { PropType, watch, unref, ref } from 'vue'
|
import { PropType, watch, unref, ref } from 'vue'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ watch(
|
|||||||
}"
|
}"
|
||||||
@click="colorVal = item"
|
@click="colorVal = item"
|
||||||
>
|
>
|
||||||
<Icon v-if="colorVal === item" color="#fff" icon="ep:check" :size="16" />
|
<AppIcon v-if="colorVal === item" color="#fff" :icon="AppIcons.check" :size="16" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const layout = computed(() => appStore.getLayout)
|
|||||||
.@{prefix-cls} {
|
.@{prefix-cls} {
|
||||||
&__classic {
|
&__classic {
|
||||||
border: 2px solid #e5e7eb;
|
border: 2px solid #e5e7eb;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -77,7 +77,7 @@ const layout = computed(() => appStore.getLayout)
|
|||||||
width: 33%;
|
width: 33%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #273352;
|
background-color: #273352;
|
||||||
border-radius: 4px 0 0 4px;
|
border-radius: var(--app-radius-sm) 0 0 4px;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,14 +88,14 @@ const layout = computed(() => appStore.getLayout)
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 25%;
|
height: 25%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 4px 4px 0;
|
border-radius: var(--app-radius-sm) 4px 0;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__top-left {
|
&__top-left {
|
||||||
border: 2px solid #e5e7eb;
|
border: 2px solid #e5e7eb;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -105,7 +105,7 @@ const layout = computed(() => appStore.getLayout)
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 33%;
|
height: 33%;
|
||||||
background-color: #273352;
|
background-color: #273352;
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: var(--app-radius-sm) 4px 0 0;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,14 +116,14 @@ const layout = computed(() => appStore.getLayout)
|
|||||||
width: 33%;
|
width: 33%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 4px 0 0 4px;
|
border-radius: var(--app-radius-sm) 0 0 4px;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__top {
|
&__top {
|
||||||
border: 2px solid #e5e7eb;
|
border: 2px solid #e5e7eb;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -133,14 +133,14 @@ const layout = computed(() => appStore.getLayout)
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 33%;
|
height: 33%;
|
||||||
background-color: #273352;
|
background-color: #273352;
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: var(--app-radius-sm) 4px 0 0;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__cut-menu {
|
&__cut-menu {
|
||||||
border: 2px solid #e5e7eb;
|
border: 2px solid #e5e7eb;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -150,7 +150,7 @@ const layout = computed(() => appStore.getLayout)
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 33%;
|
height: 33%;
|
||||||
background-color: #273352;
|
background-color: #273352;
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: var(--app-radius-sm) 4px 0 0;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ const layout = computed(() => appStore.getLayout)
|
|||||||
width: 10%;
|
width: 10%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 4px 0 0 4px;
|
border-radius: var(--app-radius-sm) 0 0 4px;
|
||||||
content: '';
|
content: '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { useAppStore } from '@/store/modules/app'
|
|||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { propTypes } from '@/utils/propTypes'
|
import { propTypes } from '@/utils/propTypes'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -29,7 +30,7 @@ const setCurrentSize = (size: ComponentSize) => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<ElDropdown :class="prefixCls" trigger="click" @command="setCurrentSize">
|
<ElDropdown :class="prefixCls" trigger="click" @command="setCurrentSize">
|
||||||
<Icon :size="18" icon="mdi:format-size" :color="color" class="cursor-pointer" />
|
<AppIcon :size="18" :icon="AppIcons.formatSize" :color="color" class="cursor-pointer" />
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<ElDropdownMenu>
|
<ElDropdownMenu>
|
||||||
<ElDropdownItem v-for="item in sizeMap" :key="item" :command="item">
|
<ElDropdownItem v-for="item in sizeMap" :key="item" :command="item">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useAppStore } from '@/store/modules/app'
|
|||||||
import { computed, unref, defineComponent, watch, ref, onMounted } from 'vue'
|
import { computed, unref, defineComponent, watch, ref, onMounted } from 'vue'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { ElScrollbar } from 'element-plus'
|
import { ElScrollbar } from 'element-plus'
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
import { Menu } from '@/components/Menu'
|
import { Menu } from '@/components/Menu'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { pathResolve } from '@/utils/routerHelper'
|
import { pathResolve } from '@/utils/routerHelper'
|
||||||
@@ -14,6 +14,7 @@ import { cloneDeep } from 'lodash-es'
|
|||||||
import { filterMenusPath, initTabMap, tabPathMap } from './helper'
|
import { filterMenusPath, initTabMap, tabPathMap } from './helper'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
import { isUrl } from '@/utils/is'
|
import { isUrl } from '@/utils/is'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls, variables } = useDesign()
|
const { getPrefixCls, variables } = useDesign()
|
||||||
|
|
||||||
@@ -180,7 +181,7 @@ export default defineComponent({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<Icon icon={item?.meta?.icon}></Icon>
|
<AppIcon icon={item?.meta?.icon}></AppIcon>
|
||||||
</div>
|
</div>
|
||||||
{!unref(showTitle) ? undefined : (
|
{!unref(showTitle) ? undefined : (
|
||||||
<p class="break-words mt-5px px-2px">{t(item.meta?.title)}</p>
|
<p class="break-words mt-5px px-2px">{t(item.meta?.title)}</p>
|
||||||
@@ -198,7 +199,7 @@ export default defineComponent({
|
|||||||
]}
|
]}
|
||||||
onClick={setCollapse}
|
onClick={setCollapse}
|
||||||
>
|
>
|
||||||
<Icon icon={unref(collapse) ? 'ep:d-arrow-right' : 'ep:d-arrow-left'}></Icon>
|
<AppIcon icon={unref(collapse) ? AppIcons.chevronRight : AppIcons.chevronLeft}></AppIcon>
|
||||||
</div>
|
</div>
|
||||||
<Menu
|
<Menu
|
||||||
class={[
|
class={[
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ import { CSSProperties } from 'vue'
|
|||||||
import { getSlot } from '@/utils/tsxHelper'
|
import { getSlot } from '@/utils/tsxHelper'
|
||||||
import TableActions from './components/TableActions.vue'
|
import TableActions from './components/TableActions.vue'
|
||||||
import { createVideoViewer } from '@/components/VideoPlayer'
|
import { createVideoViewer } from '@/components/VideoPlayer'
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
import { BaseButton } from '@/components/Button'
|
import { BaseButton } from '@/components/Button'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Table',
|
name: 'Table',
|
||||||
@@ -408,7 +409,7 @@ export default defineComponent({
|
|||||||
) : videoPreview.includes(field) ? (
|
) : videoPreview.includes(field) ? (
|
||||||
<BaseButton
|
<BaseButton
|
||||||
type="primary"
|
type="primary"
|
||||||
icon={<Icon icon="ep:video-play" />}
|
icon={<AppIcon icon={AppIcons.videoPlay} />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
createVideoViewer({
|
createVideoViewer({
|
||||||
url
|
url
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { TableColumn } from '../types'
|
|||||||
import { PropType, ref, watch, unref } from 'vue'
|
import { PropType, ref, watch, unref } from 'vue'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
import { DEFAULT_FILTER_COLUMN } from '@/constants'
|
import { DEFAULT_FILTER_COLUMN } from '@/constants'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
import { VueDraggable } from 'vue-draggable-plus'
|
import { VueDraggable } from 'vue-draggable-plus'
|
||||||
|
|
||||||
const modelValue = defineModel<boolean>()
|
const modelValue = defineModel<boolean>()
|
||||||
@@ -141,17 +142,19 @@ watch(
|
|||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<ElRadioGroup size="small" v-model="item.fixed">
|
<ElRadioGroup size="small" v-model="item.fixed">
|
||||||
<ElRadioButton label="left">
|
<ElRadioButton label="left">
|
||||||
<Icon icon="ep:arrow-left" />
|
<AppIcon :icon="AppIcons.chevronLeft" />
|
||||||
</ElRadioButton>
|
</ElRadioButton>
|
||||||
<ElRadioButton :label="undefined">
|
<ElRadioButton :label="undefined">
|
||||||
<Icon icon="ep:close" />
|
<AppIcon :icon="AppIcons.close" />
|
||||||
</ElRadioButton>
|
</ElRadioButton>
|
||||||
<ElRadioButton label="right">
|
<ElRadioButton label="right">
|
||||||
<Icon icon="ep:arrow-right" />
|
<AppIcon :icon="AppIcons.chevronRight" />
|
||||||
</ElRadioButton>
|
</ElRadioButton>
|
||||||
</ElRadioGroup>
|
</ElRadioGroup>
|
||||||
|
|
||||||
<div class="ml-12px cursor-move handle"><Icon icon="ep:rank" /></div>
|
<div class="ml-12px cursor-move handle">
|
||||||
|
<AppIcon :icon="AppIcons.drag" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ElCheckboxGroup>
|
</ElCheckboxGroup>
|
||||||
|
|||||||
@@ -3,11 +3,12 @@
|
|||||||
<script lang="tsx">
|
<script lang="tsx">
|
||||||
import { defineComponent, unref, computed, PropType, ref } from 'vue'
|
import { defineComponent, unref, computed, PropType, ref } from 'vue'
|
||||||
import { ElDropdown, ElDropdownMenu, ElDropdownItem, ComponentSize } from 'element-plus'
|
import { ElDropdown, ElDropdownMenu, ElDropdownItem, ComponentSize } from 'element-plus'
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { useAppStore } from '@/store/modules/app'
|
import { useAppStore } from '@/store/modules/app'
|
||||||
import { TableColumn } from '../types'
|
import { TableColumn } from '../types'
|
||||||
import ColumnSetting from './ColumnSetting.vue'
|
import ColumnSetting from './ColumnSetting.vue'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'TableActions',
|
name: 'TableActions',
|
||||||
@@ -47,8 +48,8 @@ export default defineComponent({
|
|||||||
<>
|
<>
|
||||||
<div class="text-right h-28px flex items-center justify-end">
|
<div class="text-right h-28px flex items-center justify-end">
|
||||||
<div title="刷新" class="w-30px h-20px flex items-center justify-end" onClick={refresh}>
|
<div title="刷新" class="w-30px h-20px flex items-center justify-end" onClick={refresh}>
|
||||||
<Icon
|
<AppIcon
|
||||||
icon="ant-design:sync-outlined"
|
icon={AppIcons.refresh}
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
hover-color="var(--el-color-primary)"
|
hover-color="var(--el-color-primary)"
|
||||||
/>
|
/>
|
||||||
@@ -59,8 +60,8 @@ export default defineComponent({
|
|||||||
default: () => {
|
default: () => {
|
||||||
return (
|
return (
|
||||||
<div title="尺寸" class="w-30px h-20px flex items-center justify-end">
|
<div title="尺寸" class="w-30px h-20px flex items-center justify-end">
|
||||||
<Icon
|
<AppIcon
|
||||||
icon="ant-design:column-height-outlined"
|
icon={AppIcons.viewColumn}
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
hover-color="var(--el-color-primary)"
|
hover-color="var(--el-color-primary)"
|
||||||
/>
|
/>
|
||||||
@@ -92,8 +93,8 @@ export default defineComponent({
|
|||||||
class="w-30px h-20px flex items-center justify-end"
|
class="w-30px h-20px flex items-center justify-end"
|
||||||
onClick={showColumnSetting}
|
onClick={showColumnSetting}
|
||||||
>
|
>
|
||||||
<Icon
|
<AppIcon
|
||||||
icon="ant-design:setting-outlined"
|
icon={AppIcons.settings}
|
||||||
class="cursor-pointer"
|
class="cursor-pointer"
|
||||||
hover-color="var(--el-color-primary)"
|
hover-color="var(--el-color-primary)"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { ElScrollbar } from 'element-plus'
|
|||||||
import { useScrollTo } from '@/hooks/event/useScrollTo'
|
import { useScrollTo } from '@/hooks/event/useScrollTo'
|
||||||
import { useTagsView } from '@/hooks/web/useTagsView'
|
import { useTagsView } from '@/hooks/web/useTagsView'
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -262,18 +263,14 @@ watch(
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div :id="prefixCls" :class="prefixCls" class="flex w-full relative bg-[var(--el-bg-color)]">
|
||||||
:id="prefixCls"
|
|
||||||
:class="prefixCls"
|
|
||||||
class="flex w-full relative bg-[#fff] dark:bg-[var(--el-bg-color)]"
|
|
||||||
>
|
|
||||||
<span
|
<span
|
||||||
:class="`${prefixCls}__tool ${prefixCls}__tool--first`"
|
:class="`${prefixCls}__tool ${prefixCls}__tool--first`"
|
||||||
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
|
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
|
||||||
@click="move(-200)"
|
@click="move(-200)"
|
||||||
>
|
>
|
||||||
<Icon
|
<AppIcon
|
||||||
icon="ep:d-arrow-left"
|
:icon="AppIcons.chevronLeft"
|
||||||
color="var(--el-text-color-placeholder)"
|
color="var(--el-text-color-placeholder)"
|
||||||
:hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
|
:hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
|
||||||
/>
|
/>
|
||||||
@@ -285,7 +282,7 @@ watch(
|
|||||||
:ref="itemRefs.set"
|
:ref="itemRefs.set"
|
||||||
:schema="[
|
:schema="[
|
||||||
{
|
{
|
||||||
icon: 'ant-design:sync-outlined',
|
icon: AppIcons.refresh,
|
||||||
label: t('common.reload'),
|
label: t('common.reload'),
|
||||||
disabled: selectedTag?.fullPath !== item.fullPath,
|
disabled: selectedTag?.fullPath !== item.fullPath,
|
||||||
command: () => {
|
command: () => {
|
||||||
@@ -293,7 +290,7 @@ watch(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'ant-design:close-outlined',
|
icon: AppIcons.close,
|
||||||
label: t('common.closeTab'),
|
label: t('common.closeTab'),
|
||||||
disabled: !!visitedViews?.length && selectedTag?.meta.affix,
|
disabled: !!visitedViews?.length && selectedTag?.meta.affix,
|
||||||
command: () => {
|
command: () => {
|
||||||
@@ -302,7 +299,7 @@ watch(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
divided: true,
|
divided: true,
|
||||||
icon: 'ant-design:vertical-right-outlined',
|
icon: AppIcons.splitRight,
|
||||||
label: t('common.closeTheLeftTab'),
|
label: t('common.closeTheLeftTab'),
|
||||||
disabled:
|
disabled:
|
||||||
!!visitedViews?.length &&
|
!!visitedViews?.length &&
|
||||||
@@ -313,7 +310,7 @@ watch(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'ant-design:vertical-left-outlined',
|
icon: AppIcons.splitLeft,
|
||||||
label: t('common.closeTheRightTab'),
|
label: t('common.closeTheRightTab'),
|
||||||
disabled:
|
disabled:
|
||||||
!!visitedViews?.length &&
|
!!visitedViews?.length &&
|
||||||
@@ -325,7 +322,7 @@ watch(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
divided: true,
|
divided: true,
|
||||||
icon: 'ant-design:tag-outlined',
|
icon: AppIcons.tag,
|
||||||
label: t('common.closeOther'),
|
label: t('common.closeOther'),
|
||||||
disabled: selectedTag?.fullPath !== item.fullPath,
|
disabled: selectedTag?.fullPath !== item.fullPath,
|
||||||
command: () => {
|
command: () => {
|
||||||
@@ -333,7 +330,7 @@ watch(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'ant-design:line-outlined',
|
icon: AppIcons.line,
|
||||||
label: t('common.closeAll'),
|
label: t('common.closeAll'),
|
||||||
command: () => {
|
command: () => {
|
||||||
closeAllTags()
|
closeAllTags()
|
||||||
@@ -358,7 +355,7 @@ watch(
|
|||||||
@click="navigate"
|
@click="navigate"
|
||||||
class="h-full flex justify-center items-center whitespace-nowrap pl-15px"
|
class="h-full flex justify-center items-center whitespace-nowrap pl-15px"
|
||||||
>
|
>
|
||||||
<Icon
|
<AppIcon
|
||||||
v-if="
|
v-if="
|
||||||
item?.matched &&
|
item?.matched &&
|
||||||
item?.matched[1] &&
|
item?.matched[1] &&
|
||||||
@@ -370,10 +367,10 @@ watch(
|
|||||||
class="mr-5px"
|
class="mr-5px"
|
||||||
/>
|
/>
|
||||||
{{ t(item?.meta?.title as string) }}
|
{{ t(item?.meta?.title as string) }}
|
||||||
<Icon
|
<AppIcon
|
||||||
:class="`${prefixCls}__item--close`"
|
:class="`${prefixCls}__item--close`"
|
||||||
color="#333"
|
color="var(--el-text-color-secondary)"
|
||||||
icon="ant-design:close-outlined"
|
:icon="AppIcons.close"
|
||||||
:size="12"
|
:size="12"
|
||||||
@click.prevent.stop="closeSelectedTag(item)"
|
@click.prevent.stop="closeSelectedTag(item)"
|
||||||
/>
|
/>
|
||||||
@@ -389,8 +386,8 @@ watch(
|
|||||||
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
|
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
|
||||||
@click="move(200)"
|
@click="move(200)"
|
||||||
>
|
>
|
||||||
<Icon
|
<AppIcon
|
||||||
icon="ep:d-arrow-right"
|
:icon="AppIcons.chevronRight"
|
||||||
color="var(--el-text-color-placeholder)"
|
color="var(--el-text-color-placeholder)"
|
||||||
:hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
|
:hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
|
||||||
/>
|
/>
|
||||||
@@ -400,8 +397,8 @@ watch(
|
|||||||
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
|
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer"
|
||||||
@click="refreshSelectedTag(selectedTag)"
|
@click="refreshSelectedTag(selectedTag)"
|
||||||
>
|
>
|
||||||
<Icon
|
<AppIcon
|
||||||
icon="ant-design:reload-outlined"
|
:icon="AppIcons.refresh"
|
||||||
color="var(--el-text-color-placeholder)"
|
color="var(--el-text-color-placeholder)"
|
||||||
:hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
|
:hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
|
||||||
/>
|
/>
|
||||||
@@ -410,14 +407,14 @@ watch(
|
|||||||
trigger="click"
|
trigger="click"
|
||||||
:schema="[
|
:schema="[
|
||||||
{
|
{
|
||||||
icon: 'ant-design:sync-outlined',
|
icon: AppIcons.refresh,
|
||||||
label: t('common.reload'),
|
label: t('common.reload'),
|
||||||
command: () => {
|
command: () => {
|
||||||
refreshSelectedTag(selectedTag)
|
refreshSelectedTag(selectedTag)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'ant-design:close-outlined',
|
icon: AppIcons.close,
|
||||||
label: t('common.closeTab'),
|
label: t('common.closeTab'),
|
||||||
disabled: !!visitedViews?.length && selectedTag?.meta.affix,
|
disabled: !!visitedViews?.length && selectedTag?.meta.affix,
|
||||||
command: () => {
|
command: () => {
|
||||||
@@ -426,7 +423,7 @@ watch(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
divided: true,
|
divided: true,
|
||||||
icon: 'ant-design:vertical-right-outlined',
|
icon: AppIcons.splitRight,
|
||||||
label: t('common.closeTheLeftTab'),
|
label: t('common.closeTheLeftTab'),
|
||||||
disabled: !!visitedViews?.length && selectedTag?.fullPath === visitedViews[0].fullPath,
|
disabled: !!visitedViews?.length && selectedTag?.fullPath === visitedViews[0].fullPath,
|
||||||
command: () => {
|
command: () => {
|
||||||
@@ -434,7 +431,7 @@ watch(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'ant-design:vertical-left-outlined',
|
icon: AppIcons.splitLeft,
|
||||||
label: t('common.closeTheRightTab'),
|
label: t('common.closeTheRightTab'),
|
||||||
disabled:
|
disabled:
|
||||||
!!visitedViews?.length &&
|
!!visitedViews?.length &&
|
||||||
@@ -445,14 +442,14 @@ watch(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
divided: true,
|
divided: true,
|
||||||
icon: 'ant-design:tag-outlined',
|
icon: AppIcons.tag,
|
||||||
label: t('common.closeOther'),
|
label: t('common.closeOther'),
|
||||||
command: () => {
|
command: () => {
|
||||||
closeOthersTags()
|
closeOthersTags()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'ant-design:line-outlined',
|
icon: AppIcons.line,
|
||||||
label: t('common.closeAll'),
|
label: t('common.closeAll'),
|
||||||
command: () => {
|
command: () => {
|
||||||
closeAllTags()
|
closeAllTags()
|
||||||
@@ -464,8 +461,8 @@ watch(
|
|||||||
:class="`${prefixCls}__tool`"
|
:class="`${prefixCls}__tool`"
|
||||||
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer block"
|
class="w-[var(--tags-view-height)] h-[var(--tags-view-height)] flex items-center justify-center cursor-pointer block"
|
||||||
>
|
>
|
||||||
<Icon
|
<AppIcon
|
||||||
icon="ant-design:setting-outlined"
|
:icon="AppIcons.settings"
|
||||||
color="var(--el-text-color-placeholder)"
|
color="var(--el-text-color-placeholder)"
|
||||||
:hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
|
:hover-color="isDark ? '#fff' : 'var(--el-color-black)'"
|
||||||
/>
|
/>
|
||||||
@@ -542,8 +539,8 @@ watch(
|
|||||||
|
|
||||||
&__item.is-active {
|
&__item.is-active {
|
||||||
color: var(--el-color-white);
|
color: var(--el-color-white);
|
||||||
background-color: var(--el-color-primary);
|
background-color: var(--app-primary-strong);
|
||||||
border: 1px solid var(--el-color-primary);
|
border: 1px solid var(--app-primary-strong);
|
||||||
.@{prefix-cls}__item--close {
|
.@{prefix-cls}__item--close {
|
||||||
:deep(svg) {
|
:deep(svg) {
|
||||||
color: var(--el-color-white) !important;
|
color: var(--el-color-white) !important;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useAppStore } from '@/store/modules/app'
|
|||||||
import { ElSwitch } from 'element-plus'
|
import { ElSwitch } from 'element-plus'
|
||||||
import { useIcon } from '@/hooks/web/useIcon'
|
import { useIcon } from '@/hooks/web/useIcon'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
|
|
||||||
@@ -13,18 +14,15 @@ const emit = defineEmits(['change'])
|
|||||||
|
|
||||||
const prefixCls = getPrefixCls('theme-switch')
|
const prefixCls = getPrefixCls('theme-switch')
|
||||||
|
|
||||||
const Sun = useIcon({ icon: 'emojione-monotone:sun', color: '#fde047' })
|
const Sun = useIcon({ icon: AppIcons.lightMode, color: '#fde047' })
|
||||||
|
|
||||||
const CrescentMoon = useIcon({ icon: 'emojione-monotone:crescent-moon', color: '#fde047' })
|
const CrescentMoon = useIcon({ icon: AppIcons.darkMode, color: '#fde047' })
|
||||||
|
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
|
|
||||||
// 初始化获取是否是暗黑主题
|
// 初始化获取是否是暗黑主题
|
||||||
const isDark = ref(appStore.getIsDark)
|
const isDark = ref(appStore.getIsDark)
|
||||||
|
|
||||||
// 设置switch的背景颜色
|
|
||||||
const blackColor = 'var(--el-color-black)'
|
|
||||||
|
|
||||||
const themeChange = (val: boolean) => {
|
const themeChange = (val: boolean) => {
|
||||||
appStore.setIsDark(val)
|
appStore.setIsDark(val)
|
||||||
emit('change', val)
|
emit('change', val)
|
||||||
@@ -36,9 +34,6 @@ const themeChange = (val: boolean) => {
|
|||||||
:class="prefixCls"
|
:class="prefixCls"
|
||||||
v-model="isDark"
|
v-model="isDark"
|
||||||
inline-prompt
|
inline-prompt
|
||||||
:border-color="blackColor"
|
|
||||||
:inactive-color="blackColor"
|
|
||||||
:active-color="blackColor"
|
|
||||||
:active-icon="Sun"
|
:active-icon="Sun"
|
||||||
:inactive-icon="CrescentMoon"
|
:inactive-icon="CrescentMoon"
|
||||||
@change="themeChange"
|
@change="themeChange"
|
||||||
@@ -46,7 +41,20 @@ const themeChange = (val: boolean) => {
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
:deep(.el-switch__core .el-switch__inner .is-icon) {
|
.v-theme-switch {
|
||||||
overflow: visible;
|
:deep(.el-switch__core .el-switch__inner .is-icon) {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-switch__core) {
|
||||||
|
min-width: 44px;
|
||||||
|
background: var(--el-fill-color-darker);
|
||||||
|
border-color: var(--el-text-color-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-theme-switch.is-checked :deep(.el-switch__core) {
|
||||||
|
background: var(--app-primary-strong) !important;
|
||||||
|
border-color: var(--app-primary-strong) !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -9,6 +9,8 @@ import { ref, computed } from 'vue'
|
|||||||
import LockPage from './components/LockPage.vue'
|
import LockPage from './components/LockPage.vue'
|
||||||
import { useLockStore } from '@/store/modules/lock'
|
import { useLockStore } from '@/store/modules/lock'
|
||||||
import { useUserStore } from '@/store/modules/user'
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
@@ -22,6 +24,12 @@ const prefixCls = getPrefixCls('user-info')
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const displayName = computed(
|
||||||
|
() => userStore.getUserInfo?.name || userStore.getUserInfo?.username || '-'
|
||||||
|
)
|
||||||
|
|
||||||
|
const avatarUrl = computed(() => userStore.getUserInfo?.avatar || '')
|
||||||
|
|
||||||
const loginOut = () => {
|
const loginOut = () => {
|
||||||
userStore.logoutConfirm()
|
userStore.logoutConfirm()
|
||||||
}
|
}
|
||||||
@@ -38,12 +46,19 @@ const lockScreen = () => {
|
|||||||
<ElDropdown class="custom-hover" :class="prefixCls" trigger="click">
|
<ElDropdown class="custom-hover" :class="prefixCls" trigger="click">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<img
|
<img
|
||||||
src="@/assets/imgs/avatar.jpg"
|
v-if="avatarUrl"
|
||||||
|
:src="avatarUrl"
|
||||||
alt=""
|
alt=""
|
||||||
class="w-[calc(var(--logo-height)-25px)] rounded-[50%]"
|
class="w-[calc(var(--logo-height)-25px)] h-[calc(var(--logo-height)-25px)] rounded-[50%] object-cover"
|
||||||
/>
|
/>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="w-[calc(var(--logo-height)-25px)] h-[calc(var(--logo-height)-25px)] rounded-[50%] flex items-center justify-center bg-[var(--el-fill-color)]"
|
||||||
|
>
|
||||||
|
<AppIcon :icon="AppIcons.person" />
|
||||||
|
</span>
|
||||||
<span class="<lg:hidden text-14px pl-[5px] text-[var(--top-header-text-color)]">{{
|
<span class="<lg:hidden text-14px pl-[5px] text-[var(--top-header-text-color)]">{{
|
||||||
userStore.getUserInfo?.username
|
displayName
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ import { FormSchema } from '@/components/Form'
|
|||||||
import { ElButton } from 'element-plus'
|
import { ElButton } from 'element-plus'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
import { useLockStore } from '@/store/modules/lock'
|
import { useLockStore } from '@/store/modules/lock'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const { getPrefixCls } = useDesign()
|
const { getPrefixCls } = useDesign()
|
||||||
const prefixCls = getPrefixCls('lock-dialog')
|
const prefixCls = getPrefixCls('lock-dialog')
|
||||||
@@ -21,6 +24,12 @@ const { required } = useValidator()
|
|||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
const lockStore = useLockStore()
|
const lockStore = useLockStore()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
const displayName = computed(
|
||||||
|
() => userStore.getUserInfo?.name || userStore.getUserInfo?.username || '-'
|
||||||
|
)
|
||||||
|
const avatarUrl = computed(() => userStore.getUserInfo?.avatar || '')
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
@@ -84,8 +93,18 @@ const handleLock = async () => {
|
|||||||
:title="dialogTitle"
|
:title="dialogTitle"
|
||||||
>
|
>
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<img src="@/assets/imgs/avatar.jpg" alt="" class="w-70px h-70px rounded-[50%]" />
|
<img
|
||||||
<span class="text-14px my-10px text-[var(--top-header-text-color)]">Archer</span>
|
v-if="avatarUrl"
|
||||||
|
:src="avatarUrl"
|
||||||
|
alt=""
|
||||||
|
class="w-70px h-70px rounded-[50%] object-cover"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="w-70px h-70px rounded-[50%] flex items-center justify-center bg-[var(--el-fill-color)]"
|
||||||
|
><AppIcon :icon="AppIcons.person" :size="30"
|
||||||
|
/></span>
|
||||||
|
<span class="text-14px my-10px text-[var(--top-header-text-color)]">{{ displayName }}</span>
|
||||||
</div>
|
</div>
|
||||||
<Form :is-col="false" :schema="schema" :rules="rules" @register="formRegister" />
|
<Form :is-col="false" :schema="schema" :rules="rules" @register="formRegister" />
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
import { ElInput, ElButton } from 'element-plus'
|
import { ElInput, ElButton } from 'element-plus'
|
||||||
import { resetRouter } from '@/router'
|
import { resetRouter } from '@/router'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
@@ -10,11 +10,14 @@ import { useLockStore } from '@/store/modules/lock'
|
|||||||
import { useI18n } from '@/hooks/web/useI18n'
|
import { useI18n } from '@/hooks/web/useI18n'
|
||||||
import { useNow } from '@/hooks/web/useNow'
|
import { useNow } from '@/hooks/web/useNow'
|
||||||
import { useDesign } from '@/hooks/web/useDesign'
|
import { useDesign } from '@/hooks/web/useDesign'
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
import { loginOutApi } from '@/api/login'
|
import { loginOutApi } from '@/api/login'
|
||||||
import { useTagsViewStore } from '@/store/modules/tagsView'
|
import { useTagsViewStore } from '@/store/modules/tagsView'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
|
||||||
const tagsViewStore = useTagsViewStore()
|
const tagsViewStore = useTagsViewStore()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const { clear } = useStorage()
|
const { clear } = useStorage()
|
||||||
|
|
||||||
@@ -34,6 +37,11 @@ const { hour, month, minute, meridiem, year, day, week } = useNow(true)
|
|||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const displayName = computed(
|
||||||
|
() => userStore.getUserInfo?.name || userStore.getUserInfo?.username || '-'
|
||||||
|
)
|
||||||
|
const avatarUrl = computed(() => userStore.getUserInfo?.avatar || '')
|
||||||
|
|
||||||
// 解锁
|
// 解锁
|
||||||
async function unLock() {
|
async function unLock() {
|
||||||
if (!password.value) {
|
if (!password.value) {
|
||||||
@@ -77,7 +85,7 @@ function handleShowForm(show = false) {
|
|||||||
@click="handleShowForm(false)"
|
@click="handleShowForm(false)"
|
||||||
v-show="showDate"
|
v-show="showDate"
|
||||||
>
|
>
|
||||||
<Icon icon="ep:lock" />
|
<AppIcon :icon="AppIcons.lock" />
|
||||||
<span>{{ t('lock.unlock') }}</span>
|
<span>{{ t('lock.unlock') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -96,8 +104,20 @@ function handleShowForm(show = false) {
|
|||||||
<div :class="`${prefixCls}-entry`" v-show="!showDate">
|
<div :class="`${prefixCls}-entry`" v-show="!showDate">
|
||||||
<div :class="`${prefixCls}-entry-content`">
|
<div :class="`${prefixCls}-entry-content`">
|
||||||
<div class="flex flex-col items-center">
|
<div class="flex flex-col items-center">
|
||||||
<img src="@/assets/imgs/avatar.jpg" alt="" class="w-70px h-70px rounded-[50%]" />
|
<img
|
||||||
<span class="text-14px my-10px text-[var(--logo-title-text-color)]">Archer</span>
|
v-if="avatarUrl"
|
||||||
|
:src="avatarUrl"
|
||||||
|
alt=""
|
||||||
|
class="w-70px h-70px rounded-[50%] object-cover"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
v-else
|
||||||
|
class="w-70px h-70px rounded-[50%] flex items-center justify-center bg-[var(--el-fill-color)]"
|
||||||
|
><AppIcon :icon="AppIcons.person" :size="30"
|
||||||
|
/></span>
|
||||||
|
<span class="text-14px my-10px text-[var(--logo-title-text-color)]">{{
|
||||||
|
displayName
|
||||||
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<ElInput
|
<ElInput
|
||||||
type="password"
|
type="password"
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
import { VideoPlayer } from '@/components/VideoPlayer'
|
import { VideoPlayer } from '@/components/VideoPlayer'
|
||||||
import { ElOverlay } from 'element-plus'
|
import { ElOverlay } from 'element-plus'
|
||||||
import { ref, nextTick } from 'vue'
|
import { ref, nextTick } from 'vue'
|
||||||
import { Icon } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
|
import { AppIcons } from '@/constants/icons'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
show: {
|
show: {
|
||||||
@@ -43,7 +44,7 @@ const close = async () => {
|
|||||||
class="w-44px h-44px color-[#fff] bg-[var(--el-text-color-regular)] rounded-full border-[#fff] flex justify-center items-center cursor-pointer absolute top-40px right-40px"
|
class="w-44px h-44px color-[#fff] bg-[var(--el-text-color-regular)] rounded-full border-[#fff] flex justify-center items-center cursor-pointer absolute top-40px right-40px"
|
||||||
@click="close"
|
@click="close"
|
||||||
>
|
>
|
||||||
<Icon icon="ep:close" :size="24" />
|
<AppIcon :icon="AppIcons.close" :size="24" />
|
||||||
</div>
|
</div>
|
||||||
<VideoPlayer :url="url" :poster="poster" />
|
<VideoPlayer :url="url" :poster="poster" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
import type { App } from 'vue'
|
import type { App } from 'vue'
|
||||||
import { Icon } from './Icon'
|
import { Icon } from './Icon'
|
||||||
|
import { AppIcon } from './AppIcon'
|
||||||
import { BaseButton } from './Button'
|
import { BaseButton } from './Button'
|
||||||
|
|
||||||
export const setupGlobCom = (app: App<Element>): void => {
|
export const setupGlobCom = (app: App<Element>): void => {
|
||||||
app.component('Icon', Icon)
|
app.component('Icon', Icon)
|
||||||
|
app.component('AppIcon', AppIcon)
|
||||||
app.component('BaseButton', BaseButton)
|
app.component('BaseButton', BaseButton)
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 后台统一图标语义表。所有值都来自 material-symbols-rounded。
|
||||||
|
*/
|
||||||
|
export const AppIcons = {
|
||||||
|
menu: 'material-symbols:menu-rounded',
|
||||||
|
menuOpen: 'material-symbols:menu-open-rounded',
|
||||||
|
dashboard: 'material-symbols:dashboard-rounded',
|
||||||
|
content: 'material-symbols:video-library-rounded',
|
||||||
|
settings: 'material-symbols:settings-rounded',
|
||||||
|
group: 'material-symbols:group-rounded',
|
||||||
|
movieEdit: 'material-symbols:movie-edit-rounded',
|
||||||
|
policy: 'material-symbols:policy-rounded',
|
||||||
|
payments: 'material-symbols:payments-rounded',
|
||||||
|
monitoring: 'material-symbols:monitoring-rounded',
|
||||||
|
videoCameraFront: 'material-symbols:video-camera-front-rounded',
|
||||||
|
campaign: 'material-symbols:campaign-rounded',
|
||||||
|
fullscreen: 'material-symbols:fullscreen-rounded',
|
||||||
|
fullscreenExit: 'material-symbols:fullscreen-exit-rounded',
|
||||||
|
formatSize: 'material-symbols:format-size-rounded',
|
||||||
|
language: 'material-symbols:translate-rounded',
|
||||||
|
darkMode: 'material-symbols:dark-mode-rounded',
|
||||||
|
lightMode: 'material-symbols:light-mode-rounded',
|
||||||
|
refresh: 'material-symbols:refresh-rounded',
|
||||||
|
restart: 'material-symbols:restart-alt-rounded',
|
||||||
|
close: 'material-symbols:close-rounded',
|
||||||
|
chevronLeft: 'material-symbols:chevron-left-rounded',
|
||||||
|
chevronRight: 'material-symbols:chevron-right-rounded',
|
||||||
|
chevronDown: 'material-symbols:keyboard-arrow-down-rounded',
|
||||||
|
chevronUp: 'material-symbols:keyboard-arrow-up-rounded',
|
||||||
|
search: 'material-symbols:search-rounded',
|
||||||
|
viewColumn: 'material-symbols:combine-columns-rounded',
|
||||||
|
help: 'material-symbols:help-rounded',
|
||||||
|
add: 'material-symbols:add-rounded',
|
||||||
|
edit: 'material-symbols:edit-rounded',
|
||||||
|
delete: 'material-symbols:delete-rounded',
|
||||||
|
upload: 'material-symbols:upload-rounded',
|
||||||
|
download: 'material-symbols:download-rounded',
|
||||||
|
visibility: 'material-symbols:visibility-rounded',
|
||||||
|
arrowUp: 'material-symbols:arrow-upward-rounded',
|
||||||
|
arrowDown: 'material-symbols:arrow-downward-rounded',
|
||||||
|
arrowBack: 'material-symbols:arrow-back-rounded',
|
||||||
|
arrowForward: 'material-symbols:arrow-forward-rounded',
|
||||||
|
check: 'material-symbols:check-rounded',
|
||||||
|
checkCircle: 'material-symbols:check-circle-rounded',
|
||||||
|
cancel: 'material-symbols:cancel-rounded',
|
||||||
|
lock: 'material-symbols:lock-person-rounded',
|
||||||
|
logout: 'material-symbols:logout-rounded',
|
||||||
|
person: 'material-symbols:person-rounded',
|
||||||
|
clock: 'material-symbols:schedule-rounded',
|
||||||
|
videoPlay: 'material-symbols:smart-display-rounded',
|
||||||
|
drag: 'material-symbols:drag-handle-rounded',
|
||||||
|
tag: 'material-symbols:label-rounded',
|
||||||
|
line: 'material-symbols:horizontal-rule-rounded',
|
||||||
|
splitLeft: 'material-symbols:split-scene-left-rounded',
|
||||||
|
splitRight: 'material-symbols:split-scene-right-rounded',
|
||||||
|
warning: 'material-symbols:warning-rounded',
|
||||||
|
error: 'material-symbols:error-rounded',
|
||||||
|
info: 'material-symbols:info-rounded'
|
||||||
|
} as const
|
||||||
|
|
||||||
|
/** 菜单管理提供的合法图标候选。 */
|
||||||
|
export const MenuIconOptions = [
|
||||||
|
AppIcons.dashboard,
|
||||||
|
AppIcons.content,
|
||||||
|
AppIcons.settings,
|
||||||
|
AppIcons.group,
|
||||||
|
AppIcons.movieEdit,
|
||||||
|
AppIcons.policy,
|
||||||
|
AppIcons.payments,
|
||||||
|
AppIcons.monitoring,
|
||||||
|
AppIcons.videoCameraFront,
|
||||||
|
AppIcons.campaign
|
||||||
|
] as const
|
||||||
|
|
||||||
|
const legacyIconAliases: Record<string, string> = {
|
||||||
|
Document: AppIcons.content,
|
||||||
|
DataAnalysis: AppIcons.monitoring,
|
||||||
|
Picture: AppIcons.content,
|
||||||
|
User: AppIcons.group,
|
||||||
|
Setting: AppIcons.settings,
|
||||||
|
VideoCamera: AppIcons.content,
|
||||||
|
Menu: AppIcons.menu,
|
||||||
|
Grid: AppIcons.dashboard,
|
||||||
|
'ep:setting': AppIcons.settings,
|
||||||
|
'ep:user': AppIcons.group,
|
||||||
|
'ep:user-filled': AppIcons.group,
|
||||||
|
'ep:chat-dot-round': AppIcons.policy,
|
||||||
|
'ep:coin': AppIcons.payments,
|
||||||
|
'ep:data-line': AppIcons.monitoring,
|
||||||
|
'ep:film': AppIcons.videoCameraFront,
|
||||||
|
'ep:bell': AppIcons.campaign,
|
||||||
|
'ep:video-camera': AppIcons.content,
|
||||||
|
'ant-design:dashboard-filled': AppIcons.dashboard
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 兼容历史短名与旧 Iconify 名,统一返回 Material Symbols Rounded。 */
|
||||||
|
export function normalizeAppIcon(icon?: string): string {
|
||||||
|
if (!icon) return AppIcons.menu
|
||||||
|
if (icon.startsWith('material-symbols:') || icon.startsWith('svg-icon:')) return icon
|
||||||
|
return legacyIconAliases[icon] || AppIcons.menu
|
||||||
|
}
|
||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
import { h } from 'vue'
|
import { h } from 'vue'
|
||||||
import type { VNode } from 'vue'
|
import type { VNode } from 'vue'
|
||||||
import { Icon, IconTypes } from '@/components/Icon'
|
import { AppIcon } from '@/components/AppIcon'
|
||||||
|
import type { IconTypes } from '@/components/Icon'
|
||||||
|
|
||||||
export const useIcon = (props: IconTypes): VNode => {
|
export const useIcon = (props: IconTypes): VNode => {
|
||||||
return h(Icon, props)
|
return h(AppIcon, props)
|
||||||
}
|
}
|
||||||
@@ -56,14 +56,20 @@ export default defineComponent({
|
|||||||
) : undefined}
|
) : undefined}
|
||||||
<div class="h-full flex items-center">
|
<div class="h-full flex items-center">
|
||||||
{screenfull.value ? (
|
{screenfull.value ? (
|
||||||
<Screenfull class="custom-hover" color="var(--top-header-text-color)"></Screenfull>
|
<Screenfull
|
||||||
|
class="<md:hidden custom-hover"
|
||||||
|
color="var(--top-header-text-color)"
|
||||||
|
></Screenfull>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{size.value ? (
|
{size.value ? (
|
||||||
<SizeDropdown class="custom-hover" color="var(--top-header-text-color)"></SizeDropdown>
|
<SizeDropdown
|
||||||
|
class="<md:hidden custom-hover"
|
||||||
|
color="var(--top-header-text-color)"
|
||||||
|
></SizeDropdown>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
{locale.value ? (
|
{locale.value ? (
|
||||||
<LocaleDropdown
|
<LocaleDropdown
|
||||||
class="custom-hover"
|
class="<sm:hidden custom-hover"
|
||||||
color="var(--top-header-text-color)"
|
color="var(--top-header-text-color)"
|
||||||
></LocaleDropdown>
|
></LocaleDropdown>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
@@ -79,6 +85,20 @@ export default defineComponent({
|
|||||||
@prefix-cls: ~'@{namespace}-tool-header';
|
@prefix-cls: ~'@{namespace}-tool-header';
|
||||||
|
|
||||||
.@{prefix-cls} {
|
.@{prefix-cls} {
|
||||||
|
min-width: 0;
|
||||||
|
gap: 8px;
|
||||||
transition: left var(--transition-time-02);
|
transition: left var(--transition-time-02);
|
||||||
|
|
||||||
|
:deep(.el-dropdown),
|
||||||
|
:deep(.v-user-info) {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.@{prefix-cls} {
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -86,6 +86,7 @@ export default {
|
|||||||
cutMenu: 'Cut Menu',
|
cutMenu: 'Cut Menu',
|
||||||
copy: 'Copy',
|
copy: 'Copy',
|
||||||
clearAndReset: 'Clear cache and reset',
|
clearAndReset: 'Clear cache and reset',
|
||||||
|
clearCacheMessage: 'Clear local cache and reload the admin console?',
|
||||||
copySuccess: 'Copy success',
|
copySuccess: 'Copy success',
|
||||||
copyFailed: 'Copy failed',
|
copyFailed: 'Copy failed',
|
||||||
footer: 'Footer',
|
footer: 'Footer',
|
||||||
@@ -103,6 +104,7 @@ export default {
|
|||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
welcome: 'Short-drama workspace',
|
welcome: 'Short-drama workspace',
|
||||||
|
consoleLabel: 'Content Operations',
|
||||||
message: 'Manage dramas, episodes, publishing, and access.',
|
message: 'Manage dramas, episodes, publishing, and access.',
|
||||||
hint: 'Sign in with an admin account',
|
hint: 'Sign in with an admin account',
|
||||||
noAccount: 'No account yet?',
|
noAccount: 'No account yet?',
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ export default {
|
|||||||
cutMenu: '切割菜单',
|
cutMenu: '切割菜单',
|
||||||
copy: '拷贝',
|
copy: '拷贝',
|
||||||
clearAndReset: '清除缓存并且重置',
|
clearAndReset: '清除缓存并且重置',
|
||||||
|
clearCacheMessage: '确认清除本地缓存并重新加载后台吗?',
|
||||||
copySuccess: '拷贝成功',
|
copySuccess: '拷贝成功',
|
||||||
copyFailed: '拷贝失败',
|
copyFailed: '拷贝失败',
|
||||||
footer: '页脚',
|
footer: '页脚',
|
||||||
@@ -103,6 +104,7 @@ export default {
|
|||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
welcome: '短剧内容管理',
|
welcome: '短剧内容管理',
|
||||||
|
consoleLabel: '内容运营后台',
|
||||||
message: '管理短剧、剧集、发布状态和后台权限。',
|
message: '管理短剧、剧集、发布状态和后台权限。',
|
||||||
hint: '使用管理员账号进入工作台',
|
hint: '使用管理员账号进入工作台',
|
||||||
noAccount: '还没有账号?',
|
noAccount: '还没有账号?',
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ export const useAppStore = defineStore('app', {
|
|||||||
// 左侧菜单浅色背景颜色
|
// 左侧菜单浅色背景颜色
|
||||||
leftMenuBgLightColor: '#0f2438',
|
leftMenuBgLightColor: '#0f2438',
|
||||||
// 左侧菜单选中背景颜色
|
// 左侧菜单选中背景颜色
|
||||||
leftMenuBgActiveColor: 'var(--el-color-primary)',
|
leftMenuBgActiveColor: 'var(--app-primary-strong)',
|
||||||
// 左侧菜单收起选中背景颜色
|
// 左侧菜单收起选中背景颜色
|
||||||
leftMenuCollapseBgActiveColor: 'var(--el-color-primary)',
|
leftMenuCollapseBgActiveColor: 'var(--app-primary-strong)',
|
||||||
// 左侧菜单字体颜色
|
// 左侧菜单字体颜色
|
||||||
leftMenuTextColor: '#bfcbd9',
|
leftMenuTextColor: '#bfcbd9',
|
||||||
// 左侧菜单选中字体颜色
|
// 左侧菜单选中字体颜色
|
||||||
@@ -288,11 +288,11 @@ export const useAppStore = defineStore('app', {
|
|||||||
leftMenuBgLightColor: isDarkColor ? lighten(color!, 6) : color,
|
leftMenuBgLightColor: isDarkColor ? lighten(color!, 6) : color,
|
||||||
// 左侧菜单选中背景颜色
|
// 左侧菜单选中背景颜色
|
||||||
leftMenuBgActiveColor: isDarkColor
|
leftMenuBgActiveColor: isDarkColor
|
||||||
? 'var(--el-color-primary)'
|
? 'var(--app-primary-strong)'
|
||||||
: hexToRGB(unref(primaryColor), 0.1),
|
: hexToRGB(unref(primaryColor), 0.1),
|
||||||
// 左侧菜单收起选中背景颜色
|
// 左侧菜单收起选中背景颜色
|
||||||
leftMenuCollapseBgActiveColor: isDarkColor
|
leftMenuCollapseBgActiveColor: isDarkColor
|
||||||
? 'var(--el-color-primary)'
|
? 'var(--app-primary-strong)'
|
||||||
: hexToRGB(unref(primaryColor), 0.1),
|
: hexToRGB(unref(primaryColor), 0.1),
|
||||||
// 左侧菜单字体颜色
|
// 左侧菜单字体颜色
|
||||||
leftMenuTextColor: isDarkColor ? '#bfcbd9' : '#333',
|
leftMenuTextColor: isDarkColor ? '#bfcbd9' : '#333',
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ export const useUserStore = defineStore('user', {
|
|||||||
token: '',
|
token: '',
|
||||||
roleRouters: undefined,
|
roleRouters: undefined,
|
||||||
// 记住我
|
// 记住我
|
||||||
rememberMe: true,
|
rememberMe: false,
|
||||||
loginInfo: undefined
|
loginInfo: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -87,6 +87,8 @@ export const useUserStore = defineStore('user', {
|
|||||||
this.setToken('')
|
this.setToken('')
|
||||||
this.setUserInfo(undefined)
|
this.setUserInfo(undefined)
|
||||||
this.setRoleRouters([])
|
this.setRoleRouters([])
|
||||||
|
this.setLoginInfo(undefined)
|
||||||
|
this.setRememberMe(false)
|
||||||
tagsViewStore.delAllViews()
|
tagsViewStore.delAllViews()
|
||||||
// 菜单/路由一起清:否则换账号后 permissionStore 里还是上一个账号的路由表
|
// 菜单/路由一起清:否则换账号后 permissionStore 里还是上一个账号的路由表
|
||||||
permissionStore.clearRoutes()
|
permissionStore.clearRoutes()
|
||||||
@@ -102,7 +104,17 @@ export const useUserStore = defineStore('user', {
|
|||||||
this.loginInfo = loginInfo
|
this.loginInfo = loginInfo
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
persist: true
|
persist: {
|
||||||
|
afterRestore: (context) => {
|
||||||
|
const loginInfo = context.store.loginInfo as
|
||||||
|
(UserLoginType & { password?: string }) | undefined
|
||||||
|
if (loginInfo?.password !== undefined) {
|
||||||
|
context.store.setLoginInfo(
|
||||||
|
loginInfo.username ? { username: loginInfo.username } : undefined
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export const useUserStoreWithOut = () => {
|
export const useUserStoreWithOut = () => {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
height: 90px;
|
height: 90px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 1px solid var(--el-border-color-lighter);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #f0f2f4 !important;
|
background: #f0f2f4 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
place-content: center;
|
place-content: center;
|
||||||
width: 160px;
|
width: 160px;
|
||||||
height: 90px;
|
height: 90px;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #f0f2f4 !important;
|
background: #f0f2f4 !important;
|
||||||
color: #7e8791;
|
color: #7e8791;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
flex: 0 0 200px;
|
flex: 0 0 200px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
border: 1px solid var(--el-border-color-lighter);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
background: #f0f2f4 !important;
|
background: #f0f2f4 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ section .console-hint.el-alert {
|
|||||||
min-height: 74px;
|
min-height: 74px;
|
||||||
padding: 12px 14px;
|
padding: 12px 14px;
|
||||||
border: 1px solid #e6e8eb;
|
border: 1px solid #e6e8eb;
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
width: 34px;
|
width: 34px;
|
||||||
height: 46px;
|
height: 46px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #eef0f5;
|
background: #eef0f5;
|
||||||
color: #9a97a8;
|
color: #9a97a8;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@@ -193,7 +193,7 @@
|
|||||||
height: 76px;
|
height: 76px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid #e6e8eb;
|
border: 1px solid #e6e8eb;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #fafbfc;
|
background: #fafbfc;
|
||||||
color: #9a97a8;
|
color: #9a97a8;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
width: 48px;
|
width: 48px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 3px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #eef0f5;
|
background: #eef0f5;
|
||||||
color: #9a97a8;
|
color: #9a97a8;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
@@ -226,7 +226,7 @@
|
|||||||
padding: 10px 14px;
|
padding: 10px 14px;
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
border: 1px solid #f0e6cf;
|
border: 1px solid #f0e6cf;
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
background: #fdf9ef;
|
background: #fdf9ef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ html.dark .panel-heading h2,
|
|||||||
html.dark .episode-toolbar h2,
|
html.dark .episode-toolbar h2,
|
||||||
html.dark .stat-value,
|
html.dark .stat-value,
|
||||||
html.dark .drama-cell b,
|
html.dark .drama-cell b,
|
||||||
html.dark .brand b,
|
|
||||||
html.dark .role-card,
|
html.dark .role-card,
|
||||||
html.dark .cover-card-info b {
|
html.dark .cover-card-info b {
|
||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
@@ -22,19 +21,13 @@ html.dark .table-result-count {
|
|||||||
|
|
||||||
html.dark .stat-card,
|
html.dark .stat-card,
|
||||||
html.dark .panel,
|
html.dark .panel,
|
||||||
html.dark .role-card,
|
html.dark .role-card {
|
||||||
html.dark .topbar,
|
|
||||||
html.dark .sidebar {
|
|
||||||
background: var(--el-bg-color-overlay);
|
background: var(--el-bg-color-overlay);
|
||||||
border-color: var(--el-border-color-light);
|
border-color: var(--el-border-color-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
html.dark .stat-icon,
|
html.dark .stat-icon,
|
||||||
html.dark .role-icon,
|
html.dark .role-icon {
|
||||||
html.dark .help-icon,
|
|
||||||
html.dark .workspace-avatar,
|
|
||||||
html.dark .profile-avatar,
|
|
||||||
html.dark .top-avatar {
|
|
||||||
background: rgb(64 158 255 / 16%) !important;
|
background: rgb(64 158 255 / 16%) !important;
|
||||||
color: var(--el-color-primary) !important;
|
color: var(--el-color-primary) !important;
|
||||||
}
|
}
|
||||||
@@ -128,3 +121,33 @@ html.dark .el-tag.status-badge.is-offline {
|
|||||||
border-color: rgba(245, 108, 108, 0.45) !important;
|
border-color: rgba(245, 108, 108, 0.45) !important;
|
||||||
color: #f3a6a6 !important;
|
color: #f3a6a6 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.v-tool-header {
|
||||||
|
color: var(--top-header-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-tags-view {
|
||||||
|
background: var(--el-bg-color);
|
||||||
|
border-color: var(--el-border-color-lighter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-tags-view__item--close {
|
||||||
|
color: var(--el-text-color-secondary) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .v-tool-header,
|
||||||
|
html.dark .v-tags-view {
|
||||||
|
background: var(--el-bg-color-overlay);
|
||||||
|
border-color: var(--el-border-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark .v-tags-view__item {
|
||||||
|
color: var(--el-text-color-regular);
|
||||||
|
}
|
||||||
|
|
||||||
|
html.dark #v-menu .el-menu-item.is-active,
|
||||||
|
html.dark #v-menu .el-sub-menu.is-active > .el-sub-menu__title,
|
||||||
|
html.dark .v-tags-view__item.is-active {
|
||||||
|
background-color: var(--app-primary-strong) !important;
|
||||||
|
border-color: var(--app-primary-strong) !important;
|
||||||
|
}
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
padding: 0 10px !important;
|
padding: 0 10px !important;
|
||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
font-weight: 500 !important;
|
font-weight: 500 !important;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Element Plus 默认给相邻按钮加 12px 外边距,会和这里的 gap 叠加导致换行 */
|
/* Element Plus 默认给相邻按钮加 12px 外边距,会和这里的 gap 叠加导致换行 */
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
width: 44px;
|
width: 44px;
|
||||||
height: 56px;
|
height: 56px;
|
||||||
flex: 0 0 44px;
|
flex: 0 0 44px;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
.drama-cell .drama-cover {
|
.drama-cell .drama-cover {
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
flex: 0 0 84px;
|
flex: 0 0 84px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 1px solid var(--el-border-color-lighter);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
background: #f0f2f4 !important;
|
background: #f0f2f4 !important;
|
||||||
}
|
}
|
||||||
.dark .form-cover-preview {
|
.dark .form-cover-preview {
|
||||||
@@ -134,7 +134,7 @@
|
|||||||
flex: 0 0 200px;
|
flex: 0 0 200px;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
border: 1px solid var(--el-border-color-lighter);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
background: #000 !important;
|
background: #000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
max-height: 60vh;
|
max-height: 60vh;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
border-radius: 8px;
|
border-radius: var(--app-radius-md);
|
||||||
background: #000 !important;
|
background: #000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid var(--el-border-color-lighter);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #000 !important;
|
background: #000 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,10 +231,10 @@
|
|||||||
color: #c0c6cf;
|
color: #c0c6cf;
|
||||||
}
|
}
|
||||||
.table-actions .el-button--primary {
|
.table-actions .el-button--primary {
|
||||||
--el-button-bg-color: #409eff;
|
--el-button-bg-color: var(--el-color-primary);
|
||||||
--el-button-border-color: #409eff;
|
--el-button-border-color: var(--el-color-primary);
|
||||||
--el-button-hover-bg-color: #79bbff;
|
--el-button-hover-bg-color: var(--el-color-primary-light-3);
|
||||||
--el-button-hover-border-color: #79bbff;
|
--el-button-hover-border-color: var(--el-color-primary-light-3);
|
||||||
}
|
}
|
||||||
.table-actions .el-button--success {
|
.table-actions .el-button--success {
|
||||||
--el-button-bg-color: #4d866a;
|
--el-button-bg-color: #4d866a;
|
||||||
@@ -259,7 +259,7 @@
|
|||||||
font-size: 13px !important;
|
font-size: 13px !important;
|
||||||
--el-pagination-font-size: 13px;
|
--el-pagination-font-size: 13px;
|
||||||
--el-pagination-button-bg-color: #f1f3f6;
|
--el-pagination-button-bg-color: #f1f3f6;
|
||||||
--el-pagination-hover-color: #409eff;
|
--el-pagination-hover-color: var(--el-color-primary);
|
||||||
--el-pagination-button-color: #4c5561;
|
--el-pagination-button-color: #4c5561;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
background: #f6f7f9 !important;
|
background: #f6f7f9 !important;
|
||||||
border: 1px solid var(--el-border-color-lighter);
|
border: 1px solid var(--el-border-color-lighter);
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .log-json {
|
.dark .log-json {
|
||||||
|
|||||||
+89
-374
@@ -1,316 +1,12 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Manrope:wght@400;500;600;700;800&family=Noto+Sans+SC:wght@400;500;600;700&display=swap');
|
|
||||||
:root {
|
|
||||||
font-family: 'DM Sans', 'Noto Sans SC', sans-serif;
|
|
||||||
color: var(--el-text-color-primary);
|
|
||||||
background: var(--el-bg-color-page);
|
|
||||||
font-synthesis: none;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
font-optical-sizing: auto;
|
|
||||||
font-weight: 400;
|
|
||||||
--purple: #409eff;
|
|
||||||
--muted: #9695a8;
|
|
||||||
--line: #eeedf3;
|
|
||||||
}
|
|
||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-width: 980px;
|
min-width: 0;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
.app-shell {
|
.page-heading {
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
.sidebar {
|
|
||||||
width: 250px;
|
|
||||||
position: fixed;
|
|
||||||
inset: 0 auto 0 0;
|
|
||||||
background: #fff;
|
|
||||||
border-right: 1px solid #eeedf4;
|
|
||||||
padding: 27px 17px 16px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
z-index: 4;
|
|
||||||
}
|
|
||||||
.brand {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 11px;
|
|
||||||
padding: 0 9px 28px;
|
|
||||||
}
|
|
||||||
.brand-mark {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #409eff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 2px;
|
|
||||||
transform: rotate(-8deg);
|
|
||||||
}
|
|
||||||
.brand-mark span {
|
|
||||||
width: 4px;
|
|
||||||
background: white;
|
|
||||||
border-radius: 4px;
|
|
||||||
transform: skew(-15deg);
|
|
||||||
}
|
|
||||||
.brand-mark span:nth-child(1) {
|
|
||||||
height: 11px;
|
|
||||||
opacity: 0.72;
|
|
||||||
}
|
|
||||||
.brand-mark span:nth-child(2) {
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
.brand-mark span:nth-child(3) {
|
|
||||||
height: 13px;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
.brand b {
|
|
||||||
display: block;
|
|
||||||
font:
|
|
||||||
800 18px Manrope,
|
|
||||||
sans-serif;
|
|
||||||
letter-spacing: -0.8px;
|
|
||||||
color: #242139;
|
|
||||||
}
|
|
||||||
.brand small {
|
|
||||||
font-size: 8px;
|
|
||||||
letter-spacing: 1.5px;
|
|
||||||
color: #a3a1b1;
|
|
||||||
display: block;
|
|
||||||
margin-top: 1px;
|
|
||||||
}
|
|
||||||
.workspace {
|
|
||||||
height: 58px;
|
|
||||||
border: 1px solid #efedf4;
|
|
||||||
border-radius: 10px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 10px;
|
|
||||||
margin-bottom: 27px;
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
.workspace-avatar,
|
|
||||||
.profile-avatar,
|
|
||||||
.top-avatar {
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
background: #ecf5ff;
|
|
||||||
color: #409eff;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.workspace-avatar {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
.workspace-copy {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.workspace-copy b,
|
|
||||||
.workspace-copy small {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.workspace-copy b {
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
.workspace-copy small {
|
|
||||||
color: #a09eae;
|
|
||||||
font-size: 10px;
|
|
||||||
margin-top: 3px;
|
|
||||||
}
|
|
||||||
.workspace > .el-icon {
|
|
||||||
color: #aaa8b7;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
.nav-label {
|
|
||||||
padding: 0 11px 10px;
|
|
||||||
color: #aaa8b7;
|
|
||||||
font-size: 10px;
|
|
||||||
letter-spacing: 0.5px;
|
|
||||||
}
|
|
||||||
.side-menu {
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
.side-menu .el-menu-item {
|
|
||||||
height: 43px;
|
|
||||||
line-height: 43px;
|
|
||||||
border-radius: 8px;
|
|
||||||
margin: 2px 0;
|
|
||||||
color: #777589;
|
|
||||||
font-size: 12px;
|
|
||||||
padding: 0 11px !important;
|
|
||||||
}
|
|
||||||
.side-menu .el-menu-item .el-icon {
|
|
||||||
font-size: 16px;
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
.side-menu .el-menu-item:hover {
|
|
||||||
background: #ecf5ff;
|
|
||||||
color: #409eff;
|
|
||||||
}
|
|
||||||
.side-menu .el-menu-item.is-active {
|
|
||||||
background: #ecf5ff;
|
|
||||||
color: #409eff;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.menu-count {
|
|
||||||
margin-left: auto;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #ecf5ff;
|
|
||||||
color: #79bbff;
|
|
||||||
padding: 2px 7px;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
.access-label {
|
|
||||||
margin-top: 27px;
|
|
||||||
}
|
|
||||||
.sidebar-bottom {
|
|
||||||
margin-top: auto;
|
|
||||||
}
|
|
||||||
.help-card {
|
|
||||||
background: #ecf5ff;
|
|
||||||
border: 1px solid #ecf5ff;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 13px 13px 14px;
|
|
||||||
margin: 0 2px 17px;
|
|
||||||
}
|
|
||||||
.help-icon {
|
|
||||||
width: 23px;
|
|
||||||
height: 23px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
background: #d9ecff;
|
|
||||||
border-radius: 7px;
|
|
||||||
color: #409eff;
|
|
||||||
margin-bottom: 9px;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
.help-card b {
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
.help-card p {
|
|
||||||
font-size: 10px;
|
|
||||||
line-height: 1.6;
|
|
||||||
color: #9290a2;
|
|
||||||
margin: 5px 0 9px;
|
|
||||||
}
|
|
||||||
.help-card a {
|
|
||||||
font-size: 10px;
|
|
||||||
color: #409eff;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
.help-card a span {
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
.user-profile {
|
|
||||||
border-top: 1px solid #f0eff4;
|
|
||||||
padding: 15px 4px 0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 9px;
|
|
||||||
}
|
|
||||||
.profile-avatar {
|
|
||||||
width: 33px;
|
|
||||||
height: 33px;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.profile-info {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.profile-info b,
|
|
||||||
.profile-info small {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.profile-info b {
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
.profile-info small {
|
|
||||||
font-size: 10px;
|
|
||||||
color: #a09eae;
|
|
||||||
margin-top: 3px;
|
|
||||||
}
|
|
||||||
.user-profile > .el-icon {
|
|
||||||
color: #aaa8b7;
|
|
||||||
transform: rotate(90deg);
|
|
||||||
}
|
|
||||||
.main-area {
|
|
||||||
margin-left: 250px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
|
||||||
.topbar {
|
|
||||||
height: 64px;
|
|
||||||
background: rgba(255, 255, 255, 0.92);
|
|
||||||
border-bottom: 1px solid #eeedf4;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 0 39px;
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 3;
|
|
||||||
}
|
|
||||||
.breadcrumb {
|
|
||||||
font-size: 11px;
|
|
||||||
color: #aaa8b6;
|
|
||||||
}
|
|
||||||
.breadcrumb .slash {
|
|
||||||
padding: 0 10px;
|
|
||||||
color: #d4d2dd;
|
|
||||||
}
|
|
||||||
.breadcrumb b {
|
|
||||||
font-weight: 600;
|
|
||||||
color: #555367;
|
|
||||||
}
|
|
||||||
.top-actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 18px;
|
|
||||||
}
|
|
||||||
.environment {
|
|
||||||
border: 1px solid #eeedf2;
|
|
||||||
border-radius: 15px;
|
|
||||||
padding: 6px 10px;
|
|
||||||
font-size: 10px;
|
|
||||||
color: #777589;
|
|
||||||
}
|
|
||||||
.environment i {
|
|
||||||
display: inline-block;
|
|
||||||
width: 6px;
|
|
||||||
height: 6px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #62c491;
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
.icon-button {
|
|
||||||
position: relative;
|
|
||||||
color: #777589;
|
|
||||||
}
|
|
||||||
.notification-dot {
|
|
||||||
width: 5px;
|
|
||||||
height: 5px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: #ef7d85;
|
|
||||||
position: absolute;
|
|
||||||
right: 6px;
|
|
||||||
top: 5px;
|
|
||||||
border: 1px solid white;
|
|
||||||
}
|
|
||||||
.top-avatar {
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
border-radius: 50%;
|
|
||||||
font-size: 11px;
|
|
||||||
}
|
|
||||||
.page-content {
|
|
||||||
max-width: 1440px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 35px 40px 46px;
|
|
||||||
}
|
|
||||||
.page-heading {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -323,7 +19,7 @@ body {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
.eyebrow span {
|
.eyebrow span {
|
||||||
color: #79bbff;
|
color: var(--el-color-primary-light-3);
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
.page-heading h1 {
|
.page-heading h1 {
|
||||||
@@ -344,17 +40,17 @@ body {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
.primary-button {
|
.primary-button {
|
||||||
background: #409eff !important;
|
background: var(--el-color-primary) !important;
|
||||||
border-color: #409eff !important;
|
border-color: var(--el-color-primary) !important;
|
||||||
border-radius: 7px !important;
|
border-radius: var(--app-radius-md) !important;
|
||||||
font-size: 11px !important;
|
font-size: 11px !important;
|
||||||
font-weight: 600 !important;
|
font-weight: 600 !important;
|
||||||
height: 37px !important;
|
height: 37px !important;
|
||||||
padding: 0 15px !important;
|
padding: 0 15px !important;
|
||||||
box-shadow: 0 4px 10px #409eff22;
|
box-shadow: 0 4px 10px color-mix(in srgb, var(--el-color-primary) 13%, transparent);
|
||||||
}
|
}
|
||||||
.primary-button:hover {
|
.primary-button:hover {
|
||||||
background: #337ecc !important;
|
background: var(--el-color-primary-dark-2) !important;
|
||||||
}
|
}
|
||||||
.primary-button .el-icon {
|
.primary-button .el-icon {
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
@@ -369,7 +65,7 @@ body {
|
|||||||
.panel {
|
.panel {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #efedf3;
|
border: 1px solid #efedf3;
|
||||||
border-radius: 10px;
|
border-radius: var(--app-radius-md);
|
||||||
}
|
}
|
||||||
.stat-card {
|
.stat-card {
|
||||||
padding: 16px 17px 13px;
|
padding: 16px 17px 13px;
|
||||||
@@ -387,12 +83,12 @@ body {
|
|||||||
height: 27px;
|
height: 27px;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 8px;
|
border-radius: var(--app-radius-md);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
.lilac {
|
.lilac {
|
||||||
background: #ecf5ff;
|
background: var(--el-color-primary-light-9);
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.blush {
|
.blush {
|
||||||
background: #fff0f2;
|
background: #fff0f2;
|
||||||
@@ -435,7 +131,7 @@ body {
|
|||||||
color: #49b786;
|
color: #49b786;
|
||||||
background: #eef9f4;
|
background: #eef9f4;
|
||||||
padding: 3px 5px;
|
padding: 3px 5px;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
}
|
}
|
||||||
.neutral {
|
.neutral {
|
||||||
color: #aaa8b6;
|
color: #aaa8b6;
|
||||||
@@ -565,9 +261,9 @@ body {
|
|||||||
.muted-count {
|
.muted-count {
|
||||||
display: inline-grid;
|
display: inline-grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 10px;
|
border-radius: var(--app-radius-md);
|
||||||
background: #ecf5ff;
|
background: var(--el-color-primary-light-9);
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
font:
|
font:
|
||||||
600 9px 'DM Sans',
|
600 9px 'DM Sans',
|
||||||
sans-serif;
|
sans-serif;
|
||||||
@@ -578,7 +274,7 @@ body {
|
|||||||
}
|
}
|
||||||
.view-all {
|
.view-all {
|
||||||
font-size: 10px !important;
|
font-size: 10px !important;
|
||||||
color: #409eff !important;
|
color: var(--el-color-primary) !important;
|
||||||
}
|
}
|
||||||
.view-all span {
|
.view-all span {
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
@@ -599,7 +295,7 @@ body {
|
|||||||
.review-art {
|
.review-art {
|
||||||
width: 34px;
|
width: 34px;
|
||||||
height: 37px;
|
height: 37px;
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
@@ -608,7 +304,7 @@ body {
|
|||||||
background: #fff0ed;
|
background: #fff0ed;
|
||||||
}
|
}
|
||||||
.art-two {
|
.art-two {
|
||||||
background: #ecf5ff;
|
background: var(--el-color-primary-light-9);
|
||||||
}
|
}
|
||||||
.art-three {
|
.art-three {
|
||||||
background: #eaf6f7;
|
background: #eaf6f7;
|
||||||
@@ -661,7 +357,7 @@ body {
|
|||||||
padding: 10px 11px;
|
padding: 10px 11px;
|
||||||
}
|
}
|
||||||
.drama-table th:first-child {
|
.drama-table th:first-child {
|
||||||
border-radius: 5px 0 0 5px;
|
border-radius: var(--app-radius-sm) 0 0 5px;
|
||||||
padding-left: 12px;
|
padding-left: 12px;
|
||||||
}
|
}
|
||||||
.drama-table th:last-child {
|
.drama-table th:last-child {
|
||||||
@@ -689,7 +385,7 @@ body {
|
|||||||
.drama-cover {
|
.drama-cover {
|
||||||
width: 31px;
|
width: 31px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@@ -700,7 +396,7 @@ body {
|
|||||||
background: linear-gradient(145deg, #f8d6d7, #ffece4);
|
background: linear-gradient(145deg, #f8d6d7, #ffece4);
|
||||||
}
|
}
|
||||||
.purple {
|
.purple {
|
||||||
background: linear-gradient(145deg, #d9ecff, #ecf5ff);
|
background: linear-gradient(145deg, var(--el-color-primary-light-8), var(--el-color-primary-light-9));
|
||||||
}
|
}
|
||||||
.peach {
|
.peach {
|
||||||
background: linear-gradient(145deg, #ffd6bd, #fff0d7);
|
background: linear-gradient(145deg, #ffd6bd, #fff0d7);
|
||||||
@@ -713,7 +409,7 @@ body {
|
|||||||
}
|
}
|
||||||
.row-action {
|
.row-action {
|
||||||
font-size: 9px !important;
|
font-size: 9px !important;
|
||||||
color: #409eff !important;
|
color: var(--el-color-primary) !important;
|
||||||
}
|
}
|
||||||
.inner-heading {
|
.inner-heading {
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
@@ -744,11 +440,11 @@ body {
|
|||||||
}
|
}
|
||||||
.library-toolbar .el-tabs__item.is-active,
|
.library-toolbar .el-tabs__item.is-active,
|
||||||
.cover-toolbar .el-tabs__item.is-active {
|
.cover-toolbar .el-tabs__item.is-active {
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.library-toolbar .el-tabs__active-bar,
|
.library-toolbar .el-tabs__active-bar,
|
||||||
.cover-toolbar .el-tabs__active-bar {
|
.cover-toolbar .el-tabs__active-bar {
|
||||||
background: #409eff;
|
background: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.toolbar-filters {
|
.toolbar-filters {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -795,7 +491,7 @@ body {
|
|||||||
}
|
}
|
||||||
.pagination .el-pagination {
|
.pagination .el-pagination {
|
||||||
--el-pagination-button-bg-color: #fff;
|
--el-pagination-button-bg-color: #fff;
|
||||||
--el-pagination-hover-color: #409eff;
|
--el-pagination-hover-color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.pagination .el-pager li {
|
.pagination .el-pager li {
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
@@ -818,7 +514,7 @@ body {
|
|||||||
width: 48px;
|
width: 48px;
|
||||||
height: 58px;
|
height: 58px;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
}
|
}
|
||||||
.episode-context-copy {
|
.episode-context-copy {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
@@ -854,7 +550,7 @@ body {
|
|||||||
padding: 20px 0 14px;
|
padding: 20px 0 14px;
|
||||||
}
|
}
|
||||||
.secondary-button {
|
.secondary-button {
|
||||||
border-radius: 6px !important;
|
border-radius: var(--app-radius-md) !important;
|
||||||
border-color: #eae8f0 !important;
|
border-color: #eae8f0 !important;
|
||||||
color: #6e6c80 !important;
|
color: #6e6c80 !important;
|
||||||
font-size: 10px !important;
|
font-size: 10px !important;
|
||||||
@@ -866,7 +562,7 @@ body {
|
|||||||
.episode-row {
|
.episode-row {
|
||||||
height: 69px;
|
height: 69px;
|
||||||
border: 1px solid #efedf4;
|
border: 1px solid #efedf4;
|
||||||
border-radius: 7px;
|
border-radius: var(--app-radius-md);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
@@ -881,7 +577,7 @@ body {
|
|||||||
.episode-thumb {
|
.episode-thumb {
|
||||||
width: 62px;
|
width: 62px;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: linear-gradient(135deg, #29273b, #55516e);
|
background: linear-gradient(135deg, #29273b, #55516e);
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
@@ -946,7 +642,7 @@ body {
|
|||||||
.add-cover {
|
.add-cover {
|
||||||
background: white;
|
background: white;
|
||||||
border: 1px solid #eeedf3;
|
border: 1px solid #eeedf3;
|
||||||
border-radius: 9px;
|
border-radius: var(--app-radius-md);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.poster-art {
|
.poster-art {
|
||||||
@@ -1023,7 +719,7 @@ body {
|
|||||||
border: 1px solid #ffffff8a;
|
border: 1px solid #ffffff8a;
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
border-radius: 3px;
|
border-radius: var(--app-radius-sm);
|
||||||
}
|
}
|
||||||
.cover-card-info {
|
.cover-card-info {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
@@ -1063,8 +759,8 @@ body {
|
|||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
background: #ecf5ff;
|
background: var(--el-color-primary-light-9);
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
margin-bottom: 11px;
|
margin-bottom: 11px;
|
||||||
}
|
}
|
||||||
@@ -1096,7 +792,7 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid #efedf4;
|
border: 1px solid #efedf4;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border-radius: 8px;
|
border-radius: var(--app-radius-md);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@@ -1106,10 +802,10 @@ body {
|
|||||||
font: inherit;
|
font: inherit;
|
||||||
}
|
}
|
||||||
.role-card:hover {
|
.role-card:hover {
|
||||||
border-color: #c6e2ff;
|
border-color: var(--el-color-primary-light-7);
|
||||||
}
|
}
|
||||||
.role-active {
|
.role-active {
|
||||||
border-color: #a0cfff;
|
border-color: var(--el-color-primary-light-5);
|
||||||
background: #f5faff;
|
background: #f5faff;
|
||||||
}
|
}
|
||||||
.role-icon {
|
.role-icon {
|
||||||
@@ -1117,7 +813,7 @@ body {
|
|||||||
height: 34px;
|
height: 34px;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 8px;
|
border-radius: var(--app-radius-md);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
.role-icon.red {
|
.role-icon.red {
|
||||||
@@ -1125,12 +821,12 @@ body {
|
|||||||
color: #e47b79;
|
color: #e47b79;
|
||||||
}
|
}
|
||||||
.role-icon.purple {
|
.role-icon.purple {
|
||||||
background: #ecf5ff;
|
background: var(--el-color-primary-light-9);
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.role-icon.blue {
|
.role-icon.blue {
|
||||||
background: #edf5ff;
|
background: #edf5ff;
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.role-icon.green {
|
.role-icon.green {
|
||||||
background: #eaf8f0;
|
background: #eaf8f0;
|
||||||
@@ -1165,9 +861,9 @@ body {
|
|||||||
}
|
}
|
||||||
.role-badge {
|
.role-badge {
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
background: #ecf5ff;
|
background: var(--el-color-primary-light-9);
|
||||||
border-radius: 10px;
|
border-radius: var(--app-radius-md);
|
||||||
padding: 4px 7px;
|
padding: 4px 7px;
|
||||||
vertical-align: 2px;
|
vertical-align: 2px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
@@ -1193,7 +889,7 @@ body {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.permission-group .el-checkbox {
|
.permission-group .el-checkbox {
|
||||||
height: auto;
|
height: auto;
|
||||||
@@ -1204,13 +900,13 @@ body {
|
|||||||
color: #858397;
|
color: #858397;
|
||||||
}
|
}
|
||||||
.permission-group .el-checkbox__input.is-checked .el-checkbox__inner {
|
.permission-group .el-checkbox__input.is-checked .el-checkbox__inner {
|
||||||
background: #409eff;
|
background: var(--el-color-primary);
|
||||||
border-color: #409eff;
|
border-color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.permission-note {
|
.permission-note {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: #f8f7fc;
|
background: #f8f7fc;
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
color: #9997a8;
|
color: #9997a8;
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -1218,7 +914,7 @@ body {
|
|||||||
gap: 7px;
|
gap: 7px;
|
||||||
}
|
}
|
||||||
.permission-note .el-icon {
|
.permission-note .el-icon {
|
||||||
color: #79bbff;
|
color: var(--el-color-primary-light-3);
|
||||||
}
|
}
|
||||||
.placeholder-panel {
|
.placeholder-panel {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@@ -1229,10 +925,10 @@ body {
|
|||||||
place-items: center;
|
place-items: center;
|
||||||
width: 45px;
|
width: 45px;
|
||||||
height: 45px;
|
height: 45px;
|
||||||
border-radius: 12px;
|
border-radius: var(--app-radius-lg);
|
||||||
margin: auto;
|
margin: auto;
|
||||||
background: #ecf5ff;
|
background: var(--el-color-primary-light-9);
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
.placeholder-panel h2 {
|
.placeholder-panel h2 {
|
||||||
@@ -1244,7 +940,7 @@ body {
|
|||||||
color: #a09eae;
|
color: #a09eae;
|
||||||
}
|
}
|
||||||
.el-dialog {
|
.el-dialog {
|
||||||
border-radius: 11px !important;
|
border-radius: var(--app-radius-md) !important;
|
||||||
}
|
}
|
||||||
.el-dialog__header {
|
.el-dialog__header {
|
||||||
padding: 20px 22px 12px !important;
|
padding: 20px 22px 12px !important;
|
||||||
@@ -1296,13 +992,13 @@ body {
|
|||||||
.upload-area .el-upload-dragger {
|
.upload-area .el-upload-dragger {
|
||||||
height: 112px;
|
height: 112px;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
border-radius: 7px;
|
border-radius: var(--app-radius-md);
|
||||||
border-color: #e8e5ef;
|
border-color: #e8e5ef;
|
||||||
background: #fcfbfe;
|
background: #fcfbfe;
|
||||||
}
|
}
|
||||||
.upload-icon {
|
.upload-icon {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
margin-bottom: 6px;
|
margin-bottom: 6px;
|
||||||
}
|
}
|
||||||
.upload-area .el-upload__text {
|
.upload-area .el-upload__text {
|
||||||
@@ -1311,7 +1007,7 @@ body {
|
|||||||
}
|
}
|
||||||
.upload-area .el-upload__text em {
|
.upload-area .el-upload__text em {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.upload-hint {
|
.upload-hint {
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
@@ -1325,10 +1021,6 @@ body {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@media (min-width: 1500px) {
|
@media (min-width: 1500px) {
|
||||||
.page-content {
|
|
||||||
padding-left: 48px;
|
|
||||||
padding-right: 48px;
|
|
||||||
}
|
|
||||||
.stats-grid {
|
.stats-grid {
|
||||||
gap: 18px;
|
gap: 18px;
|
||||||
}
|
}
|
||||||
@@ -1341,17 +1033,15 @@ body {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
.sidebar {
|
.page-heading {
|
||||||
width: 220px;
|
gap: 14px;
|
||||||
}
|
}
|
||||||
.main-area {
|
.library-toolbar,
|
||||||
margin-left: 220px;
|
.admin-user-toolbar,
|
||||||
}
|
.app-user-toolbar,
|
||||||
.page-content {
|
.console-toolbar {
|
||||||
padding: 30px 26px;
|
flex-wrap: wrap;
|
||||||
}
|
gap: 10px;
|
||||||
.topbar {
|
|
||||||
padding: 0 26px;
|
|
||||||
}
|
}
|
||||||
.stats-grid {
|
.stats-grid {
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
@@ -1367,3 +1057,28 @@ body {
|
|||||||
grid-template-columns: repeat(4, minmax(130px, 1fr));
|
grid-template-columns: repeat(4, minmax(130px, 1fr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.page-heading {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
.page-heading h1 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
.panel {
|
||||||
|
padding: 14px;
|
||||||
|
}
|
||||||
|
.library-toolbar > .el-input,
|
||||||
|
.library-toolbar > .el-select,
|
||||||
|
.admin-user-toolbar > .el-input,
|
||||||
|
.admin-user-toolbar > .el-select,
|
||||||
|
.app-user-toolbar > .el-input,
|
||||||
|
.app-user-toolbar > .el-select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.stats-grid,
|
||||||
|
.dashboard-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
+48
-112
@@ -1,5 +1,18 @@
|
|||||||
:root {
|
:root {
|
||||||
font-family: Arial, 'Noto Sans SC', sans-serif;
|
--font-display: 'Manrope', 'Noto Sans SC', sans-serif;
|
||||||
|
--font-body: 'DM Sans', 'Noto Sans SC', sans-serif;
|
||||||
|
--app-radius-sm: 4px;
|
||||||
|
--app-radius-md: 6px;
|
||||||
|
--app-radius-lg: 12px;
|
||||||
|
--app-brand: #c4322a;
|
||||||
|
--app-brand-pressed: #8e221c;
|
||||||
|
--app-brand-soft: #ff8a72;
|
||||||
|
--app-primary-strong: color-mix(in srgb, var(--el-color-primary) 72%, #000 28%);
|
||||||
|
--brand-mark-size: 38px;
|
||||||
|
--brand-mark-radius: var(--app-radius-lg);
|
||||||
|
--el-border-radius-base: var(--app-radius-md);
|
||||||
|
--el-border-radius-small: var(--app-radius-sm);
|
||||||
|
font-family: var(--font-body);
|
||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
background: var(--el-bg-color-page);
|
background: var(--el-bg-color-page);
|
||||||
--el-color-primary: #409eff;
|
--el-color-primary: #409eff;
|
||||||
@@ -17,83 +30,6 @@ body {
|
|||||||
background: var(--el-bg-color-page);
|
background: var(--el-bg-color-page);
|
||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
}
|
}
|
||||||
.sidebar {
|
|
||||||
background: #fff;
|
|
||||||
border-right-color: #e7e9ec;
|
|
||||||
padding-top: 22px;
|
|
||||||
}
|
|
||||||
.brand {
|
|
||||||
padding-bottom: 23px;
|
|
||||||
}
|
|
||||||
.brand-mark {
|
|
||||||
background: #409eff;
|
|
||||||
border-radius: 7px;
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
.brand b {
|
|
||||||
font:
|
|
||||||
700 16px Arial,
|
|
||||||
sans-serif;
|
|
||||||
letter-spacing: -0.4px;
|
|
||||||
color: #29313b;
|
|
||||||
}
|
|
||||||
.brand small {
|
|
||||||
letter-spacing: 0.9px;
|
|
||||||
}
|
|
||||||
.workspace {
|
|
||||||
border-radius: 5px;
|
|
||||||
border-color: #e5e7eb;
|
|
||||||
margin-bottom: 22px;
|
|
||||||
}
|
|
||||||
.workspace-avatar,
|
|
||||||
.profile-avatar,
|
|
||||||
.top-avatar {
|
|
||||||
background: #ecf5ff;
|
|
||||||
color: #409eff;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
.nav-label {
|
|
||||||
color: #9298a1;
|
|
||||||
font-size: 10px;
|
|
||||||
}
|
|
||||||
.side-menu .el-menu-item {
|
|
||||||
border-radius: 5px;
|
|
||||||
color: #616873;
|
|
||||||
}
|
|
||||||
.side-menu .el-menu-item:hover {
|
|
||||||
background: #ecf5ff;
|
|
||||||
color: #409eff;
|
|
||||||
}
|
|
||||||
.side-menu .el-menu-item.is-active {
|
|
||||||
background: #ecf5ff;
|
|
||||||
color: #409eff;
|
|
||||||
}
|
|
||||||
.menu-count {
|
|
||||||
background: #eef1f4;
|
|
||||||
color: #747d88;
|
|
||||||
}
|
|
||||||
.help-card {
|
|
||||||
background: #f7f8fa;
|
|
||||||
border-color: #eceef0;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
.help-icon {
|
|
||||||
background: #ecf5ff;
|
|
||||||
color: #409eff;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
.help-card a {
|
|
||||||
color: #409eff;
|
|
||||||
}
|
|
||||||
.topbar {
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
.environment {
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
.page-content {
|
|
||||||
padding-top: 30px;
|
|
||||||
}
|
|
||||||
.eyebrow {
|
.eyebrow {
|
||||||
letter-spacing: 0.7px;
|
letter-spacing: 0.7px;
|
||||||
color: #9298a1;
|
color: #9298a1;
|
||||||
@@ -110,14 +46,14 @@ body {
|
|||||||
color: #818791;
|
color: #818791;
|
||||||
}
|
}
|
||||||
.primary-button {
|
.primary-button {
|
||||||
background: #409eff !important;
|
background: var(--el-color-primary) !important;
|
||||||
border-color: #409eff !important;
|
border-color: var(--el-color-primary) !important;
|
||||||
border-radius: 5px !important;
|
border-radius: var(--app-radius-sm) !important;
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
.primary-button:hover {
|
.primary-button:hover {
|
||||||
background: #79bbff !important;
|
background: var(--el-color-primary-light-3) !important;
|
||||||
border-color: #79bbff !important;
|
border-color: var(--el-color-primary-light-3) !important;
|
||||||
}
|
}
|
||||||
.stats-grid {
|
.stats-grid {
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
@@ -125,7 +61,7 @@ body {
|
|||||||
.stat-card,
|
.stat-card,
|
||||||
.panel {
|
.panel {
|
||||||
border-color: #e6e8eb;
|
border-color: #e6e8eb;
|
||||||
border-radius: 6px;
|
border-radius: var(--app-radius-md);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
.stat-card {
|
.stat-card {
|
||||||
@@ -136,12 +72,12 @@ body {
|
|||||||
color: #727983;
|
color: #727983;
|
||||||
}
|
}
|
||||||
.stat-icon {
|
.stat-icon {
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #ecf5ff !important;
|
background: #ecf5ff !important;
|
||||||
color: #409eff !important;
|
color: var(--el-color-primary) !important;
|
||||||
}
|
}
|
||||||
.stat-value {
|
.stat-value {
|
||||||
font-family: Arial, sans-serif;
|
font-family: var(--font-display);
|
||||||
color: #303640;
|
color: #303640;
|
||||||
}
|
}
|
||||||
.stat-foot .positive {
|
.stat-foot .positive {
|
||||||
@@ -164,15 +100,15 @@ body {
|
|||||||
fill: #d9ecff;
|
fill: #d9ecff;
|
||||||
}
|
}
|
||||||
.chart-svg path:last-of-type {
|
.chart-svg path:last-of-type {
|
||||||
stroke: #409eff;
|
stroke: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.view-all,
|
.view-all,
|
||||||
.row-action {
|
.row-action {
|
||||||
color: #409eff !important;
|
color: var(--el-color-primary) !important;
|
||||||
}
|
}
|
||||||
.review-art {
|
.review-art {
|
||||||
background: #f1f3f5 !important;
|
background: #f1f3f5 !important;
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
}
|
}
|
||||||
.review-art:after {
|
.review-art:after {
|
||||||
@@ -183,12 +119,12 @@ body {
|
|||||||
.review-row .el-tag,
|
.review-row .el-tag,
|
||||||
.drama-table .el-tag,
|
.drama-table .el-tag,
|
||||||
.episode-row .el-tag {
|
.episode-row .el-tag {
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #f0f2f4 !important;
|
background: #f0f2f4 !important;
|
||||||
color: #606b78 !important;
|
color: #606b78 !important;
|
||||||
}
|
}
|
||||||
.drama-cover {
|
.drama-cover {
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
background: #eceff2 !important;
|
background: #eceff2 !important;
|
||||||
@@ -220,16 +156,16 @@ body {
|
|||||||
}
|
}
|
||||||
.library-toolbar .el-tabs__item.is-active,
|
.library-toolbar .el-tabs__item.is-active,
|
||||||
.cover-toolbar .el-tabs__item.is-active {
|
.cover-toolbar .el-tabs__item.is-active {
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.library-toolbar .el-tabs__active-bar,
|
.library-toolbar .el-tabs__active-bar,
|
||||||
.cover-toolbar .el-tabs__active-bar {
|
.cover-toolbar .el-tabs__active-bar {
|
||||||
background: #409eff;
|
background: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.toolbar-filters .el-input__wrapper,
|
.toolbar-filters .el-input__wrapper,
|
||||||
.toolbar-filters .el-select__wrapper,
|
.toolbar-filters .el-select__wrapper,
|
||||||
.drama-select .el-input__wrapper {
|
.drama-select .el-input__wrapper {
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
}
|
}
|
||||||
.episode-panel {
|
.episode-panel {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
@@ -237,10 +173,10 @@ body {
|
|||||||
}
|
}
|
||||||
.episode-row {
|
.episode-row {
|
||||||
border-color: #e7e9ec;
|
border-color: #e7e9ec;
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
}
|
}
|
||||||
.episode-thumb {
|
.episode-thumb {
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #e9ecef;
|
background: #e9ecef;
|
||||||
color: #7d8792;
|
color: #7d8792;
|
||||||
}
|
}
|
||||||
@@ -256,7 +192,7 @@ body {
|
|||||||
.cover-card,
|
.cover-card,
|
||||||
.add-cover {
|
.add-cover {
|
||||||
border-color: #e6e8eb;
|
border-color: #e6e8eb;
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
}
|
}
|
||||||
.poster-art {
|
.poster-art {
|
||||||
background: #e9ecef !important;
|
background: #e9ecef !important;
|
||||||
@@ -296,12 +232,12 @@ body {
|
|||||||
color: #656d77;
|
color: #656d77;
|
||||||
}
|
}
|
||||||
.add-cover > span {
|
.add-cover > span {
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #edf0f3;
|
background: #edf0f3;
|
||||||
color: #68798d;
|
color: #68798d;
|
||||||
}
|
}
|
||||||
.role-card {
|
.role-card {
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
border-color: #e7e9ec;
|
border-color: #e7e9ec;
|
||||||
}
|
}
|
||||||
.role-active {
|
.role-active {
|
||||||
@@ -309,48 +245,48 @@ body {
|
|||||||
background: #ecf5ff;
|
background: #ecf5ff;
|
||||||
}
|
}
|
||||||
.role-icon {
|
.role-icon {
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #ecf5ff !important;
|
background: #ecf5ff !important;
|
||||||
color: #409eff !important;
|
color: var(--el-color-primary) !important;
|
||||||
}
|
}
|
||||||
.role-badge {
|
.role-badge {
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #eef1f4;
|
background: #eef1f4;
|
||||||
color: #65758a;
|
color: #65758a;
|
||||||
}
|
}
|
||||||
.permission-group h3 .el-icon {
|
.permission-group h3 .el-icon {
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.permission-group .el-checkbox__input.is-checked .el-checkbox__inner {
|
.permission-group .el-checkbox__input.is-checked .el-checkbox__inner {
|
||||||
background: #409eff;
|
background: var(--el-color-primary);
|
||||||
border-color: #409eff;
|
border-color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.permission-note {
|
.permission-note {
|
||||||
background: #f6f7f8;
|
background: #f6f7f8;
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
}
|
}
|
||||||
.el-dialog {
|
.el-dialog {
|
||||||
border-radius: 6px !important;
|
border-radius: var(--app-radius-md) !important;
|
||||||
}
|
}
|
||||||
.el-dialog__header,
|
.el-dialog__header,
|
||||||
.el-dialog__footer {
|
.el-dialog__footer {
|
||||||
border-color: #e8eaed;
|
border-color: #e8eaed;
|
||||||
}
|
}
|
||||||
.upload-area .el-upload-dragger {
|
.upload-area .el-upload-dragger {
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
background: #fafbfc;
|
background: #fafbfc;
|
||||||
}
|
}
|
||||||
.upload-icon,
|
.upload-icon,
|
||||||
.upload-area .el-upload__text em {
|
.upload-area .el-upload__text em {
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
}
|
}
|
||||||
.el-tabs__item,
|
.el-tabs__item,
|
||||||
.el-input__inner,
|
.el-input__inner,
|
||||||
.el-select__placeholder {
|
.el-select__placeholder {
|
||||||
font-family: Arial, 'Noto Sans SC', sans-serif;
|
font-family: var(--font-body);
|
||||||
}
|
}
|
||||||
.el-tag.status-badge {
|
.el-tag.status-badge {
|
||||||
border-radius: 4px;
|
border-radius: var(--app-radius-sm);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.el-tag.status-badge.is-online {
|
.el-tag.status-badge.is-online {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
flex: 0 0 30px;
|
flex: 0 0 30px;
|
||||||
display: grid;
|
display: grid;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
border-radius: 5px;
|
border-radius: var(--app-radius-sm);
|
||||||
}
|
}
|
||||||
.stat-top > .stat-icon .el-icon {
|
.stat-top > .stat-icon .el-icon {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|||||||
+10
-7
@@ -6,17 +6,17 @@
|
|||||||
|
|
||||||
--left-menu-min-width: 64px;
|
--left-menu-min-width: 64px;
|
||||||
|
|
||||||
--left-menu-bg-color: #001529;
|
--left-menu-bg-color: #17110f;
|
||||||
|
|
||||||
--left-menu-bg-light-color: #0f2438;
|
--left-menu-bg-light-color: #221815;
|
||||||
|
|
||||||
--left-menu-bg-active-color: var(--el-color-primary);
|
--left-menu-bg-active-color: var(--app-primary-strong);
|
||||||
|
|
||||||
--left-menu-text-color: #bfcbd9;
|
--left-menu-text-color: #d7cbc4;
|
||||||
|
|
||||||
--left-menu-text-active-color: #fff;
|
--left-menu-text-active-color: #fff;
|
||||||
|
|
||||||
--left-menu-collapse-bg-active-color: var(--el-color-primary);
|
--left-menu-collapse-bg-active-color: var(--app-primary-strong);
|
||||||
/* left menu end */
|
/* left menu end */
|
||||||
|
|
||||||
/* logo start */
|
/* logo start */
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
/* logo end */
|
/* logo end */
|
||||||
|
|
||||||
/* header start */
|
/* header start */
|
||||||
--top-header-bg-color: '#fff';
|
--top-header-bg-color: #fff;
|
||||||
|
|
||||||
--top-header-text-color: 'inherit';
|
--top-header-text-color: #303133;
|
||||||
|
|
||||||
--top-header-hover-color: #f6f6f6;
|
--top-header-hover-color: #f6f6f6;
|
||||||
|
|
||||||
@@ -58,4 +58,7 @@
|
|||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--app-content-bg-color: var(--el-bg-color);
|
--app-content-bg-color: var(--el-bg-color);
|
||||||
|
--top-header-bg-color: var(--el-bg-color-overlay);
|
||||||
|
--top-header-text-color: var(--el-text-color-primary);
|
||||||
|
--top-header-hover-color: var(--el-fill-color);
|
||||||
}
|
}
|
||||||
+67
-22
@@ -29,11 +29,11 @@ const themeChange = () => {
|
|||||||
<div class="login-shell">
|
<div class="login-shell">
|
||||||
<section class="login-hero">
|
<section class="login-hero">
|
||||||
<div class="hero-brand">
|
<div class="hero-brand">
|
||||||
<img src="@/assets/imgs/logo.png" alt="" />
|
<img src="@/assets/imgs/brand-mark.png" alt="" />
|
||||||
<span>{{ underlineToHump(appStore.getTitle) }}</span>
|
<span>{{ underlineToHump(appStore.getTitle) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="hero-copy">
|
<div class="hero-copy">
|
||||||
<p class="hero-kicker">FruitShorts Studio</p>
|
<p class="hero-kicker">{{ t('login.consoleLabel') }}</p>
|
||||||
<h1>{{ t('login.welcome') }}</h1>
|
<h1>{{ t('login.welcome') }}</h1>
|
||||||
<p>{{ t('login.message') }}</p>
|
<p>{{ t('login.message') }}</p>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -63,7 +63,7 @@ const themeChange = () => {
|
|||||||
.login-page {
|
.login-page {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
color: var(--el-text-color-primary);
|
color: var(--el-text-color-primary);
|
||||||
background: #eef3f9;
|
background: var(--el-bg-color-page);
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-scroll {
|
.login-scroll {
|
||||||
@@ -82,9 +82,9 @@ const themeChange = () => {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at 18% 18%, rgb(255 255 255 / 16%), transparent 28%),
|
radial-gradient(circle at 18% 18%, rgb(255 255 255 / 10%), transparent 28%),
|
||||||
radial-gradient(circle at 82% 78%, rgb(64 158 255 / 45%), transparent 32%),
|
radial-gradient(circle at 82% 78%, rgb(196 50 42 / 34%), transparent 34%),
|
||||||
linear-gradient(155deg, #0d2344 0%, #1a4f96 52%, #409eff 100%);
|
linear-gradient(155deg, #17100f 0%, #241714 55%, #3b1d19 100%);
|
||||||
flex: 1.05;
|
flex: 1.05;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -111,8 +111,10 @@ const themeChange = () => {
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
width: 42px;
|
width: var(--brand-mark-size);
|
||||||
height: 42px;
|
height: var(--brand-mark-size);
|
||||||
|
border-radius: var(--brand-mark-radius);
|
||||||
|
box-shadow: 0 10px 24px rgb(196 50 42 / 28%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,7 +171,7 @@ const themeChange = () => {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 88px 32px 48px;
|
padding: 88px 32px 48px;
|
||||||
background: #f4f7fb;
|
background: var(--el-bg-color-page);
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-tools {
|
.login-tools {
|
||||||
@@ -184,28 +186,28 @@ const themeChange = () => {
|
|||||||
.login-card {
|
.login-card {
|
||||||
width: min(420px, 100%);
|
width: min(420px, 100%);
|
||||||
padding: 36px 32px 28px;
|
padding: 36px 32px 28px;
|
||||||
background: #fff;
|
background: var(--el-bg-color);
|
||||||
border: 1px solid #e6edf5;
|
border: 1px solid var(--el-border-color-light);
|
||||||
border-radius: 18px;
|
border-radius: 18px;
|
||||||
box-shadow: 0 18px 50px rgb(15 39 68 / 8%);
|
box-shadow: 0 18px 50px rgb(42 24 16 / 10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.is-dark {
|
.is-dark {
|
||||||
background: #0e1116;
|
background: var(--el-bg-color-page);
|
||||||
|
|
||||||
.login-hero {
|
.login-hero {
|
||||||
background:
|
background:
|
||||||
radial-gradient(circle at 18% 18%, rgb(64 158 255 / 18%), transparent 30%),
|
radial-gradient(circle at 18% 18%, rgb(255 255 255 / 8%), transparent 30%),
|
||||||
linear-gradient(155deg, #07111f 0%, #0e2744 58%, #163e73 100%);
|
linear-gradient(155deg, #0e0a09 0%, #1a1110 58%, #2c1513 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-panel {
|
.login-panel {
|
||||||
background: #0e1116;
|
background: var(--el-bg-color-page);
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-card {
|
.login-card {
|
||||||
background: #161b22;
|
background: var(--el-bg-color-overlay);
|
||||||
border-color: #2a313c;
|
border-color: var(--el-border-color);
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,16 +219,46 @@ const themeChange = () => {
|
|||||||
|
|
||||||
.login-hero {
|
.login-hero {
|
||||||
flex: none;
|
flex: none;
|
||||||
min-height: 280px;
|
min-height: 132px;
|
||||||
padding: 28px 24px 32px;
|
padding: 16px 24px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hero-copy h1 {
|
.hero-copy h1 {
|
||||||
font-size: 30px;
|
margin: 6px 0 8px;
|
||||||
|
font-size: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-copy ul {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-panel {
|
.login-panel {
|
||||||
padding: 72px 16px 32px;
|
padding: 44px 16px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-card {
|
||||||
|
padding-top: 28px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-tools {
|
||||||
|
top: 8px;
|
||||||
|
right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width <= 600px) {
|
||||||
|
.login-hero {
|
||||||
|
min-height: 118px;
|
||||||
|
padding: 16px 18px 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-copy p {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-card {
|
||||||
|
padding: 28px 20px 24px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -269,6 +301,19 @@ const themeChange = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-card :deep(.el-button--primary) {
|
||||||
|
--el-button-bg-color: var(--app-brand);
|
||||||
|
--el-button-border-color: var(--app-brand);
|
||||||
|
--el-button-hover-bg-color: var(--app-brand-pressed);
|
||||||
|
--el-button-hover-border-color: var(--app-brand-pressed);
|
||||||
|
--el-button-active-bg-color: var(--app-brand-pressed);
|
||||||
|
--el-button-active-border-color: var(--app-brand-pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-card :deep(.el-input__wrapper.is-focus) {
|
||||||
|
box-shadow: 0 0 0 1px var(--app-brand) inset;
|
||||||
|
}
|
||||||
|
|
||||||
body:has(.login-page) {
|
body:has(.login-page) {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ const schema = reactive<FormSchema[]>([
|
|||||||
span: 24
|
span: 24
|
||||||
},
|
},
|
||||||
componentProps: {
|
componentProps: {
|
||||||
placeholder: 'admin'
|
placeholder: t('login.usernamePlaceholder')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -79,7 +79,7 @@ const schema = reactive<FormSchema[]>([
|
|||||||
style: {
|
style: {
|
||||||
width: '100%'
|
width: '100%'
|
||||||
},
|
},
|
||||||
placeholder: 'admin123'
|
placeholder: t('login.passwordPlaceholder')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -143,8 +143,7 @@ const remember = ref(userStore.getRememberMe)
|
|||||||
const initLoginInfo = () => {
|
const initLoginInfo = () => {
|
||||||
const loginInfo = userStore.getLoginInfo
|
const loginInfo = userStore.getLoginInfo
|
||||||
if (loginInfo) {
|
if (loginInfo) {
|
||||||
const { username, password } = loginInfo
|
setValues({ username: loginInfo.username })
|
||||||
setValues({ username, password })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -170,6 +169,7 @@ watch(
|
|||||||
|
|
||||||
// 登录
|
// 登录
|
||||||
const signIn = async () => {
|
const signIn = async () => {
|
||||||
|
if (loading.value) return
|
||||||
const formRef = await getElFormExpose()
|
const formRef = await getElFormExpose()
|
||||||
await formRef?.validate(async (isValid) => {
|
await formRef?.validate(async (isValid) => {
|
||||||
if (isValid) {
|
if (isValid) {
|
||||||
@@ -183,8 +183,7 @@ const signIn = async () => {
|
|||||||
// 是否记住我
|
// 是否记住我
|
||||||
if (unref(remember)) {
|
if (unref(remember)) {
|
||||||
userStore.setLoginInfo({
|
userStore.setLoginInfo({
|
||||||
username: formData.username,
|
username: formData.username
|
||||||
password: formData.password
|
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
userStore.setLoginInfo(undefined)
|
userStore.setLoginInfo(undefined)
|
||||||
@@ -196,7 +195,7 @@ const signIn = async () => {
|
|||||||
}
|
}
|
||||||
// 是否使用动态路由
|
// 是否使用动态路由
|
||||||
if (appStore.getDynamicRouter) {
|
if (appStore.getDynamicRouter) {
|
||||||
getRole()
|
await getRole()
|
||||||
} else {
|
} else {
|
||||||
await permissionStore.generateRoutes('static').catch(() => {})
|
await permissionStore.generateRoutes('static').catch(() => {})
|
||||||
permissionStore.getAddRouters.forEach((route) => {
|
permissionStore.getAddRouters.forEach((route) => {
|
||||||
@@ -254,6 +253,7 @@ const toRegister = () => {
|
|||||||
hide-required-asterisk
|
hide-required-asterisk
|
||||||
size="large"
|
size="large"
|
||||||
class="login-form"
|
class="login-form"
|
||||||
|
@keyup.enter="signIn"
|
||||||
@register="formRegister"
|
@register="formRegister"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, reactive, ref } from 'vue'
|
import { onMounted, reactive, ref } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import {
|
import {
|
||||||
createProductApi,
|
createProductApi,
|
||||||
deleteProductApi,
|
deleteProductApi,
|
||||||
@@ -245,7 +245,7 @@ onMounted(load)
|
|||||||
class="primary-button"
|
class="primary-button"
|
||||||
@click="openCreate"
|
@click="openCreate"
|
||||||
>
|
>
|
||||||
<el-icon><Plus /></el-icon>
|
<AppIcon :icon="AppIcons.add" />
|
||||||
新建商品
|
新建商品
|
||||||
</el-button>
|
</el-button>
|
||||||
</PageHeading>
|
</PageHeading>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { computed, onMounted, ref } from 'vue'
|
import { computed, onMounted, ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { VideoCamera, CaretRight, Clock, CircleCheck, Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import { pageDramasApi } from '@/api/admin/drama'
|
import { pageDramasApi } from '@/api/admin/drama'
|
||||||
import { useRbac } from '@/stores/rbac'
|
import { useRbac } from '@/stores/rbac'
|
||||||
import { formatCount } from '@/utils/format'
|
import { formatCount } from '@/utils/format'
|
||||||
@@ -52,36 +52,32 @@ onMounted(async () => {
|
|||||||
type="primary"
|
type="primary"
|
||||||
class="primary-button"
|
class="primary-button"
|
||||||
@click="router.push({ name: 'dramas' })"
|
@click="router.push({ name: 'dramas' })"
|
||||||
><el-icon><Plus /></el-icon>上传新短剧</el-button
|
><AppIcon :icon="AppIcons.add" />上传新短剧</el-button
|
||||||
></div
|
></div
|
||||||
>
|
>
|
||||||
<div v-loading="loading" class="stats-grid">
|
<div v-loading="loading" class="stats-grid">
|
||||||
<div class="stat-card"
|
<div class="stat-card"
|
||||||
><div class="stat-top"
|
><div class="stat-top"
|
||||||
><span>短剧总数</span
|
><span>短剧总数</span
|
||||||
><span class="stat-icon"
|
><span class="stat-icon"><AppIcon :icon="AppIcons.content" /></span></div
|
||||||
><el-icon><VideoCamera /></el-icon></span></div
|
|
||||||
><div class="stat-value">{{ total }} <small>部</small></div></div
|
><div class="stat-value">{{ total }} <small>部</small></div></div
|
||||||
>
|
>
|
||||||
<div class="stat-card"
|
<div class="stat-card"
|
||||||
><div class="stat-top"
|
><div class="stat-top"
|
||||||
><span>累计播放量</span
|
><span>累计播放量</span
|
||||||
><span class="stat-icon"
|
><span class="stat-icon"><AppIcon :icon="AppIcons.videoPlay" /></span></div
|
||||||
><el-icon><CaretRight /></el-icon></span></div
|
|
||||||
><div class="stat-value">{{ formatCount(totalViews) }}</div></div
|
><div class="stat-value">{{ formatCount(totalViews) }}</div></div
|
||||||
>
|
>
|
||||||
<div class="stat-card"
|
<div class="stat-card"
|
||||||
><div class="stat-top"
|
><div class="stat-top"
|
||||||
><span>待审核内容</span
|
><span>待审核内容</span
|
||||||
><span class="stat-icon"
|
><span class="stat-icon"><AppIcon :icon="AppIcons.clock" /></span></div
|
||||||
><el-icon><Clock /></el-icon></span></div
|
|
||||||
><div class="stat-value">{{ reviewingCount }} <small>项</small></div></div
|
><div class="stat-value">{{ reviewingCount }} <small>项</small></div></div
|
||||||
>
|
>
|
||||||
<div class="stat-card"
|
<div class="stat-card"
|
||||||
><div class="stat-top"
|
><div class="stat-top"
|
||||||
><span>已上线</span
|
><span>已上线</span
|
||||||
><span class="stat-icon"
|
><span class="stat-icon"><AppIcon :icon="AppIcons.checkCircle" /></span></div
|
||||||
><el-icon><CircleCheck /></el-icon></span></div
|
|
||||||
><div class="stat-value">{{ publishedCount }} <small>部</small></div></div
|
><div class="stat-value">{{ publishedCount }} <small>部</small></div></div
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, reactive, ref } from 'vue'
|
import { onMounted, reactive, ref } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import {
|
import {
|
||||||
createBannerApi,
|
createBannerApi,
|
||||||
deleteBannerApi,
|
deleteBannerApi,
|
||||||
@@ -219,7 +219,7 @@ onMounted(async () => {
|
|||||||
class="primary-button"
|
class="primary-button"
|
||||||
@click="openCreate"
|
@click="openCreate"
|
||||||
>
|
>
|
||||||
<el-icon><Plus /></el-icon>
|
<AppIcon :icon="AppIcons.add" />
|
||||||
新建轮播图
|
新建轮播图
|
||||||
</el-button>
|
</el-button>
|
||||||
</PageHeading>
|
</PageHeading>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, reactive, ref } from 'vue'
|
import { onMounted, reactive, ref } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import {
|
import {
|
||||||
createDramaCategoryApi,
|
createDramaCategoryApi,
|
||||||
deleteDramaCategoryApi,
|
deleteDramaCategoryApi,
|
||||||
@@ -100,7 +100,7 @@ onMounted(load)
|
|||||||
description="维护短剧类型,供新建短剧选择,也作为客户端分类筛选的依据。"
|
description="维护短剧类型,供新建短剧选择,也作为客户端分类筛选的依据。"
|
||||||
>
|
>
|
||||||
<el-button v-if="can('drama:create')" type="primary" class="primary-button" @click="openCreate">
|
<el-button v-if="can('drama:create')" type="primary" class="primary-button" @click="openCreate">
|
||||||
<el-icon><Plus /></el-icon>
|
<AppIcon :icon="AppIcons.add" />
|
||||||
新建类型
|
新建类型
|
||||||
</el-button>
|
</el-button>
|
||||||
</PageHeading>
|
</PageHeading>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { onMounted, reactive, ref } from 'vue'
|
import { onMounted, reactive, ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus, Search } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import {
|
import {
|
||||||
changeDramaStatusApi,
|
changeDramaStatusApi,
|
||||||
createDramaApi,
|
createDramaApi,
|
||||||
@@ -242,7 +242,7 @@ onMounted(async () => {
|
|||||||
><div class="eyebrow">内容管理</div><h1>短剧管理</h1
|
><div class="eyebrow">内容管理</div><h1>短剧管理</h1
|
||||||
><p>管理短剧信息、封面、剧集和发布状态。</p></div
|
><p>管理短剧信息、封面、剧集和发布状态。</p></div
|
||||||
><el-button v-if="can('drama:create')" type="primary" class="primary-button" @click="openCreate"
|
><el-button v-if="can('drama:create')" type="primary" class="primary-button" @click="openCreate"
|
||||||
><el-icon><Plus /></el-icon>新建短剧</el-button
|
><AppIcon :icon="AppIcons.add" />新建短剧</el-button
|
||||||
></div
|
></div
|
||||||
>
|
>
|
||||||
<section class="panel library-panel">
|
<section class="panel library-panel">
|
||||||
@@ -251,11 +251,12 @@ onMounted(async () => {
|
|||||||
><el-input
|
><el-input
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
placeholder="搜索短剧名称"
|
placeholder="搜索短剧名称"
|
||||||
:prefix-icon="Search"
|
|
||||||
clearable
|
clearable
|
||||||
@keyup.enter="search"
|
@keyup.enter="search"
|
||||||
@clear="search"
|
@clear="search"
|
||||||
/><el-select v-model="statusFilter" clearable placeholder="全部状态" @change="search"
|
>
|
||||||
|
<template #prefix><AppIcon :icon="AppIcons.search" /></template> </el-input
|
||||||
|
><el-select v-model="statusFilter" clearable placeholder="全部状态" @change="search"
|
||||||
><el-option
|
><el-option
|
||||||
v-for="item in statusOptions"
|
v-for="item in statusOptions"
|
||||||
:key="item.code"
|
:key="item.code"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import { computed, onMounted, reactive, ref } from 'vue'
|
import { computed, onMounted, reactive, ref } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import { pageDramasApi } from '@/api/admin/drama'
|
import { pageDramasApi } from '@/api/admin/drama'
|
||||||
import {
|
import {
|
||||||
createEpisodeApi,
|
createEpisodeApi,
|
||||||
@@ -232,7 +232,7 @@ onMounted(async () => {
|
|||||||
class="primary-button"
|
class="primary-button"
|
||||||
:disabled="!selectedDramaId"
|
:disabled="!selectedDramaId"
|
||||||
@click="openCreate"
|
@click="openCreate"
|
||||||
><el-icon><Plus /></el-icon>新增剧集</el-button
|
><AppIcon :icon="AppIcons.add" />新增剧集</el-button
|
||||||
></div
|
></div
|
||||||
>
|
>
|
||||||
<section class="panel episode-panel">
|
<section class="panel episode-panel">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ArrowLeft, Upload } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
import CreatorCenterPage from './components/CreatorCenterPage.vue'
|
import CreatorCenterPage from './components/CreatorCenterPage.vue'
|
||||||
import { useRbac } from '@/stores/rbac'
|
import { useRbac } from '@/stores/rbac'
|
||||||
@@ -72,7 +72,7 @@ function requestDramaCover(options) {
|
|||||||
title="作品编辑"
|
title="作品编辑"
|
||||||
:description="drama ? `${drama.title}(${drama.code})` : ''"
|
:description="drama ? `${drama.title}(${drama.code})` : ''"
|
||||||
>
|
>
|
||||||
<el-button :icon="ArrowLeft" @click="back">返回</el-button>
|
<el-button @click="back"><AppIcon :icon="AppIcons.arrowBack" />返回</el-button>
|
||||||
</PageHeading>
|
</PageHeading>
|
||||||
|
|
||||||
<section v-loading="loading" class="panel">
|
<section v-loading="loading" class="panel">
|
||||||
@@ -145,7 +145,7 @@ function requestDramaCover(options) {
|
|||||||
:http-request="requestDramaCover"
|
:http-request="requestDramaCover"
|
||||||
:disabled="uploadingId !== null"
|
:disabled="uploadingId !== null"
|
||||||
>
|
>
|
||||||
<el-button size="small" :icon="Upload">上传封面</el-button>
|
<el-button size="small"> <AppIcon :icon="AppIcons.upload" />上传封面 </el-button>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -341,7 +341,7 @@ function requestDramaCover(options) {
|
|||||||
accept="image/*"
|
accept="image/*"
|
||||||
:http-request="(options) => requestEpisodeCover({ id: episodeEditingId }, options)"
|
:http-request="(options) => requestEpisodeCover({ id: episodeEditingId }, options)"
|
||||||
>
|
>
|
||||||
<el-button size="small" :icon="Upload">上传封面</el-button>
|
<el-button size="small"> <AppIcon :icon="AppIcons.upload" />上传封面 </el-button>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { Search } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
import CreatorCenterPage from './components/CreatorCenterPage.vue'
|
import CreatorCenterPage from './components/CreatorCenterPage.vue'
|
||||||
import { useCreatorAccess } from './composables/useCreatorAccess'
|
import { useCreatorAccess } from './composables/useCreatorAccess'
|
||||||
@@ -112,12 +112,13 @@ function openEdit(row) {
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="dramas.keyword"
|
v-model="dramas.keyword"
|
||||||
class="console-keyword"
|
class="console-keyword"
|
||||||
:prefix-icon="Search"
|
|
||||||
clearable
|
clearable
|
||||||
placeholder="搜索作品名称"
|
placeholder="搜索作品名称"
|
||||||
@keyup.enter="queryDramas"
|
@keyup.enter="queryDramas"
|
||||||
@clear="queryDramas"
|
@clear="queryDramas"
|
||||||
/>
|
>
|
||||||
|
<template #prefix><AppIcon :icon="AppIcons.search" /></template>
|
||||||
|
</el-input>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="dramas.status"
|
v-model="dramas.status"
|
||||||
class="console-select"
|
class="console-select"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Search } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
import { useRbac } from '@/stores/rbac'
|
import { useRbac } from '@/stores/rbac'
|
||||||
import { dateCell } from '@/utils/format'
|
import { dateCell } from '@/utils/format'
|
||||||
@@ -72,12 +72,13 @@ const {
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
class="console-keyword"
|
class="console-keyword"
|
||||||
:prefix-icon="Search"
|
|
||||||
clearable
|
clearable
|
||||||
placeholder="搜索名称 / 编号 / 联系人 / 联系方式"
|
placeholder="搜索名称 / 编号 / 联系人 / 联系方式"
|
||||||
@keyup.enter="query"
|
@keyup.enter="query"
|
||||||
@clear="query"
|
@clear="query"
|
||||||
/>
|
>
|
||||||
|
<template #prefix><AppIcon :icon="AppIcons.search" /></template>
|
||||||
|
</el-input>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="statusFilter"
|
v-model="statusFilter"
|
||||||
class="console-select"
|
class="console-select"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, reactive, ref } from 'vue'
|
import { onMounted, reactive, ref } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import {
|
import {
|
||||||
createNoticeApi,
|
createNoticeApi,
|
||||||
deleteNoticeApi,
|
deleteNoticeApi,
|
||||||
@@ -184,7 +184,7 @@ onMounted(load)
|
|||||||
class="primary-button"
|
class="primary-button"
|
||||||
@click="openCreate"
|
@click="openCreate"
|
||||||
>
|
>
|
||||||
<el-icon><Plus /></el-icon>
|
<AppIcon :icon="AppIcons.add" />
|
||||||
新建公告
|
新建公告
|
||||||
</el-button>
|
</el-button>
|
||||||
</PageHeading>
|
</PageHeading>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import { menuIconNames, useMenuManagement } from '@/views/permission/composables/useMenuManagement'
|
import { menuIconNames, useMenuManagement } from '@/views/permission/composables/useMenuManagement'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ const { treeData, loading, form, parentOptions, resetForm, selectNode, saveMenu,
|
|||||||
<template>
|
<template>
|
||||||
<PageHeading eyebrow="后台管理" title="菜单管理" description="维护系统菜单结构、路由与按钮权限。">
|
<PageHeading eyebrow="后台管理" title="菜单管理" description="维护系统菜单结构、路由与按钮权限。">
|
||||||
<el-button type="primary" @click="resetForm(0)">
|
<el-button type="primary" @click="resetForm(0)">
|
||||||
<el-icon><Plus /></el-icon>
|
<AppIcon :icon="AppIcons.add" />
|
||||||
新增菜单
|
新增菜单
|
||||||
</el-button>
|
</el-button>
|
||||||
</PageHeading>
|
</PageHeading>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import { useRoleCategories } from '@/views/permission/composables/useRoleCategories'
|
import { useRoleCategories } from '@/views/permission/composables/useRoleCategories'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ const {
|
|||||||
description="维护角色分类,方便按职责整理权限角色。"
|
description="维护角色分类,方便按职责整理权限角色。"
|
||||||
>
|
>
|
||||||
<el-button type="primary" class="primary-button" @click="openCreateDialog">
|
<el-button type="primary" class="primary-button" @click="openCreateDialog">
|
||||||
<el-icon><Plus /></el-icon>
|
<AppIcon :icon="AppIcons.add" />
|
||||||
新增分类
|
新增分类
|
||||||
</el-button>
|
</el-button>
|
||||||
</PageHeading>
|
</PageHeading>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Plus } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import { useRolePermissionEditor } from '@/views/permission/composables/useRolePermissionEditor'
|
import { useRolePermissionEditor } from '@/views/permission/composables/useRolePermissionEditor'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ function removeRoleRow(row) {
|
|||||||
description="角色等级数字越小权限越高,低等级角色不能修改高等级角色。"
|
description="角色等级数字越小权限越高,低等级角色不能修改高等级角色。"
|
||||||
>
|
>
|
||||||
<el-button type="primary" class="primary-button" @click="dialogVisible = true">
|
<el-button type="primary" class="primary-button" @click="dialogVisible = true">
|
||||||
<el-icon><Plus /></el-icon>
|
<AppIcon :icon="AppIcons.add" />
|
||||||
新增角色
|
新增角色
|
||||||
</el-button>
|
</el-button>
|
||||||
</PageHeading>
|
</PageHeading>
|
||||||
|
|||||||
@@ -3,17 +3,9 @@
|
|||||||
import { computed, onMounted, reactive, ref } from 'vue'
|
import { computed, onMounted, reactive, ref } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { createMenuApi, deleteMenuApi, getMenuTreeApi, updateMenuApi } from '@/api/admin/role'
|
import { createMenuApi, deleteMenuApi, getMenuTreeApi, updateMenuApi } from '@/api/admin/role'
|
||||||
|
import { MenuIconOptions, normalizeAppIcon } from '@/constants/icons'
|
||||||
|
|
||||||
export const menuIconNames = [
|
export const menuIconNames = MenuIconOptions
|
||||||
'Document',
|
|
||||||
'DataAnalysis',
|
|
||||||
'Picture',
|
|
||||||
'User',
|
|
||||||
'Setting',
|
|
||||||
'VideoCamera',
|
|
||||||
'Menu',
|
|
||||||
'Grid'
|
|
||||||
]
|
|
||||||
|
|
||||||
/** 菜单管理:直接读写后端 sys_menu,变更后重新登录生效。 */
|
/** 菜单管理:直接读写后端 sys_menu,变更后重新登录生效。 */
|
||||||
export function useMenuManagement() {
|
export function useMenuManagement() {
|
||||||
@@ -101,7 +93,7 @@ export function useMenuManagement() {
|
|||||||
routePath: raw.path || '',
|
routePath: raw.path || '',
|
||||||
routeName: raw.name || '',
|
routeName: raw.name || '',
|
||||||
component: raw.component === '#' ? '' : raw.component || '',
|
component: raw.component === '#' ? '' : raw.component || '',
|
||||||
icon: raw.icon || '',
|
icon: normalizeAppIcon(raw.icon),
|
||||||
permissionCode: raw.permissionCode || '',
|
permissionCode: raw.permissionCode || '',
|
||||||
type: raw.type || 'MENU',
|
type: raw.type || 'MENU',
|
||||||
sort: raw.sort ?? 1,
|
sort: raw.sort ?? 1,
|
||||||
@@ -121,7 +113,7 @@ export function useMenuManagement() {
|
|||||||
routePath: form.routePath.trim(),
|
routePath: form.routePath.trim(),
|
||||||
routeName: form.routeName.trim(),
|
routeName: form.routeName.trim(),
|
||||||
component: form.type === 'CATALOG' ? '#' : form.component.trim(),
|
component: form.type === 'CATALOG' ? '#' : form.component.trim(),
|
||||||
icon: form.icon,
|
icon: form.type === 'BUTTON' ? '' : normalizeAppIcon(form.icon),
|
||||||
permissionCode: form.permissionCode.trim(),
|
permissionCode: form.permissionCode.trim(),
|
||||||
type: form.type,
|
type: form.type,
|
||||||
sort: Number(form.sort) || 1,
|
sort: Number(form.sort) || 1,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, reactive, ref } from 'vue'
|
import { onMounted, reactive, ref } from 'vue'
|
||||||
import { Search } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import { getOperationLogApi, pageOperationLogsApi } from '@/api/admin/log'
|
import { getOperationLogApi, pageOperationLogsApi } from '@/api/admin/log'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
|
|
||||||
@@ -103,12 +103,13 @@ onMounted(load)
|
|||||||
<div class="drama-filters">
|
<div class="drama-filters">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="filters.username"
|
v-model="filters.username"
|
||||||
:prefix-icon="Search"
|
|
||||||
clearable
|
clearable
|
||||||
placeholder="操作人"
|
placeholder="操作人"
|
||||||
@keyup.enter="search"
|
@keyup.enter="search"
|
||||||
@clear="search"
|
@clear="search"
|
||||||
/>
|
>
|
||||||
|
<template #prefix><AppIcon :icon="AppIcons.search" /></template>
|
||||||
|
</el-input>
|
||||||
<el-select v-model="filters.module" clearable placeholder="全部模块" @change="search">
|
<el-select v-model="filters.module" clearable placeholder="全部模块" @change="search">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in moduleOptions"
|
v-for="item in moduleOptions"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!-- Author: fruit.com.cn -->
|
<!-- Author: fruit.com.cn -->
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { Plus, Search } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import { useAdminUsers } from '@/views/userManagement/composables/useAdminUsers'
|
import { useAdminUsers } from '@/views/userManagement/composables/useAdminUsers'
|
||||||
import { useRbac } from '@/stores/rbac'
|
import { useRbac } from '@/stores/rbac'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
@@ -44,18 +44,19 @@ const {
|
|||||||
<div class="admin-user-toolbar">
|
<div class="admin-user-toolbar">
|
||||||
<el-input
|
<el-input
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
:prefix-icon="Search"
|
|
||||||
clearable
|
clearable
|
||||||
placeholder="搜索登录账号"
|
placeholder="搜索登录账号"
|
||||||
@keyup.enter="queryUsers"
|
@keyup.enter="queryUsers"
|
||||||
@clear="queryUsers"
|
@clear="queryUsers"
|
||||||
/>
|
>
|
||||||
|
<template #prefix><AppIcon :icon="AppIcons.search" /></template>
|
||||||
|
</el-input>
|
||||||
<el-select v-model="roleFilter" clearable placeholder="全部角色" @change="queryUsers">
|
<el-select v-model="roleFilter" clearable placeholder="全部角色" @change="queryUsers">
|
||||||
<el-option v-for="role in roles" :key="role.id" :label="role.name" :value="role.id" />
|
<el-option v-for="role in roles" :key="role.id" :label="role.name" :value="role.id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-button type="primary" @click="queryUsers">查询</el-button>
|
<el-button type="primary" @click="queryUsers">查询</el-button>
|
||||||
<el-button v-if="can('system:admin-user')" type="primary" @click="openCreate">
|
<el-button v-if="can('system:admin-user')" type="primary" @click="openCreate">
|
||||||
<el-icon><Plus /></el-icon>
|
<AppIcon :icon="AppIcons.add" />
|
||||||
添加用户
|
添加用户
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { Search } from '@element-plus/icons-vue'
|
import { AppIcons } from '@/constants/icons'
|
||||||
import PageHeading from '@/views/components/PageHeading.vue'
|
import PageHeading from '@/views/components/PageHeading.vue'
|
||||||
import { useRbac } from '@/stores/rbac'
|
import { useRbac } from '@/stores/rbac'
|
||||||
import {
|
import {
|
||||||
@@ -87,12 +87,13 @@ function canBeBanned(row) {
|
|||||||
<el-input
|
<el-input
|
||||||
v-model="keyword"
|
v-model="keyword"
|
||||||
class="app-user-keyword"
|
class="app-user-keyword"
|
||||||
:prefix-icon="Search"
|
|
||||||
clearable
|
clearable
|
||||||
placeholder="搜索 uid / 昵称 / 手机号 / 邮箱"
|
placeholder="搜索 uid / 昵称 / 手机号 / 邮箱"
|
||||||
@keyup.enter="queryUsers"
|
@keyup.enter="queryUsers"
|
||||||
@clear="queryUsers"
|
@clear="queryUsers"
|
||||||
/>
|
>
|
||||||
|
<template #prefix><AppIcon :icon="AppIcons.search" /></template>
|
||||||
|
</el-input>
|
||||||
<el-select
|
<el-select
|
||||||
v-model="statusFilter"
|
v-model="statusFilter"
|
||||||
class="app-user-status"
|
class="app-user-status"
|
||||||
|
|||||||
Reference in new issue
Block a user