mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-06 00:18:51 +08:00
perf: 首屏优化,减少 1.5MB
资源
This commit is contained in:
parent
a22bc8622e
commit
d2b1bd5b44
@ -32,13 +32,14 @@ export const include = [
|
||||
"lodash-unified",
|
||||
"@ctrl/tinycolor",
|
||||
"china-area-data",
|
||||
"@faker-js/faker",
|
||||
"vue-json-pretty",
|
||||
"@logicflow/core",
|
||||
"@pureadmin/utils",
|
||||
"@wangeditor/editor",
|
||||
"responsive-storage",
|
||||
"@howdyjs/mouse-menu",
|
||||
"@logicflow/extension",
|
||||
"vue-virtual-scroller",
|
||||
"element-resize-detector",
|
||||
"@amap/amap-jsapi-loader",
|
||||
"el-table-infinite-scroll",
|
||||
|
@ -86,7 +86,6 @@
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "13.1.0",
|
||||
"@commitlint/config-conventional": "13.1.0",
|
||||
"@faker-js/faker": "^7.5.0",
|
||||
"@iconify-icons/carbon": "^1.2.8",
|
||||
"@iconify-icons/ep": "^1.2.7",
|
||||
"@iconify-icons/fa": "^1.2.3",
|
||||
|
6199
pnpm-lock.yaml
generated
6199
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,12 @@
|
||||
import iconifyIconOffline from "./src/iconifyIconOffline";
|
||||
import iconifyIconOnline from "./src/iconifyIconOnline";
|
||||
import iconSelect from "./src/Select.vue";
|
||||
import fontIcon from "./src/iconfont";
|
||||
|
||||
/** 本地图标组件 */
|
||||
const IconifyIconOffline = iconifyIconOffline;
|
||||
/** 在线图标组件 */
|
||||
const IconifyIconOnline = iconifyIconOnline;
|
||||
/** 图标选择器组件 */
|
||||
const IconSelect = iconSelect;
|
||||
/** iconfont组件 */
|
||||
const FontIcon = fontIcon;
|
||||
|
||||
export { IconifyIconOffline, IconifyIconOnline, IconSelect, FontIcon };
|
||||
export { IconifyIconOffline, IconifyIconOnline, FontIcon };
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { cloneDeep } from "lodash-unified";
|
||||
import { ref, computed, CSSProperties, toRef, watch } from "vue";
|
||||
import { IconJson } from "@/components/ReIcon/data";
|
||||
import { ref, computed, CSSProperties, toRef, watch } from "vue";
|
||||
type ParameterCSSProperties = (item?: string) => CSSProperties | undefined;
|
||||
|
||||
defineOptions({
|
||||
|
@ -42,7 +42,6 @@ const verticalRef = ref();
|
||||
const horizontalRef = ref();
|
||||
|
||||
const {
|
||||
body,
|
||||
dataTheme,
|
||||
layoutTheme,
|
||||
themeColors,
|
||||
@ -165,8 +164,6 @@ function setFalse(Doms): any {
|
||||
}
|
||||
|
||||
watch($storage, ({ layout }) => {
|
||||
/* 设置wangeditorV5主题色 */
|
||||
body.style.setProperty("--w-e-toolbar-active-color", layout["epThemeColor"]);
|
||||
switch (layout["layout"]) {
|
||||
case "vertical":
|
||||
toggleClass(true, isSelect, unref(verticalRef));
|
||||
|
@ -8,7 +8,6 @@ import { useGlobal } from "@pureadmin/utils";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { router, remainingPaths } from "@/router";
|
||||
import { useAppStoreHook } from "@/store/modules/app";
|
||||
import { i18nChangeLanguage } from "@wangeditor/editor";
|
||||
import { useUserStoreHook } from "@/store/modules/user";
|
||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||
@ -136,15 +135,6 @@ export function useNav() {
|
||||
return remainingPaths.includes(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换wangEditorV5国际化
|
||||
* @param language string 可选值 en、zh-CN
|
||||
* @returns void
|
||||
*/
|
||||
function changeWangeditorLanguage(language: string): void {
|
||||
i18nChangeLanguage(language);
|
||||
}
|
||||
|
||||
return {
|
||||
title,
|
||||
device,
|
||||
@ -164,7 +154,6 @@ export function useNav() {
|
||||
username,
|
||||
avatarsStyle,
|
||||
getDropdownItemStyle,
|
||||
getDropdownItemClass,
|
||||
changeWangeditorLanguage
|
||||
getDropdownItemClass
|
||||
};
|
||||
}
|
||||
|
@ -4,8 +4,7 @@ import { useRoute } from "vue-router";
|
||||
import { watch, type Ref } from "vue";
|
||||
|
||||
export function useTranslationLang(ref?: Ref) {
|
||||
const { $storage, changeTitle, changeWangeditorLanguage, handleResize } =
|
||||
useNav();
|
||||
const { $storage, changeTitle, handleResize } = useNav();
|
||||
const { locale, t } = useI18n();
|
||||
const route = useRoute();
|
||||
|
||||
@ -25,9 +24,6 @@ export function useTranslationLang(ref?: Ref) {
|
||||
() => locale.value,
|
||||
() => {
|
||||
changeTitle(route.meta);
|
||||
locale.value === "en"
|
||||
? changeWangeditorLanguage(locale.value)
|
||||
: changeWangeditorLanguage("zh-CN");
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import "animate.css";
|
||||
import { setType } from "./types";
|
||||
import { emitter } from "@/utils/mitt";
|
||||
import { useLayout } from "./hooks/useLayout";
|
||||
|
@ -8,13 +8,11 @@ import { createApp, Directive } from "vue";
|
||||
import { MotionPlugin } from "@vueuse/motion";
|
||||
import { useEcharts } from "@/plugins/echarts";
|
||||
import { useTable } from "@/plugins/vxe-table";
|
||||
import VirtualScroller from "vue-virtual-scroller";
|
||||
import { injectResponsiveStorage } from "@/utils/responsive";
|
||||
|
||||
import Table from "@pureadmin/table";
|
||||
import PureDescriptions from "@pureadmin/descriptions";
|
||||
|
||||
import "animate.css";
|
||||
// 引入重置样式
|
||||
import "./style/reset.scss";
|
||||
// 导入公共样式
|
||||
@ -23,8 +21,6 @@ import "element-plus/dist/index.css";
|
||||
// 导入字体图标
|
||||
import "./assets/iconfont/iconfont.js";
|
||||
import "./assets/iconfont/iconfont.css";
|
||||
import "v-contextmenu/dist/themes/default.css";
|
||||
import "vue-virtual-scroller/dist/vue-virtual-scroller.css";
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
@ -60,7 +56,6 @@ getServerConfig(app).then(async config => {
|
||||
.use(Table)
|
||||
.use(PureDescriptions)
|
||||
.use(useTable)
|
||||
.use(useEcharts)
|
||||
.use(VirtualScroller);
|
||||
.use(useEcharts);
|
||||
app.mount("#app");
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { IconSelect } from "@/components/ReIcon";
|
||||
import IconSelect from "@/components/ReIcon/src/Select.vue";
|
||||
|
||||
defineOptions({
|
||||
name: "IconSelect"
|
||||
|
@ -1,70 +0,0 @@
|
||||
import { faker } from "@faker-js/faker";
|
||||
|
||||
let uid = 0;
|
||||
|
||||
function generateItem() {
|
||||
return {
|
||||
name: faker.name.findName(),
|
||||
avatar: faker.internet.avatar()
|
||||
};
|
||||
}
|
||||
|
||||
export function getData(count, letters) {
|
||||
const raw = {};
|
||||
|
||||
const alphabet = "abcdefghijklmnopqrstuvwxyz".split("");
|
||||
|
||||
for (const l of alphabet) {
|
||||
raw[l] = [];
|
||||
}
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
const item = generateItem();
|
||||
const letter = item.name.charAt(0).toLowerCase();
|
||||
raw[letter].push(item);
|
||||
}
|
||||
|
||||
const list = [];
|
||||
let index = 1;
|
||||
|
||||
for (const l of alphabet) {
|
||||
raw[l] = raw[l].sort((a, b) => (a.name < b.name ? -1 : 1));
|
||||
if (letters) {
|
||||
list.push({
|
||||
id: uid++,
|
||||
index: index++,
|
||||
type: "letter",
|
||||
value: l,
|
||||
height: 200
|
||||
});
|
||||
}
|
||||
for (const item of raw[l]) {
|
||||
list.push({
|
||||
id: uid++,
|
||||
index: index++,
|
||||
type: "person",
|
||||
value: item,
|
||||
height: 50
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
export function addItem(list) {
|
||||
list.push({
|
||||
id: uid++,
|
||||
index: list.length + 1,
|
||||
type: "person",
|
||||
value: generateItem(),
|
||||
height: 50
|
||||
});
|
||||
}
|
||||
|
||||
export function generateMessage() {
|
||||
return {
|
||||
avatar: faker.internet.avatar(),
|
||||
message: faker.lorem.text()
|
||||
};
|
||||
}
|
@ -1,33 +1,27 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
import { generateMessage } from "./data";
|
||||
import { DynamicScroller, DynamicScrollerItem } from "vue-virtual-scroller";
|
||||
|
||||
const items = ref([]);
|
||||
const search = ref("");
|
||||
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
for (let i = 0; i < 800; i++) {
|
||||
items.value.push({
|
||||
id: i,
|
||||
...generateMessage()
|
||||
id: i
|
||||
});
|
||||
}
|
||||
|
||||
const filteredItems = computed(() => {
|
||||
if (!search.value) return items.value;
|
||||
const lowerCaseSearch = search.value.toLowerCase();
|
||||
return items.value.filter(i =>
|
||||
i.message.toLowerCase().includes(lowerCaseSearch)
|
||||
);
|
||||
const lowerCaseSearch = search.value;
|
||||
return items.value.filter(i => i.id == lowerCaseSearch);
|
||||
});
|
||||
|
||||
function changeMessage(message) {
|
||||
Object.assign(message, generateMessage());
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dynamic-scroller-demo">
|
||||
<div class="flex justify-around mb-4">
|
||||
<div class="flex-ac mb-4 shadow-2xl">
|
||||
水平模式 horizontal
|
||||
<el-input
|
||||
class="mr-2 !w-[1/1.5]"
|
||||
clearable
|
||||
@ -35,7 +29,6 @@ function changeMessage(message) {
|
||||
placeholder="Filter..."
|
||||
style="width: 300px"
|
||||
/>
|
||||
<el-tag effect="dark">水平模式horizontal</el-tag>
|
||||
</div>
|
||||
|
||||
<DynamicScroller
|
||||
@ -48,31 +41,21 @@ function changeMessage(message) {
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.message]"
|
||||
:size-dependencies="[item.id]"
|
||||
:data-index="index"
|
||||
:data-active="active"
|
||||
:title="`Click to change message ${index}`"
|
||||
:style="{
|
||||
width: `${Math.max(
|
||||
130,
|
||||
Math.round((item.message.length / 20) * 20)
|
||||
)}px`
|
||||
width: `${Math.max(130, Math.round((item.id?.length / 20) * 20))}px`
|
||||
}"
|
||||
class="message"
|
||||
@click="changeMessage(item)"
|
||||
>
|
||||
<div class="avatar">
|
||||
<div>
|
||||
<IconifyIconOnline
|
||||
icon="openmoji:beaming-face-with-smiling-eyes"
|
||||
width="40"
|
||||
/>
|
||||
</div>
|
||||
<div class="text">
|
||||
{{ item.message }}
|
||||
</div>
|
||||
<div class="index">
|
||||
<span>{{ item.id }} (id)</span>
|
||||
<span>{{ index }} (index)</span>
|
||||
<p class="text-center">{{ item.id }}</p>
|
||||
</div>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
@ -104,35 +87,4 @@ function changeMessage(message) {
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
flex: auto 0 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.avatar .image {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.index,
|
||||
.text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.index {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.index span {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import verticalList from "./vertical.vue";
|
||||
import horizontalList from "./horizontal.vue";
|
||||
import "vue-virtual-scroller/dist/vue-virtual-scroller.css";
|
||||
|
||||
defineOptions({
|
||||
name: "VirtualList"
|
||||
|
@ -1,75 +1,56 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from "vue";
|
||||
import { generateMessage } from "./data";
|
||||
import { DynamicScroller, DynamicScrollerItem } from "vue-virtual-scroller";
|
||||
|
||||
const items = ref([]);
|
||||
const search = ref("");
|
||||
|
||||
for (let i = 0; i < 10000; i++) {
|
||||
for (let i = 0; i < 800; i++) {
|
||||
items.value.push({
|
||||
id: i,
|
||||
...generateMessage()
|
||||
id: i
|
||||
});
|
||||
}
|
||||
|
||||
const filteredItems = computed(() => {
|
||||
if (!search.value) return items.value;
|
||||
const lowerCaseSearch = search.value.toLowerCase();
|
||||
return items.value.filter(i =>
|
||||
i.message.toLowerCase().includes(lowerCaseSearch)
|
||||
);
|
||||
const lowerCaseSearch = search.value;
|
||||
return items.value.filter(i => i.id == lowerCaseSearch);
|
||||
});
|
||||
|
||||
function changeMessage(message) {
|
||||
Object.assign(message, generateMessage());
|
||||
}
|
||||
|
||||
function onResize() {
|
||||
console.log("resize");
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="dynamic-scroller-demo">
|
||||
<div class="flex justify-around mb-4">
|
||||
<div class="flex-ac mb-4 shadow-2xl">
|
||||
垂直模式 vertical
|
||||
<el-input
|
||||
class="mr-2 !w-[1/1.5]"
|
||||
class="!w-[350px]"
|
||||
clearable
|
||||
v-model="search"
|
||||
placeholder="Filter..."
|
||||
/>
|
||||
<el-tag effect="dark">垂直模式vertical</el-tag>
|
||||
</div>
|
||||
|
||||
<DynamicScroller
|
||||
:items="filteredItems"
|
||||
:min-item-size="54"
|
||||
class="scroller"
|
||||
@resize="onResize"
|
||||
>
|
||||
<template #default="{ item, index, active }">
|
||||
<DynamicScrollerItem
|
||||
:item="item"
|
||||
:active="active"
|
||||
:size-dependencies="[item.message]"
|
||||
:size-dependencies="[item.id]"
|
||||
:data-index="index"
|
||||
:data-active="active"
|
||||
:title="`Click to change message ${index}`"
|
||||
class="message"
|
||||
@click="changeMessage(item)"
|
||||
>
|
||||
<div class="avatar">
|
||||
<div class="flex items-center">
|
||||
<IconifyIconOnline
|
||||
icon="openmoji:beaming-face-with-smiling-eyes"
|
||||
width="40"
|
||||
/>
|
||||
</div>
|
||||
<div class="text">
|
||||
{{ item.message }}
|
||||
</div>
|
||||
<div class="index">
|
||||
<span>{{ item.id }} (id)</span>
|
||||
<span>{{ index }} (index)</span>
|
||||
<span>{{ item.id }}</span>
|
||||
</div>
|
||||
</DynamicScrollerItem>
|
||||
</template>
|
||||
@ -94,31 +75,4 @@ function onResize() {
|
||||
padding: 12px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
flex: auto 0 0;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.index,
|
||||
.text {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.text {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.index {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.index span {
|
||||
display: inline-block;
|
||||
width: 160px;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
@ -2,6 +2,7 @@
|
||||
import basic from "./basic.vue";
|
||||
import menuGroup from "./menuGroup.vue";
|
||||
import menuDynamic from "./menuDynamic.vue";
|
||||
import "v-contextmenu/dist/themes/default.css";
|
||||
|
||||
defineOptions({
|
||||
name: "ContextMenu"
|
||||
|
@ -195,7 +195,7 @@ onUnmounted(() => {
|
||||
>
|
||||
<TypeIt
|
||||
:className="'type-it2'"
|
||||
:values="['Pure-Admin 版本日志']"
|
||||
:values="['PureAdmin 版本日志']"
|
||||
:cursor="false"
|
||||
:speed="80"
|
||||
/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user