Merge branch 'main' of github.com:pure-admin/vue-pure-admin into gitee

This commit is contained in:
xiaoxian521
2023-05-10 01:52:32 +08:00
13 changed files with 341 additions and 13 deletions

View File

@@ -128,7 +128,7 @@ interface DialogOptions extends DialogProps {
close: Function;
titleId: string;
titleClass: string;
}) => VNode;
}) => VNode | Component;
/** 自定义内容渲染器 */
contentRenderer?: ({
options,
@@ -136,7 +136,7 @@ interface DialogOptions extends DialogProps {
}: {
options: DialogOptions;
index: number;
}) => VNode;
}) => VNode | Component;
/** 自定义按钮操作区的内容渲染器,会覆盖`footerButtons`以及默认的 `取消` 和 `确定` 按钮 */
footerRenderer?: ({
options,
@@ -144,7 +144,7 @@ interface DialogOptions extends DialogProps {
}: {
options: DialogOptions;
index: number;
}) => VNode;
}) => VNode | Component;
/** 自定义底部按钮操作 */
footerButtons?: Array<ButtonProps>;
/** `Dialog` 打开后的回调 */

View File

@@ -60,6 +60,7 @@ onBeforeMount(() => {
watch(
() => [route.path, usePermissionStoreHook().wholeMenus],
() => {
if (route.path.includes("/redirect")) return;
getSubMenuData(route.path);
menuSelect(route.path, routers);
}

View File

@@ -169,6 +169,7 @@ function onFresh() {
path: "/redirect" + fullPath,
query
});
handleAliveRoute(route as toRouteType, "refresh");
}
function deleteDynamicTag(obj: any, current: any, tag?: string) {

View File

@@ -270,6 +270,12 @@ function handleAliveRoute({ name }: toRouteType, mode?: string) {
name
});
break;
case "refresh":
usePermissionStoreHook().cacheOperate({
mode: "refresh",
name
});
break;
default:
usePermissionStoreHook().cacheOperate({
mode: "delete",

View File

@@ -24,13 +24,15 @@ export const usePermissionStore = defineStore({
);
},
cacheOperate({ mode, name }: cacheType) {
const delIndex = this.cachePageList.findIndex(v => v === name);
switch (mode) {
case "refresh":
this.cachePageList = this.cachePageList.filter(v => v !== name);
break;
case "add":
this.cachePageList.push(name);
break;
case "delete":
// eslint-disable-next-line no-case-declarations
const delIndex = this.cachePageList.findIndex(v => v === name);
delIndex !== -1 && this.cachePageList.splice(delIndex, 1);
break;
}

View File

@@ -0,0 +1,45 @@
<script setup lang="ts">
import { ref } from "vue";
// 声明 props 类型
export interface FormProps {
formInline: {
user: string;
region: string;
};
}
// 声明 props 默认值
// 推荐阅读https://cn.vuejs.org/guide/typescript/composition-api.html#typing-component-props
const props = withDefaults(defineProps<FormProps>(), {
formInline: () => ({ user: "", region: "" })
});
// vue 规定所有的 prop 都遵循着单向绑定原则,不能在子组件中更改 prop 值,该 form.vue 文件为子组件
// 如果需要拿到初始化的 prop 值并使得组件变量可修改,则需要在子组件定义一个新的变量接受这个子组件的 prop
// 推荐阅读https://cn.vuejs.org/guide/components/props.html#one-way-data-flow
const newFormInline = ref(props.formInline);
</script>
<template>
<el-form :model="newFormInline">
<el-form-item label="姓名">
<el-input
class="!w-[220px]"
v-model="newFormInline.user"
placeholder="请输入姓名"
/>
</el-form-item>
<el-form-item label="城市">
<el-select
class="!w-[220px]"
v-model="newFormInline.region"
placeholder="请选择城市"
>
<el-option label="上海" value="上海" />
<el-option label="浙江" value="浙江" />
<el-option label="深圳" value="深圳" />
</el-select>
</el-form-item>
</el-form>
</template>

View File

@@ -1,6 +1,8 @@
<script setup lang="tsx">
import { h, createVNode } from "vue";
import { h, createVNode, ref } from "vue";
import { message } from "@/utils/message";
import { cloneDeep } from "@pureadmin/utils";
import forms, { type FormProps } from "./form.vue";
import { addDialog, closeDialog, closeAllDialog } from "@/components/ReDialog";
defineOptions({
@@ -225,6 +227,102 @@ function onNestingClick() {
)
});
}
// 结合Form表单第一种方式弹框关闭立刻恢复初始值通过 props 属性接收子组件的 prop 并赋值
function onFormOneClick() {
addDialog({
width: "30%",
title: "结合Form表单第一种方式",
contentRenderer: () => forms,
props: {
// 赋默认值
formInline: {
user: "菜虚鲲",
region: "浙江"
}
},
closeCallBack: ({ options, args }) => {
// options.props 是响应式的
const { formInline } = options.props as FormProps;
const text = `姓名:${formInline.user} 城市:${formInline.region}`;
if (args?.command === "cancel") {
// 您点击了取消按钮
message(`您点击了取消按钮,当前表单数据为 ${text}`);
} else if (args?.command === "sure") {
message(`您点击了确定按钮,当前表单数据为 ${text}`);
} else {
message(`您点击了右上角关闭按钮或者空白页,当前表单数据为 ${text}`);
}
}
});
}
// 结合Form表单第二种方式h 渲染函数 https://cn.vuejs.org/api/render-function.html#h
const formInline = ref({
user: "菜虚鲲",
region: "浙江"
});
const resetFormInline = cloneDeep(formInline.value);
function onFormTwoClick() {
addDialog({
width: "30%",
title: "结合Form表单第二种方式",
contentRenderer: () => h(forms, { formInline: formInline.value }),
closeCallBack: () => {
message(
`当前表单数据为 姓名:${formInline.value.user} 城市:${formInline.value.region}`
);
// 重置表单数据
formInline.value = cloneDeep(resetFormInline);
}
});
}
// 结合Form表单第三种方式createVNode 渲染函数 https://cn.vuejs.org/guide/extras/render-function.html#creating-vnodes
const formThreeInline = ref({
user: "菜虚鲲",
region: "浙江"
});
const resetFormThreeInline = cloneDeep(formThreeInline.value);
function onFormThreeClick() {
addDialog({
width: "30%",
title: "结合Form表单第三种方式",
contentRenderer: () =>
createVNode(forms, { formInline: formThreeInline.value }),
closeCallBack: () => {
message(
`当前表单数据为 姓名:${formThreeInline.value.user} 城市:${formThreeInline.value.region}`
);
// 重置表单数据
formThreeInline.value = cloneDeep(resetFormThreeInline);
}
});
}
// 结合Form表单第四种方式使用jsx语法
// 需要注意的是如果 forms 没注册,这里 forms 注册了是因为上面 contentRenderer: () => forms、h(forms) 、createVNode(createVNode) 间接给注册了
// 如果只使用了jsx语法如下 `contentRenderer: () => <forms formInline={formFourInline.value} />` 是不会给 forms 组件进行注册的,需要在 `script` 中任意位置(最好是末尾)写上 forms 即可
// 同理如果在 tsx 文件中,这么使用 `contentRenderer: () => <forms formInline={formFourInline.value} />`,也是不会给 forms 组件进行注册,需要在 return 中写上 forms
const formFourInline = ref({
user: "菜虚鲲",
region: "浙江"
});
const resetFormFourInline = cloneDeep(formFourInline.value);
function onFormFourClick() {
addDialog({
width: "30%",
title: "结合Form表单第四种方式",
contentRenderer: () => <forms formInline={formFourInline.value} />,
closeCallBack: () => {
message(
`当前表单数据为 姓名:${formFourInline.value.user} 城市:${formFourInline.value.region}`
);
// 重置表单数据
formFourInline.value = cloneDeep(resetFormFourInline);
}
});
}
</script>
<template>
@@ -267,5 +365,20 @@ function onNestingClick() {
<el-button @click="onCloseCallBackClick"> 关闭后的回调 </el-button>
<el-button @click="onNestingClick"> 嵌套的弹框 </el-button>
</el-space>
<el-divider />
<el-space wrap>
<el-button @click="onFormOneClick">
结合Form表单第一种方式
</el-button>
<el-button @click="onFormTwoClick">
结合Form表单第二种方式
</el-button>
<el-button @click="onFormThreeClick">
结合Form表单第三种方式
</el-button>
<el-button @click="onFormFourClick">
结合Form表单第四种方式
</el-button>
</el-space>
</el-card>
</template>

View File

@@ -6,6 +6,7 @@ import Bar from "./components/Bar.vue";
import Pie from "./components/Pie.vue";
import Line from "./components/Line.vue";
import TypeIt from "@/components/ReTypeit";
import { useWindowSize } from "@vueuse/core";
import { ref, computed, markRaw } from "vue";
import Github from "./components/Github.vue";
import { randomColor } from "@pureadmin/utils";
@@ -17,10 +18,13 @@ defineOptions({
const list = ref();
const loading = ref<boolean>(true);
const { version } = __APP_INFO__.pkg;
const titleClass = computed(() => {
return ["text-base", "font-medium"];
});
const { height } = useWindowSize();
setTimeout(() => {
loading.value = !loading.value;
}, 800);
@@ -65,7 +69,10 @@ axios
}
}"
>
<el-card shadow="never" style="height: 347px">
<el-card
shadow="never"
:style="{ height: `calc(${height}px - 35vh - 250px)` }"
>
<template #header>
<a
:class="titleClass"
@@ -74,15 +81,15 @@ axios
>
<TypeIt
:className="'type-it2'"
:values="['PureAdmin 版本日志']"
:values="[`PureAdmin 版本日志(当前版本 v${version}`]"
:cursor="false"
:speed="80"
:speed="60"
/>
</a>
</template>
<el-skeleton animated :rows="7" :loading="loading">
<template #default>
<el-scrollbar height="324px">
<el-scrollbar :height="`calc(${height}px - 35vh - 340px)`">
<el-timeline v-show="list?.length > 0">
<el-timeline-item
v-for="(item, index) in list"
@@ -120,7 +127,10 @@ axios
}
}"
>
<el-card shadow="never" style="height: 347px">
<el-card
shadow="never"
:style="{ height: `calc(${height}px - 35vh - 250px)` }"
>
<template #header>
<a
:class="titleClass"