mirror of
				https://github.com/pure-admin/vue-pure-admin.git
				synced 2025-11-03 13:44:47 +08:00 
			
		
		
		
	Merge branch 'main' into pages
This commit is contained in:
		
						commit
						9d351ab600
					
				@ -180,17 +180,18 @@ You are very welcome to join       |    [code](https://github.com/pure-admin/vue-pure-admin/commits?author=hb0730)    |
 | 
					|       [hb0730](https://github.com/hb0730)       | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=hb0730) |
 | 
				
			||||||
|         [o-cc](https://github.com/o-cc)         |     [code](https://github.com/pure-admin/vue-pure-admin/commits?author=o-cc)     |
 | 
					|         [o-cc](https://github.com/o-cc)         | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=o-cc) |
 | 
				
			||||||
| [yj-liuzepeng](https://github.com/yj-liuzepeng) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=yj-liuzepeng) |
 | 
					| [yj-liuzepeng](https://github.com/yj-liuzepeng) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=yj-liuzepeng) |
 | 
				
			||||||
|   [skyline523](https://github.com/skyline523)   |  [code](https://github.com/pure-admin/vue-pure-admin/commits?author=skyline523)  |
 | 
					|   [skyline523](https://github.com/skyline523)   | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=skyline523) |
 | 
				
			||||||
| [shark-lajiao](https://github.com/shark-lajiao) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=shark-lajiao) |
 | 
					| [shark-lajiao](https://github.com/shark-lajiao) | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=shark-lajiao) |
 | 
				
			||||||
|      [WitMiao](https://github.com/WitMiao)      |   [code](https://github.com/pure-admin/vue-pure-admin/commits?author=WitMiao)    |
 | 
					|      [WitMiao](https://github.com/WitMiao)      | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=WitMiao) |
 | 
				
			||||||
|     [QFifteen](https://github.com/QFifteen)     |   [code](https://github.com/pure-admin/vue-pure-admin/commits?author=QFifteen)   |
 | 
					|     [QFifteen](https://github.com/QFifteen)     | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=QFifteen) |
 | 
				
			||||||
|      [edgexie](https://github.com/edgexie)      |   [code](https://github.com/pure-admin/vue-pure-admin/commits?author=edgexie)    |
 | 
					|      [edgexie](https://github.com/edgexie)      | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=edgexie) |
 | 
				
			||||||
|       [way-jm](https://github.com/way-jm)       |    [code](https://github.com/pure-admin/vue-pure-admin/commits?author=way-jm)    |
 | 
					|       [way-jm](https://github.com/way-jm)       | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=way-jm) |
 | 
				
			||||||
 | 
					|   [simple-hui](https://github.com/simple-hui)   | [code](https://github.com/pure-admin/vue-pure-admin/commits?author=simple-hui) |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Git Contribution submission specification
 | 
					## Git Contribution submission specification
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										19
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								README.md
									
									
									
									
									
								
							@ -181,17 +181,18 @@ docker run -dp 8080:80  --name pure-admin vue-pure-admin
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
非常感谢你们能深入了解源码并对 `pure-admin` 组织作出优秀贡献 ❤️
 | 
					非常感谢你们能深入了解源码并对 `pure-admin` 组织作出优秀贡献 ❤️
 | 
				
			||||||
 | 
					
 | 
				
			||||||
|                   **贡献人**                    |                                   **具体代码**                                   |
 | 
					|                   **贡献人**                    |                         **具体代码**                         |
 | 
				
			||||||
| :---------------------------------------------: | :------------------------------------------------------------------------------: |
 | 
					| :---------------------------------------------: | :----------------------------------------------------------: |
 | 
				
			||||||
|       [hb0730](https://github.com/hb0730)       |    [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=hb0730)    |
 | 
					|       [hb0730](https://github.com/hb0730)       | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=hb0730) |
 | 
				
			||||||
|         [o-cc](https://github.com/o-cc)         |     [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=o-cc)     |
 | 
					|         [o-cc](https://github.com/o-cc)         | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=o-cc) |
 | 
				
			||||||
| [yj-liuzepeng](https://github.com/yj-liuzepeng) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=yj-liuzepeng) |
 | 
					| [yj-liuzepeng](https://github.com/yj-liuzepeng) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=yj-liuzepeng) |
 | 
				
			||||||
|   [skyline523](https://github.com/skyline523)   |  [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=skyline523)  |
 | 
					|   [skyline523](https://github.com/skyline523)   | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=skyline523) |
 | 
				
			||||||
| [shark-lajiao](https://github.com/shark-lajiao) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=shark-lajiao) |
 | 
					| [shark-lajiao](https://github.com/shark-lajiao) | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=shark-lajiao) |
 | 
				
			||||||
|      [WitMiao](https://github.com/WitMiao)      |   [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=WitMiao)    |
 | 
					|      [WitMiao](https://github.com/WitMiao)      | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=WitMiao) |
 | 
				
			||||||
|     [QFifteen](https://github.com/QFifteen)     |   [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=QFifteen)   |
 | 
					|     [QFifteen](https://github.com/QFifteen)     | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=QFifteen) |
 | 
				
			||||||
|      [edgexie](https://github.com/edgexie)      |   [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=edgexie)    |
 | 
					|      [edgexie](https://github.com/edgexie)      | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=edgexie) |
 | 
				
			||||||
|       [way-jm](https://github.com/way-jm)       |    [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=way-jm)    |
 | 
					|       [way-jm](https://github.com/way-jm)       | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=way-jm) |
 | 
				
			||||||
 | 
					|   [simple-hui](https://github.com/simple-hui)   | [代码](https://github.com/pure-admin/vue-pure-admin/commits?author=simple-hui) |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## `Git` 贡献提交规范
 | 
					## `Git` 贡献提交规范
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -83,6 +83,7 @@ menus:
 | 
				
			|||||||
  pureFive: "500"
 | 
					  pureFive: "500"
 | 
				
			||||||
  pureComponents: Components
 | 
					  pureComponents: Components
 | 
				
			||||||
  pureDialog: Dialog
 | 
					  pureDialog: Dialog
 | 
				
			||||||
 | 
					  pureDrawer: Drawer
 | 
				
			||||||
  pureMessage: Message Tips
 | 
					  pureMessage: Message Tips
 | 
				
			||||||
  pureVideo: Video
 | 
					  pureVideo: Video
 | 
				
			||||||
  pureSegmented: Segmented
 | 
					  pureSegmented: Segmented
 | 
				
			||||||
 | 
				
			|||||||
@ -83,6 +83,7 @@ menus:
 | 
				
			|||||||
  pureFive: "500"
 | 
					  pureFive: "500"
 | 
				
			||||||
  pureComponents: 组件
 | 
					  pureComponents: 组件
 | 
				
			||||||
  pureDialog: 函数式弹框
 | 
					  pureDialog: 函数式弹框
 | 
				
			||||||
 | 
					  pureDrawer: 函数式抽屉
 | 
				
			||||||
  pureMessage: 消息提示
 | 
					  pureMessage: 消息提示
 | 
				
			||||||
  pureVideo: 视频
 | 
					  pureVideo: 视频
 | 
				
			||||||
  pureSegmented: 分段控制器
 | 
					  pureSegmented: 分段控制器
 | 
				
			||||||
@ -233,4 +234,4 @@ login:
 | 
				
			|||||||
  purePassWordRuleReg: 密码格式应为8-18位数字、字母、符号的任意两种组合
 | 
					  purePassWordRuleReg: 密码格式应为8-18位数字、字母、符号的任意两种组合
 | 
				
			||||||
  purePassWordSureReg: 请输入确认密码
 | 
					  purePassWordSureReg: 请输入确认密码
 | 
				
			||||||
  purePassWordDifferentReg: 两次密码不一致!
 | 
					  purePassWordDifferentReg: 两次密码不一致!
 | 
				
			||||||
  purePassWordUpdateReg: 修改密码成功
 | 
					  purePassWordUpdateReg: 修改密码成功
 | 
				
			||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
  <el-config-provider :locale="currentLocale">
 | 
					  <el-config-provider :locale="currentLocale">
 | 
				
			||||||
    <router-view />
 | 
					    <router-view />
 | 
				
			||||||
    <ReDialog />
 | 
					    <ReDialog />
 | 
				
			||||||
 | 
					    <ReDrawer />
 | 
				
			||||||
  </el-config-provider>
 | 
					  </el-config-provider>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -10,6 +11,7 @@ import { defineComponent } from "vue";
 | 
				
			|||||||
import { checkVersion } from "version-rocket";
 | 
					import { checkVersion } from "version-rocket";
 | 
				
			||||||
import { ElConfigProvider } from "element-plus";
 | 
					import { ElConfigProvider } from "element-plus";
 | 
				
			||||||
import { ReDialog } from "@/components/ReDialog";
 | 
					import { ReDialog } from "@/components/ReDialog";
 | 
				
			||||||
 | 
					import { ReDrawer } from "@/components/ReDrawer";
 | 
				
			||||||
import en from "element-plus/es/locale/lang/en";
 | 
					import en from "element-plus/es/locale/lang/en";
 | 
				
			||||||
import zhCn from "element-plus/es/locale/lang/zh-cn";
 | 
					import zhCn from "element-plus/es/locale/lang/zh-cn";
 | 
				
			||||||
import plusEn from "plus-pro-components/es/locale/lang/en";
 | 
					import plusEn from "plus-pro-components/es/locale/lang/en";
 | 
				
			||||||
@ -20,7 +22,8 @@ export default defineComponent({
 | 
				
			|||||||
  name: "app",
 | 
					  name: "app",
 | 
				
			||||||
  components: {
 | 
					  components: {
 | 
				
			||||||
    [ElConfigProvider.name]: ElConfigProvider,
 | 
					    [ElConfigProvider.name]: ElConfigProvider,
 | 
				
			||||||
    ReDialog
 | 
					    ReDialog,
 | 
				
			||||||
 | 
					    ReDrawer
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  computed: {
 | 
					  computed: {
 | 
				
			||||||
    currentLocale() {
 | 
					    currentLocale() {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										64
									
								
								src/components/ReDrawer/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/components/ReDrawer/index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					import { ref } from "vue";
 | 
				
			||||||
 | 
					import reDrawer from "./index.vue";
 | 
				
			||||||
 | 
					import { useTimeoutFn } from "@vueuse/core";
 | 
				
			||||||
 | 
					import { withInstall } from "@pureadmin/utils";
 | 
				
			||||||
 | 
					import type {
 | 
				
			||||||
 | 
					  EventType,
 | 
				
			||||||
 | 
					  ArgsType,
 | 
				
			||||||
 | 
					  DrawerProps,
 | 
				
			||||||
 | 
					  DrawerOptions,
 | 
				
			||||||
 | 
					  ButtonProps
 | 
				
			||||||
 | 
					} from "./type";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const drawerStore = ref<Array<DrawerOptions>>([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 打开抽屉 */
 | 
				
			||||||
 | 
					const addDrawer = (options: DrawerOptions) => {
 | 
				
			||||||
 | 
					  const open = () =>
 | 
				
			||||||
 | 
					    drawerStore.value.push(Object.assign(options, { visible: true }));
 | 
				
			||||||
 | 
					  if (options?.openDelay) {
 | 
				
			||||||
 | 
					    useTimeoutFn(() => {
 | 
				
			||||||
 | 
					      open();
 | 
				
			||||||
 | 
					    }, options.openDelay);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    open();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 关闭抽屉 */
 | 
				
			||||||
 | 
					const closeDrawer = (options: DrawerOptions, index: number, args?: any) => {
 | 
				
			||||||
 | 
					  drawerStore.value[index].visible = false;
 | 
				
			||||||
 | 
					  options.closeCallBack && options.closeCallBack({ options, index, args });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const closeDelay = options?.closeDelay ?? 200;
 | 
				
			||||||
 | 
					  useTimeoutFn(() => {
 | 
				
			||||||
 | 
					    drawerStore.value.splice(index, 1);
 | 
				
			||||||
 | 
					  }, closeDelay);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @description 更改抽屉自身属性值
 | 
				
			||||||
 | 
					 * @param value 属性值
 | 
				
			||||||
 | 
					 * @param key 属性,默认`title`
 | 
				
			||||||
 | 
					 * @param index 弹框索引(默认`0`,代表只有一个弹框,对于嵌套弹框要改哪个弹框的属性值就把该弹框索引赋给`index`)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					const updateDrawer = (value: any, key = "title", index = 0) => {
 | 
				
			||||||
 | 
					  drawerStore.value[index][key] = value;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 关闭所有弹框 */
 | 
				
			||||||
 | 
					const closeAllDrawer = () => {
 | 
				
			||||||
 | 
					  drawerStore.value = [];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const ReDrawer = withInstall(reDrawer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type { EventType, ArgsType, DrawerOptions, DrawerProps, ButtonProps };
 | 
				
			||||||
 | 
					export {
 | 
				
			||||||
 | 
					  ReDrawer,
 | 
				
			||||||
 | 
					  drawerStore,
 | 
				
			||||||
 | 
					  addDrawer,
 | 
				
			||||||
 | 
					  closeDrawer,
 | 
				
			||||||
 | 
					  updateDrawer,
 | 
				
			||||||
 | 
					  closeAllDrawer
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										169
									
								
								src/components/ReDrawer/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								src/components/ReDrawer/index.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  type EventType,
 | 
				
			||||||
 | 
					  type ButtonProps,
 | 
				
			||||||
 | 
					  type DrawerOptions,
 | 
				
			||||||
 | 
					  closeDrawer,
 | 
				
			||||||
 | 
					  drawerStore
 | 
				
			||||||
 | 
					} from "./index";
 | 
				
			||||||
 | 
					import { computed, ref } from "vue";
 | 
				
			||||||
 | 
					import { isFunction } from "@pureadmin/utils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					defineOptions({
 | 
				
			||||||
 | 
					  name: "ReDrawer"
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const sureBtnMap = ref({});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const footerButtons = computed(() => {
 | 
				
			||||||
 | 
					  return (options: DrawerOptions) => {
 | 
				
			||||||
 | 
					    return options?.footerButtons?.length > 0
 | 
				
			||||||
 | 
					      ? options.footerButtons
 | 
				
			||||||
 | 
					      : ([
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            label: "取消",
 | 
				
			||||||
 | 
					            text: true,
 | 
				
			||||||
 | 
					            bg: true,
 | 
				
			||||||
 | 
					            btnClick: ({ drawer: { options, index } }) => {
 | 
				
			||||||
 | 
					              const done = () =>
 | 
				
			||||||
 | 
					                closeDrawer(options, index, { command: "cancel" });
 | 
				
			||||||
 | 
					              if (options?.beforeCancel && isFunction(options?.beforeCancel)) {
 | 
				
			||||||
 | 
					                options.beforeCancel(done, { options, index });
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                done();
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          },
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            label: "确定",
 | 
				
			||||||
 | 
					            type: "primary",
 | 
				
			||||||
 | 
					            text: true,
 | 
				
			||||||
 | 
					            bg: true,
 | 
				
			||||||
 | 
					            popConfirm: options?.popConfirm,
 | 
				
			||||||
 | 
					            btnClick: ({ drawer: { options, index } }) => {
 | 
				
			||||||
 | 
					              if (options?.sureBtnLoading) {
 | 
				
			||||||
 | 
					                sureBtnMap.value[index] = Object.assign(
 | 
				
			||||||
 | 
					                  {},
 | 
				
			||||||
 | 
					                  sureBtnMap.value[index],
 | 
				
			||||||
 | 
					                  {
 | 
				
			||||||
 | 
					                    loading: true
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					              const closeLoading = () => {
 | 
				
			||||||
 | 
					                if (options?.sureBtnLoading) {
 | 
				
			||||||
 | 
					                  sureBtnMap.value[index].loading = false;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					              const done = () => {
 | 
				
			||||||
 | 
					                closeLoading();
 | 
				
			||||||
 | 
					                closeDrawer(options, index, { command: "sure" });
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					              if (options?.beforeSure && isFunction(options?.beforeSure)) {
 | 
				
			||||||
 | 
					                options.beforeSure(done, { options, index, closeLoading });
 | 
				
			||||||
 | 
					              } else {
 | 
				
			||||||
 | 
					                done();
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ] as Array<ButtonProps>);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function eventsCallBack(
 | 
				
			||||||
 | 
					  event: EventType,
 | 
				
			||||||
 | 
					  options: DrawerOptions,
 | 
				
			||||||
 | 
					  index: number
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  if (options?.[event] && isFunction(options?.[event])) {
 | 
				
			||||||
 | 
					    return options?.[event]({ options, index });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param {DrawerOptions} options - 包含抽屉相关配置的对象
 | 
				
			||||||
 | 
					 * @param {number} index - 抽屉的索引
 | 
				
			||||||
 | 
					 * @param {Object} args - 传递给关闭抽屉操作的参数对象,默认为 { command: 'close' }
 | 
				
			||||||
 | 
					 * @returns {void} 这个函数不返回任何值
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function handleClose(
 | 
				
			||||||
 | 
					  options: DrawerOptions,
 | 
				
			||||||
 | 
					  index: number,
 | 
				
			||||||
 | 
					  args = { command: "close" }
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  closeDrawer(options, index, args);
 | 
				
			||||||
 | 
					  eventsCallBack("close", options, index);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <el-drawer
 | 
				
			||||||
 | 
					    v-for="(options, index) in drawerStore"
 | 
				
			||||||
 | 
					    :key="index"
 | 
				
			||||||
 | 
					    v-bind="options"
 | 
				
			||||||
 | 
					    v-model="options.visible"
 | 
				
			||||||
 | 
					    class="pure-drawer"
 | 
				
			||||||
 | 
					    :append-to-body="!!options?.appendToBody"
 | 
				
			||||||
 | 
					    :append-to="options?.appendTo ? options.appendTo : 'body'"
 | 
				
			||||||
 | 
					    :destroy-on-close="!!options?.destroyOnClose"
 | 
				
			||||||
 | 
					    :lock-scroll="!!options?.lockScroll"
 | 
				
			||||||
 | 
					    @closed="handleClose(options, index)"
 | 
				
			||||||
 | 
					    @opened="eventsCallBack('open', options, index)"
 | 
				
			||||||
 | 
					    @open-auto-focus="eventsCallBack('openAutoFocus', options, index)"
 | 
				
			||||||
 | 
					    @close-auto-focus="eventsCallBack('closeAutoFocus', options, index)"
 | 
				
			||||||
 | 
					  >
 | 
				
			||||||
 | 
					    <!-- header  -->
 | 
				
			||||||
 | 
					    <template
 | 
				
			||||||
 | 
					      v-if="options?.headerRenderer"
 | 
				
			||||||
 | 
					      #header="{ close, titleId, titleClass }"
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      <component
 | 
				
			||||||
 | 
					        :is="options?.headerRenderer({ close, titleId, titleClass })"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
 | 
					    <!--  body  -->
 | 
				
			||||||
 | 
					    <component
 | 
				
			||||||
 | 
					      v-bind="options?.props"
 | 
				
			||||||
 | 
					      :is="options.contentRenderer({ options, index })"
 | 
				
			||||||
 | 
					      @close="args => handleClose(options, index, args)"
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					    <!-- footer  -->
 | 
				
			||||||
 | 
					    <template v-if="!options?.hideFooter" #footer>
 | 
				
			||||||
 | 
					      <template v-if="options?.footerRenderer">
 | 
				
			||||||
 | 
					        <component :is="options?.footerRenderer({ options, index })" />
 | 
				
			||||||
 | 
					      </template>
 | 
				
			||||||
 | 
					      <span v-else>
 | 
				
			||||||
 | 
					        <template v-for="(btn, key) in footerButtons(options)" :key="key">
 | 
				
			||||||
 | 
					          <el-popconfirm
 | 
				
			||||||
 | 
					            v-if="btn.popConfirm"
 | 
				
			||||||
 | 
					            v-bind="btn.popConfirm"
 | 
				
			||||||
 | 
					            @confirm="
 | 
				
			||||||
 | 
					              btn.btnClick({
 | 
				
			||||||
 | 
					                drawer: { options, index },
 | 
				
			||||||
 | 
					                button: { btn, index: key }
 | 
				
			||||||
 | 
					              })
 | 
				
			||||||
 | 
					            "
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            <template #reference>
 | 
				
			||||||
 | 
					              <el-button v-bind="btn">{{ btn?.label }}</el-button>
 | 
				
			||||||
 | 
					            </template>
 | 
				
			||||||
 | 
					          </el-popconfirm>
 | 
				
			||||||
 | 
					          <el-button
 | 
				
			||||||
 | 
					            v-else
 | 
				
			||||||
 | 
					            v-bind="btn"
 | 
				
			||||||
 | 
					            :loading="key === 1 && sureBtnMap[index]?.loading"
 | 
				
			||||||
 | 
					            @click="
 | 
				
			||||||
 | 
					              btn.btnClick({
 | 
				
			||||||
 | 
					                drawer: { options, index },
 | 
				
			||||||
 | 
					                button: { btn, index: key }
 | 
				
			||||||
 | 
					              })
 | 
				
			||||||
 | 
					            "
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {{ btn?.label }}
 | 
				
			||||||
 | 
					          </el-button>
 | 
				
			||||||
 | 
					        </template>
 | 
				
			||||||
 | 
					      </span>
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
 | 
					  </el-drawer>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
							
								
								
									
										262
									
								
								src/components/ReDrawer/type.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										262
									
								
								src/components/ReDrawer/type.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,262 @@
 | 
				
			|||||||
 | 
					import type { CSSProperties, VNode, Component } from "vue";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DoneFn = (cancel?: boolean) => void;
 | 
				
			||||||
 | 
					type EventType = "open" | "close" | "openAutoFocus" | "closeAutoFocus";
 | 
				
			||||||
 | 
					type ArgsType = {
 | 
				
			||||||
 | 
					  /** `cancel` 点击取消按钮、`sure` 点击确定按钮、`close` 点击右上角关闭按钮或空白页或按下了 `esc` 键 */
 | 
				
			||||||
 | 
					  command: "cancel" | "sure" | "close";
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ButtonType =
 | 
				
			||||||
 | 
					  | "primary"
 | 
				
			||||||
 | 
					  | "success"
 | 
				
			||||||
 | 
					  | "warning"
 | 
				
			||||||
 | 
					  | "danger"
 | 
				
			||||||
 | 
					  | "info"
 | 
				
			||||||
 | 
					  | "text";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DrawerProps = {
 | 
				
			||||||
 | 
					  /** `Drawer` 的显示与隐藏 */
 | 
				
			||||||
 | 
					  visible?: boolean;
 | 
				
			||||||
 | 
					  /** `Drawer` 自身是否插入至 `body` 元素上。嵌套的 `Drawer` 必须指定该属性并赋值为 `true`,默认 `false` */
 | 
				
			||||||
 | 
					  appendToBody?: boolean;
 | 
				
			||||||
 | 
					  /** 挂载到哪个 `DOM` 元素 将覆盖 `appendToBody` */
 | 
				
			||||||
 | 
					  appendTo?: string;
 | 
				
			||||||
 | 
					  /** 是否在 `Drawer` 出现时将 `body` 滚动锁定,默认 `true` */
 | 
				
			||||||
 | 
					  lockScroll?: boolean;
 | 
				
			||||||
 | 
					  /** 关闭前的回调,会暂停 `Drawer` 的关闭 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
 | 
				
			||||||
 | 
					  beforeClose?: (done: DoneFn) => void;
 | 
				
			||||||
 | 
					  /** 是否可以通过点击 `modal` 关闭 `Drawer` ,默认 `true` */
 | 
				
			||||||
 | 
					  closeOnClickModal?: boolean;
 | 
				
			||||||
 | 
					  /** 是否可以通过按下 `ESC` 关闭 `Drawer` ,默认 `true` */
 | 
				
			||||||
 | 
					  closeOnPressEscape?: boolean;
 | 
				
			||||||
 | 
					  /** 是否显示关闭按钮,默认 `true` */
 | 
				
			||||||
 | 
					  showClose?: boolean;
 | 
				
			||||||
 | 
					  /** `Drawer` 打开的延时时间,单位毫秒,默认 `0` */
 | 
				
			||||||
 | 
					  openDelay?: number;
 | 
				
			||||||
 | 
					  /** `Drawer` 关闭的延时时间,单位毫秒,默认 `0` */
 | 
				
			||||||
 | 
					  closeDelay?: number;
 | 
				
			||||||
 | 
					  /** `Drawer` 自定义类名 */
 | 
				
			||||||
 | 
					  class?: string;
 | 
				
			||||||
 | 
					  /** `Drawer` 的自定义样式 */
 | 
				
			||||||
 | 
					  style?: CSSProperties;
 | 
				
			||||||
 | 
					  /** 控制是否在关闭 `Drawer` 之后将子元素全部销毁,默认 `false` */
 | 
				
			||||||
 | 
					  destroyOnClose?: boolean;
 | 
				
			||||||
 | 
					  /** 是否需要遮罩层,默认 `true` */
 | 
				
			||||||
 | 
					  modal?: boolean;
 | 
				
			||||||
 | 
					  /** `Drawer` 打开的方向,默认 `rtl` */
 | 
				
			||||||
 | 
					  direction?: "rtl" | "ltr" | "ttb" | "btt";
 | 
				
			||||||
 | 
					  /** `Drawer` 窗体的大小, 当使用 `number` 类型时, 以像素为单位, 当使用 `string` 类型时, 请传入 `'x%'`, 否则便会以 `number` 类型解释 */
 | 
				
			||||||
 | 
					  size?: string | number;
 | 
				
			||||||
 | 
					  /** `Drawer` 的标题 */
 | 
				
			||||||
 | 
					  title?: string;
 | 
				
			||||||
 | 
					  /** 控制是否显示 `header` 栏, 默认为 `true`, 当此项为 `false` 时, `title attribute` 和 `title slot` 均不生效 */
 | 
				
			||||||
 | 
					  withHeader?: boolean;
 | 
				
			||||||
 | 
					  /** 遮罩层的自定义类名 */
 | 
				
			||||||
 | 
					  modalClass?: string;
 | 
				
			||||||
 | 
					  /** 设置 `z-index` */
 | 
				
			||||||
 | 
					  zIndex?: number;
 | 
				
			||||||
 | 
					  /** `header` 的 `aria-level` 属性,默认 `2` */
 | 
				
			||||||
 | 
					  headerAriaLevel?: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//element-plus.org/zh-CN/component/popConfirm.html#attributes
 | 
				
			||||||
 | 
					type PopConfirm = {
 | 
				
			||||||
 | 
					  /** 标题 */
 | 
				
			||||||
 | 
					  title?: string;
 | 
				
			||||||
 | 
					  /** 确认按钮文字 */
 | 
				
			||||||
 | 
					  confirmButtonText?: string;
 | 
				
			||||||
 | 
					  /** 取消按钮文字 */
 | 
				
			||||||
 | 
					  cancelButtonText?: string;
 | 
				
			||||||
 | 
					  /** 确认按钮类型,默认 `primary` */
 | 
				
			||||||
 | 
					  confirmButtonType?: ButtonType;
 | 
				
			||||||
 | 
					  /** 取消按钮类型,默认 `text` */
 | 
				
			||||||
 | 
					  cancelButtonType?: ButtonType;
 | 
				
			||||||
 | 
					  /** 自定义图标,默认 `QuestionFilled` */
 | 
				
			||||||
 | 
					  icon?: string | Component;
 | 
				
			||||||
 | 
					  /** `Icon` 颜色,默认 `#f90` */
 | 
				
			||||||
 | 
					  iconColor?: string;
 | 
				
			||||||
 | 
					  /** 是否隐藏 `Icon`,默认 `false` */
 | 
				
			||||||
 | 
					  hideIcon?: boolean;
 | 
				
			||||||
 | 
					  /** 关闭时的延迟,默认 `200` */
 | 
				
			||||||
 | 
					  hideAfter?: number;
 | 
				
			||||||
 | 
					  /** 是否将 `popover` 的下拉列表插入至 `body` 元素,默认 `true` */
 | 
				
			||||||
 | 
					  teleported?: boolean;
 | 
				
			||||||
 | 
					  /** 当 `popover` 组件长时间不触发且 `persistent` 属性设置为 `false` 时, `popover` 将会被删除,默认 `false` */
 | 
				
			||||||
 | 
					  persistent?: boolean;
 | 
				
			||||||
 | 
					  /** 弹层宽度,最小宽度 `150px`,默认 `150` */
 | 
				
			||||||
 | 
					  width?: string | number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BtnClickDrawer = {
 | 
				
			||||||
 | 
					  options?: DrawerOptions;
 | 
				
			||||||
 | 
					  index?: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					type BtnClickButton = {
 | 
				
			||||||
 | 
					  btn?: ButtonProps;
 | 
				
			||||||
 | 
					  index?: number;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					/** https://element-plus.org/zh-CN/component/button.html#button-attributes */
 | 
				
			||||||
 | 
					type ButtonProps = {
 | 
				
			||||||
 | 
					  /** 按钮文字 */
 | 
				
			||||||
 | 
					  label: string;
 | 
				
			||||||
 | 
					  /** 按钮尺寸 */
 | 
				
			||||||
 | 
					  size?: "large" | "default" | "small";
 | 
				
			||||||
 | 
					  /** 按钮类型 */
 | 
				
			||||||
 | 
					  type?: "primary" | "success" | "warning" | "danger" | "info";
 | 
				
			||||||
 | 
					  /** 是否为朴素按钮,默认 `false` */
 | 
				
			||||||
 | 
					  plain?: boolean;
 | 
				
			||||||
 | 
					  /** 是否为文字按钮,默认 `false` */
 | 
				
			||||||
 | 
					  text?: boolean;
 | 
				
			||||||
 | 
					  /** 是否显示文字按钮背景颜色,默认 `false` */
 | 
				
			||||||
 | 
					  bg?: boolean;
 | 
				
			||||||
 | 
					  /** 是否为链接按钮,默认 `false` */
 | 
				
			||||||
 | 
					  link?: boolean;
 | 
				
			||||||
 | 
					  /** 是否为圆角按钮,默认 `false` */
 | 
				
			||||||
 | 
					  round?: boolean;
 | 
				
			||||||
 | 
					  /** 是否为圆形按钮,默认 `false` */
 | 
				
			||||||
 | 
					  circle?: boolean;
 | 
				
			||||||
 | 
					  /** 确认按钮的 `PopConfirm` 气泡确认框相关配置 */
 | 
				
			||||||
 | 
					  popConfirm?: PopConfirm;
 | 
				
			||||||
 | 
					  /** 是否为加载中状态,默认 `false` */
 | 
				
			||||||
 | 
					  loading?: boolean;
 | 
				
			||||||
 | 
					  /** 自定义加载中状态图标组件 */
 | 
				
			||||||
 | 
					  loadingIcon?: string | Component;
 | 
				
			||||||
 | 
					  /** 按钮是否为禁用状态,默认 `false` */
 | 
				
			||||||
 | 
					  disabled?: boolean;
 | 
				
			||||||
 | 
					  /** 图标组件 */
 | 
				
			||||||
 | 
					  icon?: string | Component;
 | 
				
			||||||
 | 
					  /** 是否开启原生 `autofocus` 属性,默认 `false` */
 | 
				
			||||||
 | 
					  autofocus?: boolean;
 | 
				
			||||||
 | 
					  /** 原生 `type` 属性,默认 `button` */
 | 
				
			||||||
 | 
					  nativeType?: "button" | "submit" | "reset";
 | 
				
			||||||
 | 
					  /** 自动在两个中文字符之间插入空格 */
 | 
				
			||||||
 | 
					  autoInsertSpace?: boolean;
 | 
				
			||||||
 | 
					  /** 自定义按钮颜色, 并自动计算 `hover` 和 `active` 触发后的颜色 */
 | 
				
			||||||
 | 
					  color?: string;
 | 
				
			||||||
 | 
					  /** `dark` 模式, 意味着自动设置 `color` 为 `dark` 模式的颜色,默认 `false` */
 | 
				
			||||||
 | 
					  dark?: boolean;
 | 
				
			||||||
 | 
					  /** 自定义元素标签 */
 | 
				
			||||||
 | 
					  tag?: string | Component;
 | 
				
			||||||
 | 
					  /** 点击按钮后触发的回调 */
 | 
				
			||||||
 | 
					  btnClick?: ({
 | 
				
			||||||
 | 
					    drawer,
 | 
				
			||||||
 | 
					    button
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    /** 当前 `Drawer` 信息 */
 | 
				
			||||||
 | 
					    drawer: BtnClickDrawer;
 | 
				
			||||||
 | 
					    /** 当前 `button` 信息 */
 | 
				
			||||||
 | 
					    button: BtnClickButton;
 | 
				
			||||||
 | 
					  }) => void;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface DrawerOptions extends DrawerProps {
 | 
				
			||||||
 | 
					  /** 内容区组件的 `props`,可通过 `defineProps` 接收 */
 | 
				
			||||||
 | 
					  props?: any;
 | 
				
			||||||
 | 
					  /** 是否隐藏 `Drawer` 按钮操作区的内容 */
 | 
				
			||||||
 | 
					  hideFooter?: boolean;
 | 
				
			||||||
 | 
					  /** 确认按钮的 `PopConfirm` 气泡确认框相关配置 */
 | 
				
			||||||
 | 
					  popConfirm?: PopConfirm;
 | 
				
			||||||
 | 
					  /** 点击确定按钮后是否开启 `loading` 加载动画 */
 | 
				
			||||||
 | 
					  sureBtnLoading?: boolean;
 | 
				
			||||||
 | 
					  /**
 | 
				
			||||||
 | 
					   * @description 自定义抽屉标题的内容渲染器
 | 
				
			||||||
 | 
					   * @see {@link https://element-plus.org/zh-CN/component/drawer.html#%E6%8F%92%E6%A7%BD}
 | 
				
			||||||
 | 
					   */
 | 
				
			||||||
 | 
					  headerRenderer?: ({
 | 
				
			||||||
 | 
					    close,
 | 
				
			||||||
 | 
					    titleId,
 | 
				
			||||||
 | 
					    titleClass
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    close: Function;
 | 
				
			||||||
 | 
					    titleId: string;
 | 
				
			||||||
 | 
					    titleClass: string;
 | 
				
			||||||
 | 
					  }) => VNode | Component;
 | 
				
			||||||
 | 
					  /** 自定义内容渲染器 */
 | 
				
			||||||
 | 
					  contentRenderer?: ({
 | 
				
			||||||
 | 
					    options,
 | 
				
			||||||
 | 
					    index
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    options: DrawerOptions;
 | 
				
			||||||
 | 
					    index: number;
 | 
				
			||||||
 | 
					  }) => VNode | Component;
 | 
				
			||||||
 | 
					  /** 自定义按钮操作区的内容渲染器,会覆盖`footerButtons`以及默认的 `取消` 和 `确定` 按钮 */
 | 
				
			||||||
 | 
					  footerRenderer?: ({
 | 
				
			||||||
 | 
					    options,
 | 
				
			||||||
 | 
					    index
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    options: DrawerOptions;
 | 
				
			||||||
 | 
					    index: number;
 | 
				
			||||||
 | 
					  }) => VNode | Component;
 | 
				
			||||||
 | 
					  /** 自定义底部按钮操作 */
 | 
				
			||||||
 | 
					  footerButtons?: Array<ButtonProps>;
 | 
				
			||||||
 | 
					  /** `Drawer` 打开后的回调 */
 | 
				
			||||||
 | 
					  open?: ({
 | 
				
			||||||
 | 
					    options,
 | 
				
			||||||
 | 
					    index
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    options: DrawerOptions;
 | 
				
			||||||
 | 
					    index: number;
 | 
				
			||||||
 | 
					  }) => void;
 | 
				
			||||||
 | 
					  /** `Drawer` 关闭后的回调(只有点击右上角关闭按钮或空白页或按下了esc键关闭页面时才会触发) */
 | 
				
			||||||
 | 
					  close?: ({
 | 
				
			||||||
 | 
					    options,
 | 
				
			||||||
 | 
					    index
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    options: DrawerOptions;
 | 
				
			||||||
 | 
					    index: number;
 | 
				
			||||||
 | 
					  }) => void;
 | 
				
			||||||
 | 
					  /** `Drawer` 关闭后的回调。 `args` 返回的 `command` 值解析:`cancel` 点击取消按钮、`sure` 点击确定按钮、`close` 点击右上角关闭按钮或空白页或按下了esc键  */
 | 
				
			||||||
 | 
					  closeCallBack?: ({
 | 
				
			||||||
 | 
					    options,
 | 
				
			||||||
 | 
					    index,
 | 
				
			||||||
 | 
					    args
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    options: DrawerOptions;
 | 
				
			||||||
 | 
					    index: number;
 | 
				
			||||||
 | 
					    args: any;
 | 
				
			||||||
 | 
					  }) => void;
 | 
				
			||||||
 | 
					  /** 输入焦点聚焦在 `Drawer` 内容时的回调 */
 | 
				
			||||||
 | 
					  openAutoFocus?: ({
 | 
				
			||||||
 | 
					    options,
 | 
				
			||||||
 | 
					    index
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    options: DrawerOptions;
 | 
				
			||||||
 | 
					    index: number;
 | 
				
			||||||
 | 
					  }) => void;
 | 
				
			||||||
 | 
					  /** 输入焦点从 `Drawer` 内容失焦时的回调 */
 | 
				
			||||||
 | 
					  closeAutoFocus?: ({
 | 
				
			||||||
 | 
					    options,
 | 
				
			||||||
 | 
					    index
 | 
				
			||||||
 | 
					  }: {
 | 
				
			||||||
 | 
					    options: DrawerOptions;
 | 
				
			||||||
 | 
					    index: number;
 | 
				
			||||||
 | 
					  }) => void;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /** 点击底部取消按钮的回调,会暂停 `Drawer` 的关闭. 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
 | 
				
			||||||
 | 
					  beforeCancel?: (
 | 
				
			||||||
 | 
					    done: Function,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      options,
 | 
				
			||||||
 | 
					      index
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					      options: DrawerOptions;
 | 
				
			||||||
 | 
					      index: number;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ) => void;
 | 
				
			||||||
 | 
					  /** 点击底部确定按钮的回调,会暂停 `Drawer` 的关闭. 回调函数内执行 `done` 参数方法的时候才是真正关闭对话框的时候 */
 | 
				
			||||||
 | 
					  beforeSure?: (
 | 
				
			||||||
 | 
					    done: Function,
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      options,
 | 
				
			||||||
 | 
					      index,
 | 
				
			||||||
 | 
					      closeLoading
 | 
				
			||||||
 | 
					    }: {
 | 
				
			||||||
 | 
					      options: DrawerOptions;
 | 
				
			||||||
 | 
					      index: number;
 | 
				
			||||||
 | 
					      closeLoading: Function;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type { ButtonProps, DrawerOptions, ArgsType, DrawerProps, EventType };
 | 
				
			||||||
@ -18,6 +18,14 @@ export default {
 | 
				
			|||||||
        title: $t("menus.pureDialog")
 | 
					        title: $t("menus.pureDialog")
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      path: "/components/drawer",
 | 
				
			||||||
 | 
					      name: "DrawerPage",
 | 
				
			||||||
 | 
					      component: () => import("@/views/components/drawer/index.vue"),
 | 
				
			||||||
 | 
					      meta: {
 | 
				
			||||||
 | 
					        title: $t("menus.pureDrawer")
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      path: "/components/message",
 | 
					      path: "/components/message",
 | 
				
			||||||
      name: "Message",
 | 
					      name: "Message",
 | 
				
			||||||
 | 
				
			|||||||
@ -280,11 +280,11 @@ function onUpdateClick() {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// popconfirm 确认框
 | 
					// Popconfirm 确认框
 | 
				
			||||||
function onPopconfirmClick() {
 | 
					function onPopconfirmClick() {
 | 
				
			||||||
  addDialog({
 | 
					  addDialog({
 | 
				
			||||||
    width: "30%",
 | 
					    width: "30%",
 | 
				
			||||||
    title: "popconfirm确认框示例",
 | 
					    title: "Popconfirm确认框示例",
 | 
				
			||||||
    popconfirm: { title: "是否确认修改当前数据" },
 | 
					    popconfirm: { title: "是否确认修改当前数据" },
 | 
				
			||||||
    contentRenderer: () => <p>点击右下方确定按钮看看效果吧</p>
 | 
					    contentRenderer: () => <p>点击右下方确定按钮看看效果吧</p>
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
@ -519,7 +519,7 @@ function onSureBtnLoading() {
 | 
				
			|||||||
      <el-button @click="onCloseCallBackClick"> 关闭后的回调 </el-button>
 | 
					      <el-button @click="onCloseCallBackClick"> 关闭后的回调 </el-button>
 | 
				
			||||||
      <el-button @click="onNestingClick"> 嵌套的弹框 </el-button>
 | 
					      <el-button @click="onNestingClick"> 嵌套的弹框 </el-button>
 | 
				
			||||||
      <el-button @click="onUpdateClick"> 更改弹框自身属性值 </el-button>
 | 
					      <el-button @click="onUpdateClick"> 更改弹框自身属性值 </el-button>
 | 
				
			||||||
      <el-button @click="onPopconfirmClick">popconfirm确认框</el-button>
 | 
					      <el-button @click="onPopconfirmClick">Popconfirm确认框</el-button>
 | 
				
			||||||
    </el-space>
 | 
					    </el-space>
 | 
				
			||||||
    <el-divider />
 | 
					    <el-divider />
 | 
				
			||||||
    <el-space wrap>
 | 
					    <el-space wrap>
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										47
									
								
								src/views/components/drawer/form.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/views/components/drawer/form.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					<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 时,Vue 会抛出警告。此处的写法仅仅是为了消除警告。
 | 
				
			||||||
 | 
					// 因为对一个 reactive 对象执行 ref,返回 Ref 对象的 value 值仍为传入的 reactive 对象,
 | 
				
			||||||
 | 
					// 即 newFormInline === props.formInline 为 true,所以此处代码的实际效果,仍是直接修改 props.formInline。
 | 
				
			||||||
 | 
					// 但该写法仅适用于 props.formInline 是一个对象类型的情况,原始类型需抛出事件
 | 
				
			||||||
 | 
					// 推荐阅读: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
 | 
				
			||||||
 | 
					        v-model="newFormInline.user"
 | 
				
			||||||
 | 
					        class="!w-[220px]"
 | 
				
			||||||
 | 
					        placeholder="请输入姓名"
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					    </el-form-item>
 | 
				
			||||||
 | 
					    <el-form-item label="城市">
 | 
				
			||||||
 | 
					      <el-select
 | 
				
			||||||
 | 
					        v-model="newFormInline.region"
 | 
				
			||||||
 | 
					        class="!w-[220px]"
 | 
				
			||||||
 | 
					        placeholder="请选择城市"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        <el-option label="上海" value="上海" />
 | 
				
			||||||
 | 
					        <el-option label="浙江" value="浙江" />
 | 
				
			||||||
 | 
					        <el-option label="深圳" value="深圳" />
 | 
				
			||||||
 | 
					      </el-select>
 | 
				
			||||||
 | 
					    </el-form-item>
 | 
				
			||||||
 | 
					  </el-form>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
							
								
								
									
										22
									
								
								src/views/components/drawer/formPrimitive.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/views/components/drawer/formPrimitive.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					<script setup lang="ts">
 | 
				
			||||||
 | 
					import { useVModel } from "@vueuse/core";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 声明 props 类型
 | 
				
			||||||
 | 
					export interface FormProps {
 | 
				
			||||||
 | 
					  data: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 声明 props 默认值
 | 
				
			||||||
 | 
					// 推荐阅读:https://cn.vuejs.org/guide/typescript/composition-api.html#typing-component-props
 | 
				
			||||||
 | 
					const props = withDefaults(defineProps<FormProps>(), {
 | 
				
			||||||
 | 
					  data: () => ""
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 使用 vueuse 的双向绑定工具
 | 
				
			||||||
 | 
					const emit = defineEmits(["update:data"]);
 | 
				
			||||||
 | 
					const data = useVModel(props, "data", emit);
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <el-input v-model="data" class="!w-[220px]" placeholder="请输入内容" />
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
							
								
								
									
										502
									
								
								src/views/components/drawer/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										502
									
								
								src/views/components/drawer/index.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,502 @@
 | 
				
			|||||||
 | 
					<script setup lang="tsx">
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  addDrawer,
 | 
				
			||||||
 | 
					  closeDrawer,
 | 
				
			||||||
 | 
					  closeAllDrawer,
 | 
				
			||||||
 | 
					  updateDrawer
 | 
				
			||||||
 | 
					} from "@/components/ReDrawer/index";
 | 
				
			||||||
 | 
					import { cloneDeep, debounce } from "@pureadmin/utils";
 | 
				
			||||||
 | 
					import { message } from "@/utils/message";
 | 
				
			||||||
 | 
					import { createVNode, h, ref } from "vue";
 | 
				
			||||||
 | 
					import formPrimitive from "./formPrimitive.vue";
 | 
				
			||||||
 | 
					import forms, { type FormProps } from "./form.vue";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onBaseClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "基础用法",
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-基础用法</p> // jsx 语法 (注意在.vue文件启用jsx语法,需要在script开启lang="tsx")
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onModalClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "无背景遮罩层",
 | 
				
			||||||
 | 
					    modal: false,
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-无背景遮罩层</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 添加 600ms 防抖
 | 
				
			||||||
 | 
					const onoOpenDelayClick = debounce(
 | 
				
			||||||
 | 
					  () =>
 | 
				
			||||||
 | 
					    addDrawer({
 | 
				
			||||||
 | 
					      title: "延时2秒打开抽屉",
 | 
				
			||||||
 | 
					      openDelay: 2000 - 600,
 | 
				
			||||||
 | 
					      contentRenderer: () => <p>抽屉内容-延时2秒打开抽屉</p>
 | 
				
			||||||
 | 
					    }),
 | 
				
			||||||
 | 
					  600
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onCloseDelayClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "延时2秒关闭抽屉",
 | 
				
			||||||
 | 
					    closeDelay: 2000,
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-延时2秒关闭抽屉</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onShowCloseClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "不显示右上角关闭按钮图标",
 | 
				
			||||||
 | 
					    showClose: false,
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-不显示右上角关闭按钮图标</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onBeforeCloseClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "禁止通过键盘ESC关闭",
 | 
				
			||||||
 | 
					    closeOnPressEscape: false,
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-禁止通过键盘ESC关闭</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onCloseOnClickModalClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "禁止通过点击modal关闭",
 | 
				
			||||||
 | 
					    closeOnClickModal: false,
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-禁止通过点击modal关闭</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onHideFooterClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "隐藏底部取消、确定按钮",
 | 
				
			||||||
 | 
					    hideFooter: true,
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-隐藏底部取消、确定按钮</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onHeaderRendererClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "自定义头部",
 | 
				
			||||||
 | 
					    showClose: false,
 | 
				
			||||||
 | 
					    headerRenderer: ({ close, titleId, titleClass }) => (
 | 
				
			||||||
 | 
					      // jsx 语法
 | 
				
			||||||
 | 
					      <div class="flex flex-row justify-between">
 | 
				
			||||||
 | 
					        <h4 id={titleId} class={titleClass}>
 | 
				
			||||||
 | 
					          自定义头部
 | 
				
			||||||
 | 
					        </h4>
 | 
				
			||||||
 | 
					        <el-button type="danger" onClick={close}>
 | 
				
			||||||
 | 
					          关闭
 | 
				
			||||||
 | 
					        </el-button>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-自定义头部</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onFooterRendererClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "自定义底部",
 | 
				
			||||||
 | 
					    footerRenderer: ({ options, index }) => (
 | 
				
			||||||
 | 
					      <el-button onClick={() => closeDrawer(options, index)}>
 | 
				
			||||||
 | 
					        {options.title}-{index}
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-自定义底部</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onFooterButtonsClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "自定义底部按钮",
 | 
				
			||||||
 | 
					    footerButtons: [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        label: "按钮1",
 | 
				
			||||||
 | 
					        size: "small",
 | 
				
			||||||
 | 
					        type: "success",
 | 
				
			||||||
 | 
					        btnClick: ({ drawer: { options, index }, button }) => {
 | 
				
			||||||
 | 
					          console.log(options, index, button);
 | 
				
			||||||
 | 
					          closeDrawer(options, index);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        label: "按钮2",
 | 
				
			||||||
 | 
					        text: true,
 | 
				
			||||||
 | 
					        bg: true,
 | 
				
			||||||
 | 
					        btnClick: ({ drawer: { options, index }, button }) => {
 | 
				
			||||||
 | 
					          console.log(options, index, button);
 | 
				
			||||||
 | 
					          closeDrawer(options, index);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        label: "按钮3",
 | 
				
			||||||
 | 
					        size: "large",
 | 
				
			||||||
 | 
					        type: "warning",
 | 
				
			||||||
 | 
					        btnClick: ({ drawer: { options, index }, button }) => {
 | 
				
			||||||
 | 
					          console.log(options, index, button);
 | 
				
			||||||
 | 
					          closeDrawer(options, index);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-自定义底部按钮</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onOpenClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "打开后的回调",
 | 
				
			||||||
 | 
					    open: ({ options, index }) => message({ options, index } as any),
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-打开后的回调</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onCloseCallBackClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "关闭后的回调",
 | 
				
			||||||
 | 
					    closeCallBack: ({ options, index, args }) => {
 | 
				
			||||||
 | 
					      console.log(options, index, args);
 | 
				
			||||||
 | 
					      let text = "";
 | 
				
			||||||
 | 
					      if (args?.command === "cancel") {
 | 
				
			||||||
 | 
					        text = "您点击了取消按钮";
 | 
				
			||||||
 | 
					      } else if (args?.command === "sure") {
 | 
				
			||||||
 | 
					        text = "您点击了确定按钮";
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        text = "您点击了右上角关闭按钮或空白页或按下了esc键";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      message(text);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-关闭后的回调</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 这里为了演示方便,使用了嵌套写法,实际情况下最好把 addDrawer 函数抽出来 套娃不可取
 | 
				
			||||||
 | 
					function onNestingClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "嵌套的抽屉",
 | 
				
			||||||
 | 
					    size: "50%",
 | 
				
			||||||
 | 
					    contentRenderer: ({ index }) => (
 | 
				
			||||||
 | 
					      <el-button
 | 
				
			||||||
 | 
					        onClick={() =>
 | 
				
			||||||
 | 
					          addDrawer({
 | 
				
			||||||
 | 
					            title: `第${index + 1}个子抽屉`,
 | 
				
			||||||
 | 
					            size: "40%",
 | 
				
			||||||
 | 
					            contentRenderer: ({ index }) => (
 | 
				
			||||||
 | 
					              <el-button
 | 
				
			||||||
 | 
					                onClick={() =>
 | 
				
			||||||
 | 
					                  addDrawer({
 | 
				
			||||||
 | 
					                    title: `第${index + 1}个子抽屉`,
 | 
				
			||||||
 | 
					                    size: "30%",
 | 
				
			||||||
 | 
					                    contentRenderer: () => (
 | 
				
			||||||
 | 
					                      <>
 | 
				
			||||||
 | 
					                        <el-button round onClick={() => closeAllDrawer()}>
 | 
				
			||||||
 | 
					                          哎呦,你干嘛,赶快关闭所有抽屉
 | 
				
			||||||
 | 
					                        </el-button>
 | 
				
			||||||
 | 
					                      </>
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                  })
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					              >
 | 
				
			||||||
 | 
					                点击打开第{index + 1}个子抽屉
 | 
				
			||||||
 | 
					              </el-button>
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					          })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        点击打开第{index + 1}个子抽屉
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 满足在 contentRenderer 内容区更改抽屉自身属性值的场景
 | 
				
			||||||
 | 
					function onUpdateClick() {
 | 
				
			||||||
 | 
					  const curPage = ref(1);
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: `第${curPage.value}页`,
 | 
				
			||||||
 | 
					    contentRenderer: () => (
 | 
				
			||||||
 | 
					      <>
 | 
				
			||||||
 | 
					        <el-button
 | 
				
			||||||
 | 
					          disabled={curPage.value <= 1}
 | 
				
			||||||
 | 
					          onClick={() => {
 | 
				
			||||||
 | 
					            curPage.value -= 1;
 | 
				
			||||||
 | 
					            updateDrawer(`第${curPage.value}页`);
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          上一页
 | 
				
			||||||
 | 
					        </el-button>
 | 
				
			||||||
 | 
					        <el-button
 | 
				
			||||||
 | 
					          onClick={() => {
 | 
				
			||||||
 | 
					            curPage.value += 1;
 | 
				
			||||||
 | 
					            updateDrawer(`第${curPage.value}页`);
 | 
				
			||||||
 | 
					          }}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					          下一页
 | 
				
			||||||
 | 
					        </el-button>
 | 
				
			||||||
 | 
					      </>
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Popconfirm 确认框
 | 
				
			||||||
 | 
					function onPopConfirmClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    size: "30%",
 | 
				
			||||||
 | 
					    title: "Popconfirm确认框示例",
 | 
				
			||||||
 | 
					    popConfirm: { title: "是否确认修改当前数据" },
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>点击右下方确定按钮看看效果吧</p>
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 结合Form表单(第一种方式,抽屉关闭立刻恢复初始值)通过 props 属性接收子组件的 prop 并赋值
 | 
				
			||||||
 | 
					function onFormOneClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    size: "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(
 | 
				
			||||||
 | 
					          `您点击了右上角关闭按钮或空白页或按下了esc键,当前表单数据为 ${text}`
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 结合Form表单(第二种方式)h 渲染函数 https://cn.vuejs.org/api/render-function.html#h
 | 
				
			||||||
 | 
					const formInline = ref({
 | 
				
			||||||
 | 
					  user: "菜虚鲲",
 | 
				
			||||||
 | 
					  region: "浙江"
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					const resetFormInline = cloneDeep(formInline.value);
 | 
				
			||||||
 | 
					function onFormTwoClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    size: "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() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    size: "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() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    size: "30%",
 | 
				
			||||||
 | 
					    title: "结合Form表单(第四种方式)",
 | 
				
			||||||
 | 
					    contentRenderer: () => <forms formInline={formFourInline.value} />,
 | 
				
			||||||
 | 
					    closeCallBack: () => {
 | 
				
			||||||
 | 
					      message(
 | 
				
			||||||
 | 
					        `当前表单数据为 姓名:${formFourInline.value.user} 城市:${formFourInline.value.region}`
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      // 重置表单数据
 | 
				
			||||||
 | 
					      formFourInline.value = cloneDeep(resetFormFourInline);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 子组件 prop 为 primitive 类型的 demo
 | 
				
			||||||
 | 
					const formPrimitiveParam = ref("Hello World");
 | 
				
			||||||
 | 
					const resetFormPrimitiveParam = ref(formPrimitiveParam.value);
 | 
				
			||||||
 | 
					function onFormPrimitiveFormClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    size: "30%",
 | 
				
			||||||
 | 
					    title: "子组件 prop 为 primitive 类型 demo",
 | 
				
			||||||
 | 
					    contentRenderer: () =>
 | 
				
			||||||
 | 
					      h(formPrimitive, {
 | 
				
			||||||
 | 
					        data: formPrimitiveParam.value,
 | 
				
			||||||
 | 
					        "onUpdate:data": val => (formPrimitiveParam.value = val)
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					    closeCallBack: () => {
 | 
				
			||||||
 | 
					      message(`当前表单内容:${formPrimitiveParam.value}`);
 | 
				
			||||||
 | 
					      // 重置表单数据
 | 
				
			||||||
 | 
					      formPrimitiveParam.value = resetFormPrimitiveParam.value;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onBeforeCancelClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "点击底部取消按钮的回调",
 | 
				
			||||||
 | 
					    contentRenderer: () => (
 | 
				
			||||||
 | 
					      <p>抽屉内容-点击底部取消按钮的回调(会暂停抽屉的关闭)</p>
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    beforeCancel: (done, { options, index }) => {
 | 
				
			||||||
 | 
					      console.log(
 | 
				
			||||||
 | 
					        "%coptions, index===>>>: ",
 | 
				
			||||||
 | 
					        "color: MidnightBlue; background: Aquamarine; font-size: 20px;",
 | 
				
			||||||
 | 
					        options,
 | 
				
			||||||
 | 
					        index
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      // done(); // 需要关闭把注释解开即可
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onBeforeSureClick() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    title: "点击底部确定按钮的回调",
 | 
				
			||||||
 | 
					    contentRenderer: () => (
 | 
				
			||||||
 | 
					      <p>
 | 
				
			||||||
 | 
					        抽屉内容-点击底部确定按钮的回调(会暂停抽屉的关闭,经常用于新增、修改抽屉内容后调用接口)
 | 
				
			||||||
 | 
					      </p>
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					    beforeSure: (done, { options, index }) => {
 | 
				
			||||||
 | 
					      console.log(
 | 
				
			||||||
 | 
					        "%coptions, index===>>>: ",
 | 
				
			||||||
 | 
					        "color: MidnightBlue; background: Aquamarine; font-size: 20px;",
 | 
				
			||||||
 | 
					        options,
 | 
				
			||||||
 | 
					        index
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      // done(); // 需要关闭把注释解开即可
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function onSureBtnLoading() {
 | 
				
			||||||
 | 
					  addDrawer({
 | 
				
			||||||
 | 
					    sureBtnLoading: true,
 | 
				
			||||||
 | 
					    title: "点击底部确定按钮可开启按钮动画",
 | 
				
			||||||
 | 
					    contentRenderer: () => <p>抽屉内容-点击底部确定按钮可开启按钮动画</p>,
 | 
				
			||||||
 | 
					    beforeSure: (done, { closeLoading }) => {
 | 
				
			||||||
 | 
					      // closeLoading(); // 关闭确定按钮动画,不关闭抽屉
 | 
				
			||||||
 | 
					      // done() // 关闭确定按钮动画并关闭抽屉
 | 
				
			||||||
 | 
					      setTimeout(() => done(), 800);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<template>
 | 
				
			||||||
 | 
					  <el-card shadow="never">
 | 
				
			||||||
 | 
					    <template #header>
 | 
				
			||||||
 | 
					      <div class="card-header">
 | 
				
			||||||
 | 
					        <span class="font-medium">
 | 
				
			||||||
 | 
					          二次封装 Element Plus 的
 | 
				
			||||||
 | 
					          <el-link
 | 
				
			||||||
 | 
					            href="https://element-plus.org/zh-CN/component/drawer.html"
 | 
				
			||||||
 | 
					            target="_blank"
 | 
				
			||||||
 | 
					            style="margin: 0 4px 5px; font-size: 16px"
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            Drawer
 | 
				
			||||||
 | 
					          </el-link>
 | 
				
			||||||
 | 
					        </span>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <el-link
 | 
				
			||||||
 | 
					        href="https://github.com/pure-admin/vue-pure-admin/tree/main/src/views/components/drawer"
 | 
				
			||||||
 | 
					        target="_blank"
 | 
				
			||||||
 | 
					      >
 | 
				
			||||||
 | 
					        代码位置 src/views/components/drawer
 | 
				
			||||||
 | 
					      </el-link>
 | 
				
			||||||
 | 
					    </template>
 | 
				
			||||||
 | 
					    <el-space wrap>
 | 
				
			||||||
 | 
					      <el-button @click="onBaseClick">基础用法</el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onModalClick"> 无背景遮罩层 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onoOpenDelayClick"> 延时2秒打开抽屉 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onCloseDelayClick"> 延时2秒关闭抽屉 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onShowCloseClick">
 | 
				
			||||||
 | 
					        不显示右上角关闭按钮图标
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onBeforeCloseClick"> 禁止通过键盘ESC关闭 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onCloseOnClickModalClick">
 | 
				
			||||||
 | 
					        禁止通过点击modal关闭
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onHideFooterClick"> 隐藏底部取消、确定按钮 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onHeaderRendererClick"> 自定义头部 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onFooterRendererClick"> 自定义底部 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onFooterButtonsClick"> 自定义底部按钮 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onOpenClick"> 打开后的回调 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onCloseCallBackClick"> 关闭后的回调 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onNestingClick"> 嵌套的抽屉 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onUpdateClick"> 更改抽屉自身属性值 </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onPopConfirmClick">Popconfirm确认框</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-button @click="onFormPrimitiveFormClick">
 | 
				
			||||||
 | 
					        子组件 prop 为 primitive 类型
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					    </el-space>
 | 
				
			||||||
 | 
					    <el-divider />
 | 
				
			||||||
 | 
					    <el-space wrap>
 | 
				
			||||||
 | 
					      <el-button @click="onBeforeCancelClick">
 | 
				
			||||||
 | 
					        点击底部取消按钮的回调(会暂停抽屉的关闭)
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onBeforeSureClick">
 | 
				
			||||||
 | 
					        点击底部确定按钮的回调(会暂停抽屉的关闭,经常用于新增、修改抽屉内容后调用接口)
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					      <el-button @click="onSureBtnLoading">
 | 
				
			||||||
 | 
					        点击底部确定按钮可开启按钮动画
 | 
				
			||||||
 | 
					      </el-button>
 | 
				
			||||||
 | 
					    </el-space>
 | 
				
			||||||
 | 
					  </el-card>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user