perf: 大优化,移除 @pureadmin/components , 打包大小未启用压缩前减少 0.4 MB , 首屏请求减少 2.3 MB 的资源

This commit is contained in:
xiaoxian521
2022-11-26 23:37:00 +08:00
parent 63f2540745
commit 4f786d6262
28 changed files with 416 additions and 803 deletions

View File

@@ -1,72 +0,0 @@
<script setup lang="ts">
import { Anchor, AnchorLink } from "@pureadmin/components";
defineOptions({
name: "AntAnchor"
});
function handleAnchorClick(e, link) {
e.preventDefault();
const srcolls = document.getElementById(link.href);
srcolls.scrollIntoView({ block: "start", behavior: "smooth" });
}
</script>
<template>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">
仿antdv锚点采用
<el-link
href="https://www.npmjs.com/package/@pureadmin/components"
target="_blank"
style="font-size: 16px; margin: 0 4px 5px"
>
@pureadmin/components
</el-link>
完全兼容antdv的
<el-link
href="https://next.antdv.com/components/anchor-cn"
target="_blank"
style="font-size: 16px; margin: 0 4px 5px"
>
Anchor
</el-link>
写法
</span>
</div>
</template>
<div class="w-[400px]">
<Anchor class="float-left mt-[200px]" @click="handleAnchorClick">
<AnchorLink href="one" title="测试one" />
<AnchorLink href="two" title="测试two" />
<AnchorLink href="three" title="测试three" />
</Anchor>
<el-scrollbar class="float-right overflow-auto" height="600px">
<header
id="one"
class="w-[200px] h-[600px] text-cyan-50 flex justify-center items-center text-4xl"
style="background: #409eff"
>
测试one
</header>
<header
id="two"
class="w-[200px] h-[600px] text-cyan-50 flex justify-center items-center text-4xl"
style="background: #67c23a"
>
测试two
</header>
<header
id="three"
class="w-[200px] h-[600px] text-cyan-50 flex justify-center items-center text-4xl"
style="background: #f56c6c"
>
测试three
</header>
</el-scrollbar>
</div>
</el-card>
</template>

View File

@@ -1,56 +0,0 @@
<script setup lang="ts">
import { ref } from "vue";
import { Tabs, TabPane } from "@pureadmin/components";
defineOptions({
name: "AntTabs"
});
const mode = ref("top");
const activeKey = ref(1);
const callback = (val: string) => {
console.log(val);
};
</script>
<template>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">
仿antdv标签页采用
<el-link
href="https://www.npmjs.com/package/@pureadmin/components"
target="_blank"
style="font-size: 16px; margin: 0 4px 5px"
>
@pureadmin/components
</el-link>
完全兼容antdv的
<el-link
href="https://next.antdv.com/components/tabs-cn"
target="_blank"
style="font-size: 16px; margin: 0 4px 5px"
>
Tabs
</el-link>
写法
</span>
</div>
</template>
<el-radio-group v-model="mode" size="small" class="mb-2">
<el-radio label="top" border>Horizontal</el-radio>
<el-radio label="left" border>Vertical</el-radio>
</el-radio-group>
<Tabs
v-model:activeKey="activeKey"
:tab-position="mode"
:style="{ height: '200px' }"
@tabScroll="callback"
>
<TabPane v-for="i in 30" :key="i" :tab="`Tab-${i}`">
Content of tab {{ i }}
</TabPane>
</Tabs>
</el-card>
</template>

View File

