diff --git a/build/info.ts b/build/info.ts
index 7ef3f11f3..06006411d 100644
--- a/build/info.ts
+++ b/build/info.ts
@@ -1,8 +1,8 @@
import type { Plugin } from "vite";
+import picocolors from "picocolors";
import dayjs, { Dayjs } from "dayjs";
-import utils from "@pureadmin/utils";
+import { getPackageSize } from "./utils";
import duration from "dayjs/plugin/duration";
-import { green, blue, bold } from "picocolors";
dayjs.extend(duration);
export function viteBuildInfo(): Plugin {
@@ -10,6 +10,7 @@ export function viteBuildInfo(): Plugin {
let startTime: Dayjs;
let endTime: Dayjs;
let outDir: string;
+ const { green, blue, bold } = picocolors;
return {
name: "vite:buildInfo",
configResolved(resolvedConfig) {
@@ -33,7 +34,7 @@ export function viteBuildInfo(): Plugin {
closeBundle() {
if (config.command === "build") {
endTime = dayjs(new Date());
- utils.getPackageSize({
+ getPackageSize({
folder: outDir,
callback: (size: string) => {
console.log(
diff --git a/build/plugins.ts b/build/plugins.ts
index 731e802a1..89bc49e25 100644
--- a/build/plugins.ts
+++ b/build/plugins.ts
@@ -8,7 +8,7 @@ import { viteMockServe } from "vite-plugin-mock";
import { configCompressPlugin } from "./compress";
import { visualizer } from "rollup-plugin-visualizer";
import removeConsole from "vite-plugin-remove-console";
-import themePreprocessorPlugin from "@pureadmin/theme";
+import { themePreprocessorPlugin } from "@pureadmin/theme";
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
import { genScssMultipleScopeVars } from "../src/layout/theme";
diff --git a/build/utils.ts b/build/utils.ts
new file mode 100644
index 000000000..2f11e0f15
--- /dev/null
+++ b/build/utils.ts
@@ -0,0 +1,34 @@
+import { readdir, stat } from "node:fs";
+import { sum, formatBytes } from "@pureadmin/utils";
+
+const fileListTotal: number[] = [];
+
+/**
+ * @description 获取指定文件夹中所有文件的总大小
+ */
+export const getPackageSize = options => {
+ const { folder = "dist", callback, format = true } = options;
+ readdir(folder, (err, files: string[]) => {
+ if (err) throw err;
+ let count = 0;
+ const checkEnd = () => {
+ ++count == files.length &&
+ callback(format ? formatBytes(sum(fileListTotal)) : sum(fileListTotal));
+ };
+ files.forEach((item: string) => {
+ stat(`${folder}/${item}`, async (err, stats) => {
+ if (err) throw err;
+ if (stats.isFile()) {
+ fileListTotal.push(stats.size);
+ checkEnd();
+ } else if (stats.isDirectory()) {
+ getPackageSize({
+ folder: `${folder}/${item}/`,
+ callback: checkEnd
+ });
+ }
+ });
+ });
+ files.length === 0 && callback(0);
+ });
+};
diff --git a/locales/en.yaml b/locales/en.yaml
index cf9858c04..f4c8abcd1 100644
--- a/locales/en.yaml
+++ b/locales/en.yaml
@@ -46,6 +46,7 @@ menus:
hssplitPane: Split Pane
hsbutton: Button Components
hscropping: Picture Cropping
+ hsanimatecss: AnimateCss Selector
hscountTo: Digital Animation
hsselector: Selector Components
hsflowChart: Flow Chart
diff --git a/locales/zh-CN.yaml b/locales/zh-CN.yaml
index a04e3539e..27f836063 100644
--- a/locales/zh-CN.yaml
+++ b/locales/zh-CN.yaml
@@ -46,6 +46,7 @@ menus:
hssplitPane: 切割面板
hsbutton: 按钮组件
hscropping: 图片裁剪
+ hsanimatecss: AnimateCss选择器组件
hscountTo: 数字动画
hsselector: 选择器组件
hsflowChart: 流程图
diff --git a/package.json b/package.json
index af416ca3d..fdf726e85 100644
--- a/package.json
+++ b/package.json
@@ -81,7 +81,7 @@
"qs": "^6.11.2",
"responsive-storage": "^2.2.0",
"sortablejs": "^1.15.0",
- "swiper": "^10.3.1",
+ "swiper": "^11.0.0",
"typeit": "^8.7.1",
"v-contextmenu": "3.0.0",
"v3-infinite-loading": "^1.3.1",
@@ -108,7 +108,7 @@
"@iconify-icons/ri": "^1.2.10",
"@iconify/vue": "^4.1.1",
"@intlify/unplugin-vue-i18n": "^1.4.0",
- "@pureadmin/theme": "^3.1.0",
+ "@pureadmin/theme": "^3.2.0",
"@types/intro.js": "^5.1.2",
"@types/js-cookie": "^3.0.4",
"@types/mockjs": "^1.0.8",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2e2521993..352f8431a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -13,7 +13,7 @@ specifiers:
'@logicflow/extension': ^1.2.16
'@pureadmin/descriptions': ^1.1.1
'@pureadmin/table': ^2.3.3
- '@pureadmin/theme': ^3.1.0
+ '@pureadmin/theme': ^3.2.0
'@pureadmin/utils': ^1.9.10
'@types/intro.js': ^5.1.2
'@types/js-cookie': ^3.0.4
@@ -88,7 +88,7 @@ specifiers:
stylelint-prettier: ^4.0.2
stylelint-scss: ^5.2.1
svgo: ^3.0.2
- swiper: ^10.3.1
+ swiper: ^11.0.0
tailwindcss: ^3.3.3
terser: ^5.21.0
typeit: ^8.7.1
@@ -156,7 +156,7 @@ dependencies:
qs: 6.11.2
responsive-storage: 2.2.0
sortablejs: 1.15.0
- swiper: 10.3.1
+ swiper: 11.0.0
typeit: 8.7.1
v-contextmenu: 3.0.0_vue@3.3.4
v3-infinite-loading: 1.3.1
@@ -183,7 +183,7 @@ devDependencies:
'@iconify-icons/ri': 1.2.10
'@iconify/vue': 4.1.1_vue@3.3.4
'@intlify/unplugin-vue-i18n': 1.4.0_vue-i18n@9.5.0
- '@pureadmin/theme': 3.1.0
+ '@pureadmin/theme': 3.2.0
'@types/intro.js': 5.1.2
'@types/js-cookie': 3.0.4
'@types/mockjs': 1.0.8
@@ -1654,8 +1654,8 @@ packages:
vue: 3.3.4
dev: false
- /@pureadmin/theme/3.1.0:
- resolution: {integrity: sha512-3kBbqB6Uua096w91w1SrGna0dM8AYO5HFk/HU8G0DsEaijgRrm+dYIJUrqbv+stLUxlYPNVXpDS/APZjF0cOAg==}
+ /@pureadmin/theme/3.2.0:
+ resolution: {integrity: sha512-SBlTvEl0rmfqTW/mOJUPftvZe4yF+38CJdlBOvVITpehzCytqlG5i8XKpcs8aAR9SVfhcrLVS5Q6xh7xDVQcJQ==}
dependencies:
'@zougt/some-loader-utils': 1.4.3
fs-extra: 11.1.1
@@ -8228,8 +8228,8 @@ packages:
picocolors: 1.0.0
dev: true
- /swiper/10.3.1:
- resolution: {integrity: sha512-24Wk3YUdZHxjc9faID97GTu6xnLNia+adMt6qMTZG/HgdSUt4fS0REsGUXJOgpTED0Amh/j+gRGQxsLayJUlBQ==}
+ /swiper/11.0.0:
+ resolution: {integrity: sha512-JHTJDUBVkG5L5bD+ZOw/6GkM0vArxV26b/EnciyCSgUPOa9MvAfVQLJJd+dJjo4dj5Yjp6zQaDYqOj+pF+lgzQ==}
engines: {node: '>= 4.7.0'}
dev: false
diff --git a/public/platform-config.json b/public/platform-config.json
index 6860406f9..c4ceff9d0 100644
--- a/public/platform-config.json
+++ b/public/platform-config.json
@@ -12,7 +12,7 @@
"Grey": false,
"Weak": false,
"HideTabs": false,
- "HideFooter": false,
+ "HideFooter": true,
"SidebarStatus": true,
"EpThemeColor": "#409EFF",
"ShowLogo": true,
diff --git a/src/components/ReAnimateSelector/index.ts b/src/components/ReAnimateSelector/index.ts
new file mode 100644
index 000000000..8b0293cd6
--- /dev/null
+++ b/src/components/ReAnimateSelector/index.ts
@@ -0,0 +1,7 @@
+import reAnimateSelector from "./src/index.vue";
+import { withInstall } from "@pureadmin/utils";
+
+/** [animate.css](https://animate.style/) 选择器组件 */
+export const ReAnimateSelector = withInstall(reAnimateSelector);
+
+export default ReAnimateSelector;
diff --git a/src/components/ReAnimateSelector/src/animate.ts b/src/components/ReAnimateSelector/src/animate.ts
new file mode 100644
index 000000000..2b0593c7f
--- /dev/null
+++ b/src/components/ReAnimateSelector/src/animate.ts
@@ -0,0 +1,114 @@
+export const animates = [
+ /* Attention seekers */
+ "bounce",
+ "flash",
+ "pulse",
+ "rubberBand",
+ "shakeX",
+ "headShake",
+ "swing",
+ "tada",
+ "wobble",
+ "jello",
+ "heartBeat",
+ /* Back entrances */
+ "backInDown",
+ "backInLeft",
+ "backInRight",
+ "backInUp",
+ /* Back exits */
+ "backOutDown",
+ "backOutLeft",
+ "backOutRight",
+ "backOutUp",
+ /* Bouncing entrances */
+ "bounceIn",
+ "bounceInDown",
+ "bounceInLeft",
+ "bounceInRight",
+ "bounceInUp",
+ /* Bouncing exits */
+ "bounceOut",
+ "bounceOutDown",
+ "bounceOutLeft",
+ "bounceOutRight",
+ "bounceOutUp",
+ /* Fading entrances */
+ "fadeIn",
+ "fadeInDown",
+ "fadeInDownBig",
+ "fadeInLeft",
+ "fadeInLeftBig",
+ "fadeInRight",
+ "fadeInRightBig",
+ "fadeInUp",
+ "fadeInUpBig",
+ "fadeInTopLeft",
+ "fadeInTopRight",
+ "fadeInBottomLeft",
+ "fadeInBottomRight",
+ /* Fading exits */
+ "fadeOut",
+ "fadeOutDown",
+ "fadeOutDownBig",
+ "fadeOutLeft",
+ "fadeOutLeftBig",
+ "fadeOutRight",
+ "fadeOutRightBig",
+ "fadeOutUp",
+ "fadeOutUpBig",
+ "fadeOutTopLeft",
+ "fadeOutTopRight",
+ "fadeOutBottomRight",
+ "fadeOutBottomLeft",
+ /* Flippers */
+ "flip",
+ "flipInX",
+ "flipInY",
+ "flipOutX",
+ "flipOutY",
+ /* Lightspeed */
+ "lightSpeedInRight",
+ "lightSpeedInLeft",
+ "lightSpeedOutRight",
+ "lightSpeedOutLeft",
+ /* Rotating entrances */
+ "rotateIn",
+ "rotateInDownLeft",
+ "rotateInDownRight",
+ "rotateInUpLeft",
+ "rotateInUpRight",
+ /* Rotating exits */
+ "rotateOut",
+ "rotateOutDownLeft",
+ "rotateOutDownRight",
+ "rotateOutUpLeft",
+ "rotateOutUpRight",
+ /* Specials */
+ "hinge",
+ "jackInTheBox",
+ "rollIn",
+ "rollOut",
+ /* Zooming entrances */
+ "zoomIn",
+ "zoomInDown",
+ "zoomInLeft",
+ "zoomInRight",
+ "zoomInUp",
+ /* Zooming exits */
+ "zoomOut",
+ "zoomOutDown",
+ "zoomOutLeft",
+ "zoomOutRight",
+ "zoomOutUp",
+ /* Sliding entrances */
+ "slideInDown",
+ "slideInLeft",
+ "slideInRight",
+ "slideInUp",
+ /* Sliding exits */
+ "slideOutDown",
+ "slideOutLeft",
+ "slideOutRight",
+ "slideOutUp"
+];
diff --git a/src/components/ReAnimateSelector/src/index.vue b/src/components/ReAnimateSelector/src/index.vue
new file mode 100644
index 000000000..e2f44053b
--- /dev/null
+++ b/src/components/ReAnimateSelector/src/index.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+ -
+
+ {{ animate }}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ReSegmented/src/index.tsx b/src/components/ReSegmented/src/index.tsx
index f7f5a6796..8378f4ad6 100644
--- a/src/components/ReSegmented/src/index.tsx
+++ b/src/components/ReSegmented/src/index.tsx
@@ -2,31 +2,33 @@ import "./index.css";
import {
h,
ref,
+ toRef,
watch,
nextTick,
defineComponent,
getCurrentInstance
} from "vue";
import type { OptionsType } from "./type";
-import { isFunction, useDark } from "@pureadmin/utils";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
+import { isFunction, isNumber, useDark } from "@pureadmin/utils";
const props = {
options: {
type: Array,
default: () => []
},
- /** 默认选中,按照第一个索引为 `0` 的模式 */
- defaultValue: {
- type: Number,
- default: 0
+ /** 默认选中,按照第一个索引为 `0` 的模式,可选(`modelValue`只有传`number`类型时才为响应式) */
+ modelValue: {
+ type: undefined,
+ require: false,
+ default: "0"
}
};
export default defineComponent({
name: "ReSegmented",
props,
- emits: ["change"],
+ emits: ["change", "update:modelValue"],
setup(props, { emit }) {
const width = ref(0);
const translateX = ref(0);
@@ -35,12 +37,16 @@ export default defineComponent({
const curMouseActive = ref(-1);
const segmentedItembg = ref("");
const instance = getCurrentInstance()!;
- const curIndex = ref(props.defaultValue);
+ const curIndex = isNumber(props.modelValue)
+ ? toRef(props, "modelValue")
+ : ref(0);
function handleChange({ option, index }, event: Event) {
if (option.disabled) return;
event.preventDefault();
- curIndex.value = index;
+ isNumber(props.modelValue)
+ ? emit("update:modelValue", index)
+ : (curIndex.value = index);
segmentedItembg.value = "";
emit("change", { index, option });
}
diff --git a/src/layout/components/sidebar/horizontal.vue b/src/layout/components/sidebar/horizontal.vue
index 18cc09497..0ec91ccec 100644
--- a/src/layout/components/sidebar/horizontal.vue
+++ b/src/layout/components/sidebar/horizontal.vue
@@ -21,6 +21,7 @@ const {
logout,
backTopMenu,
onPanel,
+ getLogo,
username,
userAvatar,
avatarsStyle,
@@ -43,7 +44,7 @@ nextTick(() => {
class="horizontal-header"
>
@@ -19,7 +19,7 @@ const { title } = useNav();
class="sidebar-logo-link"
:to="getTopMenu()?.path ?? '/'"
>
-
+
diff --git a/src/layout/components/tag/index.vue b/src/layout/components/tag/index.vue
index 685b7e30a..adf775fcb 100644
--- a/src/layout/components/tag/index.vue
+++ b/src/layout/components/tag/index.vue
@@ -6,10 +6,10 @@ import { useTags } from "../../hooks/useTag";
import { routerArrays } from "@/layout/types";
import { handleAliveRoute, getTopMenu } from "@/router/utils";
import { useSettingStoreHook } from "@/store/modules/settings";
-import { useResizeObserver, useFullscreen } from "@vueuse/core";
import { isEqual, isAllEmpty, debounce } from "@pureadmin/utils";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
import { ref, watch, unref, toRaw, nextTick, onBeforeUnmount } from "vue";
+import { useResizeObserver, useFullscreen, onClickOutside } from "@vueuse/core";
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
import Fullscreen from "@iconify-icons/ri/fullscreen-fill";
@@ -49,6 +49,7 @@ const {
const tabDom = ref();
const containerDom = ref();
const scrollbarDom = ref();
+const contextmenuRef = ref();
const isShowArrow = ref(false);
const topPath = getTopMenu()?.path;
const { VITE_HIDE_HOME } = import.meta.env;
@@ -328,6 +329,7 @@ function handleCommand(command: any) {
/** 触发右键中菜单的点击事件 */
function selectTag(key, item) {
+ closeMenu();
onClickDrop(key, item, currentSelect.value);
}
@@ -462,6 +464,10 @@ function tagOnClick(item) {
// showMenuModel(item?.path, item?.query);
}
+onClickOutside(contextmenuRef, closeMenu, {
+ detectIframe: true
+});
+
watch(route, () => {
activeIndex.value = -1;
dynamicTagView();
@@ -558,6 +564,7 @@ onBeforeUnmount(() => {