mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-21 04:46:26 +00:00
refactor: 将组件前缀从Art统一替换为Fa
- 更新所有FA前缀的组件文件 - 新增Fa前缀的对应组件 - 更新所有引用路径和组件名 - 修改相关样式和变量名 - 调整部分组件目录结构
This commit is contained in:
@@ -16,7 +16,7 @@
|
||||
<RouterView></RouterView>
|
||||
|
||||
<!-- AI 助手 -->
|
||||
<AiAssistant v-if="enableAiAssistant" />
|
||||
<FaAiAssistant v-if="enableAiAssistant" />
|
||||
</ElWatermark>
|
||||
</ElConfigProvider>
|
||||
</template>
|
||||
@@ -27,7 +27,7 @@ import { useAppStore, useUserStore } from "./store";
|
||||
import { useSettingsStore } from "./store/modules/setting.store";
|
||||
import { defaultSettings } from "./config/setting";
|
||||
import { ComponentSize } from "./enums/settings/layout.enum";
|
||||
import AiAssistant from "./components/AiAssistant/index.vue";
|
||||
import FaAiAssistant from "./components/others/fa-ai-assistant/index.vue";
|
||||
import { hexToRgba, toggleTransition } from "./utils/ui";
|
||||
import { checkStorageCompatibility } from "./utils/storage";
|
||||
import { initializeTheme } from "./hooks/core/useTheme";
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/** 通用弹窗、抽屉(与业务 CRUD 解耦) */
|
||||
export { default as ArtDialog } from "./art-dialog/index.vue";
|
||||
export { default as ArtDrawer } from "./art-drawer/index.vue";
|
||||
export { default as ArtImportDialog } from "./art-import-dialog/index.vue";
|
||||
export { default as ArtExportDialog } from "./art-export-dialog/index.vue";
|
||||
@@ -1 +0,0 @@
|
||||
export { default as ArtWidgetDemoTitle } from "./ArtWidgetDemoTitle.vue";
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
<!-- 基础横幅组件 -->
|
||||
<template>
|
||||
<div
|
||||
class="art-card basic-banner"
|
||||
class="fa-card basic-banner"
|
||||
:class="[{ 'has-decoration': decoration }, boxStyle]"
|
||||
:style="{ height }"
|
||||
@click="emit('click')"
|
||||
@@ -72,7 +72,7 @@ import { useSettingsStore } from "@stores/modules/setting.store";
|
||||
const settingStore = useSettingsStore();
|
||||
const { isDark } = storeToRefs(settingStore);
|
||||
|
||||
defineOptions({ name: "ArtBasicBanner" });
|
||||
defineOptions({ name: "FaBasicBanner" });
|
||||
|
||||
// 流星对象接口定义
|
||||
interface Meteor {
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<!-- 卡片横幅组件 -->
|
||||
<template>
|
||||
<div class="art-card-sm flex-c flex-col pb-6" :style="{ height: height }">
|
||||
<div class="fa-card-sm flex-c flex-col pb-6" :style="{ height: height }">
|
||||
<div class="flex-c flex-col gap-4 text-center">
|
||||
<div class="w-45">
|
||||
<img :src="image" :alt="title" class="w-full h-full object-contain" />
|
||||
@@ -38,7 +38,7 @@
|
||||
// 导入默认图标
|
||||
import defaultIcon from "@imgs/3d/icon1.webp";
|
||||
|
||||
defineOptions({ name: "ArtCardBanner" });
|
||||
defineOptions({ name: "FaCardBanner" });
|
||||
|
||||
// 定义卡片横幅组件的属性接口
|
||||
interface CardBannerProps {
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
class="fixed right-10 bottom-15 size-9.5 flex-cc c-p border border-g-300 rounded-md tad-300 hover:bg-g-200"
|
||||
@click="scrollToTop"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:arrow-up-wide-line" class="text-g-500 text-lg" />
|
||||
<FaSvgIcon icon="ri:arrow-up-wide-line" class="text-g-500 text-lg" />
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
@@ -21,7 +21,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useCommon } from "@/hooks/core/useCommon";
|
||||
|
||||
defineOptions({ name: "ArtBackToTop" });
|
||||
defineOptions({ name: "FaBackToTop" });
|
||||
|
||||
const { scrollToTop } = useCommon();
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
<script setup lang="ts">
|
||||
import defaultLogoUrl from "@icons/vite.svg";
|
||||
|
||||
defineOptions({ name: "ArtLogo" });
|
||||
defineOptions({ name: "FaLogo" });
|
||||
|
||||
interface Props {
|
||||
/** logo 大小 */
|
||||
+35
-35
@@ -1,12 +1,12 @@
|
||||
<!-- 图标组件 -->
|
||||
<template>
|
||||
<Icon v-if="icon" :icon="icon" v-bind="bindAttrs" class="art-svg-icon inline" />
|
||||
<Icon v-if="icon" :icon="icon" v-bind="bindAttrs" class="fa-svg-icon inline" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Icon } from "@iconify/vue";
|
||||
|
||||
defineOptions({ name: "ArtSvgIcon", inheritAttrs: false });
|
||||
defineOptions({ name: "FaSvgIcon", inheritAttrs: false });
|
||||
|
||||
interface Props {
|
||||
/** Iconify icon name */
|
||||
@@ -50,48 +50,48 @@ const bindAttrs = computed<{ class: string; style: string }>(() => ({
|
||||
</div> -->
|
||||
|
||||
<!-- Iconify 图标 -->
|
||||
<!-- <div class="art-card-sm p-5">
|
||||
<!-- <div class="fa-card-sm p-5">
|
||||
<div class="text-lg font-semibold mb-4">Iconify</div>
|
||||
<div class="flex items-center gap-6">
|
||||
<ArtSvgIcon icon="ri:github-fill" class="text-2xl" />
|
||||
<ArtSvgIcon icon="ri:copilot-line" class="text-2xl text-theme" />
|
||||
<ArtSvgIcon icon="ri:edge-line" class="text-2xl text-secondary" />
|
||||
<ArtSvgIcon icon="ri:planet-line" class="text-2xl text-warning" />
|
||||
<ArtSvgIcon icon="ri:windows-line" class="text-2xl text-info" />
|
||||
<ArtSvgIcon icon="ri:thumb-up-line" class="text-2xl text-danger" />
|
||||
<ArtSvgIcon icon="ri:gift-2-line" class="text-2xl text-success" />
|
||||
<ArtSvgIcon icon="ri:apple-line" class="text-2xl text-secondary" />
|
||||
<FaSvgIcon icon="ri:github-fill" class="text-2xl" />
|
||||
<FaSvgIcon icon="ri:copilot-line" class="text-2xl text-theme" />
|
||||
<FaSvgIcon icon="ri:edge-line" class="text-2xl text-secondary" />
|
||||
<FaSvgIcon icon="ri:planet-line" class="text-2xl text-warning" />
|
||||
<FaSvgIcon icon="ri:windows-line" class="text-2xl text-info" />
|
||||
<FaSvgIcon icon="ri:thumb-up-line" class="text-2xl text-danger" />
|
||||
<FaSvgIcon icon="ri:gift-2-line" class="text-2xl text-success" />
|
||||
<FaSvgIcon icon="ri:apple-line" class="text-2xl text-secondary" />
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Svg Icons -->
|
||||
<!-- <div class="art-card-sm p-5">
|
||||
<!-- <div class="fa-card-sm p-5">
|
||||
<div class="text-lg font-semibold mb-4">Svg Icons</div>
|
||||
<div class="flex items-center gap-6">
|
||||
<ArtSvgIcon icon="svg-spinners:3-dots-fade" class="text-2xl text-red-400" />
|
||||
<ArtSvgIcon icon="svg-spinners:3-dots-bounce" class="text-2xl text-blue-400" />
|
||||
<ArtSvgIcon icon="svg-spinners:3-dots-move" class="text-2xl text-orange-400" />
|
||||
<ArtSvgIcon icon="svg-spinners:3-dots-rotate" class="text-2xl text-purple-400" />
|
||||
<ArtSvgIcon icon="svg-spinners:blocks-shuffle-2" class="text-2xl text-pink-300" />
|
||||
<ArtSvgIcon icon="svg-spinners:clock" class="text-2xl text-yellow-500" />
|
||||
<ArtSvgIcon icon="svg-spinners:tadpole" class="text-2xl text-orange-500" />
|
||||
<ArtSvgIcon icon="svg-spinners:blocks-wave" class="text-2xl text-blue-500" />
|
||||
<FaSvgIcon icon="svg-spinners:3-dots-fade" class="text-2xl text-red-400" />
|
||||
<FaSvgIcon icon="svg-spinners:3-dots-bounce" class="text-2xl text-blue-400" />
|
||||
<FaSvgIcon icon="svg-spinners:3-dots-move" class="text-2xl text-orange-400" />
|
||||
<FaSvgIcon icon="svg-spinners:3-dots-rotate" class="text-2xl text-purple-400" />
|
||||
<FaSvgIcon icon="svg-spinners:blocks-shuffle-2" class="text-2xl text-pink-300" />
|
||||
<FaSvgIcon icon="svg-spinners:clock" class="text-2xl text-yellow-500" />
|
||||
<FaSvgIcon icon="svg-spinners:tadpole" class="text-2xl text-orange-500" />
|
||||
<FaSvgIcon icon="svg-spinners:blocks-wave" class="text-2xl text-blue-500" />
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Svg Icons -->
|
||||
<!-- <div class="art-card-sm p-5">
|
||||
<!-- <div class="fa-card-sm p-5">
|
||||
<div class="text-lg font-semibold mb-4">Material Line Icons</div>
|
||||
<div class="flex items-center gap-6">
|
||||
<ArtSvgIcon icon="line-md:phone-call-twotone-loop" class="text-2xl text-blue-500" />
|
||||
<FaSvgIcon icon="line-md:phone-call-twotone-loop" class="text-2xl text-blue-500" />
|
||||
|
||||
<ArtSvgIcon icon="line-md:switch-off" class="text-2xl text-green-500" />
|
||||
<ArtSvgIcon icon="line-md:sun-rising-filled-loop" class="text-2xl text-yellow-400" />
|
||||
<ArtSvgIcon icon="line-md:volume-high-filled" class="text-2xl text-purple-500" />
|
||||
<ArtSvgIcon icon="line-md:github-twotone" class="text-2xl text-gray-700" />
|
||||
<ArtSvgIcon icon="line-md:telegram" class="text-2xl text-sky-500" />
|
||||
<ArtSvgIcon icon="line-md:reddit-loop" class="text-2xl text-orange-400" />
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon icon="line-md:switch-off" class="text-2xl text-green-500" />
|
||||
<FaSvgIcon icon="line-md:sun-rising-filled-loop" class="text-2xl text-yellow-400" />
|
||||
<FaSvgIcon icon="line-md:volume-high-filled" class="text-2xl text-purple-500" />
|
||||
<FaSvgIcon icon="line-md:github-twotone" class="text-2xl text-gray-700" />
|
||||
<FaSvgIcon icon="line-md:telegram" class="text-2xl text-sky-500" />
|
||||
<FaSvgIcon icon="line-md:reddit-loop" class="text-2xl text-orange-400" />
|
||||
<FaSvgIcon
|
||||
icon="line-md:coffee-half-empty-filled-loop"
|
||||
class="text-2xl text-emerald-500"
|
||||
/>
|
||||
@@ -99,31 +99,31 @@ const bindAttrs = computed<{ class: string; style: string }>(() => ({
|
||||
</div> -->
|
||||
|
||||
<!-- 使用示例 -->
|
||||
<!-- <div class="art-card-sm p-5">
|
||||
<!-- <div class="fa-card-sm p-5">
|
||||
<div class="text-lg font-semibold mb-4">使用示例</div>
|
||||
<div class="space-y-4">
|
||||
<div>
|
||||
<div class="text-sm text-g-600 mb-2">基础使用</div>
|
||||
<div class="bg-g-200 dark:bg-g-300/30 p-4 rounded font-mono text-sm text-g-800">
|
||||
<ArtSvgIcon icon="ri:home-line" />
|
||||
<FaSvgIcon icon="ri:home-line" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-g-600 mb-2">自定义大小</div>
|
||||
<div class="bg-g-200 dark:bg-g-300/30 p-4 rounded font-mono text-sm text-g-800">
|
||||
<ArtSvgIcon icon="ri:user-line" class="text-2xl" />
|
||||
<FaSvgIcon icon="ri:user-line" class="text-2xl" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-g-600 mb-2">自定义颜色</div>
|
||||
<div class="bg-g-200 dark:bg-g-300/30 p-4 rounded font-mono text-sm text-g-800">
|
||||
<ArtSvgIcon icon="ri:heart-fill" class="text-red-500" />
|
||||
<FaSvgIcon icon="ri:hefa-fill" class="text-red-500" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm text-g-600 mb-2">组合使用</div>
|
||||
<div class="bg-g-200 dark:bg-g-300/30 p-4 rounded font-mono text-sm text-g-800">
|
||||
<ArtSvgIcon icon="ri:star-fill" class="text-4xl text-yellow-500" />
|
||||
<FaSvgIcon icon="ri:star-fill" class="text-4xl text-yellow-500" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -132,7 +132,7 @@ const bindAttrs = computed<{ class: string; style: string }>(() => ({
|
||||
</template> -->
|
||||
|
||||
<!-- <script setup lang="ts">
|
||||
import ArtSvgIcon from "@/components/Core/base/art-svg-icon/index.vue";
|
||||
import FaSvgIcon from "@/components/base/fa-svg-icon/index.vue";
|
||||
|
||||
defineOptions({ name: "IconPage" });
|
||||
</script> -->
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<!-- 柱状图卡片 -->
|
||||
<template>
|
||||
<div class="art-card relative overflow-hidden" :style="{ height: `${height}rem` }">
|
||||
<div class="fa-card relative overflow-hidden" :style="{ height: `${height}rem` }">
|
||||
<div class="mb-5 flex-b items-start px-5 pt-5">
|
||||
<div>
|
||||
<p class="m-0 text-2xl font-medium leading-tight text-g-900">
|
||||
@@ -31,7 +31,7 @@
|
||||
import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
import { type EChartsOption } from "@/plugins/echarts";
|
||||
|
||||
defineOptions({ name: "ArtBarChartCard" });
|
||||
defineOptions({ name: "FaBarChartCard" });
|
||||
|
||||
interface Props {
|
||||
/** 数值 */
|
||||
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="min-h-0">
|
||||
<ElEmpty
|
||||
v-if="!loading && isEmpty"
|
||||
:image-size="emptyImageSize"
|
||||
:description="emptyDescription"
|
||||
class="py-8"
|
||||
/>
|
||||
<div v-else class="min-h-0" :class="gridClass">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "FaCardList" });
|
||||
|
||||
interface FaCardListProps {
|
||||
loading?: boolean;
|
||||
isEmpty?: boolean;
|
||||
emptyDescription?: string;
|
||||
emptyImageSize?: number;
|
||||
/** Tailwind/Grid class string for layout */
|
||||
gridClass?: string;
|
||||
}
|
||||
|
||||
withDefaults(defineProps<FaCardListProps>(), {
|
||||
loading: false,
|
||||
isEmpty: false,
|
||||
emptyDescription: "暂无数据",
|
||||
emptyImageSize: 80,
|
||||
gridClass:
|
||||
"grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 auto-rows-max content-start",
|
||||
});
|
||||
</script>
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
<!-- 数据列表卡片 -->
|
||||
<template>
|
||||
<div class="art-card p-5">
|
||||
<div class="fa-card p-5">
|
||||
<div class="pb-3.5">
|
||||
<p class="text-lg font-medium">{{ title }}</p>
|
||||
<p class="text-sm text-g-600">{{ subtitle }}</p>
|
||||
@@ -8,7 +8,7 @@
|
||||
<ElScrollbar :style="{ height: maxHeight }">
|
||||
<div v-for="(item, index) in list" :key="index" class="flex-c py-3">
|
||||
<div v-if="item.icon" class="flex-cc mr-3 size-10 rounded-lg" :class="item.class">
|
||||
<ArtSvgIcon :icon="item.icon" class="text-xl" />
|
||||
<FaSvgIcon :icon="item.icon" class="text-xl" />
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="mb-1 text-sm">{{ item.title }}</div>
|
||||
@@ -29,7 +29,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "ArtDataListCard" });
|
||||
defineOptions({ name: "FaDataListCard" });
|
||||
|
||||
interface Props {
|
||||
/** 数据列表 */
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<!-- 环型图卡片 -->
|
||||
<template>
|
||||
<div class="art-card overflow-hidden" :style="{ height: `${height}rem` }">
|
||||
<div class="fa-card overflow-hidden" :style="{ height: `${height}rem` }">
|
||||
<div class="flex box-border h-full p-5 pr-2">
|
||||
<div class="flex w-full items-start gap-5">
|
||||
<div class="flex-b h-full flex-1 flex-col">
|
||||
@@ -42,7 +42,7 @@
|
||||
import { type EChartsOption } from "@/plugins/echarts";
|
||||
import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
|
||||
defineOptions({ name: "ArtDonutChartCard" });
|
||||
defineOptions({ name: "FaDonutChartCard" });
|
||||
|
||||
interface Props {
|
||||
/** 数值 */
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
<!-- 图片卡片 -->
|
||||
<template>
|
||||
<div class="w-full c-p" @click="handleClick">
|
||||
<div class="art-card overflow-hidden">
|
||||
<div class="fa-card overflow-hidden">
|
||||
<div class="relative w-full aspect-[16/10] overflow-hidden">
|
||||
<ElImage
|
||||
:src="props.imageUrl"
|
||||
@@ -50,7 +50,7 @@
|
||||
<script setup lang="ts">
|
||||
import { Picture, View, ChatLineRound } from "@element-plus/icons-vue";
|
||||
|
||||
defineOptions({ name: "ArtImageCard" });
|
||||
defineOptions({ name: "FaImageCard" });
|
||||
|
||||
interface Props {
|
||||
/** 图片地址 */
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<!-- 折线图卡片 -->
|
||||
<template>
|
||||
<div class="art-card relative overflow-hidden" :style="{ height: `${height}rem` }">
|
||||
<div class="fa-card relative overflow-hidden" :style="{ height: `${height}rem` }">
|
||||
<div class="mb-2.5 flex-b items-start p-5">
|
||||
<div>
|
||||
<p class="text-2xl font-medium leading-none">
|
||||
@@ -35,7 +35,7 @@ import { graphic, type EChartsOption } from "@/plugins/echarts";
|
||||
import { getCssVar, hexToRgba } from "@utils/ui";
|
||||
import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
|
||||
defineOptions({ name: "ArtLineChartCard" });
|
||||
defineOptions({ name: "FaLineChartCard" });
|
||||
|
||||
interface Props {
|
||||
/** 数值 */
|
||||
+4
-4
@@ -1,12 +1,12 @@
|
||||
<!-- 进度条卡片 -->
|
||||
<template>
|
||||
<div class="art-card h-32 flex flex-col justify-center px-5">
|
||||
<div class="fa-card h-32 flex flex-col justify-center px-5">
|
||||
<div class="mb-3.5 flex-c" :style="{ justifyContent: icon ? 'space-between' : 'flex-start' }">
|
||||
<div v-if="icon" class="size-11 flex-cc bg-g-300 text-xl rounded-lg" :class="iconStyle">
|
||||
<ArtSvgIcon :icon="icon" class="text-2xl"></ArtSvgIcon>
|
||||
<FaSvgIcon :icon="icon" class="text-2xl"></FaSvgIcon>
|
||||
</div>
|
||||
<div>
|
||||
<ArtCountTo
|
||||
<FaCountTo
|
||||
class="mb-1 block text-2xl font-semibold"
|
||||
:target="percentage"
|
||||
:duration="2000"
|
||||
@@ -27,7 +27,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "ArtProgressCard" });
|
||||
defineOptions({ name: "FaProgressCard" });
|
||||
|
||||
interface Props {
|
||||
/** 进度百分比 */
|
||||
+5
-5
@@ -1,17 +1,17 @@
|
||||
<!-- 统计卡片 -->
|
||||
<template>
|
||||
<div
|
||||
class="art-card h-32 flex-c px-5 transition-transform duration-200 hover:-translate-y-0.5"
|
||||
class="fa-card h-32 flex-c px-5 transition-transform duration-200 hover:-translate-y-0.5"
|
||||
:class="boxStyle"
|
||||
>
|
||||
<div v-if="icon" class="mr-4 size-11 flex-cc rounded-lg text-xl text-white" :class="iconStyle">
|
||||
<ArtSvgIcon :icon="icon"></ArtSvgIcon>
|
||||
<FaSvgIcon :icon="icon"></FaSvgIcon>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<p class="m-0 text-lg font-medium" :style="{ color: textColor }" v-if="title">
|
||||
{{ title }}
|
||||
</p>
|
||||
<ArtCountTo
|
||||
<FaCountTo
|
||||
class="m-0 text-2xl font-medium"
|
||||
v-if="count !== undefined"
|
||||
:target="count"
|
||||
@@ -28,13 +28,13 @@
|
||||
</p>
|
||||
</div>
|
||||
<div v-if="showArrow">
|
||||
<ArtSvgIcon icon="ri:arrow-right-s-line" class="text-xl text-g-500" />
|
||||
<FaSvgIcon icon="ri:arrow-right-s-line" class="text-xl text-g-500" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "ArtStatsCard" });
|
||||
defineOptions({ name: "FaStatsCard" });
|
||||
|
||||
interface StatsCardProps {
|
||||
/** 盒子样式 */
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
<!-- 时间轴列表卡片 -->
|
||||
<template>
|
||||
<div class="art-card p-5">
|
||||
<div class="fa-card p-5">
|
||||
<div class="pb-3.5">
|
||||
<p class="text-lg font-medium">{{ title }}</p>
|
||||
<p class="text-sm text-g-600">{{ subtitle }}</p>
|
||||
@@ -28,7 +28,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "ArtTimelineListCard" });
|
||||
defineOptions({ name: "FaTimelineListCard" });
|
||||
|
||||
// 常量配置
|
||||
const ITEM_HEIGHT = 65;
|
||||
+1
-1
@@ -9,7 +9,7 @@ import { getCssVar } from "@utils/ui";
|
||||
import { graphic, type EChartsOption } from "@/plugins/echarts";
|
||||
import type { BarChartProps, BarDataItem } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtBarChart" });
|
||||
defineOptions({ name: "FaBarChart" });
|
||||
|
||||
const props = withDefaults(defineProps<BarChartProps>(), {
|
||||
// 基础配置
|
||||
+1
-1
@@ -8,7 +8,7 @@ import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
import type { EChartsOption, BarSeriesOption } from "@/plugins/echarts";
|
||||
import type { BidirectionalBarChartProps } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtDualBarCompareChart" });
|
||||
defineOptions({ name: "FaDualBarCompareChart" });
|
||||
|
||||
const props = withDefaults(defineProps<BidirectionalBarChartProps>(), {
|
||||
// 基础配置
|
||||
+1
-1
@@ -14,7 +14,7 @@ import { getCssVar } from "@utils/ui";
|
||||
import { graphic, type EChartsOption } from "@/plugins/echarts";
|
||||
import type { BarChartProps, BarDataItem } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtHBarChart" });
|
||||
defineOptions({ name: "FaHBarChart" });
|
||||
|
||||
const props = withDefaults(defineProps<BarChartProps>(), {
|
||||
// 基础配置
|
||||
+1
-1
@@ -13,7 +13,7 @@ import type { EChartsOption } from "@/plugins/echarts";
|
||||
import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
import type { KLineChartProps } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtKLineChart" });
|
||||
defineOptions({ name: "FaKLineChart" });
|
||||
|
||||
const props = withDefaults(defineProps<KLineChartProps>(), {
|
||||
// 基础配置
|
||||
+1
-1
@@ -14,7 +14,7 @@ import { getCssVar, hexToRgba } from "@utils/ui";
|
||||
import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
import type { LineChartProps, LineDataItem } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtLineChart" });
|
||||
defineOptions({ name: "FaLineChart" });
|
||||
|
||||
const props = withDefaults(defineProps<LineChartProps>(), {
|
||||
// 基础配置
|
||||
+1
-1
@@ -15,7 +15,7 @@ import { useSettingsStore } from "@stores/modules/setting.store";
|
||||
import chinaMapJson from "@/mock/json/chinaMap.json";
|
||||
import type { MapChartProps } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtMapChart" });
|
||||
defineOptions({ name: "FaMapChart" });
|
||||
|
||||
const chinaMapRef = ref<HTMLElement | null>(null);
|
||||
const chartInstance = shallowRef<echarts.ECharts | null>(null);
|
||||
+1
-1
@@ -13,7 +13,7 @@ import type { EChartsOption } from "@/plugins/echarts";
|
||||
import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
import type { RadarChartProps } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtRadarChart" });
|
||||
defineOptions({ name: "FaRadarChart" });
|
||||
|
||||
const props = withDefaults(defineProps<RadarChartProps>(), {
|
||||
// 基础配置
|
||||
+1
-1
@@ -13,7 +13,7 @@ import type { EChartsOption } from "@/plugins/echarts";
|
||||
import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
import type { RingChartProps } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtRingChart" });
|
||||
defineOptions({ name: "FaRingChart" });
|
||||
|
||||
const props = withDefaults(defineProps<RingChartProps>(), {
|
||||
// 基础配置
|
||||
+1
-1
@@ -14,7 +14,7 @@ import { getCssVar } from "@utils/ui";
|
||||
import { useChartOps, useChartComponent } from "@/hooks/core/useChart";
|
||||
import type { ScatterChartProps } from "@/types/component/chart";
|
||||
|
||||
defineOptions({ name: "ArtScatterChart" });
|
||||
defineOptions({ name: "FaScatterChart" });
|
||||
|
||||
const props = withDefaults(defineProps<ScatterChartProps>(), {
|
||||
// 基础配置
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<ElDropdown v-if="hasAnyAuthItem">
|
||||
<ArtIconButton icon="ri:more-2-fill" class="!size-8 bg-g-200 dark:bg-g-300/45 text-sm" />
|
||||
<FaIconButton icon="ri:more-2-fill" class="!size-8 bg-g-200 dark:bg-g-300/45 text-sm" />
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
<template v-for="item in list" :key="item.key">
|
||||
@@ -12,7 +12,7 @@
|
||||
@click="handleClick(item)"
|
||||
>
|
||||
<div class="flex-c gap-2" :style="{ color: item.color }">
|
||||
<ArtSvgIcon v-if="item.icon" :icon="item.icon" />
|
||||
<FaSvgIcon v-if="item.icon" :icon="item.icon" />
|
||||
<span>{{ item.label }}</span>
|
||||
</div>
|
||||
</ElDropdownItem>
|
||||
@@ -26,7 +26,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useAuth } from "@/hooks/core/useAuth";
|
||||
|
||||
defineOptions({ name: "ArtButtonMore" });
|
||||
defineOptions({ name: "FaButtonMore" });
|
||||
|
||||
const { hasAuth } = useAuth();
|
||||
|
||||
+2
-2
@@ -8,12 +8,12 @@
|
||||
:style="{ backgroundColor: buttonBgColor, color: iconColor }"
|
||||
@click="handleClick"
|
||||
>
|
||||
<ArtSvgIcon :icon="iconContent" />
|
||||
<FaSvgIcon :icon="iconContent" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "ArtButtonTable" });
|
||||
defineOptions({ name: "FaButtonTable" });
|
||||
|
||||
interface Props {
|
||||
/** 按钮类型 */
|
||||
+2
-2
@@ -34,13 +34,13 @@
|
||||
ref="handler"
|
||||
:style="handlerStyle"
|
||||
>
|
||||
<ArtSvgIcon :icon="value ? successIcon : handlerIcon" class="text-g-600"></ArtSvgIcon>
|
||||
<FaSvgIcon :icon="value ? successIcon : handlerIcon" class="text-g-600"></FaSvgIcon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "ArtDragVerify" });
|
||||
defineOptions({ name: "FaDragVerify" });
|
||||
|
||||
// 事件定义
|
||||
const emit = defineEmits(["handlerMove", "update:value", "passCallback"]);
|
||||
+8
-8
@@ -26,7 +26,7 @@ import { Loading } from "@element-plus/icons-vue";
|
||||
import type { ButtonType } from "element-plus";
|
||||
import { useThrottleFn } from "@vueuse/core";
|
||||
|
||||
defineOptions({ name: "ArtExcelExport" });
|
||||
defineOptions({ name: "FaExcelExport" });
|
||||
|
||||
/** 导出数据类型 */
|
||||
type ExportValue = string | number | boolean | null | undefined | Date;
|
||||
@@ -390,11 +390,11 @@ defineExpose({
|
||||
|
||||
<!-- <template>
|
||||
<div class="page-content">
|
||||
<ArtExcelImport @import-success="handleImportSuccess" @import-error="handleImportError">
|
||||
<FaExcelImport @import-success="handleImportSuccess" @import-error="handleImportError">
|
||||
<template #import-text>上传 Excel</template>
|
||||
</ArtExcelImport>
|
||||
</FaExcelImport>
|
||||
|
||||
<ArtExcelExport
|
||||
<FaExcelExport
|
||||
style="margin-left: 10px"
|
||||
:data="tableData"
|
||||
filename="用户数据-1"
|
||||
@@ -408,23 +408,23 @@ defineExpose({
|
||||
@export-progress="handleProgress"
|
||||
>
|
||||
导出 Excel
|
||||
</ArtExcelExport>
|
||||
</FaExcelExport>
|
||||
|
||||
<ElButton type="danger" @click="handleClear" v-ripple>清除数据</ElButton>
|
||||
|
||||
<ArtTable :data="tableData" style="margin-top: 10px">
|
||||
<FaTable :data="tableData" style="margin-top: 10px">
|
||||
<ElTableColumn
|
||||
v-for="key in Object.keys(headers)"
|
||||
:key="key"
|
||||
:prop="key"
|
||||
:label="headers[key as keyof typeof headers]"
|
||||
/>
|
||||
</ArtTable>
|
||||
</FaTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "WidgetsExcel" });
|
||||
defineOptions({ name: "FaExcelExportDemo" });
|
||||
|
||||
/**
|
||||
* 表格数据类型定义
|
||||
+8
-8
@@ -18,7 +18,7 @@
|
||||
import * as XLSX from "xlsx";
|
||||
import type { UploadFile } from "element-plus";
|
||||
|
||||
defineOptions({ name: "ArtExcelImport" });
|
||||
defineOptions({ name: "FaExcelImport" });
|
||||
|
||||
// Excel 导入工具函数
|
||||
async function importExcel(file: File): Promise<Array<Record<string, unknown>>> {
|
||||
@@ -63,11 +63,11 @@ const handleFileChange = async (uploadFile: UploadFile) => {
|
||||
|
||||
<!-- <template>
|
||||
<div class="page-content">
|
||||
<ArtExcelImport @import-success="handleImportSuccess" @import-error="handleImportError">
|
||||
<FaExcelImport @import-success="handleImportSuccess" @import-error="handleImportError">
|
||||
<template #import-text>上传 Excel</template>
|
||||
</ArtExcelImport>
|
||||
</FaExcelImport>
|
||||
|
||||
<ArtExcelExport
|
||||
<FaExcelExport
|
||||
style="margin-left: 10px"
|
||||
:data="tableData"
|
||||
filename="用户数据-1"
|
||||
@@ -81,23 +81,23 @@ const handleFileChange = async (uploadFile: UploadFile) => {
|
||||
@export-progress="handleProgress"
|
||||
>
|
||||
导出 Excel
|
||||
</ArtExcelExport>
|
||||
</FaExcelExport>
|
||||
|
||||
<ElButton type="danger" @click="handleClear" v-ripple>清除数据</ElButton>
|
||||
|
||||
<ArtTable :data="tableData" style="margin-top: 10px">
|
||||
<FaTable :data="tableData" style="margin-top: 10px">
|
||||
<ElTableColumn
|
||||
v-for="key in Object.keys(headers)"
|
||||
:key="key"
|
||||
:prop="key"
|
||||
:label="headers[key as keyof typeof headers]"
|
||||
/>
|
||||
</ArtTable>
|
||||
</FaTable>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "WidgetsExcel" });
|
||||
defineOptions({ name: "FaExcelImportDemo" });
|
||||
|
||||
/**
|
||||
* 表格数据类型定义
|
||||
+1
-1
@@ -120,7 +120,7 @@ import {
|
||||
} from "element-plus";
|
||||
import { calculateResponsiveSpan, type ResponsiveBreakpoint } from "@utils/form";
|
||||
|
||||
defineOptions({ name: "ArtForm" });
|
||||
defineOptions({ name: "FaForm" });
|
||||
|
||||
const componentMap = {
|
||||
input: ElInput, // 输入框
|
||||
+7
-7
@@ -1,6 +1,6 @@
|
||||
<!-- 在 ArtSearchBar 上追加「创建人 / 更新人 / 创建时间 / 更新时间」,并内置 UserTableSelect 插槽;业务页只传自己的 items 即可 -->
|
||||
<!-- 在 FaSearchBar 上追加「创建人 / 更新人 / 创建时间 / 更新时间」,并内置 UserTableSelect 插槽;业务页只传自己的 items 即可 -->
|
||||
<template>
|
||||
<ArtSearchBar
|
||||
<FaSearchBar
|
||||
ref="innerRef"
|
||||
v-model="modelValue"
|
||||
v-bind="forwardedAttrs"
|
||||
@@ -31,12 +31,12 @@
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</ArtSearchBar>
|
||||
</FaSearchBar>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, useAttrs } from "vue";
|
||||
import ArtSearchBar from "./index.vue";
|
||||
import FaSearchBar from "./index.vue";
|
||||
import type { SearchFormItem } from "./index.vue";
|
||||
import {
|
||||
getAuditSearchFormItems,
|
||||
@@ -44,13 +44,13 @@ import {
|
||||
} from "./auditSearchFormItems";
|
||||
import UserTableSelect from "@views/module_system/user/components/UserTableSelect.vue";
|
||||
|
||||
defineOptions({ name: "ArtSearchBarWithAudit", inheritAttrs: false });
|
||||
defineOptions({ name: "FaSearchBarWithAudit", inheritAttrs: false });
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
/** 仅业务条件表单项,不含审计四字段 */
|
||||
items: SearchFormItem[];
|
||||
/** 为 false 时与原生 ArtSearchBar 一致,仅使用 `items` */
|
||||
/** 为 false 时与原生 FaSearchBar 一致,仅使用 `items` */
|
||||
includeAudit?: boolean;
|
||||
/** 传给 getAuditSearchFormItems 的选项 */
|
||||
auditItemOptions?: GetAuditSearchFormItemsOptions;
|
||||
@@ -66,7 +66,7 @@ const emit = defineEmits<{
|
||||
const modelValue = defineModel<Record<string, any>>({ default: () => ({}) });
|
||||
const attrs = useAttrs();
|
||||
|
||||
const innerRef = ref<InstanceType<typeof ArtSearchBar> | null>(null);
|
||||
const innerRef = ref<InstanceType<typeof FaSearchBar> | null>(null);
|
||||
|
||||
const forwardedAttrs = computed(() => attrs as Record<string, unknown>);
|
||||
|
||||
+3
-3
@@ -9,7 +9,7 @@ export type AuditSearchFormParams = {
|
||||
};
|
||||
|
||||
export interface GetAuditSearchFormItemsOptions {
|
||||
/** 栅格列宽,与 ArtSearchBar `span` 一致时建议传相同值,默认 6 */
|
||||
/** 栅格列宽,与 FaSearchBar `span` 一致时建议传相同值,默认 6 */
|
||||
span?: number;
|
||||
createdByLabel?: string;
|
||||
updatedByLabel?: string;
|
||||
@@ -25,8 +25,8 @@ export interface GetAuditSearchFormItemsOptions {
|
||||
}
|
||||
|
||||
/**
|
||||
* 常见「创建人 / 更新人 / 创建时间 / 更新时间」搜索项,供 ArtSearchBar `items` 使用。
|
||||
* 创建人、更新人需配合 `#created_id`、`#updated_id` 插槽(如 ArtSearchBarWithAudit)。
|
||||
* 常见「创建人 / 更新人 / 创建时间 / 更新时间」搜索项,供 FaSearchBar `items` 使用。
|
||||
* 创建人、更新人需配合 `#created_id`、`#updated_id` 插槽(如 FaSearchBarWithAudit)。
|
||||
*/
|
||||
export function getAuditSearchFormItems(
|
||||
options?: GetAuditSearchFormItemsOptions
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
<!-- 支持常用表单组件、自定义组件、插槽、校验、隐藏表单项 -->
|
||||
<!-- 写法同 ElementPlus 官方文档组件,把属性写在 props 里面就可以了 -->
|
||||
<template>
|
||||
<section class="art-search-bar art-card-xs" :class="{ 'is-expanded': isExpanded }">
|
||||
<section class="fa-search-bar fa-card-xs" :class="{ 'is-expanded': isExpanded }">
|
||||
<ElForm
|
||||
ref="formRef"
|
||||
:model="modelValue"
|
||||
@@ -133,7 +133,7 @@ import {
|
||||
} from "element-plus";
|
||||
import { calculateResponsiveSpan, type ResponsiveBreakpoint } from "@utils/form";
|
||||
|
||||
defineOptions({ name: "ArtSearchBar" });
|
||||
defineOptions({ name: "FaSearchBar" });
|
||||
|
||||
const componentMap = {
|
||||
input: ElInput, // 输入框
|
||||
@@ -512,7 +512,7 @@ const { span, gutter, labelPosition, labelWidth } = toRefs(props);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.art-search-bar {
|
||||
.fa-search-bar {
|
||||
padding: 15px 20px 0;
|
||||
|
||||
.action-column {
|
||||
@@ -563,7 +563,7 @@ const { span, gutter, labelPosition, labelWidth } = toRefs(props);
|
||||
|
||||
// 响应式优化
|
||||
@media (width <= 768px) {
|
||||
.art-search-bar {
|
||||
.fa-search-bar {
|
||||
padding: 16px 16px 0;
|
||||
|
||||
.action-column {
|
||||
+1
-1
@@ -27,7 +27,7 @@ import { IDomEditor, IToolbarConfig, IEditorConfig } from "@wangeditor/editor";
|
||||
import request from "@utils/http";
|
||||
import type { AxiosResponse } from "axios";
|
||||
|
||||
defineOptions({ name: "ArtWangEditor" });
|
||||
defineOptions({ name: "FaWangEditor" });
|
||||
|
||||
type InsertFnType = (url: string, alt: string, href: string) => void;
|
||||
|
||||
+2
-2
@@ -47,7 +47,7 @@
|
||||
<script setup lang="ts">
|
||||
import ImgCutter from "vue-img-cutter";
|
||||
|
||||
defineOptions({ name: "ArtCutterImg" });
|
||||
defineOptions({ name: "FaCutterImg" });
|
||||
|
||||
interface CutterProps {
|
||||
// 基础配置
|
||||
@@ -268,7 +268,7 @@ function downloadImg() {
|
||||
|
||||
.preview-container {
|
||||
.preview-box {
|
||||
background-color: var(--art-active-color) !important;
|
||||
background-color: var(--fa-active-color) !important;
|
||||
|
||||
.preview-img {
|
||||
width: 100%;
|
||||
+3
-3
@@ -7,7 +7,7 @@
|
||||
import Player from "xgplayer";
|
||||
import "xgplayer/dist/index.min.css";
|
||||
|
||||
defineOptions({ name: "ArtVideoPlayer" });
|
||||
defineOptions({ name: "FaVideoPlayer" });
|
||||
|
||||
interface Props {
|
||||
/** 播放器容器 ID */
|
||||
@@ -113,7 +113,7 @@ onBeforeUnmount(() => {
|
||||
<!-- <template>
|
||||
<div class="page-content">
|
||||
<div class="max-w-150">
|
||||
<ArtVideoPlayer
|
||||
<FaVideoPlayer
|
||||
playerId="my-video-1"
|
||||
:videoUrl="videoUrl"
|
||||
:posterUrl="posterUrl"
|
||||
@@ -128,7 +128,7 @@ onBeforeUnmount(() => {
|
||||
<script setup lang="ts">
|
||||
import lockImg from "@imgs/lock/bg_dark.webp";
|
||||
|
||||
defineOptions({ name: "WidgetsVideo" });
|
||||
defineOptions({ name: "FaVideoPlayerDemo" });
|
||||
|
||||
/**
|
||||
* 视频源 URL
|
||||
+1
-1
@@ -50,7 +50,7 @@ import { Close, Fold, FullScreen } from "@element-plus/icons-vue";
|
||||
import type { DialogProps } from "element-plus";
|
||||
import { computed, ref, useAttrs, watch } from "vue";
|
||||
|
||||
defineOptions({ name: "ArtDialog", inheritAttrs: false });
|
||||
defineOptions({ name: "FaDialog", inheritAttrs: false });
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
+1
-1
@@ -34,7 +34,7 @@ import { Close } from "@element-plus/icons-vue";
|
||||
import type { DrawerProps } from "element-plus";
|
||||
import { computed, useAttrs } from "vue";
|
||||
|
||||
defineOptions({ name: "ArtDrawer", inheritAttrs: false });
|
||||
defineOptions({ name: "FaDrawer", inheritAttrs: false });
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="crud-export-modal-host">
|
||||
<!-- 导出弹窗 -->
|
||||
<ArtDialog
|
||||
<FaDialog
|
||||
v-model="exportsModalVisible"
|
||||
title="导出数据"
|
||||
width="600px"
|
||||
@@ -59,19 +59,19 @@
|
||||
<ElButton @click="handleCloseExportsModal">取 消</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ArtDialog>
|
||||
</FaDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import ArtDialog from "@/components/Core/modal/art-dialog/index.vue";
|
||||
import FaDialog from "@/components/modal/fa-dialog/index.vue";
|
||||
import ExcelJS from "exceljs";
|
||||
import type { IContentConfig, IObject } from "@/components/Core/modal/types";
|
||||
import type { IContentConfig, IObject } from "@/components/modal/types";
|
||||
import { useThrottleFn } from "@vueuse/core";
|
||||
import { type FormInstance, type FormRules, ElMessage } from "element-plus";
|
||||
import { nextTick, ref, reactive, computed } from "vue";
|
||||
|
||||
defineOptions({ name: "ArtExportDialog", inheritAttrs: false });
|
||||
defineOptions({ name: "FaExportDialog", inheritAttrs: false });
|
||||
|
||||
function saveBlobDownload(blob: Blob, rawName: string) {
|
||||
const name = /\.xlsx?$/i.test(rawName) ? rawName : `${rawName}.xlsx`;
|
||||
@@ -86,7 +86,7 @@ function saveBlobDownload(blob: Blob, rawName: string) {
|
||||
/**
|
||||
* 导出模态框组件属性定义
|
||||
*/
|
||||
interface ArtExportDialogProps {
|
||||
interface FaExportDialogProps {
|
||||
/** 内容配置 */
|
||||
contentConfig: Pick<
|
||||
IContentConfig,
|
||||
@@ -101,7 +101,7 @@ interface ArtExportDialogProps {
|
||||
}
|
||||
|
||||
// 定义接收的属性
|
||||
const props = defineProps<ArtExportDialogProps>();
|
||||
const props = defineProps<FaExportDialogProps>();
|
||||
|
||||
const remoteExportEnabled = computed(
|
||||
() => !!(props.contentConfig.exportsAction || props.contentConfig.exportsBlobAction)
|
||||
+7
-7
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="crud-import-modal-host">
|
||||
<!-- 导入弹窗 -->
|
||||
<ArtDialog
|
||||
<FaDialog
|
||||
v-model="importModalVisible"
|
||||
:title="props.title"
|
||||
:width="props.width"
|
||||
@@ -70,23 +70,23 @@
|
||||
</ElButton>
|
||||
</div>
|
||||
</template>
|
||||
</ArtDialog>
|
||||
</FaDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Download, UploadFilled } from "@element-plus/icons-vue";
|
||||
import ArtDialog from "@/components/Core/modal/art-dialog/index.vue";
|
||||
import FaDialog from "@/components/modal/fa-dialog/index.vue";
|
||||
import { ElMessage, type UploadUserFile } from "element-plus";
|
||||
import { ref, reactive } from "vue";
|
||||
import type { IContentConfig, IObject } from "@/components/Core/modal/types";
|
||||
import type { IContentConfig, IObject } from "@/components/modal/types";
|
||||
|
||||
defineOptions({ name: "ArtImportDialog", inheritAttrs: false });
|
||||
defineOptions({ name: "FaImportDialog", inheritAttrs: false });
|
||||
|
||||
/**
|
||||
* 导入模态框组件属性定义
|
||||
*/
|
||||
interface ArtImportDialogProps {
|
||||
interface FaImportDialogProps {
|
||||
/**
|
||||
* 弹窗标题
|
||||
*/
|
||||
@@ -179,7 +179,7 @@ interface ArtImportDialogProps {
|
||||
}
|
||||
|
||||
// 定义props
|
||||
const props = withDefaults(defineProps<ArtImportDialogProps>(), {
|
||||
const props = withDefaults(defineProps<FaImportDialogProps>(), {
|
||||
title: "导入数据",
|
||||
width: "600px",
|
||||
maxHeight: "60vh",
|
||||
@@ -0,0 +1,5 @@
|
||||
/** 通用弹窗、抽屉(与业务 CRUD 解耦) */
|
||||
export { default as FaDialog } from "./fa-dialog/index.vue";
|
||||
export { default as FaDrawer } from "./fa-drawer/index.vue";
|
||||
export { default as FaImportDialog } from "./fa-import-dialog/index.vue";
|
||||
export { default as FaExportDialog } from "./fa-export-dialog/index.vue";
|
||||
+20
-20
@@ -121,36 +121,36 @@ export interface ISearchConfig {
|
||||
/** 重置按钮权限 */
|
||||
resetButtonPerm?: string | string[];
|
||||
/**
|
||||
* 搜索区形态:与「高级表格」示例一致用 `art`(ArtSearchBar + art-card-xs);
|
||||
* 搜索区形态:与「高级表格」示例一致用 `art`(FaSearchBar + fa-card-xs);
|
||||
* `grid` 等复杂布局仍走 `legacy`(或显式传 legacy)
|
||||
*/
|
||||
searchVariant?: "legacy" | "art";
|
||||
/**
|
||||
* ArtSearchBar `span`(不传则组件默认 6)。
|
||||
* 若需与 legacy `showNumber` 折叠条数对齐,可自行传入 `computeArtSearchSpan(showNumber)` 的结果。
|
||||
* FaSearchBar `span`(不传则组件默认 6)。
|
||||
* 若需与 legacy `showNumber` 折叠条数对齐,可自行传入 `computeFaSearchSpan(showNumber)` 的结果。
|
||||
*/
|
||||
artSearchSpan?: number;
|
||||
/** ArtSearchBar `showExpand`(不传则 `isExpandable !== false`,否则与组件默认 true 一致) */
|
||||
/** FaSearchBar `showExpand`(不传则 `isExpandable !== false`,否则与组件默认 true 一致) */
|
||||
artSearchShowExpand?: boolean;
|
||||
/** ArtSearchBar 栅格 gutter(不传则用组件默认 12) */
|
||||
/** FaSearchBar 栅格 gutter(不传则用组件默认 12) */
|
||||
artSearchGutter?: number;
|
||||
/** art 搜索区默认展开全部筛选项(对应 ArtSearchBar defaultExpanded) */
|
||||
/** art 搜索区默认展开全部筛选项(对应 FaSearchBar defaultExpanded) */
|
||||
searchDefaultExpanded?: boolean;
|
||||
/**
|
||||
* art 搜索区内控件最大宽度(不传则不限制,与 ArtSearchBar 示例一致)。
|
||||
* art 搜索区内控件最大宽度(不传则不限制,与 FaSearchBar 示例一致)。
|
||||
* 需要限制时再传,如 `"200px"`、`"min(100%, 280px)"`;`false` 显式铺满栅格列。
|
||||
*/
|
||||
artSearchFieldMaxWidth?: string | false;
|
||||
/** 透传 ArtSearchBar → ElForm.rules */
|
||||
/** 透传 FaSearchBar → ElForm.rules */
|
||||
artSearchRules?: FormRules;
|
||||
/** 透传 ArtSearchBar `sanitizeOutput`,控制搜索提交前清洗空值等行为 */
|
||||
/** 透传 FaSearchBar `sanitizeOutput`,控制搜索提交前清洗空值等行为 */
|
||||
artSearchSanitizeOutput?: IObject;
|
||||
/** 透传 ArtSearchBar `buttonLeftLimit`(表单项数 ≤ 该值时操作按钮靠左,默认 2) */
|
||||
/** 透传 FaSearchBar `buttonLeftLimit`(表单项数 ≤ 该值时操作按钮靠左,默认 2) */
|
||||
artSearchButtonLeftLimit?: number;
|
||||
/** 透传 ArtSearchBar `disabledSearch`,为 true 时禁用查询按钮 */
|
||||
/** 透传 FaSearchBar `disabledSearch`,为 true 时禁用查询按钮 */
|
||||
artSearchDisabledSearch?: boolean;
|
||||
/**
|
||||
* 透传 ArtSearchBar `isExpand`:为 true 时始终展示全部筛选项(不出现「展开更多」)。
|
||||
* 透传 FaSearchBar `isExpand`:为 true 时始终展示全部筛选项(不出现「展开更多」)。
|
||||
* 不传时:`isExpandable === false` 自动为 true(与 legacy 全展示一致);可折叠搜索时为 false。
|
||||
*/
|
||||
artSearchIsExpand?: boolean;
|
||||
@@ -244,25 +244,25 @@ export interface IContentConfig<T = any> {
|
||||
toolbar?: Array<ToolbarLeft | IToolsButton>;
|
||||
/**
|
||||
* 表格工具栏右侧图标(仅 **legacy** `el-table` 栈由 `CrudToolbarActions` 渲染)。
|
||||
* **tableVariant: 'art'** 时刷新/列设置等由 `ArtTableHeader` 自带;导入导出请用 `#toolbar` 插槽自建。
|
||||
* **tableVariant: 'art'** 时刷新/列设置等由 `FaTableHeader` 自带;导入导出请用 `#toolbar` 插槽自建。
|
||||
*/
|
||||
defaultToolbar?: Array<ToolbarRight | IToolsButton>;
|
||||
/** 为 true 时隐藏 ArtTableHeader「列筛选」按钮(默认 false,显示列筛选) */
|
||||
/** 为 true 时隐藏 FaTableHeader「列筛选」按钮(默认 false,显示列筛选) */
|
||||
hideColumnFilter?: boolean;
|
||||
/**
|
||||
* 表格栈:`art` 时使用 ArtTableHeader + ArtTable;
|
||||
* 表格栈:`art` 时使用 FaTableHeader + FaTable;
|
||||
* `legacy` 为内置 el-table(默认)。
|
||||
*/
|
||||
tableVariant?: "legacy" | "art";
|
||||
/** 内容区外层 el-card 额外 class(默认已含 `art-table-card`) */
|
||||
/** 内容区外层 el-card 额外 class(默认已含 `fa-table-card`) */
|
||||
cardClass?: string;
|
||||
/** el-card 阴影(默认 never,与 Element Plus el-card shadow 一致) */
|
||||
cardShadow?: "always" | "hover" | "never";
|
||||
/** 是否显示表格上方工具条(默认 true;纯卡片/无按钮时可设为 false) */
|
||||
showToolbar?: boolean;
|
||||
/** ArtTableHeader 布局(不传则用内置默认) */
|
||||
/** FaTableHeader 布局(不传则用内置默认) */
|
||||
artToolbarLayout?: string;
|
||||
/** 表格全屏区域 class,传给 ArtTableHeader fullClass */
|
||||
/** 表格全屏区域 class,传给 FaTableHeader fullClass */
|
||||
artFullScreenClass?: string;
|
||||
/** 更多操作按钮配置 */
|
||||
moreButtons?: Array<IToolsButton>;
|
||||
@@ -338,7 +338,7 @@ export interface IContentConfig<T = any> {
|
||||
/**
|
||||
* CrudContent 左侧 `createToolbar` 产物,供 CrudToolbarLeft 的 `configButtons` 使用。
|
||||
*/
|
||||
export type ArtTableHeaderLeftConfigButton = {
|
||||
export type FaTableHeaderLeftConfigButton = {
|
||||
name: string;
|
||||
text?: string;
|
||||
attrs?: Record<string, unknown>;
|
||||
@@ -357,7 +357,7 @@ export interface IModalConfig<T = any> {
|
||||
pk?: string;
|
||||
/** 组件类型(默认:dialog) */
|
||||
component?: "dialog" | "drawer";
|
||||
/** dialog组件属性(默认可拖拽;全屏由 core/overlays/ArtDialog 标题栏按钮切换) */
|
||||
/** dialog组件属性(默认可拖拽;全屏由 core/overlays/FaDialog 标题栏按钮切换) */
|
||||
dialog?: Partial<Omit<DialogProps, "modelValue">> & { draggable?: boolean };
|
||||
/** drawer组件属性 */
|
||||
drawer?: Partial<Omit<DrawerProps, "modelValue">>;
|
||||
+6
-4
@@ -12,7 +12,7 @@
|
||||
@contextmenu.prevent="fabCollapsed = true"
|
||||
@click="handleOpen"
|
||||
>
|
||||
<ArtSvgIcon :icon="resolveIconForArtSvgIcon('ai')" class="ai-icon" />
|
||||
<FaSvgIcon :icon="resolveIconForFaSvgIcon('ai')" class="ai-icon" />
|
||||
</ElButton>
|
||||
|
||||
<!-- 收缩态:贴边小标签,避免遮挡表单控件 -->
|
||||
@@ -36,7 +36,7 @@
|
||||
>
|
||||
<template #header>
|
||||
<div class="dialog-header">
|
||||
<ArtSvgIcon :icon="resolveIconForArtSvgIcon('ai')" class="header-icon" />
|
||||
<FaSvgIcon :icon="resolveIconForFaSvgIcon('ai')" class="header-icon" />
|
||||
<span class="title">AI 智能助手</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -119,8 +119,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ArtSvgIcon from "@/components/Core/base/art-svg-icon/index.vue";
|
||||
import { resolveIconForArtSvgIcon } from "@utils/menuIcon/remix";
|
||||
defineOptions({ name: "FaAiAssistant" });
|
||||
|
||||
import FaSvgIcon from "@/components/base/fa-svg-icon/index.vue";
|
||||
import { resolveIconForFaSvgIcon } from "@utils/menuIcon/remix";
|
||||
import { nextTick, onBeforeUnmount, onMounted, watch, ref, computed } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { ElMessage } from "element-plus";
|
||||
+1
-1
@@ -77,7 +77,7 @@
|
||||
<script setup lang="ts">
|
||||
import { dayjs } from "element-plus";
|
||||
|
||||
defineOptions({ name: "HomeCalendar" });
|
||||
defineOptions({ name: "FaCalendar" });
|
||||
|
||||
interface CalendarEvent {
|
||||
date: string;
|
||||
+3
-1
@@ -8,8 +8,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
defineOptions({
|
||||
name: "CopyButton",
|
||||
name: "FaCopyButton",
|
||||
inheritAttrs: false,
|
||||
});
|
||||
|
||||
+3
@@ -28,6 +28,9 @@
|
||||
</svg>
|
||||
</a>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "FaGithubCorner" });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.github-corner:hover .octo-arm {
|
||||
+1
@@ -59,6 +59,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "FaGuide" });
|
||||
import { computed, type PropType } from "vue";
|
||||
import { useSettingsStore } from "@stores";
|
||||
import { MenuTypeEnum } from "@/enums/appEnum";
|
||||
+5
-7
@@ -11,10 +11,7 @@
|
||||
<ElIcon v-if="elementIconComp">
|
||||
<component :is="elementIconComp" />
|
||||
</ElIcon>
|
||||
<ArtSvgIcon
|
||||
v-else-if="selectedIcon"
|
||||
:icon="resolveIconForArtSvgIcon(selectedIcon)"
|
||||
/>
|
||||
<FaSvgIcon v-else-if="selectedIcon" :icon="resolveIconForFaSvgIcon(selectedIcon)" />
|
||||
</template>
|
||||
<template #suffix>
|
||||
<!-- 清空按钮 -->
|
||||
@@ -54,7 +51,7 @@
|
||||
@click="selectIcon(icon)"
|
||||
>
|
||||
<ElTooltip :content="icon" placement="bottom" effect="light">
|
||||
<ArtSvgIcon :icon="resolveIconForArtSvgIcon(icon)" />
|
||||
<FaSvgIcon :icon="resolveIconForFaSvgIcon(icon)" />
|
||||
</ElTooltip>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -83,11 +80,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "FaIconSelect" });
|
||||
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
|
||||
import ArtSvgIcon from "@/components/Core/base/art-svg-icon/index.vue";
|
||||
import FaSvgIcon from "@/components/base/fa-svg-icon/index.vue";
|
||||
import { listLocalIconBasenames } from "@utils/icons";
|
||||
import { isIconifyStoredIcon, resolveElementPlusIconComponent } from "@utils/menuIcon";
|
||||
import { resolveIconForArtSvgIcon } from "@utils/menuIcon/remix";
|
||||
import { resolveIconForFaSvgIcon } from "@utils/menuIcon/remix";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
+2
@@ -64,6 +64,8 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineOptions({ name: "FaIntervalTab" });
|
||||
|
||||
// 定义接口,增强类型安全
|
||||
interface CrontabValue {
|
||||
second: string;
|
||||
+2
@@ -14,6 +14,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "FaJsonPretty" });
|
||||
|
||||
import { computed } from "vue";
|
||||
import VueJsonPretty from "vue-json-pretty";
|
||||
import "vue-json-pretty/lib/styles.css";
|
||||
+9
-9
@@ -5,7 +5,7 @@
|
||||
<div
|
||||
v-show="visible"
|
||||
:style="menuStyle"
|
||||
class="context-menu art-card-xs !shadow-xl min-w-[var(--menu-width)] w-[var(--menu-width)]"
|
||||
class="context-menu fa-card-xs !shadow-xl min-w-[var(--menu-width)] w-[var(--menu-width)]"
|
||||
>
|
||||
<ul class="menu-list m-0 list-none" :style="menuListStyle">
|
||||
<template v-for="item in menuItems" :key="item.key">
|
||||
@@ -17,7 +17,7 @@
|
||||
:style="menuItemStyle"
|
||||
@click="handleMenuClick(item)"
|
||||
>
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
v-if="item.icon"
|
||||
class="mr-2 shrink-0 text-base text-g-800"
|
||||
:icon="item.icon"
|
||||
@@ -36,7 +36,7 @@
|
||||
:style="menuItemStyle"
|
||||
>
|
||||
<div class="submenu-title flex-c w-full">
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
v-if="item.icon"
|
||||
class="mr-2 shrink-0 text-base text-g-800"
|
||||
:icon="item.icon"
|
||||
@@ -46,13 +46,13 @@
|
||||
>
|
||||
{{ item.label }}
|
||||
</span>
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
icon="ri:arrow-right-s-line"
|
||||
class="ubmenu-arrow ml-auto mr-0 text-base text-g-500 transition-transform duration-150"
|
||||
/>
|
||||
</div>
|
||||
<ul
|
||||
class="submenu-list art-card-xs absolute left-full top-0 z-[2001] hidden w-max min-w-max list-none !shadow-xl"
|
||||
class="submenu-list fa-card-xs absolute left-full top-0 z-[2001] hidden w-max min-w-max list-none !shadow-xl"
|
||||
:style="submenuListStyle"
|
||||
>
|
||||
<li
|
||||
@@ -63,7 +63,7 @@
|
||||
:style="menuItemStyle"
|
||||
@click="handleMenuClick(child)"
|
||||
>
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
v-if="child.icon"
|
||||
class="r-2 shrink-0 text-base text-g-800 mr-1"
|
||||
:icon="child.icon"
|
||||
@@ -86,7 +86,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { CSSProperties } from "vue";
|
||||
|
||||
defineOptions({ name: "ArtMenuRight" });
|
||||
defineOptions({ name: "FaMenuRight" });
|
||||
|
||||
export interface MenuItemType {
|
||||
/** 菜单项唯一标识 */
|
||||
@@ -369,7 +369,7 @@ defineExpose({
|
||||
left: 0;
|
||||
height: 1px;
|
||||
content: "";
|
||||
background-color: var(--art-gray-300);
|
||||
background-color: var(--fa-gray-300);
|
||||
}
|
||||
|
||||
.menu-item.is-disabled {
|
||||
@@ -382,7 +382,7 @@ defineExpose({
|
||||
}
|
||||
|
||||
.menu-item.is-disabled i:not(.submenu-arrow),
|
||||
.menu-item.is-disabled :deep(.art-svg-icon) {
|
||||
.menu-item.is-disabled :deep(.fa-svg-icon) {
|
||||
color: var(--el-text-color-disabled) !important;
|
||||
}
|
||||
|
||||
+6
-12
@@ -11,7 +11,7 @@
|
||||
<component :is="elementComponent" />
|
||||
</ElIcon>
|
||||
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
v-else-if="isInvalidElementPrefix"
|
||||
:icon="epFallback"
|
||||
:color="color"
|
||||
@@ -19,26 +19,20 @@
|
||||
:style="mergedStyle"
|
||||
/>
|
||||
|
||||
<ArtSvgIcon
|
||||
v-else
|
||||
:icon="resolvedArtIcon"
|
||||
:color="color"
|
||||
:class="iconClass"
|
||||
:style="mergedStyle"
|
||||
/>
|
||||
<FaSvgIcon v-else :icon="resolvedFaIcon" :color="color" :class="iconClass" :style="mergedStyle" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import ArtSvgIcon from "@/components/Core/base/art-svg-icon/index.vue";
|
||||
import FaSvgIcon from "@/components/base/fa-svg-icon/index.vue";
|
||||
import {
|
||||
elementMenuIconToEpIconify,
|
||||
isElementPlusStoredIcon,
|
||||
resolveElementPlusIconComponent,
|
||||
} from "@utils/menuIcon";
|
||||
import { resolveIconForArtSvgIcon } from "@utils/menuIcon/remix";
|
||||
import { resolveIconForFaSvgIcon } from "@utils/menuIcon/remix";
|
||||
|
||||
defineOptions({ name: "MenuRouteIcon", inheritAttrs: false });
|
||||
defineOptions({ name: "FaMenuRouteIcon", inheritAttrs: false });
|
||||
|
||||
const props = defineProps<{
|
||||
icon?: string;
|
||||
@@ -60,7 +54,7 @@ const isInvalidElementPrefix = computed(
|
||||
const epFallback = computed(() => elementMenuIconToEpIconify(trimmedIcon.value));
|
||||
|
||||
/** Iconify(含历史本地 SVG 文件名 → Remix `ri:`) */
|
||||
const resolvedArtIcon = computed(() => resolveIconForArtSvgIcon(trimmedIcon.value));
|
||||
const resolvedFaIcon = computed(() => resolveIconForFaSvgIcon(trimmedIcon.value));
|
||||
|
||||
const iconClass = computed(() =>
|
||||
props.class === false || props.class == null ? undefined : props.class
|
||||
-7
@@ -101,11 +101,4 @@ function handleCurrentChange(val: number) {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.pagination {
|
||||
padding: 12px;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<component :is="tag" class="art-widget-demo-title">
|
||||
<component :is="tag" class="fa-widget-demo-title">
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
@@ -7,7 +7,7 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* Widget 演示页章节标题(与历史 `page-title` Tailwind 一致)。
|
||||
* 业务页如需同款排版可直接复用;CRUD 列表页优先用 ArtSearchBar + 表格区标题即可。
|
||||
* 业务页如需同款排版可直接复用;CRUD 列表页优先用 FaSearchBar + 表格区标题即可。
|
||||
*/
|
||||
withDefaults(
|
||||
defineProps<{
|
||||
@@ -21,7 +21,7 @@ withDefaults(
|
||||
<style scoped>
|
||||
@reference "@styles/core/tailwind.css";
|
||||
|
||||
.art-widget-demo-title {
|
||||
.fa-widget-demo-title {
|
||||
@apply my-5 text-xl font-medium first:mt-0;
|
||||
}
|
||||
</style>
|
||||
+6
-7
@@ -1,12 +1,9 @@
|
||||
<!-- 布局大小(触发器与顶栏 ArtIconButton 一致,避免与其它图标尺寸/悬停不一致) -->
|
||||
<!-- 布局大小(触发器与顶栏 FaIconButton 一致,避免与其它图标尺寸/悬停不一致) -->
|
||||
<template>
|
||||
<ElTooltip :content="t('sizeSelect.tooltip')" effect="dark" placement="bottom">
|
||||
<ElDropdown trigger="click" @command="handleSizeChange">
|
||||
<span class="inline-flex outline-none leading-none">
|
||||
<ArtIconButton
|
||||
:icon="resolveIconForArtSvgIcon('size')"
|
||||
class="size-select-btn text-[19px]"
|
||||
/>
|
||||
<FaIconButton :icon="resolveIconForFaSvgIcon('size')" class="size-select-btn text-[19px]" />
|
||||
</span>
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
@@ -25,10 +22,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ArtIconButton from "@/components/Core/widget/art-icon-button/index.vue";
|
||||
defineOptions({ name: "FaSizeSelect" });
|
||||
|
||||
import FaIconButton from "@/components/widget/fa-icon-button/index.vue";
|
||||
import { ComponentSize } from "@/enums/settings/layout.enum";
|
||||
import { useAppStore } from "@stores/modules/app.store";
|
||||
import { resolveIconForArtSvgIcon } from "@utils/menuIcon/remix";
|
||||
import { resolveIconForFaSvgIcon } from "@utils/menuIcon/remix";
|
||||
import { computed } from "vue";
|
||||
|
||||
const { t } = useI18n();
|
||||
+7
@@ -143,6 +143,13 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineOptions({ name: "FaTableSelect" });
|
||||
|
||||
// 显式声明插槽类型(支持动态列插槽)
|
||||
defineSlots<{
|
||||
[slotName: string]: (props: Record<string, any>) => void;
|
||||
}>();
|
||||
|
||||
import { ref, reactive, computed } from "vue";
|
||||
import { useResizeObserver } from "@vueuse/core";
|
||||
import type { FormInstance, PopoverProps, TableInstance } from "element-plus";
|
||||
+4
-2
@@ -10,7 +10,7 @@
|
||||
class="single-image-upload__crop-dialog"
|
||||
@closed="onCropDialogClosed"
|
||||
>
|
||||
<ArtCutterImg
|
||||
<FaCutterImg
|
||||
v-if="cropVisible && cropSourceUrl"
|
||||
:key="cropSourceUrl"
|
||||
:img-url="cropSourceUrl"
|
||||
@@ -76,10 +76,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "FaUpload" });
|
||||
|
||||
import { ref, watch } from "vue";
|
||||
import { UploadRawFile, UploadRequestOptions, ElMessage, type UploadUserFile } from "element-plus";
|
||||
import ParamsAPI from "@/api/module_system/params";
|
||||
import ArtCutterImg from "@/components/Core/media/art-cutter-img/index.vue";
|
||||
import FaCutterImg from "@/components/media/fa-cutter-img/index.vue";
|
||||
import { dataURLToFile } from "@utils/file/dataUrl";
|
||||
|
||||
const props = defineProps({
|
||||
+1
-1
@@ -26,7 +26,7 @@ import { ThemeMode } from "@/enums";
|
||||
import { hexToRgba } from "@utils/ui";
|
||||
import { useSettingsStore } from "@stores/modules/setting.store";
|
||||
|
||||
defineOptions({ name: "ArtWatermark" });
|
||||
defineOptions({ name: "FaWatermark" });
|
||||
|
||||
interface WatermarkProps {
|
||||
/** 水印内容 */
|
||||
+2
-2
@@ -87,12 +87,12 @@
|
||||
<script setup lang="ts">
|
||||
import { ArrowDown, Delete, Download, Plus, Upload } from "@element-plus/icons-vue";
|
||||
import { computed } from "vue";
|
||||
import type { ArtTableHeaderLeftConfigButton } from "@/components/Core/modal/types";
|
||||
import type { FaTableHeaderLeftConfigButton } from "@/components/modal/types";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
/** 与 CrudContent `toolbarLeftBtn` 一致时走配置驱动(与 handleToolbar 对齐) */
|
||||
configButtons?: ArtTableHeaderLeftConfigButton[];
|
||||
configButtons?: FaTableHeaderLeftConfigButton[];
|
||||
/** 勾选行主键,用于禁用批删 / 更多(插槽完全自定义时可不传) */
|
||||
removeIds?: Array<string | number>;
|
||||
/** 新增按钮权限,不传则不显示(configButtons 未传时) */
|
||||
+18
-11
@@ -1,6 +1,6 @@
|
||||
<!-- 表格头部,包含表格大小、刷新、全屏、列设置、其他设置 -->
|
||||
<template>
|
||||
<div class="flex-cb max-md:!block" id="art-table-header">
|
||||
<div class="flex-cb max-md:!block" id="fa-table-header">
|
||||
<div class="flex-wrap">
|
||||
<slot name="left"></slot>
|
||||
</div>
|
||||
@@ -17,7 +17,7 @@
|
||||
@click="search"
|
||||
:class="!showSearchBar ? 'active !bg-theme hover:!bg-theme/80' : ''"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:search-line" :class="!showSearchBar ? 'text-white' : 'text-g-700'" />
|
||||
<FaSvgIcon icon="ri:search-line" :class="!showSearchBar ? 'text-white' : 'text-g-700'" />
|
||||
</div>
|
||||
</ElTooltip>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
@click="refresh"
|
||||
:class="{ loading: loading && isManualRefresh }"
|
||||
>
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
icon="ri:refresh-line"
|
||||
:class="loading && isManualRefresh ? 'animate-spin text-g-600' : ''"
|
||||
/>
|
||||
@@ -37,7 +37,7 @@
|
||||
<!-- 表格大小 -->
|
||||
<ElDropdown v-if="shouldShow('size')" @command="handleTableSizeChange">
|
||||
<div class="button">
|
||||
<ArtSvgIcon icon="ri:arrow-up-down-fill" />
|
||||
<FaSvgIcon icon="ri:arrow-up-down-fill" />
|
||||
</div>
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
<!-- 全屏 -->
|
||||
<div v-if="shouldShow('fullscreen')" class="button" @click="toggleFullScreen">
|
||||
<ArtSvgIcon :icon="isFullScreen ? 'ri:fullscreen-exit-line' : 'ri:fullscreen-line'" />
|
||||
<FaSvgIcon :icon="isFullScreen ? 'ri:fullscreen-exit-line' : 'ri:fullscreen-line'" />
|
||||
</div>
|
||||
|
||||
<!-- 行拖拽排序 -->
|
||||
@@ -74,7 +74,7 @@
|
||||
@click="toggleRowDrag"
|
||||
:class="isRowDrag ? 'active !bg-theme hover:!bg-theme/80' : ''"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:drag-move-line" :class="isRowDrag ? 'text-white' : 'text-g-700'" />
|
||||
<FaSvgIcon icon="ri:drag-move-line" :class="isRowDrag ? 'text-white' : 'text-g-700'" />
|
||||
</div>
|
||||
</ElTooltip>
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
<ElPopover v-if="shouldShow('columns')" placement="bottom" trigger="click">
|
||||
<template #reference>
|
||||
<div class="button">
|
||||
<ArtSvgIcon icon="ri:align-right" />
|
||||
<FaSvgIcon icon="ri:align-right" />
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
@@ -104,7 +104,7 @@
|
||||
class="drag-icon mr-2 h-4.5 flex-cc text-g-500"
|
||||
:class="item.fixed ? 'cursor-default text-g-300' : 'cursor-move'"
|
||||
>
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
:icon="item.fixed ? 'ri:unpin-line' : 'ri:drag-move-2-fill'"
|
||||
class="text-base"
|
||||
/>
|
||||
@@ -126,7 +126,7 @@
|
||||
<ElPopover v-if="shouldShow('settings')" placement="bottom" trigger="click">
|
||||
<template #reference>
|
||||
<div class="button">
|
||||
<ArtSvgIcon icon="ri:settings-line" />
|
||||
<FaSvgIcon icon="ri:settings-line" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="flex min-w-[200px] flex-col gap-2">
|
||||
@@ -156,7 +156,14 @@ import { useI18n } from "vue-i18n";
|
||||
import type { ColumnOption } from "@/types/component";
|
||||
import { ElScrollbar } from "element-plus";
|
||||
|
||||
defineOptions({ name: "ArtTableHeader" });
|
||||
defineOptions({ name: "FaTableHeader" });
|
||||
|
||||
// 显式声明插槽类型
|
||||
defineSlots<{
|
||||
default?: () => void;
|
||||
left?: () => void;
|
||||
right?: () => void;
|
||||
}>();
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -172,7 +179,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
fullClass: "art-page-view",
|
||||
fullClass: "fa-page-view",
|
||||
layout: "search,refresh,size,fullscreen,columns,rowDrag,settings",
|
||||
showSearchBar: undefined,
|
||||
});
|
||||
+36
-31
@@ -1,24 +1,27 @@
|
||||
<!-- 表格组件 -->
|
||||
<!-- 支持:el-table 全部属性、事件、插槽,同官方文档写法 -->
|
||||
<!-- 扩展功能:分页组件、渲染自定义列、loading、表格全局边框、斑马纹、表格尺寸、表头背景配置 -->
|
||||
<!-- 获取 ref:默认暴露了 elTableRef 外部通过 ref.value.elTableRef 可以调用 el-table 方法 -->
|
||||
<!--
|
||||
FaTable:ElTable 透传 + 分页 + 列渲染约定。
|
||||
- 属性 / 事件 / 插槽与 EP 文档一致;样式可由 tableStore 与 props 覆盖。
|
||||
- 暴露 `elTableRef`、`scrollToTop`;formatter 列见 TableFormatterOutlet 注释。
|
||||
-->
|
||||
<template>
|
||||
<div class="art-table" :class="{ 'is-empty': isEmpty }" :style="containerHeight">
|
||||
<VueDraggable
|
||||
target="tbody"
|
||||
v-model="dragModel"
|
||||
:animation="150"
|
||||
:disabled="rowDragDisabled"
|
||||
@end="onRowDragEnd"
|
||||
>
|
||||
<ElTable ref="elTableRef" v-loading="!!loading" v-bind="mergedTableProps">
|
||||
<template v-for="col in columns" :key="col.prop || col.type">
|
||||
<!-- 渲染全局序号列 -->
|
||||
<ElTableColumn v-if="col.type === 'globalIndex'" v-bind="{ ...col }">
|
||||
<template #default="{ $index }">
|
||||
<span>{{ getGlobalIndex($index) }}</span>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
<div class="fa-table">
|
||||
<div class="fa-table__main">
|
||||
<VueDraggable
|
||||
class="fa-table__drag-wrap"
|
||||
target="tbody"
|
||||
v-model="dragModel"
|
||||
:animation="150"
|
||||
:disabled="rowDragDisabled"
|
||||
@end="onRowDragEnd"
|
||||
>
|
||||
<ElTable ref="elTableRef" v-loading="!!loading" v-bind="mergedTableProps">
|
||||
<template v-for="col in columns" :key="col.prop || col.type">
|
||||
<!-- 渲染全局序号列 -->
|
||||
<ElTableColumn v-if="col.type === 'globalIndex'" v-bind="{ ...col }">
|
||||
<template #default="{ $index }">
|
||||
<span>{{ getGlobalIndex($index) }}</span>
|
||||
</template>
|
||||
</ElTableColumn>
|
||||
|
||||
<!-- 渲染展开行 -->
|
||||
<ElTableColumn v-else-if="col.type === 'expand'" v-bind="cleanColumnProps(col)">
|
||||
@@ -73,7 +76,7 @@
|
||||
:class="mergedPaginationOptions?.align"
|
||||
ref="paginationRef"
|
||||
>
|
||||
<Pagination
|
||||
<FaPagination
|
||||
v-if="pagination"
|
||||
:page="pagination.current"
|
||||
:limit="pagination.size"
|
||||
@@ -109,12 +112,14 @@ import { storeToRefs } from "pinia";
|
||||
import { ColumnOption } from "@/types";
|
||||
import { useTableStore } from "@stores/modules/table.store";
|
||||
import { useCommon } from "@/hooks/core/useCommon";
|
||||
import { useTableHeight } from "@/hooks/core/useTableHeight";
|
||||
import { useResizeObserver, useWindowSize } from "@vueuse/core";
|
||||
import Pagination from "@/components/Pagination/index.vue";
|
||||
import { useWindowSize } from "@vueuse/core";
|
||||
import FaPagination from "@/components/others/fa-pagination/index.vue";
|
||||
import { VueDraggable } from "vue-draggable-plus";
|
||||
|
||||
defineOptions({ name: "ArtTable" });
|
||||
/** 空状态插画高度(列表页统一常量) */
|
||||
const ART_TABLE_EMPTY_IMAGE_SIZE = 120;
|
||||
|
||||
defineOptions({ name: "FaTable" });
|
||||
|
||||
const { width } = useWindowSize();
|
||||
const elTableRef = ref<InstanceType<typeof ElTable> | null>(null);
|
||||
@@ -152,8 +157,8 @@ interface PaginationOptions {
|
||||
pagerCount?: number;
|
||||
}
|
||||
|
||||
/** ArtTable 组件的 Props 接口 */
|
||||
interface ArtTableProps extends TableProps<Record<string, any>> {
|
||||
/** FaTable 组件的 Props 接口 */
|
||||
interface FaTableProps extends TableProps<Record<string, any>> {
|
||||
/** 加载状态 */
|
||||
loading?: boolean;
|
||||
/** 列渲染配置 */
|
||||
@@ -166,13 +171,13 @@ interface ArtTableProps extends TableProps<Record<string, any>> {
|
||||
emptyHeight?: string;
|
||||
/** 空数据时显示的文本 */
|
||||
emptyText?: string;
|
||||
/** 是否开启 ArtTableHeader,解决表格高度自适应问题 */
|
||||
/** 是否开启 FaTableHeader,解决表格高度自适应问题 */
|
||||
showTableHeader?: boolean;
|
||||
/** 为 true 时关闭行拖拽(忽略工具栏「行拖拽」开关) */
|
||||
disableRowDrag?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<ArtTableProps>(), {
|
||||
const props = withDefaults(defineProps<FaTableProps>(), {
|
||||
columns: () => [],
|
||||
fit: true,
|
||||
showHeader: true,
|
||||
@@ -311,7 +316,7 @@ const mergedTableProps = computed(() => ({
|
||||
border: border.value,
|
||||
size: size.value,
|
||||
headerCellStyle: headerCellStyle.value,
|
||||
// Element Plus 默认值为 true,未显式传入时不应被 ArtTable 覆盖成 false。
|
||||
// Element Plus 默认值为 true,未显式传入时不应被 FaTable 覆盖成 false。
|
||||
selectOnIndeterminate: hasExplicitTableProp("selectOnIndeterminate")
|
||||
? props.selectOnIndeterminate
|
||||
: undefined,
|
||||
@@ -361,7 +366,7 @@ const shouldRenderSlotScope = (slotScope: { $index?: number }) => {
|
||||
/**
|
||||
* ElTableColumn 若存在 default 插槽且插槽产物含任意非 Comment 的 vnode(含空白文本节点),
|
||||
* 将不会执行 formatter(见 element-plus render-helper setColumnRenders)。
|
||||
* ArtTable 中 ElTableColumn 与子节点之间的换行/缩进可能被编译进默认插槽,导致 formatter(如操作列里的按钮)永远不渲染。
|
||||
* FaTable 中 ElTableColumn 与子节点之间的换行/缩进可能被编译进默认插槽,导致 formatter(如操作列里的按钮)永远不渲染。
|
||||
* 对声明了 formatter 且未使用 useSlot 的列,在此显式渲染 formatter 返回值。
|
||||
*/
|
||||
const renderColumnFormatter = (col: ColumnOption, row: Record<string, unknown>) => {
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
class="overflow-hidden transition-[height] duration-300 ease-in-out"
|
||||
:style="{ height: showFestivalStrip ? '48px' : '0' }"
|
||||
>
|
||||
<ArtTextScroll
|
||||
<FaTextScroll
|
||||
v-if="showFestivalStrip"
|
||||
class="!mb-3"
|
||||
type="primary"
|
||||
@@ -23,7 +23,7 @@ import { useSettingsStore } from "@stores/modules/setting.store";
|
||||
import { useCeremony } from "@/hooks/core/useCeremony";
|
||||
import { WEB_LINKS } from "@utils/constants";
|
||||
|
||||
defineOptions({ name: "ArtFestivalTextScroll" });
|
||||
defineOptions({ name: "FaFestivalTextScroll" });
|
||||
|
||||
const settingStore = useSettingsStore();
|
||||
const { showFestivalText } = storeToRefs(settingStore);
|
||||
+14
-14
@@ -7,7 +7,7 @@
|
||||
:style="containerStyle"
|
||||
>
|
||||
<div class="flex-cc absolute left-0 h-full w-9 z-10" :style="{ backgroundColor: bgColor }">
|
||||
<ArtSvgIcon icon="ri:volume-down-line" class="text-lg" />
|
||||
<FaSvgIcon icon="ri:volume-down-line" class="text-lg" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -37,7 +37,7 @@
|
||||
:style="{ backgroundColor: bgColor }"
|
||||
@click="handleClose"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:close-fill" class="text-lg" />
|
||||
<FaSvgIcon icon="ri:close-fill" class="text-lg" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -155,7 +155,7 @@ const themeClasses = computed(() => {
|
||||
// 背景色
|
||||
const bgColor = computed(
|
||||
() =>
|
||||
`color-mix(in oklch, var(--color-${props.type}) ${isDark.value ? "25" : "10"}%, var(--art-color))`
|
||||
`color-mix(in oklch, var(--color-${props.type}) ${isDark.value ? "25" : "10"}%, var(--fa-color))`
|
||||
);
|
||||
|
||||
const containerStyle = computed(() => ({
|
||||
@@ -286,42 +286,42 @@ onBeforeUnmount(() => {
|
||||
|
||||
<!-- <template>
|
||||
<div class="page-content space-y-5">
|
||||
<ArtTextScroll
|
||||
<FaTextScroll
|
||||
text="Art Design Pro 是一款兼具设计美学与高效开发的后台系统 <a target='_blank' href='https://www.artd.pro/docs/'>点击我 </a>访问官方文档"
|
||||
showClose
|
||||
/>
|
||||
|
||||
<ArtTextScroll type="success" text="这是一条成功类型的滚动公告" />
|
||||
<FaTextScroll type="success" text="这是一条成功类型的滚动公告" />
|
||||
|
||||
<ArtTextScroll type="warning" text="这是一条警告类型的滚动公告" />
|
||||
<FaTextScroll type="warning" text="这是一条警告类型的滚动公告" />
|
||||
|
||||
<ArtTextScroll type="danger" text="这是一条危险类型的滚动公告" />
|
||||
<FaTextScroll type="danger" text="这是一条危险类型的滚动公告" />
|
||||
|
||||
<ArtTextScroll type="info" text="这是一条信息类型的滚动公告" />
|
||||
<FaTextScroll type="info" text="这是一条信息类型的滚动公告" />
|
||||
|
||||
<ArtTextScroll text="这是一条可关闭的滚动公告" @close="handleClose" />
|
||||
<FaTextScroll text="这是一条可关闭的滚动公告" @close="handleClose" />
|
||||
|
||||
<ArtTextScroll
|
||||
<FaTextScroll
|
||||
type="warning"
|
||||
text="这是一条速度较慢、向右滚动的公告"
|
||||
:speed="30"
|
||||
direction="right"
|
||||
/>
|
||||
|
||||
<ArtTextScroll
|
||||
<FaTextScroll
|
||||
text="这是一条文字溢出才会滚动的公告,当文本内容超出容器宽度时才会开始滚动显示,否则保持静止状态"
|
||||
@close="handleClose"
|
||||
:alwaysScroll="false"
|
||||
/>
|
||||
|
||||
<ArtTextScroll type="danger" direction="up" :speed="30" text="这是一条向上滚动的公告" />
|
||||
<FaTextScroll type="danger" direction="up" :speed="30" text="这是一条向上滚动的公告" />
|
||||
|
||||
<ArtTextScroll type="info" direction="down" :speed="30" text="这是一条向下滚动的公告" />
|
||||
<FaTextScroll type="info" direction="down" :speed="30" text="这是一条向下滚动的公告" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "WidgetsTextScroll" });
|
||||
defineOptions({ name: "FaTextScroll" });
|
||||
|
||||
|
||||
const handleClose = () => {
|
||||
+2
-1
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="page-content !border-0 !bg-transparent min-h-screen flex-cc">
|
||||
<div class="flex-cc max-md:!block max-md:text-center">
|
||||
<ThemeSvg :src="data.imgUrl" size="100%" class="!w-100" />
|
||||
<FaThemeSvg :src="data.imgUrl" size="100%" class="!w-100" />
|
||||
<div class="ml-15 w-75 max-md:mx-auto max-md:mt-10 max-md:w-full max-md:text-center">
|
||||
<p class="text-xl leading-7 text-g-600 max-md:text-lg">{{ data.desc }}</p>
|
||||
<ElButton type="primary" size="large" @click="backHome" v-ripple class="mt-5">
|
||||
@@ -15,6 +15,7 @@
|
||||
<script setup lang="ts">
|
||||
import { useCommon } from "@/hooks/core/useCommon";
|
||||
import { useUserStore } from "@stores/modules/user.store";
|
||||
import FaThemeSvg from "@/components/theme/fa-theme-svg/index.vue";
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
+15
-23
@@ -4,7 +4,7 @@
|
||||
class="auth-top-bar pointer-events-none fixed left-0 right-0 top-0 z-[100] flex items-center justify-between gap-3 bg-transparent px-5 py-[1.125rem] md:gap-4 md:px-10"
|
||||
>
|
||||
<div class="pointer-events-auto flex min-w-0 flex-1 items-center gap-3">
|
||||
<ArtLogo class="icon shrink-0" size="46" :src="webLogoSrc" />
|
||||
<FaLogo class="icon shrink-0" size="46" :src="webLogoSrc" />
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<h1 class="auth-top-bar__site-title">{{ siteTitle }}</h1>
|
||||
@@ -30,17 +30,13 @@
|
||||
:style="{ background: _color, '--index': index }"
|
||||
@click="changeThemeColor(_color)"
|
||||
>
|
||||
<ArtSvgIcon
|
||||
v-if="_color === systemThemeColor"
|
||||
icon="ri:check-fill"
|
||||
class="text-white"
|
||||
/>
|
||||
<FaSvgIcon v-if="_color === systemThemeColor" icon="ri:check-fill" class="text-white" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="btn palette-btn auth-top-bar__action relative z-[2] h-8 w-8 c-p flex-cc tad-300"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:palette-line" class="text-xl transition-colors duration-300" />
|
||||
<FaSvgIcon icon="ri:palette-line" class="text-xl transition-colors duration-300" />
|
||||
</div>
|
||||
</div>
|
||||
<ElDropdown
|
||||
@@ -52,7 +48,7 @@
|
||||
class="btn layout-align-btn auth-top-bar__action h-8 w-8 c-p flex-cc tad-300"
|
||||
:title="$t('login.panelAlign.label')"
|
||||
>
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
:icon="panelAlignTriggerIcon"
|
||||
class="text-xl text-g-800 transition-colors duration-300"
|
||||
/>
|
||||
@@ -64,13 +60,9 @@
|
||||
:command="opt.value"
|
||||
:class="{ 'is-selected': panelAlign === opt.value }"
|
||||
>
|
||||
<ArtSvgIcon :icon="opt.icon" class="mr-2 text-base" />
|
||||
<FaSvgIcon :icon="opt.icon" class="mr-2 text-base" />
|
||||
<span class="menu-txt">{{ $t(opt.labelKey) }}</span>
|
||||
<ArtSvgIcon
|
||||
icon="ri:check-fill"
|
||||
class="text-base"
|
||||
v-if="panelAlign === opt.value"
|
||||
/>
|
||||
<FaSvgIcon icon="ri:check-fill" class="text-base" v-if="panelAlign === opt.value" />
|
||||
</ElDropdownItem>
|
||||
</div>
|
||||
</ElDropdownMenu>
|
||||
@@ -82,7 +74,7 @@
|
||||
popper-class="langDropDownStyle"
|
||||
>
|
||||
<div class="btn language-btn auth-top-bar__action h-8 w-8 c-p flex-cc tad-300">
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
icon="ri:translate-2"
|
||||
class="text-[19px] text-g-800 transition-colors duration-300"
|
||||
/>
|
||||
@@ -95,7 +87,7 @@
|
||||
:class="{ 'is-selected': locale === lang.value }"
|
||||
>
|
||||
<span class="menu-txt">{{ lang.label }}</span>
|
||||
<ArtSvgIcon icon="ri:check-fill" class="text-base" v-if="locale === lang.value" />
|
||||
<FaSvgIcon icon="ri:check-fill" class="text-base" v-if="locale === lang.value" />
|
||||
</ElDropdownItem>
|
||||
</div>
|
||||
</ElDropdownMenu>
|
||||
@@ -106,7 +98,7 @@
|
||||
class="btn theme-btn auth-top-bar__action h-8 w-8 c-p flex-cc tad-300"
|
||||
@click="themeAnimation"
|
||||
>
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
:icon="isDark ? 'ri:sun-fill' : 'ri:moon-line'"
|
||||
class="text-xl text-g-800 transition-colors duration-300"
|
||||
/>
|
||||
@@ -260,7 +252,7 @@ const changeThemeColor = (color: string) => {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.auth-top-bar__action:hover :deep(.art-svg-icon) {
|
||||
.auth-top-bar__action:hover :deep(.fa-svg-icon) {
|
||||
color: var(--el-color-primary);
|
||||
}
|
||||
|
||||
@@ -277,7 +269,7 @@ const changeThemeColor = (color: string) => {
|
||||
|
||||
.color-dots {
|
||||
pointer-events: none;
|
||||
box-shadow: 0 2px 12px var(--art-gray-300);
|
||||
box-shadow: 0 2px 12px var(--fa-gray-300);
|
||||
backdrop-filter: blur(10px);
|
||||
transform: translateX(10px);
|
||||
transition:
|
||||
@@ -313,20 +305,20 @@ const changeThemeColor = (color: string) => {
|
||||
}
|
||||
|
||||
.dark .color-dots {
|
||||
background-color: var(--art-gray-200);
|
||||
background-color: var(--fa-gray-200);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
/* 调色盘:图标颜色与当前主题主色一致(含单独悬浮、整块调色区悬浮) */
|
||||
.palette-btn :deep(.art-svg-icon) {
|
||||
.palette-btn :deep(.fa-svg-icon) {
|
||||
color: v-bind("themeColorForCss");
|
||||
}
|
||||
|
||||
.auth-top-bar__action.palette-btn:hover :deep(.art-svg-icon) {
|
||||
.auth-top-bar__action.palette-btn:hover :deep(.fa-svg-icon) {
|
||||
color: v-bind("themeColorForCss");
|
||||
}
|
||||
|
||||
.color-picker-expandable:hover .palette-btn :deep(.art-svg-icon) {
|
||||
.color-picker-expandable:hover .palette-btn :deep(.fa-svg-icon) {
|
||||
color: v-bind("themeColorForCss");
|
||||
}
|
||||
</style>
|
||||
+2
-1
@@ -7,13 +7,14 @@
|
||||
>
|
||||
<div class="login-center-backdrop__bg" />
|
||||
<div class="login-center-backdrop__hero-wrap">
|
||||
<ThemeSvg :src="loginIcon" size="100%" class="login-center-backdrop__hero" />
|
||||
<FaThemeSvg :src="loginIcon" size="100%" class="login-center-backdrop__hero" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import loginIcon from "@imgs/svg/login_icon.svg";
|
||||
import FaThemeSvg from "@/components/theme/fa-theme-svg/index.vue";
|
||||
|
||||
defineOptions({ name: "LoginCenterBackdrop" });
|
||||
|
||||
+6
-5
@@ -2,7 +2,7 @@
|
||||
<template>
|
||||
<div class="login-left-view">
|
||||
<div v-if="!hideTopBranding" class="logo">
|
||||
<ArtLogo class="icon" size="46" :src="webLogoSrc" />
|
||||
<FaLogo class="icon" size="46" :src="webLogoSrc" />
|
||||
<div class="logo-title-wrap">
|
||||
<div class="logo-title-inline">
|
||||
<h1 class="title">{{ siteTitle }}</h1>
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
|
||||
<div class="left-img">
|
||||
<ThemeSvg :src="loginIcon" size="100%" />
|
||||
<FaThemeSvg :src="loginIcon" size="100%" />
|
||||
</div>
|
||||
|
||||
<div class="text-wrap">
|
||||
@@ -82,6 +82,7 @@ import AppConfig from "@/config";
|
||||
import loginIcon from "@imgs/svg/login_icon.svg";
|
||||
import { useConfigStore } from "@stores/modules/config.store";
|
||||
import { themeAnimation } from "@utils/ui";
|
||||
import FaThemeSvg from "@/components/theme/fa-theme-svg/index.vue";
|
||||
|
||||
defineProps<{
|
||||
hideContent?: boolean;
|
||||
@@ -91,7 +92,7 @@ defineProps<{
|
||||
|
||||
const configStore = useConfigStore();
|
||||
|
||||
/** 接口 sys_web_logo,空则 ArtLogo 内置默认图 */
|
||||
/** 接口 sys_web_logo,空则 FaLogo 内置默认图 */
|
||||
const webLogoSrc = computed(
|
||||
() => configStore.configData.sys_web_logo?.config_value?.trim() || undefined
|
||||
);
|
||||
@@ -206,13 +207,13 @@ $bg-mix-light-7: color-mix(in srgb, $primary-light-7 80%, $main-bg);
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
color: var(--art-gray-900) !important;
|
||||
color: var(--fa-gray-900) !important;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 10px;
|
||||
font-size: 14px;
|
||||
color: var(--art-gray-600) !important;
|
||||
color: var(--fa-gray-600) !important;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-2
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="page-content box-border !px-20 py-3.5 text-center max-md:!px-5" :class="type">
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
class="icon size-22 p-2 mt-16 block rounded-full !text-white"
|
||||
:icon="iconCode"
|
||||
:class="type === 'success' ? 'bg-[#19BE6B]' : 'bg-[#ED4014]'"
|
||||
@@ -21,7 +21,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineOptions({ name: "ArtResultPage" });
|
||||
defineOptions({ name: "FaResultPage" });
|
||||
|
||||
// 显式声明插槽类型
|
||||
defineSlots<{
|
||||
default?: () => void;
|
||||
content?: () => void;
|
||||
buttons?: () => void;
|
||||
}>();
|
||||
|
||||
interface ResultPageProps {
|
||||
/** 成功/失败 */
|
||||
+2
-2
@@ -4,13 +4,13 @@
|
||||
class="size-8.5 inline-flex flex-cc c-p text-g-600 dark:text-g-800 text-xl rounded tad-300 hover:bg-hover-color"
|
||||
:class="{ 'rounded-full': circle }"
|
||||
>
|
||||
<ArtSvgIcon :icon="icon"></ArtSvgIcon>
|
||||
<FaSvgIcon :icon="icon"></FaSvgIcon>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
defineOptions({ name: "ArtIconButton" });
|
||||
defineOptions({ name: "FaIconButton" });
|
||||
|
||||
interface Props {
|
||||
/** 图标名称 */
|
||||
@@ -88,7 +88,7 @@ const appConfig: SystemConfig = {
|
||||
{
|
||||
theme: MenuThemeEnum.DESIGN,
|
||||
background: "#FFFFFF",
|
||||
systemNameColor: "var(--art-gray-800)",
|
||||
systemNameColor: "var(--fa-gray-800)",
|
||||
iconColor: "#6B6B6B",
|
||||
textColor: "#29343D",
|
||||
img: configImages.menuStyles.design,
|
||||
@@ -104,7 +104,7 @@ const appConfig: SystemConfig = {
|
||||
{
|
||||
theme: MenuThemeEnum.LIGHT,
|
||||
background: "#ffffff",
|
||||
systemNameColor: "var(--art-gray-800)",
|
||||
systemNameColor: "var(--fa-gray-800)",
|
||||
iconColor: "#6B6B6B",
|
||||
textColor: "#29343D",
|
||||
img: configImages.menuStyles.light,
|
||||
|
||||
@@ -24,39 +24,37 @@ export const globalComponentsConfig: GlobalComponentConfig[] = [
|
||||
{
|
||||
name: "设置面板",
|
||||
key: "settings-panel",
|
||||
component: defineAsyncComponent(() => import("@/layouts/art-settings-panel/index.vue")),
|
||||
component: defineAsyncComponent(() => import("@/layouts/fa-settings-panel/index.vue")),
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
name: "全局搜索",
|
||||
key: "global-search",
|
||||
component: defineAsyncComponent(() => import("@/layouts/art-global-search/index.vue")),
|
||||
component: defineAsyncComponent(() => import("@/layouts/fa-global-search/index.vue")),
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
name: "锁屏",
|
||||
key: "screen-lock",
|
||||
component: defineAsyncComponent(() => import("@/layouts/art-screen-lock/index.vue")),
|
||||
component: defineAsyncComponent(() => import("@/layouts/fa-screen-lock/index.vue")),
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
name: "聊天窗口",
|
||||
key: "chat-window",
|
||||
component: defineAsyncComponent(() => import("@/layouts/art-chat-window/index.vue")),
|
||||
component: defineAsyncComponent(() => import("@/layouts/fa-chat-window/index.vue")),
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
name: "礼花效果",
|
||||
key: "fireworks-effect",
|
||||
component: defineAsyncComponent(() => import("@/layouts/art-fireworks-effect/index.vue")),
|
||||
component: defineAsyncComponent(() => import("@/layouts/fa-fireworks-effect/index.vue")),
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
name: "水印效果",
|
||||
key: "watermark",
|
||||
component: defineAsyncComponent(
|
||||
() => import("@/components/Core/others/art-watermark/index.vue")
|
||||
),
|
||||
component: defineAsyncComponent(() => import("@/components/others/fa-watermark/index.vue")),
|
||||
enabled: true,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -13,7 +13,7 @@ const fastEnterConfig: FastEnterConfig = {
|
||||
{
|
||||
name: "工作台",
|
||||
description: "系统概览与数据统计",
|
||||
icon: "ri:pie-chart-line",
|
||||
icon: "ri:pie-chfa-line",
|
||||
iconColor: "#377dff",
|
||||
enabled: true,
|
||||
order: 1,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
* - `image` 为红包碎屑 hb、雪花 sd、礼花筒 yd 等时,须在下方 import,勿手写路径字符串。
|
||||
* - 全局快捷键:**Ctrl + Shift + P**(Windows / Linux)或 **⌘ + Shift + P**(macOS)立即触发一发礼花;
|
||||
* 若当天命中某条「带礼花」的节日配置则使用该配置的 `image`,否则为几何礼花。
|
||||
* - 实现:`src/layouts/art-fireworks-effect/index.vue`(键盘)、`src/hooks/core/useCeremony.ts`(自动连发)。
|
||||
* - 实现:`src/layouts/fa-fireworks-effect/index.vue`(键盘)、`src/hooks/core/useCeremony.ts`(自动连发)。
|
||||
*
|
||||
* ## 自动公历节日
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* ## 注意事项
|
||||
*
|
||||
* 1. 修改此文件的配置项时,需要同步更新以下文件:
|
||||
* - src/layouts/art-settings-panel/widget/SettingActions.vue(复制配置和重置配置逻辑)
|
||||
* - src/layouts/fa-settings-panel/widget/SettingActions.vue(复制配置和重置配置逻辑)
|
||||
* - src/store/modules/setting.ts(Store 状态定义)
|
||||
* 2. 可以通过设置面板的"复制配置"按钮快速生成配置代码
|
||||
* 3. 枚举类型的值需要与 src/enums/appEnum.ts 中的定义保持一致
|
||||
|
||||
@@ -54,7 +54,7 @@ export const useAuth = () => {
|
||||
: [];
|
||||
|
||||
/**
|
||||
* 检查是否拥有某权限标识(与 v-hasPerm / 表格内 ArtButtonMore 全码一致)
|
||||
* 检查是否拥有某权限标识(与 v-hasPerm / 表格内 FaButtonMore 全码一致)
|
||||
* @param auth 权限标识(多为后端菜单 permission 全码,如 module_system:role:update)
|
||||
*/
|
||||
const hasAuth = (auth: string): boolean => {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
*
|
||||
* ## 手动礼花快捷键
|
||||
*
|
||||
* 全局 **Ctrl+Shift+P** / **⌘+Shift+P** 由 `art-fireworks-effect` 监听;礼花图与当天节日配置一致,
|
||||
* 全局 **Ctrl+Shift+P** / **⌘+Shift+P** 由 `fa-fireworks-effect` 监听;礼花图与当天节日配置一致,
|
||||
* 详见 `src/config/modules/festival.ts` 文件头说明。
|
||||
*
|
||||
* ## 使用示例
|
||||
|
||||
@@ -29,10 +29,7 @@ export function useCommon() {
|
||||
*/
|
||||
const homePath = computed(() => menuStore.getHomePath());
|
||||
|
||||
/**
|
||||
* 刷新当前页面
|
||||
* 通过切换 setting store 中的 refresh 状态触发页面重新渲染
|
||||
*/
|
||||
/** 触发 `FaPageContent` 级重建(与布局 settings 联动) */
|
||||
const refresh = () => {
|
||||
settingStore.reload();
|
||||
};
|
||||
|
||||
@@ -82,7 +82,7 @@ export function useHeaderBar() {
|
||||
return isFeatureEnabled("breadcrumb") && showCrumbs.value;
|
||||
});
|
||||
|
||||
// 全局搜索:新版 ArtGlobalSearch 体验更好,显示条件 = 配置开启 ∧ 旧版「菜单搜索」开关
|
||||
// 全局搜索:新版 FaGlobalSearch 体验更好,显示条件 = 配置开启 ∧ 旧版「菜单搜索」开关
|
||||
const shouldShowGlobalSearch = computed(() => {
|
||||
return isFeatureEnabled("globalSearch") && showMenuSearch.value;
|
||||
});
|
||||
|
||||
@@ -27,12 +27,12 @@ interface LayoutHeightOptions {
|
||||
extraSpacing?: number;
|
||||
/** 是否自动更新 CSS 变量(默认 true) */
|
||||
updateCssVar?: boolean;
|
||||
/** CSS 变量名称(默认 '--art-full-height') */
|
||||
/** CSS 变量名称(默认 '--fa-full-height') */
|
||||
cssVarName?: string;
|
||||
}
|
||||
|
||||
export function useLayoutHeight(options: LayoutHeightOptions = {}) {
|
||||
const { extraSpacing = 15, updateCssVar = true, cssVarName = "--art-full-height" } = options;
|
||||
const { extraSpacing = 15, updateCssVar = true, cssVarName = "--fa-full-height" } = options;
|
||||
|
||||
// 元素引用
|
||||
const headerRef = ref<HTMLElement>();
|
||||
@@ -87,7 +87,7 @@ export function useAutoLayoutHeight(
|
||||
headerIds: string[] = ["app-header", "app-content-header"],
|
||||
options: LayoutHeightOptions = {}
|
||||
) {
|
||||
const { extraSpacing = 15, updateCssVar = true, cssVarName = "--art-full-height" } = options;
|
||||
const { extraSpacing = 15, updateCssVar = true, cssVarName = "--fa-full-height" } = options;
|
||||
|
||||
// 创建元素引用
|
||||
const headerRef = ref<HTMLElement>();
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ import { useRouter, useRoute } from "vue-router";
|
||||
import type { RouteLocationMatched, RouteRecordRaw } from "vue-router";
|
||||
import { formatMenuTitle } from "@utils/navigation";
|
||||
|
||||
defineOptions({ name: "ArtBreadcrumb" });
|
||||
defineOptions({ name: "FaBreadcrumb" });
|
||||
|
||||
export interface BreadcrumbItem {
|
||||
path: string;
|
||||
+3
-3
@@ -78,8 +78,8 @@
|
||||
</ElInput>
|
||||
<div class="mt-3 flex-cb">
|
||||
<div class="flex-c">
|
||||
<ArtSvgIcon icon="ri:image-line" class="mr-5 c-p text-g-600 text-lg" />
|
||||
<ArtSvgIcon icon="ri:emotion-happy-line" class="mr-5 c-p text-g-600 text-lg" />
|
||||
<FaSvgIcon icon="ri:image-line" class="mr-5 c-p text-g-600 text-lg" />
|
||||
<FaSvgIcon icon="ri:emotion-happy-line" class="mr-5 c-p text-g-600 text-lg" />
|
||||
</div>
|
||||
<ElButton type="primary" @click="sendMessage" v-ripple class="min-w-20">发送</ElButton>
|
||||
</div>
|
||||
@@ -95,7 +95,7 @@ import { mittBus } from "@utils/sys";
|
||||
import meAvatar from "@imgs/avatar/avatar5.webp";
|
||||
import aiAvatar from "@imgs/avatar/avatar10.webp";
|
||||
|
||||
defineOptions({ name: "ArtChatWindow" });
|
||||
defineOptions({ name: "FaChatWindow" });
|
||||
|
||||
// 类型定义
|
||||
interface ChatMessage {
|
||||
+2
-2
@@ -30,7 +30,7 @@
|
||||
@click="handleApplicationClick(application)"
|
||||
>
|
||||
<div class="app-icon size-12 flex-cc rounded-lg bg-g-200/80 dark:bg-g-300/30">
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
class="text-xl"
|
||||
:icon="application.icon"
|
||||
:style="{ color: application.iconColor }"
|
||||
@@ -65,7 +65,7 @@
|
||||
import { useFastEnter } from "@/hooks/core/useFastEnter";
|
||||
import type { FastEnterApplication, FastEnterQuickLink } from "@/types/config";
|
||||
|
||||
defineOptions({ name: "ArtFastEnter" });
|
||||
defineOptions({ name: "FaFastEnter" });
|
||||
|
||||
const router = useRouter();
|
||||
const popoverRef = ref();
|
||||
+1
-1
@@ -17,7 +17,7 @@ import bp from "@imgs/ceremony/hb.png";
|
||||
import sd from "@imgs/ceremony/sd.png";
|
||||
import yd from "@imgs/ceremony/yd.png";
|
||||
|
||||
defineOptions({ name: "ArtFireworksEffect" });
|
||||
defineOptions({ name: "FaFireworksEffect" });
|
||||
|
||||
const { currentFestivalData } = useCeremony();
|
||||
|
||||
+1
-1
@@ -9,6 +9,6 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getEnabledGlobalComponents } from "@/config/modules/component";
|
||||
defineOptions({ name: "ArtGlobalComponent" });
|
||||
defineOptions({ name: "FaGlobalComponent" });
|
||||
const enabledComponents = computed(() => getEnabledGlobalComponents());
|
||||
</script>
|
||||
+9
-9
@@ -22,7 +22,7 @@
|
||||
<div
|
||||
class="h-4.5 flex-cc rounded border border-g-300 dark:!bg-g-200/50 !bg-box px-1.5 text-g-500"
|
||||
>
|
||||
<ArtSvgIcon icon="fluent:arrow-enter-left-20-filled" />
|
||||
<FaSvgIcon icon="fluent:arrow-enter-left-20-filled" />
|
||||
</div>
|
||||
</template>
|
||||
</ElInput>
|
||||
@@ -40,7 +40,7 @@
|
||||
@mouseenter="highlightOnHover(index)"
|
||||
>
|
||||
{{ formatMenuTitle(item.meta.title) }}
|
||||
<ArtSvgIcon v-show="isHighlighted(index)" icon="fluent:arrow-enter-left-20-filled" />
|
||||
<FaSvgIcon v-show="isHighlighted(index)" icon="fluent:arrow-enter-left-20-filled" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -65,7 +65,7 @@
|
||||
class="size-5 selected-icon select-none rounded-full text-g-500 flex-cc c-p"
|
||||
@click.stop="deleteHistory(index)"
|
||||
>
|
||||
<ArtSvgIcon icon="ri:close-large-fill" class="text-xs" />
|
||||
<FaSvgIcon icon="ri:close-large-fill" class="text-xs" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,12 +75,12 @@
|
||||
<template #footer>
|
||||
<div class="dialog-footer box-border flex-c border-t-d pt-4.5 pb-1">
|
||||
<div class="flex-cc">
|
||||
<ArtSvgIcon icon="fluent:arrow-enter-left-20-filled" class="keyboard" />
|
||||
<FaSvgIcon icon="fluent:arrow-enter-left-20-filled" class="keyboard" />
|
||||
<span class="mr-3.5 text-xs text-g-700">{{ $t("search.selectKeydown") }}</span>
|
||||
</div>
|
||||
<div class="flex-c">
|
||||
<ArtSvgIcon icon="ri:arrow-up-wide-fill" class="keyboard" />
|
||||
<ArtSvgIcon icon="ri:arrow-down-wide-fill" class="keyboard" />
|
||||
<FaSvgIcon icon="ri:arrow-up-wide-fill" class="keyboard" />
|
||||
<FaSvgIcon icon="ri:arrow-down-wide-fill" class="keyboard" />
|
||||
<span class="mr-3.5 text-xs text-g-700">{{ $t("search.switchKeydown") }}</span>
|
||||
</div>
|
||||
<div class="flex-c">
|
||||
@@ -103,7 +103,7 @@ import { formatMenuTitle } from "@utils/navigation";
|
||||
import { handleMenuJump } from "@utils/navigation";
|
||||
import { type ScrollbarInstance } from "element-plus";
|
||||
|
||||
defineOptions({ name: "ArtGlobalSearch" });
|
||||
defineOptions({ name: "FaGlobalSearch" });
|
||||
|
||||
const userStore = useUserStore();
|
||||
const { menuList } = storeToRefs(useMenuStore());
|
||||
@@ -381,14 +381,14 @@ const highlightOnHoverHistory = (index: number) => {
|
||||
|
||||
.el-input {
|
||||
:deep(.el-input__wrapper) {
|
||||
background-color: var(--art-gray-200);
|
||||
background-color: var(--fa-gray-200);
|
||||
border: 1px solid var(--default-border-dashed);
|
||||
border-radius: calc(var(--custom-radius) / 2 + 2px) !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
:deep(.el-input__inner) {
|
||||
color: var(--art-gray-800) !important;
|
||||
color: var(--fa-gray-800) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
-39
@@ -12,18 +12,18 @@
|
||||
class="relative box-border flex-b h-15 leading-15 select-none"
|
||||
:class="[
|
||||
tabStyle === 'tab-card' || tabStyle === 'tab-google' || tabStyle === 'tab-default'
|
||||
? 'border-b border-[var(--art-card-border)]'
|
||||
? 'border-b border-[var(--fa-card-border)]'
|
||||
: '',
|
||||
]"
|
||||
>
|
||||
<div class="flex-c flex-1 min-w-0 leading-15" style="display: flex">
|
||||
<!-- 系统信息:Logo + 标题一并受「显示应用 Logo」控制 -->
|
||||
<div class="flex-c c-p" @click="toHome" v-if="isTopMenu && showAppLogo">
|
||||
<ArtLogo class="pl-4.5" :src="headerLogoSrc" />
|
||||
<FaLogo class="pl-4.5" :src="headerLogoSrc" />
|
||||
<p v-if="width >= 1400" class="my-0 mx-2 ml-2 text-lg">{{ headerSystemName }}</p>
|
||||
</div>
|
||||
|
||||
<ArtLogo
|
||||
<FaLogo
|
||||
v-if="showAppLogo"
|
||||
class="!hidden pl-3.5 overflow-hidden align-[-0.15em] fill-current"
|
||||
:src="headerLogoSrc"
|
||||
@@ -31,7 +31,7 @@
|
||||
/>
|
||||
|
||||
<!-- 菜单按钮 -->
|
||||
<ArtIconButton
|
||||
<FaIconButton
|
||||
v-if="isLeftMenu && shouldShowMenuButton"
|
||||
icon="ri:menu-2-fill"
|
||||
class="ml-3 max-sm:ml-[7px]"
|
||||
@@ -39,7 +39,7 @@
|
||||
/>
|
||||
|
||||
<!-- 刷新按钮 -->
|
||||
<ArtIconButton
|
||||
<FaIconButton
|
||||
v-if="shouldShowRefreshButton"
|
||||
icon="ri:refresh-line"
|
||||
class="!ml-3 refresh-btn max-sm:!hidden"
|
||||
@@ -48,20 +48,20 @@
|
||||
/>
|
||||
|
||||
<!-- 快速入口 -->
|
||||
<ArtFastEnter v-if="shouldShowFastEnter && width >= headerBarFastEnterMinWidth">
|
||||
<ArtIconButton icon="ri:function-line" class="ml-3" />
|
||||
</ArtFastEnter>
|
||||
<FaFastEnter v-if="shouldShowFastEnter && width >= headerBarFastEnterMinWidth">
|
||||
<FaIconButton icon="ri:function-line" class="ml-3" />
|
||||
</FaFastEnter>
|
||||
|
||||
<!-- 面包屑 -->
|
||||
<ArtBreadcrumb
|
||||
<FaBreadcrumb
|
||||
v-if="(shouldShowBreadcrumb && isLeftMenu) || (shouldShowBreadcrumb && isDualMenu)"
|
||||
/>
|
||||
|
||||
<!-- 顶部菜单 -->
|
||||
<ArtHorizontalMenu v-if="isTopMenu" :list="menuList" />
|
||||
<FaHorizontalMenu v-if="isTopMenu" :list="menuList" />
|
||||
|
||||
<!-- 混合菜单-顶部 -->
|
||||
<ArtMixedMenu v-if="isTopLeftMenu" :list="menuList" />
|
||||
<FaMixedMenu v-if="isTopLeftMenu" :list="menuList" />
|
||||
</div>
|
||||
|
||||
<div id="app-header-toolbar" class="flex-c gap-2.5">
|
||||
@@ -72,18 +72,18 @@
|
||||
@click="openSearchDialog"
|
||||
>
|
||||
<div class="flex-c">
|
||||
<ArtSvgIcon icon="ri:search-line" class="text-sm text-g-500" />
|
||||
<FaSvgIcon icon="ri:search-line" class="text-sm text-g-500" />
|
||||
<span class="ml-1 text-xs font-normal text-g-500">{{ $t("topBar.search.title") }}</span>
|
||||
</div>
|
||||
<div class="flex-c h-5 px-1.5 text-g-500/80 border border-g-400 rounded">
|
||||
<ArtSvgIcon v-if="isWindows" icon="vaadin:ctrl-a" class="text-sm" />
|
||||
<ArtSvgIcon v-else icon="ri:command-fill" class="text-xs" />
|
||||
<FaSvgIcon v-if="isWindows" icon="vaadin:ctrl-a" class="text-sm" />
|
||||
<FaSvgIcon v-else icon="ri:command-fill" class="text-xs" />
|
||||
<span class="ml-0.5 text-xs">k</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 全屏按钮 -->
|
||||
<ArtIconButton
|
||||
<FaIconButton
|
||||
v-if="shouldShowFullscreen"
|
||||
:icon="isFullscreen ? 'ri:fullscreen-exit-line' : 'ri:fullscreen-fill'"
|
||||
:class="[!isFullscreen ? 'full-screen-btn' : 'exit-full-screen-btn', 'ml-3']"
|
||||
@@ -93,7 +93,7 @@
|
||||
|
||||
<!-- 组件尺寸 default/large/small(沿用旧版持久化开关 showSizeSelect) -->
|
||||
<div v-if="shouldShowSizeSelect" class="flex-cc ml-1 max-md:!hidden">
|
||||
<SizeSelect />
|
||||
<FaSizeSelect />
|
||||
</div>
|
||||
|
||||
<!-- 国际化按钮 -->
|
||||
@@ -102,7 +102,7 @@
|
||||
popper-class="langDropDownStyle"
|
||||
v-if="shouldShowLanguage"
|
||||
>
|
||||
<ArtIconButton icon="ri:translate-2" class="language-btn text-[19px]" />
|
||||
<FaIconButton icon="ri:translate-2" class="language-btn text-[19px]" />
|
||||
<template #dropdown>
|
||||
<ElDropdownMenu>
|
||||
<div v-for="item in languageOptions" :key="item.value" class="lang-btn-item">
|
||||
@@ -111,7 +111,7 @@
|
||||
:class="{ 'is-selected': locale === item.value }"
|
||||
>
|
||||
<span class="menu-txt">{{ item.label }}</span>
|
||||
<ArtSvgIcon icon="ri:check-fill" v-if="locale === item.value" />
|
||||
<FaSvgIcon icon="ri:check-fill" v-if="locale === item.value" />
|
||||
</ElDropdownItem>
|
||||
</div>
|
||||
</ElDropdownMenu>
|
||||
@@ -119,31 +119,31 @@
|
||||
</ElDropdown>
|
||||
|
||||
<!-- 通知按钮 -->
|
||||
<ArtIconButton
|
||||
<FaIconButton
|
||||
v-if="shouldShowNotification"
|
||||
icon="ri:notification-2-line"
|
||||
class="notice-button relative"
|
||||
@click="visibleNotice"
|
||||
>
|
||||
<div class="absolute top-2 right-2 size-1.5 !bg-danger rounded-full"></div>
|
||||
</ArtIconButton>
|
||||
</FaIconButton>
|
||||
|
||||
<!-- 聊天按钮 -->
|
||||
<ArtIconButton
|
||||
<FaIconButton
|
||||
v-if="shouldShowChat"
|
||||
icon="ri:message-3-line"
|
||||
class="chat-button relative"
|
||||
@click="openChat"
|
||||
>
|
||||
<div class="breathing-dot absolute top-2 right-2 size-1.5 !bg-success rounded-full"></div>
|
||||
</ArtIconButton>
|
||||
</FaIconButton>
|
||||
|
||||
<!-- 设置按钮 -->
|
||||
<div v-if="shouldShowSettings">
|
||||
<ElPopover :visible="showSettingGuide" placement="bottom-start" :width="190" :offset="0">
|
||||
<template #reference>
|
||||
<div class="flex-cc">
|
||||
<ArtIconButton icon="ri:settings-line" class="setting-btn" @click="openSetting" />
|
||||
<FaIconButton icon="ri:settings-line" class="setting-btn" @click="openSetting" />
|
||||
</div>
|
||||
</template>
|
||||
<template #default>
|
||||
@@ -159,22 +159,22 @@
|
||||
</div>
|
||||
|
||||
<!-- 主题切换按钮 -->
|
||||
<ArtIconButton
|
||||
<FaIconButton
|
||||
v-if="shouldShowThemeToggle"
|
||||
@click="themeAnimation"
|
||||
:icon="isDark ? 'ri:sun-fill' : 'ri:moon-line'"
|
||||
/>
|
||||
|
||||
<!-- 用户头像、菜单 -->
|
||||
<ArtUserMenu />
|
||||
<FaUserMenu />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 标签页 -->
|
||||
<ArtWorkTab />
|
||||
<FaWorkTab />
|
||||
|
||||
<!-- 通知 -->
|
||||
<ArtNotification v-model:value="showNotice" ref="notice" />
|
||||
<FaNotification v-model:value="showNotice" ref="notice" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -193,10 +193,10 @@ import { mittBus } from "@utils/sys";
|
||||
import { themeAnimation } from "@utils/ui";
|
||||
import { useCommon } from "@/hooks/core/useCommon";
|
||||
import { useHeaderBar } from "@/hooks/core/useHeaderBar";
|
||||
import ArtUserMenu from "./widget/ArtUserMenu.vue";
|
||||
import SizeSelect from "@/components/SizeSelect/index.vue";
|
||||
import FaUserMenu from "./widget/FaUserMenu.vue";
|
||||
import FaSizeSelect from "@/components/others/fa-size-select/index.vue";
|
||||
|
||||
defineOptions({ name: "ArtHeaderBar" });
|
||||
defineOptions({ name: "FaHeaderBar" });
|
||||
|
||||
// 检测操作系统类型
|
||||
const isWindows = navigator.userAgent.includes("Windows");
|
||||
@@ -347,7 +347,7 @@ const bodyCloseNotice = (e: any): void => {
|
||||
|
||||
// 检查是否点击了通知按钮或通知面板内部
|
||||
const isNoticeButton = target.closest(".notice-button");
|
||||
const isNoticePanel = target.closest(".art-notification-panel");
|
||||
const isNoticePanel = target.closest(".fa-notification-panel");
|
||||
|
||||
if (!isNoticeButton && !isNoticePanel) {
|
||||
showNotice.value = false;
|
||||
@@ -463,35 +463,35 @@ const openChat = (): void => {
|
||||
}
|
||||
|
||||
/* Hover animation classes */
|
||||
.refresh-btn:hover :deep(.art-svg-icon) {
|
||||
.refresh-btn:hover :deep(.fa-svg-icon) {
|
||||
animation: rotate180 0.5s;
|
||||
}
|
||||
|
||||
.language-btn:hover :deep(.art-svg-icon) {
|
||||
.language-btn:hover :deep(.fa-svg-icon) {
|
||||
animation: moveUp 0.4s;
|
||||
}
|
||||
|
||||
.setting-btn:hover :deep(.art-svg-icon) {
|
||||
.setting-btn:hover :deep(.fa-svg-icon) {
|
||||
animation: rotate180 0.5s;
|
||||
}
|
||||
|
||||
.full-screen-btn:hover :deep(.art-svg-icon) {
|
||||
.full-screen-btn:hover :deep(.fa-svg-icon) {
|
||||
animation: expand 0.6s forwards;
|
||||
}
|
||||
|
||||
:deep(.size-select-btn:hover .art-svg-icon) {
|
||||
:deep(.size-select-btn:hover .fa-svg-icon) {
|
||||
animation: expand 0.6s forwards;
|
||||
}
|
||||
|
||||
.exit-full-screen-btn:hover :deep(.art-svg-icon) {
|
||||
.exit-full-screen-btn:hover :deep(.fa-svg-icon) {
|
||||
animation: shrink 0.6s forwards;
|
||||
}
|
||||
|
||||
.notice-button:hover :deep(.art-svg-icon) {
|
||||
.notice-button:hover :deep(.fa-svg-icon) {
|
||||
animation: shake 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.chat-button:hover :deep(.art-svg-icon) {
|
||||
.chat-button:hover :deep(.fa-svg-icon) {
|
||||
animation: shake 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
+20
-20
@@ -1,7 +1,7 @@
|
||||
<!-- 用户菜单:合并旧版顶栏(配置中心、Gitee、引导)+ 新版 Popover 与链接结构 -->
|
||||
<template>
|
||||
<!-- inline-flex + items-center:与顶栏 ArtIconButton 同一中线对齐,避免 Popover 触发层基线偏移 -->
|
||||
<div class="art-user-menu inline-flex shrink-0 items-center leading-none">
|
||||
<!-- inline-flex + items-center:与顶栏 FaIconButton 同一中线对齐,避免 Popover 触发层基线偏移 -->
|
||||
<div class="fa-user-menu inline-flex shrink-0 items-center leading-none">
|
||||
<ElPopover
|
||||
ref="userMenuPopover"
|
||||
placement="bottom-end"
|
||||
@@ -15,7 +15,7 @@
|
||||
>
|
||||
<template #reference>
|
||||
<div
|
||||
class="art-user-menu__avatar-ref mr-5 max-sm:mr-[16px] c-p flex size-8.5 max-sm:w-6.5 max-sm:h-6.5 shrink-0 items-center justify-center"
|
||||
class="fa-user-menu__avatar-ref mr-5 max-sm:mr-[16px] c-p flex size-8.5 max-sm:w-6.5 max-sm:h-6.5 shrink-0 items-center justify-center"
|
||||
>
|
||||
<img
|
||||
v-if="userAvatar"
|
||||
@@ -30,7 +30,7 @@
|
||||
alt="avatar"
|
||||
/>
|
||||
<!-- 与旧版 NavbarActions.user-profile__online-indicator 一致 -->
|
||||
<span class="art-user-menu__online-dot" aria-hidden="true" />
|
||||
<span class="fa-user-menu__online-dot" aria-hidden="true" />
|
||||
</div>
|
||||
</template>
|
||||
<template #default>
|
||||
@@ -57,35 +57,35 @@
|
||||
</div>
|
||||
<ul class="py-4 mt-3 border-t border-g-300/80">
|
||||
<li class="btn-item" @click="goPage('/profile')">
|
||||
<ArtSvgIcon icon="ri:user-3-line" />
|
||||
<FaSvgIcon icon="ri:user-3-line" />
|
||||
<span>{{ $t("topBar.user.userCenter") }}</span>
|
||||
</li>
|
||||
<li class="btn-item" @click="goChangeLog">
|
||||
<ArtSvgIcon icon="ri:draft-line" />
|
||||
<FaSvgIcon icon="ri:draft-line" />
|
||||
<span>{{ $t("topBar.user.changeLog") }}</span>
|
||||
</li>
|
||||
<li class="btn-item" @click="openParamConfig">
|
||||
<ArtSvgIcon icon="ri:settings-3-line" />
|
||||
<FaSvgIcon icon="ri:settings-3-line" />
|
||||
<span>{{ $t("topBar.user.paramConfig") }}</span>
|
||||
</li>
|
||||
<li class="btn-item" @click="toDocs()">
|
||||
<ArtSvgIcon icon="ri:book-2-line" />
|
||||
<FaSvgIcon icon="ri:book-2-line" />
|
||||
<span>{{ $t("topBar.user.docs") }}</span>
|
||||
</li>
|
||||
<li class="btn-item" @click="toGithub()">
|
||||
<ArtSvgIcon icon="ri:github-line" />
|
||||
<FaSvgIcon icon="ri:github-line" />
|
||||
<span>{{ $t("topBar.user.github") }}</span>
|
||||
</li>
|
||||
<li class="btn-item" @click="toGitee">
|
||||
<ArtSvgIcon icon="ri:git-branch-line" />
|
||||
<FaSvgIcon icon="ri:git-branch-line" />
|
||||
<span>{{ $t("topBar.user.gitee") }}</span>
|
||||
</li>
|
||||
<li class="btn-item" @click="startTour">
|
||||
<ArtSvgIcon icon="ri:compass-3-line" />
|
||||
<FaSvgIcon icon="ri:compass-3-line" />
|
||||
<span>{{ $t("topBar.user.tour") }}</span>
|
||||
</li>
|
||||
<li class="btn-item" @click="lockScreen()">
|
||||
<ArtSvgIcon icon="ri:lock-line" />
|
||||
<FaSvgIcon icon="ri:lock-line" />
|
||||
<span>{{ $t("topBar.user.lockScreen") }}</span>
|
||||
</li>
|
||||
<div class="w-full h-px my-2 bg-g-300/80"></div>
|
||||
@@ -114,7 +114,7 @@ import { WEB_LINKS } from "@utils/constants";
|
||||
import { DeviceEnum } from "@/enums/settings/device.enum";
|
||||
import { mittBus } from "@utils/sys";
|
||||
|
||||
defineOptions({ name: "ArtUserMenu" });
|
||||
defineOptions({ name: "FaUserMenu" });
|
||||
|
||||
const router = useRouter();
|
||||
const { t } = useI18n();
|
||||
@@ -225,12 +225,12 @@ function closeUserMenu(): void {
|
||||
@apply text-sm;
|
||||
}
|
||||
|
||||
.art-svg-icon {
|
||||
.fa-svg-icon {
|
||||
@apply mr-2 text-base;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--art-gray-200);
|
||||
background-color: var(--fa-gray-200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,26 +240,26 @@ function closeUserMenu(): void {
|
||||
|
||||
&:hover {
|
||||
color: var(--el-color-danger);
|
||||
background-color: var(--art-gray-200);
|
||||
background-color: var(--fa-gray-200);
|
||||
border-color: var(--el-color-danger-light-3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ElPopover 基于 Tooltip:触发层默认 inline-block,与顶栏 flex 图标中线对齐 */
|
||||
.art-user-menu :deep(.el-tooltip__trigger) {
|
||||
.fa-user-menu :deep(.el-tooltip__trigger) {
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
/* 顶栏头像右下角在线状态(对齐旧版顶栏);占位与 ArtIconButton size-8.5 一致 */
|
||||
.art-user-menu__avatar-ref {
|
||||
/* 顶栏头像右下角在线状态(对齐旧版顶栏);占位与 FaIconButton size-8.5 一致 */
|
||||
.fa-user-menu__avatar-ref {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.art-user-menu__online-dot {
|
||||
.fa-user-menu__online-dot {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
:ellipsis="true"
|
||||
mode="horizontal"
|
||||
:default-active="routerPath"
|
||||
:text-color="isDark ? 'var(--art-gray-800)' : 'var(--art-gray-700)'"
|
||||
:text-color="isDark ? 'var(--fa-gray-800)' : 'var(--fa-gray-700)'"
|
||||
:popper-offset="-6"
|
||||
background-color="transparent"
|
||||
:show-timeout="50"
|
||||
@@ -29,7 +29,7 @@ import type { AppRouteRecord } from "@/types/router";
|
||||
import HorizontalSubmenu from "./widget/HorizontalSubmenu.vue";
|
||||
import { useSettingsStore } from "@stores/modules/setting.store";
|
||||
|
||||
defineOptions({ name: "ArtHorizontalMenu" });
|
||||
defineOptions({ name: "FaHorizontalMenu" });
|
||||
|
||||
const settingStore = useSettingsStore();
|
||||
const { isDark } = storeToRefs(settingStore);
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<ElSubMenu v-if="hasChildren" :index="item.path || item.meta.title" class="!p-0">
|
||||
<template #title>
|
||||
<MenuRouteIcon :icon="item.meta.icon" :color="theme?.iconColor" class="mr-1 text-lg" />
|
||||
<FaMenuRouteIcon :icon="item.meta.icon" :color="theme?.iconColor" class="mr-1 text-lg" />
|
||||
<span class="text-md">{{ formatMenuTitle(item.meta.title) }}</span>
|
||||
<div v-if="item.meta.showBadge" class="art-badge art-badge-horizontal" />
|
||||
<div v-if="item.meta.showTextBadge" class="art-text-badge">
|
||||
<div v-if="item.meta.showBadge" class="fa-badge fa-badge-horizontal" />
|
||||
<div v-if="item.meta.showTextBadge" class="fa-text-badge">
|
||||
{{ item.meta.showTextBadge }}
|
||||
</div>
|
||||
</template>
|
||||
@@ -35,10 +35,10 @@
|
||||
<span class="text-md">{{ formatMenuTitle(item.meta.title) }}</span>
|
||||
<div
|
||||
v-if="item.meta.showBadge"
|
||||
class="art-badge"
|
||||
class="fa-badge"
|
||||
:style="{ right: level === 0 ? '10px' : '20px' }"
|
||||
/>
|
||||
<div v-if="item.meta.showTextBadge && level !== 0" class="art-text-badge">
|
||||
<div v-if="item.meta.showTextBadge && level !== 0" class="fa-text-badge">
|
||||
{{ item.meta.showTextBadge }}
|
||||
</div>
|
||||
</ElMenuItem>
|
||||
+3
-3
@@ -26,7 +26,7 @@
|
||||
}"
|
||||
@click="handleMenuJump(item, true)"
|
||||
>
|
||||
<MenuRouteIcon
|
||||
<FaMenuRouteIcon
|
||||
:icon="item.meta.icon"
|
||||
class="text-lg text-g-700 dark:text-g-800 mr-1"
|
||||
:class="item.isActive && '!text-theme'"
|
||||
@@ -37,7 +37,7 @@
|
||||
>
|
||||
{{ item.formattedTitle }}
|
||||
</span>
|
||||
<div v-if="item.meta.showBadge" class="art-badge art-badge-mixed" />
|
||||
<div v-if="item.meta.showBadge" class="fa-badge fa-badge-mixed" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -60,7 +60,7 @@ import { formatMenuTitle } from "@utils/navigation";
|
||||
import { handleMenuJump } from "@utils/navigation";
|
||||
import type { AppRouteRecord } from "@/types/router";
|
||||
|
||||
defineOptions({ name: "ArtMixedMenu" });
|
||||
defineOptions({ name: "FaMixedMenu" });
|
||||
|
||||
interface Props {
|
||||
/** 菜单列表数据 */
|
||||
+8
-7
@@ -11,7 +11,7 @@
|
||||
class="dual-menu-left"
|
||||
:style="{ width: dualMenuShowText ? '80px' : '64px', background: getMenuTheme.background }"
|
||||
>
|
||||
<ArtLogo v-if="showAppLogo" class="logo" :src="sidebarLogoSrc" @click="navigateToHome" />
|
||||
<FaLogo v-if="showAppLogo" class="logo" :src="sidebarLogoSrc" @click="navigateToHome" />
|
||||
|
||||
<ElScrollbar style="height: calc(100% - 135px)">
|
||||
<ul>
|
||||
@@ -35,7 +35,7 @@
|
||||
height: dualMenuShowText ? '60px' : '46px',
|
||||
}"
|
||||
>
|
||||
<MenuRouteIcon
|
||||
<FaMenuRouteIcon
|
||||
class="menu-icon text-g-700 dark:text-g-800"
|
||||
:icon="menu.meta.icon"
|
||||
:style="{
|
||||
@@ -45,14 +45,14 @@
|
||||
<span v-if="dualMenuShowText" class="text-md text-g-700">
|
||||
{{ $t(menu.meta.title) }}
|
||||
</span>
|
||||
<div v-if="menu.meta.showBadge" class="art-badge art-badge-dual" />
|
||||
<div v-if="menu.meta.showBadge" class="fa-badge fa-badge-dual" />
|
||||
</div>
|
||||
</ElTooltip>
|
||||
</li>
|
||||
</ul>
|
||||
</ElScrollbar>
|
||||
|
||||
<ArtIconButton
|
||||
<FaIconButton
|
||||
class="switch-btn size-10"
|
||||
icon="ri:arrow-left-right-fill"
|
||||
@click="toggleDualMenuMode"
|
||||
@@ -75,7 +75,7 @@
|
||||
background: getMenuTheme.background,
|
||||
}"
|
||||
>
|
||||
<ArtLogo v-if="!isDualMenu" class="logo" :src="sidebarLogoSrc" />
|
||||
<FaLogo v-if="!isDualMenu" class="logo" :src="sidebarLogoSrc" />
|
||||
|
||||
<p
|
||||
:class="{ 'is-dual-menu-name': isDualMenu }"
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
<!-- 双列菜单右侧折叠按钮 -->
|
||||
<div class="dual-menu-collapse-btn" v-if="isDualMenu" @click="toggleMenuVisibility">
|
||||
<ArtSvgIcon
|
||||
<FaSvgIcon
|
||||
class="text-g-500/70"
|
||||
:icon="menuOpen ? 'ri:arrow-left-wide-fill' : 'ri:arrow-right-wide-fill'"
|
||||
/>
|
||||
@@ -138,10 +138,11 @@ import { useMenuStore } from "@stores/modules/menu.store";
|
||||
import { isIframe } from "@utils/navigation";
|
||||
import { handleMenuJump } from "@utils/navigation";
|
||||
import SidebarSubmenu from "./widget/SidebarSubmenu.vue";
|
||||
import FaMenuRouteIcon from "@/components/others/fa-menu-routeIcon/index.vue";
|
||||
import { useCommon } from "@/hooks/core/useCommon";
|
||||
import { useWindowSize, useTimeoutFn } from "@vueuse/core";
|
||||
|
||||
defineOptions({ name: "ArtSidebarMenu" });
|
||||
defineOptions({ name: "FaSidebarMenu" });
|
||||
|
||||
const MOBILE_BREAKPOINT = 800;
|
||||
const ANIMATION_DELAY = 350;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user