@@ -1,217 +0,0 @@
<script setup lang="ts">
import { ref } from "vue";
import { TreeSelect } from "@pureadmin/components";
defineOptions({
name: "AntTreeSelect"
});
const value1 = ref<string>("");
const treeData1 = ref([
{
title: "parent 1",
value: "parent 1",
children: [
{
title: "parent 1-0",
value: "parent 1-0",
children: [
{
title: "my leaf",
value: "leaf1"
},
{
title: "your leaf",
value: "leaf2"
}
]
},
{
title: "parent 1-1",
value: "parent 1-1"
}
]
}
]);
const SHOW_PARENT = TreeSelect.SHOW_PARENT;
function dig(path = "0", level = 3) {
const list = [];
for (let i = 0; i < 10; i += 1) {
const value = `${path}-${i}`;
const treeNode = {
title: value,
value
};
if (level > 0) {
(treeNode as any).children = dig(value, level - 1);
}
list.push(treeNode);
}
return list;
}
const checkedKeys = ref<string[]>(["0-0-0", "0-0-1"]);
const value2 = ref<string[]>(["0-0-0"]);
const treeData2 = [
{
title: "Node1",
value: "0-0",
children: [
{
title: "Child Node1",
value: "0-0-0"
}
]
},
{
title: "Node2",
value: "0-1",
children: [
{
title: "Child Node3",
value: "0-1-0",
disabled: true
},
{
title: "Child Node4",
value: "0-1-1"
},
{
title: "Child Node5",
value: "0-1-2"
}
]
}
];
const value3 = ref<string>();
const treeData3 = ref([
{ id: 1, pId: 0, value: "1", title: "Expand to load" },
{ id: 2, pId: 0, value: "2", title: "Expand to load" },
{ id: 3, pId: 0, value: "3", title: "Tree Node", isLeaf: true }
]);
const genTreeNode = (parentId: number, isLeaf = false) => {
const random = Math.random().toString(36).substring(2, 6);
return {
id: random,
pId: parentId,
value: random,
title: isLeaf ? "Tree Node" : "Expand to load",
isLeaf
};
};
const onLoadData = treeNode => {
return new Promise(resolve => {
const { id } = treeNode.dataRef;
setTimeout(() => {
treeData3.value = (treeData3 as any).value.concat([
genTreeNode(id, false),
genTreeNode(id, true)
]);
resolve(true);
}, 300);
});
};
</script>
<template>
<el-card>
<template #header>
<div class="card-header">
<span class="font-medium">
仿antdv树选择采用
<el-link
href="https://www.npmjs.com/package/@pureadmin/components"
target="_blank"
style="font-size: 16px; margin: 0 4px 5px"
>
@pureadmin/components
</el-link>
完全兼容antdv的
<el-link
href="https://next.antdv.com/components/tree-select-cn"
target="_blank"
style="font-size: 16px; margin: 0 4px 5px"
>
TreeSelect
</el-link>
写法
</span>
</div>
</template>
<div class="flex justify-around flex-wrap">
<div>
<span>线性样式</span>
<TreeSelect
class="w-[200px]"
v-model:value="value1"
show-search
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
placeholder="Please select"
allow-clear
:tree-line="true"
tree-default-expand-all
:tree-data="treeData1"
>
<template #title="{ value: val, title }">
<b v-if="val === 'parent 1-1'" style="color: #08c">sss</b>
<template v-else>{{ title }}</template>
</template>
</TreeSelect>
</div>
<div>
<span>虚拟滚动</span>
<TreeSelect
class="w-[200px] mt-6"
v-model:value="checkedKeys"
tree-checkable
tree-default-expand-all
:show-checked-strategy="SHOW_PARENT"
:height="233"
:tree-data="dig()"
:max-tag-count="10"
>
<template #title="{ title, value }">
<span v-if="value === '0-0-1-0'" style="color: #1890ff">
{{ title }}
</span>
<template v-else>{{ title }}</template>
</template>
</TreeSelect>
</div>
<div>
<span>可勾选</span>
<TreeSelect
class="w-[200px]"
v-model:value="value2"
:tree-data="treeData2"
tree-checkable
allow-clear
:show-checked-strategy="SHOW_PARENT"
placeholder="Please select"
/>
</div>
<div>
<span>异步加载</span>
<TreeSelect
class="w-[200px]"
v-model:value="value3"
tree-data-simple-mode
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
:tree-data="treeData3"
placeholder="Please select"
:load-data="onLoadData"
/>
</div>
</div>
</el-card>
</template>

View File

@@ -2,8 +2,8 @@
import { useI18n } from "vue-i18n";
import { ref, reactive } from "vue";
import Motion from "../utils/motion";
import { message } from "@/utils/message";
import { phoneRules } from "../utils/rule";
import { message } from "@pureadmin/components";
import type { FormInstance } from "element-plus";
import { $t, transformI18n } from "@/plugins/i18n";
import { useVerifyCode } from "../utils/verifyCode";
@@ -26,7 +26,7 @@ const onLogin = async (formEl: FormInstance | undefined) => {
if (valid) {
// 模拟登录请求,需根据实际开发进行修改
setTimeout(() => {
message.success(transformI18n($t("login.loginSuccess")));
message(transformI18n($t("login.loginSuccess")), "success");
loading.value = false;
}, 2000);
} else {

View File

@@ -2,8 +2,8 @@
import { useI18n } from "vue-i18n";
import { ref, reactive } from "vue";
import Motion from "../utils/motion";
import { message } from "@/utils/message";
import { updateRules } from "../utils/rule";
import { message } from "@pureadmin/components";
import type { FormInstance } from "element-plus";
import { useVerifyCode } from "../utils/verifyCode";
import { $t, transformI18n } from "@/plugins/i18n";
@@ -45,12 +45,12 @@ const onUpdate = async (formEl: FormInstance | undefined) => {
if (checked.value) {
// 模拟请求,需根据实际开发进行修改
setTimeout(() => {
message.success(transformI18n($t("login.registerSuccess")));
message(transformI18n($t("login.registerSuccess")), "success");
loading.value = false;
}, 2000);
} else {
loading.value = false;
message.warning(transformI18n($t("login.tickPrivacy")));
message(transformI18n($t("login.tickPrivacy")), "warning");
}
} else {
loading.value = false;

View File

@@ -2,8 +2,8 @@
import { useI18n } from "vue-i18n";
import { ref, reactive } from "vue";
import Motion from "../utils/motion";
import { message } from "@/utils/message";
import { updateRules } from "../utils/rule";
import { message } from "@pureadmin/components";
import type { FormInstance } from "element-plus";
import { useVerifyCode } from "../utils/verifyCode";
import { $t, transformI18n } from "@/plugins/i18n";
@@ -42,7 +42,7 @@ const onUpdate = async (formEl: FormInstance | undefined) => {
if (valid) {
// 模拟请求,需根据实际开发进行修改
setTimeout(() => {
message.success(transformI18n($t("login.passwordUpdateReg")));
message(transformI18n($t("login.passwordUpdateReg")), "success");
loading.value = false;
}, 2000);
} else {

View File

@@ -10,6 +10,7 @@ import {
import { useI18n } from "vue-i18n";
import Motion from "./utils/motion";
import { useRouter } from "vue-router";
import { message } from "@/utils/message";
import { loginRules } from "./utils/rule";
import phone from "./components/phone.vue";
import TypeIt from "@/components/ReTypeit";
@@ -18,7 +19,6 @@ import regist from "./components/regist.vue";
import update from "./components/update.vue";
import { initRouter } from "@/router/utils";
import { useNav } from "@/layout/hooks/useNav";
import { message } from "@pureadmin/components";
import type { FormInstance } from "element-plus";
import { $t, transformI18n } from "@/plugins/i18n";
import { operates, thirdParty } from "./utils/enums";
@@ -72,8 +72,8 @@ const onLogin = async (formEl: FormInstance | undefined) => {
if (res.success) {
// 获取后端路由
initRouter().then(() => {
message.success("登录成功");
router.push("/");
message("登录成功", "success");
});
}
});

View File

@@ -1,4 +1,4 @@
import { message } from "@pureadmin/components";
import { message } from "@/utils/message";
import { tableData } from "../data";
// 如果您不习惯tsx写法可以传slot然后在template里写
@@ -56,11 +56,14 @@ export function useColumns() {
];
const handleEdit = (index: number, row) => {
message.success(`您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`);
message(
`您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`,
"success"
);
};
const handleDelete = (index: number, row) => {
message.error(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`);
message(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`, "info");
};
return {

View File

@@ -1,4 +1,4 @@
import { message } from "@pureadmin/components";
import { message } from "@/utils/message";
import { tableData } from "../data";
import { ref, computed } from "vue";
@@ -15,11 +15,14 @@ export function useColumns() {
);
const handleEdit = (index: number, row) => {
message.success(`您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`);
message(
`您编辑了第 ${index} 行,数据为:${JSON.stringify(row)}`,
"success"
);
};
const handleDelete = (index: number, row) => {
message.error(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`);
message(`您删除了第 ${index} 行,数据为:${JSON.stringify(row)}`, "info");
};
const columns: TableColumnList = [

View File

@@ -1,10 +1,16 @@
<script setup lang="ts">
import { ref } from "vue";
import { list } from "./high/list";
import { Tabs, TabPane } from "@pureadmin/components";
defineOptions({
name: "PureTableHigh"
});
const selected = ref(0);
function tabClick({ index }) {
selected.value = index;
}
</script>
<template>
@@ -32,21 +38,30 @@ defineOptions({
:closable="false"
/>
<Tabs :destroyInactiveTabPane="true">
<TabPane v-for="item of list" :key="item.key">
<template #tab>
<el-tooltip :content="item.content" placement="top-end">
<span>{{ item.title }}</span>
</el-tooltip>
</template>
<component :is="item.component" />
</TabPane>
</Tabs>
<el-tabs @tab-click="tabClick">
<template v-for="(item, index) of list" :key="item.key">
<el-tab-pane :lazy="true">
<template #label>
<el-tooltip
:content="`(第 ${index + 1} 个示例)${item.content}`"
placement="top-end"
>
<span>{{ item.title }}</span>
</el-tooltip>
</template>
<component v-if="selected == index" :is="item.component" />
</el-tab-pane>
</template>
</el-tabs>
</el-card>
</template>
<style scoped>
:deep(.ant-tabs-content-holder) {
:deep(.el-tabs__nav-wrap)::after {
height: 1px;
}
:deep(.el-tabs__header) {
margin-top: 10px;
}

View File

@@ -1,7 +1,7 @@
import { ref } from "vue";
import { tableDataDrag } from "../data";
import { clone } from "@pureadmin/utils";
import { message } from "@pureadmin/components";
import { message } from "@/utils/message";
import { CustomMouseMenu } from "@howdyjs/mouse-menu";
export function useColumns() {
@@ -33,10 +33,11 @@ export function useColumns() {
label: "编辑",
tips: "Edit",
fn: row =>
message.success(
message(
`您编辑了第 ${
dataList.value.findIndex(v => v.id === row.id) + 1
} 行,数据为:${JSON.stringify(row)}`
} 行,数据为:${JSON.stringify(row)}`,
"success"
)
}
]

View File

@@ -5,9 +5,9 @@ import {
type EchartOptions
} from "@pureadmin/utils";
import { tableDataDrag } from "../data";
import { message } from "@/utils/message";
import { templateRef } from "@vueuse/core";
import { ref, type Ref, computed } from "vue";
import { message } from "@pureadmin/components";
export function useColumns() {
const dataList = ref(clone(tableDataDrag, true).splice(0, 4));
@@ -76,8 +76,9 @@ export function useColumns() {
{
name: "click",
callback: ({ data: { name, value } }) => {
message.success(
`您点击了第 ${i + 1} 行,图表标题为${name},图表数据为:${value}`
message(
`您点击了第 ${i + 1} 行,图表标题为${name},图表数据为:${value}`,
"success"
);
}
}

View File

@@ -1,6 +1,6 @@
import { tableDataEdit } from "../data";
import { message } from "@/utils/message";
import { ref, computed, Transition } from "vue";
import { message } from "@pureadmin/components";
import { clone, delay } from "@pureadmin/utils";
// 温馨提示编辑整行方法雷同将cellRenderer后面渲染的组件抽出来做对应处理即可
@@ -109,10 +109,11 @@ export function useColumns() {
function onSure(index) {
dataList.value[index].id = inputValMap.value[index].value;
message.success(
message(
`您编辑了第 ${index + 1} 行,编辑后数据为:${JSON.stringify(
dataList.value[index]
)}`
)}`,
"success"
);
// 编辑状态关闭
editStatus.value[index] = Object.assign({}, editStatus.value[index], {

View File

@@ -2,7 +2,7 @@ import { ref } from "vue";
import { utils, writeFile } from "xlsx";
import { tableDataDrag } from "../data";
import { clone } from "@pureadmin/utils";
import { message } from "@pureadmin/components";
import { message } from "@/utils/message";
export function useColumns() {
const dataList = ref(clone(tableDataDrag, true));
@@ -39,7 +39,7 @@ export function useColumns() {
const workBook = utils.book_new();
utils.book_append_sheet(workBook, workSheet, "数据报表");
writeFile(workBook, "pure-admin-table.xlsx");
message.success("导出成功");
message("导出成功", "success");
};
return {

View File

@@ -1,6 +1,5 @@
<script setup lang="ts">
import { list } from "./base/list";
import { Tabs, TabPane } from "@pureadmin/components";
defineOptions({
name: "PureTable"
@@ -33,21 +32,30 @@ defineOptions({
:closable="false"
/>
<Tabs :destroyInactiveTabPane="true">
<TabPane v-for="item of list" :key="item.key">
<template #tab>
<el-tooltip :content="item.content" placement="top-end">
<span>{{ item.title }}</span>
</el-tooltip>
</template>
<component :is="item.component" />
</TabPane>
</Tabs>
<el-tabs>
<template v-for="(item, index) of list" :key="item.key">
<el-tab-pane>
<template #label>
<el-tooltip
:content="`(第 ${index + 1} 个示例)${item.content}`"
placement="top-end"
>
<span>{{ item.title }}</span>
</el-tooltip>
</template>
<component :is="item.component" />
</el-tab-pane>
</template>
</el-tabs>
</el-card>
</template>
<style scoped>
:deep(.ant-tabs-content-holder) {
:deep(.el-tabs__nav-wrap)::after {
height: 1px;
}
:deep(.el-tabs__header) {
margin-top: 10px;
}

View File

@@ -1,7 +1,7 @@
import { ref } from "vue";
import dayjs from "dayjs";
import { message } from "@/utils/message";
import { ElMessageBox } from "element-plus";
import { Switch, message } from "@pureadmin/components";
export function useColumns() {
const switchLoadMap = ref({});
@@ -53,14 +53,15 @@ export function useColumns() {
prop: "status",
width: 130,
cellRenderer: scope => (
<Switch
<el-switch
size={scope.props.size === "small" ? "small" : "default"}
loading={switchLoadMap.value[scope.index]?.loading}
v-model:checked={scope.row.status}
checkedValue={1}
unCheckedValue={0}
checked-children="已开启"
un-checked-children="已关闭"
v-model={scope.row.status}
active-value={1}
inactive-value={0}
active-text="已开启"
inactive-text="已关闭"
inline-prompt
onChange={() => onChange(scope as any)}
/>
)
@@ -112,7 +113,7 @@ export function useColumns() {
loading: false
}
);
message.success("已成功修改角色状态");
message("已成功修改角色状态", "success");
}, 300);
})
.catch(() => {

View File

@@ -1,7 +1,7 @@
import { ref } from "vue";
import dayjs from "dayjs";
import { message } from "@/utils/message";
import { ElMessageBox } from "element-plus";
import { Switch, message } from "@pureadmin/components";
export function useColumns() {
const switchLoadMap = ref({});
@@ -58,14 +58,15 @@ export function useColumns() {
prop: "status",
width: 130,
cellRenderer: scope => (
<Switch
<el-switch
size={scope.props.size === "small" ? "small" : "default"}
loading={switchLoadMap.value[scope.index]?.loading}
v-model:checked={scope.row.status}
checkedValue={1}
unCheckedValue={0}
checked-children="已开启"
un-checked-children="已关闭"
v-model={scope.row.status}
active-value={1}
inactive-value={0}
active-text="已开启"
inactive-text="已关闭"
inline-prompt
onChange={() => onChange(scope as any)}
/>
)
@@ -117,7 +118,7 @@ export function useColumns() {
loading: false
}
);
message.success("已成功修改用户状态");
message("已成功修改用户状态", "success");
}, 300);
})
.catch(() => {

View File

@@ -1,16 +1,15 @@
<script setup lang="ts">
import { ref, computed } from "vue";
import { clone } from "@pureadmin/utils";
import { transformI18n } from "@/plugins/i18n";
import { TreeSelect } from "@pureadmin/components";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
import { usePermissionStoreHook } from "@/store/modules/permission";
import {
deleteChildren,
getNodeByUniqueId,
appendFieldByUniqueId
} from "@/utils/tree";
import { useDetail } from "./hooks";
import { ref, computed } from "vue";
import { clone } from "@pureadmin/utils";
import { transformI18n } from "@/plugins/i18n";
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
import { usePermissionStoreHook } from "@/store/modules/permission";
defineOptions({
name: "Tabs"
@@ -25,14 +24,15 @@ const treeData = computed(() => {
});
});
const value = ref<string[]>([]);
const currentValues = ref<string[]>([]);
const multiTags = computed(() => {
return useMultiTagsStoreHook()?.multiTags;
});
function onCloseTags() {
value.value.forEach(uniqueId => {
if (currentValues.value.length === 0) return;
currentValues.value.forEach(uniqueId => {
const currentPath =
getNodeByUniqueId(treeData.value, uniqueId).redirect ??
getNodeByUniqueId(treeData.value, uniqueId).path;
@@ -77,32 +77,27 @@ function onCloseTags() {
</div>
<el-divider />
<TreeSelect
<el-tree-select
class="w-[300px]"
v-model:value="value"
show-search
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
node-key="uniqueId"
placeholder="请选择要关闭的标签"
:fieldNames="{
children: 'children',
key: 'uniqueId',
value: 'uniqueId'
}"
allow-clear
clearable
multiple
tree-default-expand-all
:tree-data="treeData"
filterable
default-expand-all
:props="{
label: data => transformI18n(data.meta.title),
value: 'uniqueId',
children: 'children',
disabled: 'disabled'
}"
:data="treeData"
v-model="currentValues"
>
<template #tagRender="{ closable, onClose, option }">
<el-tag class="mr-[3px]" :closable="closable" @close="onClose">
{{ transformI18n(option.meta.title) }}
</el-tag>
</template>
<template #title="{ data }">
<template #default="{ data }">
<span>{{ transformI18n(data.meta.title) }}</span>
</template>
</TreeSelect>
</el-tree-select>
<el-button class="m-2" @click="onCloseTags">关闭标签</el-button>
<el-divider />