Merge branch 'main' of github.com:pure-admin/vue-pure-admin into gitee
@ -1,6 +1,6 @@
 | 
			
		||||
# 预发布也需要生产环境的行为
 | 
			
		||||
# https://cn.vitejs.dev/guide/env-and-mode.html#modes
 | 
			
		||||
NODE_ENV=production
 | 
			
		||||
# NODE_ENV = development
 | 
			
		||||
 | 
			
		||||
VITE_PUBLIC_PATH = /
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								.vscode/vue3.0.code-snippets
									
									
									
									
										vendored
									
									
								
							
							
						
						@ -1,19 +1,19 @@
 | 
			
		||||
{
 | 
			
		||||
  "Vue3.0快速生成模板": {
 | 
			
		||||
    "scope": "vue",
 | 
			
		||||
    "prefix": "Vue3.0",
 | 
			
		||||
    "body": [
 | 
			
		||||
      "<template>",
 | 
			
		||||
      "\t<div>\n",
 | 
			
		||||
      "\t</div>",
 | 
			
		||||
      "\t<div>test</div>",
 | 
			
		||||
      "</template>\n",
 | 
			
		||||
      "<script lang='ts'>",
 | 
			
		||||
      "export default {",
 | 
			
		||||
      "\tsetup(){",
 | 
			
		||||
      "\t\treturn{\n\n\t\t}",
 | 
			
		||||
      "\t},",
 | 
			
		||||
      "\tsetup() {",
 | 
			
		||||
      "\t\treturn {}",
 | 
			
		||||
      "\t}",
 | 
			
		||||
      "}",
 | 
			
		||||
      "</script>\n",
 | 
			
		||||
      "<style scoped>\n",
 | 
			
		||||
      "<style lang='scss' scoped>\n",
 | 
			
		||||
      "</style>",
 | 
			
		||||
      "$2"
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								.vscode/vue3.2.code-snippets
									
									
									
									
										vendored
									
									
								
							
							
						
						@ -1,14 +1,14 @@
 | 
			
		||||
{
 | 
			
		||||
  "Vue3.2+快速生成模板": {
 | 
			
		||||
    "scope": "vue",
 | 
			
		||||
    "prefix": "Vue3.2+",
 | 
			
		||||
    "body": [
 | 
			
		||||
      "<script setup lang='ts'>",
 | 
			
		||||
      "</script>\n",
 | 
			
		||||
      "<template>",
 | 
			
		||||
      "\t<div>\n",
 | 
			
		||||
      "\t</div>",
 | 
			
		||||
      "\t<div>test</div>",
 | 
			
		||||
      "</template>\n",
 | 
			
		||||
      "<style scoped>\n",
 | 
			
		||||
      "<style lang='scss' scoped>\n",
 | 
			
		||||
      "</style>",
 | 
			
		||||
      "$2"
 | 
			
		||||
    ],
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								.vscode/vue3.3.code-snippets
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,20 @@
 | 
			
		||||
{
 | 
			
		||||
  "Vue3.3+defineOptions快速生成模板": {
 | 
			
		||||
    "scope": "vue",
 | 
			
		||||
    "prefix": "Vue3.3+",
 | 
			
		||||
    "body": [
 | 
			
		||||
      "<script setup lang='ts'>",
 | 
			
		||||
      "defineOptions({",
 | 
			
		||||
      "\tname: ''",
 | 
			
		||||
      "})",
 | 
			
		||||
      "</script>\n",
 | 
			
		||||
      "<template>",
 | 
			
		||||
      "\t<div>test</div>",
 | 
			
		||||
      "</template>\n",
 | 
			
		||||
      "<style lang='scss' scoped>\n",
 | 
			
		||||
      "</style>",
 | 
			
		||||
      "$2"
 | 
			
		||||
    ],
 | 
			
		||||
    "description": "Vue3.3+defineOptions快速生成模板"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -22,7 +22,7 @@ The simplified version is based on the shelf extracted from [vue-pure-admin](htt
 | 
			
		||||
- [Click Watch Tutorial](https://www.bilibili.com/video/BV1kg411v7QT)
 | 
			
		||||
- [Click Watch UI Design](https://www.bilibili.com/video/BV17g411T7rq)
 | 
			
		||||
 | 
			
		||||
## Docs (support `PWA` fast, offline access)
 | 
			
		||||
## Docs
 | 
			
		||||
 | 
			
		||||
- [Click me to view the domestic documentation site](https://yiming_chang.gitee.io/pure-admin-doc)
 | 
			
		||||
- [Click me to view foreign document site](https://pure-admin.github.io/pure-admin-doc)
 | 
			
		||||
@ -140,34 +140,12 @@ Support modern browsers, not IE
 | 
			
		||||
 | 
			
		||||
[xiaoxian521](https://github.com/xiaoxian521)、[Ten-K](https://github.com/Ten-K)
 | 
			
		||||
 | 
			
		||||
## Donate
 | 
			
		||||
 | 
			
		||||
If you think this project is helpful to you, you can help the author buy a glass of juice 🍹 Show your support
 | 
			
		||||
 | 
			
		||||
<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f69bf13c5b854ed5b699807cafa0e3ce~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?" width="150px" height="150px" />
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
In principle, no fees and copyrights are charged, and you can use it with confidence, but if you need secondary open source, please contact the author for permission!
 | 
			
		||||
In principle, no fees and copyrights are charged, and it is commercially available, but if you need secondary open source (such as using this platform for secondary development and open source, the front-end code must be open source and free), please contact the author for permission! (Free, just take a record)
 | 
			
		||||
 | 
			
		||||
[MIT © 2020-present, pure-admin](./LICENSE)
 | 
			
		||||
 | 
			
		||||
## Backers
 | 
			
		||||
 | 
			
		||||
Thank you very much for your support, I believe the project will get better and better :heart:
 | 
			
		||||
 | 
			
		||||
|                                                                xueyuheng                                                                 |                                                                taolei1990                                                                 |                                                                hang-kim                                                                 |                                                               madwolfcrazy                                                                |                                                                limuen                                                                 |                                                                BenLakes                                                                 |
 | 
			
		||||
| :--------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: |
 | 
			
		||||
| <a href="https://github.com/xueyuheng"><img src="https://avatars.githubusercontent.com/u/48202935?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/taolei1990"><img src="https://avatars.githubusercontent.com/u/23173640?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/hang-kim"><img src="https://avatars.githubusercontent.com/u/52914259?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/madwolfcrazy"><img src="https://avatars.githubusercontent.com/u/223671?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/limuen"><img src="https://avatars.githubusercontent.com/u/31790606?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/BenLakes"><img src="https://avatars.githubusercontent.com/u/15206046?v=4" width="60px" height="60px" /></a> |
 | 
			
		||||
|                                                                mollerzhu                                                                 |                                                                  TLovers                                                                  |                                                                  cnyyk                                                                  |                                                                                                                                           |                                                                                                                                       |                                                                                                                                         |
 | 
			
		||||
| <a href="https://github.com/mollerzhu"><img src="https://avatars.githubusercontent.com/u/49627902?v=4" width="60px" height="60px" /></a> |  <a href="https://github.com/TLovers"><img src="https://avatars.githubusercontent.com/u/26561694?v=4" width="60px" height="60px" /></a>   |   <a href="https://github.com/cnyyk"><img src="https://avatars.githubusercontent.com/u/275233?v=4" width="60px" height="60px" /></a>    |                                                                                                                                           |                                                                                                                                       |                                                                                                                                         |
 | 
			
		||||
 | 
			
		||||
## Contributors
 | 
			
		||||
 | 
			
		||||
Thanks to all the people who contribute :heart:
 | 
			
		||||
 | 
			
		||||
<a href="https://github.com/pure-admin/vue-pure-admin/graphs/contributors"><img src="https://contrib.rocks/image?repo=pure-admin/vue-pure-admin" /></a>
 | 
			
		||||
 | 
			
		||||
## `Star`
 | 
			
		||||
 | 
			
		||||
Many thanks to the kind individuals who leave a star. Your support is much appreciated :heart:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								README.md
									
									
									
									
									
								
							
							
						
						@ -22,7 +22,7 @@
 | 
			
		||||
- [点我查看快速开发教程](https://www.bilibili.com/video/BV1kg411v7QT)
 | 
			
		||||
- [点我查看 UI 设计](https://www.bilibili.com/video/BV17g411T7rq)
 | 
			
		||||
 | 
			
		||||
## 配套保姆级文档(支持 `PWA` 快速、离线访问)
 | 
			
		||||
## 配套保姆级文档
 | 
			
		||||
 | 
			
		||||
- [点我查看国内文档站](https://yiming_chang.gitee.io/pure-admin-doc)
 | 
			
		||||
- [点我查看国外文档站](https://pure-admin.github.io/pure-admin-doc)
 | 
			
		||||
@ -140,38 +140,12 @@ pnpm build
 | 
			
		||||
 | 
			
		||||
[xiaoxian521](https://github.com/xiaoxian521)、[Ten-K](https://github.com/Ten-K)
 | 
			
		||||
 | 
			
		||||
## 支持
 | 
			
		||||
 | 
			
		||||
如果您觉得这个项目对您有帮助,可以帮作者买一杯果汁 🍹 表示支持
 | 
			
		||||
 | 
			
		||||
<img src="https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f69bf13c5b854ed5b699807cafa0e3ce~tplv-k3u1fbpfcp-zoom-in-crop-mark:1304:0:0:0.awebp?" width="150px" height="150px" />
 | 
			
		||||
 | 
			
		||||
## `QQ` 交流群
 | 
			
		||||
 | 
			
		||||
[点击去加入](https://yiming_chang.gitee.io/pure-admin-doc/pages/support/#qq-%E4%BA%A4%E6%B5%81%E7%BE%A4)
 | 
			
		||||
 | 
			
		||||
## 许可证
 | 
			
		||||
 | 
			
		||||
原则上不收取任何费用及版权,可以放心使用,不过如需二次开源(比如用此平台二次开发并开源)请联系作者获取许可!
 | 
			
		||||
原则上不收取任何费用及版权,可商用,不过如需二次开源(比如用此平台二次开发并开源,要求前端代码必须开源免费)请联系作者获取许可!(免费,走个记录而已)
 | 
			
		||||
 | 
			
		||||
[MIT © 2020-present, pure-admin](./LICENSE)
 | 
			
		||||
 | 
			
		||||
## 支持者
 | 
			
		||||
 | 
			
		||||
非常感谢您们的支持,相信项目会越来越好 :heart:
 | 
			
		||||
 | 
			
		||||
|                                                                xueyuheng                                                                 |                                                                taolei1990                                                                 |                                                                hang-kim                                                                 |                                                               madwolfcrazy                                                                |                                                                limuen                                                                 |                                                                BenLakes                                                                 |
 | 
			
		||||
| :--------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------------------------------------------------------------------------------: |
 | 
			
		||||
| <a href="https://github.com/xueyuheng"><img src="https://avatars.githubusercontent.com/u/48202935?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/taolei1990"><img src="https://avatars.githubusercontent.com/u/23173640?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/hang-kim"><img src="https://avatars.githubusercontent.com/u/52914259?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/madwolfcrazy"><img src="https://avatars.githubusercontent.com/u/223671?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/limuen"><img src="https://avatars.githubusercontent.com/u/31790606?v=4" width="60px" height="60px" /></a> | <a href="https://github.com/BenLakes"><img src="https://avatars.githubusercontent.com/u/15206046?v=4" width="60px" height="60px" /></a> |
 | 
			
		||||
|                                                                mollerzhu                                                                 |                                                                  TLovers                                                                  |                                                                  cnyyk                                                                  |                                                                                                                                           |                                                                                                                                       |                                                                                                                                         |
 | 
			
		||||
| <a href="https://github.com/mollerzhu"><img src="https://avatars.githubusercontent.com/u/49627902?v=4" width="60px" height="60px" /></a> |  <a href="https://github.com/TLovers"><img src="https://avatars.githubusercontent.com/u/26561694?v=4" width="60px" height="60px" /></a>   |   <a href="https://github.com/cnyyk"><img src="https://avatars.githubusercontent.com/u/275233?v=4" width="60px" height="60px" /></a>    |                                                                                                                                           |                                                                                                                                       |                                                                                                                                         |
 | 
			
		||||
 | 
			
		||||
## 贡献者
 | 
			
		||||
 | 
			
		||||
感谢所有做出贡献的人 :heart:
 | 
			
		||||
 | 
			
		||||
<a href="https://github.com/pure-admin/vue-pure-admin/graphs/contributors"><img src="https://contrib.rocks/image?repo=pure-admin/vue-pure-admin" /></a>
 | 
			
		||||
 | 
			
		||||
## `Star`
 | 
			
		||||
 | 
			
		||||
非常感谢留下星星的好心人,感谢您的支持 :heart:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								package.json
									
									
									
									
									
								
							
							
						
						@ -56,7 +56,7 @@
 | 
			
		||||
    "mockjs": "^1.1.0",
 | 
			
		||||
    "nprogress": "^0.2.0",
 | 
			
		||||
    "path": "^0.12.7",
 | 
			
		||||
    "pinia": "^2.1.1",
 | 
			
		||||
    "pinia": "^2.1.3",
 | 
			
		||||
    "qrcode": "^1.5.3",
 | 
			
		||||
    "qs": "^6.11.1",
 | 
			
		||||
    "responsive-storage": "^2.2.0",
 | 
			
		||||
@ -69,7 +69,7 @@
 | 
			
		||||
    "vue-i18n": "^9.2.2",
 | 
			
		||||
    "vue-json-pretty": "^2.2.4",
 | 
			
		||||
    "vue-pdf-embed": "^1.1.6",
 | 
			
		||||
    "vue-router": "^4.2.0",
 | 
			
		||||
    "vue-router": "^4.2.1",
 | 
			
		||||
    "vue-types": "^5.0.3",
 | 
			
		||||
    "vue-virtual-scroller": "2.0.0-beta.7",
 | 
			
		||||
    "vue-waterfall-plugin-next": "^2.2.1",
 | 
			
		||||
@ -104,9 +104,9 @@
 | 
			
		||||
    "autoprefixer": "^10.4.14",
 | 
			
		||||
    "cloc": "^2.11.0",
 | 
			
		||||
    "cssnano": "^6.0.1",
 | 
			
		||||
    "eslint": "^8.40.0",
 | 
			
		||||
    "eslint": "^8.41.0",
 | 
			
		||||
    "eslint-plugin-prettier": "^4.2.1",
 | 
			
		||||
    "eslint-plugin-vue": "^9.13.0",
 | 
			
		||||
    "eslint-plugin-vue": "^9.14.0",
 | 
			
		||||
    "husky": "^8.0.3",
 | 
			
		||||
    "lint-staged": "^13.2.2",
 | 
			
		||||
    "picocolors": "^1.0.0",
 | 
			
		||||
@ -114,12 +114,12 @@
 | 
			
		||||
    "postcss-html": "^1.5.0",
 | 
			
		||||
    "postcss-import": "^15.1.0",
 | 
			
		||||
    "postcss-scss": "^4.0.6",
 | 
			
		||||
    "prettier": "^2.8.7",
 | 
			
		||||
    "pretty-quick": "3.1.1",
 | 
			
		||||
    "rimraf": "^5.0.0",
 | 
			
		||||
    "prettier": "^2.8.8",
 | 
			
		||||
    "pretty-quick": "^3.1.3",
 | 
			
		||||
    "rimraf": "^5.0.1",
 | 
			
		||||
    "rollup-plugin-visualizer": "^5.9.0",
 | 
			
		||||
    "sass": "^1.62.1",
 | 
			
		||||
    "sass-loader": "^13.2.2",
 | 
			
		||||
    "sass-loader": "^13.3.0",
 | 
			
		||||
    "stylelint": "^15.6.2",
 | 
			
		||||
    "stylelint-config-html": "^1.1.0",
 | 
			
		||||
    "stylelint-config-recess-order": "^4.0.0",
 | 
			
		||||
@ -133,9 +133,9 @@
 | 
			
		||||
    "stylelint-scss": "^5.0.0",
 | 
			
		||||
    "svgo": "^3.0.2",
 | 
			
		||||
    "tailwindcss": "^3.3.2",
 | 
			
		||||
    "terser": "^5.17.4",
 | 
			
		||||
    "terser": "^5.17.5",
 | 
			
		||||
    "typescript": "^5.0.4",
 | 
			
		||||
    "vite": "^4.3.7",
 | 
			
		||||
    "vite": "^4.3.8",
 | 
			
		||||
    "vite-plugin-cdn-import": "^0.3.5",
 | 
			
		||||
    "vite-plugin-compression": "^0.5.1",
 | 
			
		||||
    "vite-plugin-mock": "^2.9.6",
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										8592
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						| 
		 Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.5 KiB  | 
| 
		 Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB  | 
| 
		 Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB  | 
| 
		 Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB  | 
@ -12,6 +12,7 @@ import type {
 | 
			
		||||
 | 
			
		||||
const dialogStore = ref<Array<DialogOptions>>([]);
 | 
			
		||||
 | 
			
		||||
/** 打开弹框 */
 | 
			
		||||
const addDialog = (options: DialogOptions) => {
 | 
			
		||||
  const open = () =>
 | 
			
		||||
    dialogStore.value.push(Object.assign(options, { visible: true }));
 | 
			
		||||
@ -24,16 +25,40 @@ const addDialog = (options: DialogOptions) => {
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** 关闭弹框 */
 | 
			
		||||
const closeDialog = (options: DialogOptions, index: number, args?: any) => {
 | 
			
		||||
  dialogStore.value.splice(index, 1);
 | 
			
		||||
  options.closeCallBack && options.closeCallBack({ options, index, args });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @description 更改弹框自身属性值
 | 
			
		||||
 * @param value 属性值
 | 
			
		||||
 * @param key 属性,默认`title`
 | 
			
		||||
 * @param index 弹框索引(默认`0`,代表只有一个弹框,对于嵌套弹框要改哪个弹框的属性值就把该弹框索引赋给`index`)
 | 
			
		||||
 */
 | 
			
		||||
const updateDialog = (value: any, key = "title", index = 0) => {
 | 
			
		||||
  dialogStore.value[index][key] = value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** 关闭所有弹框 */
 | 
			
		||||
const closeAllDialog = () => {
 | 
			
		||||
  dialogStore.value = [];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** 千万别忘了在下面这三处引入并注册下,放心注册,不使用`addDialog`调用就不会被挂载
 | 
			
		||||
 * https://github.com/pure-admin/vue-pure-admin/blob/main/src/App.vue#L4
 | 
			
		||||
 * https://github.com/pure-admin/vue-pure-admin/blob/main/src/App.vue#L13
 | 
			
		||||
 * https://github.com/pure-admin/vue-pure-admin/blob/main/src/App.vue#L18
 | 
			
		||||
 */
 | 
			
		||||
const ReDialog = withInstall(reDialog);
 | 
			
		||||
 | 
			
		||||
export type { EventType, ArgsType, DialogProps, ButtonProps, DialogOptions };
 | 
			
		||||
export { ReDialog, dialogStore, addDialog, closeDialog, closeAllDialog };
 | 
			
		||||
export {
 | 
			
		||||
  ReDialog,
 | 
			
		||||
  dialogStore,
 | 
			
		||||
  addDialog,
 | 
			
		||||
  closeDialog,
 | 
			
		||||
  updateDialog,
 | 
			
		||||
  closeAllDialog
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -200,9 +200,13 @@ export default defineComponent({
 | 
			
		||||
 | 
			
		||||
    return () => (
 | 
			
		||||
      <>
 | 
			
		||||
        <div {...attrs} class="w-[99/100] mt-4 px-2 pb-2 bg-bg_color">
 | 
			
		||||
        <div {...attrs} class="w-[99/100] mt-2 px-2 pb-2 bg-bg_color">
 | 
			
		||||
          <div class="flex justify-between w-full h-[60px] p-4">
 | 
			
		||||
            <p class="font-bold truncate">{props.title}</p>
 | 
			
		||||
            {slots?.title ? (
 | 
			
		||||
              slots.title()
 | 
			
		||||
            ) : (
 | 
			
		||||
              <p class="font-bold truncate">{props.title}</p>
 | 
			
		||||
            )}
 | 
			
		||||
            <div class="flex items-center justify-around">
 | 
			
		||||
              {slots?.buttons ? (
 | 
			
		||||
                <div class="flex mr-4">{slots.buttons()}</div>
 | 
			
		||||
 | 
			
		||||
@ -51,20 +51,21 @@ let startPosX = null;
 | 
			
		||||
let isHover = false;
 | 
			
		||||
let ease = "ease-in";
 | 
			
		||||
 | 
			
		||||
// eslint-disable-next-line vue/no-setup-props-destructure
 | 
			
		||||
const { classOption } = props;
 | 
			
		||||
 | 
			
		||||
if (classOption["key"] === undefined) {
 | 
			
		||||
  classOption["key"] = 0;
 | 
			
		||||
if (props.classOption["key"] === undefined) {
 | 
			
		||||
  // eslint-disable-next-line vue/no-mutating-props
 | 
			
		||||
  props.classOption["key"] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const wrap = templateRef<HTMLElement | null>(`wrap${classOption["key"]}`, null);
 | 
			
		||||
const wrap = templateRef<HTMLElement | null>(
 | 
			
		||||
  `wrap${props.classOption["key"]}`,
 | 
			
		||||
  null
 | 
			
		||||
);
 | 
			
		||||
const slotList = templateRef<HTMLElement | null>(
 | 
			
		||||
  `slotList${classOption["key"]}`,
 | 
			
		||||
  `slotList${props.classOption["key"]}`,
 | 
			
		||||
  null
 | 
			
		||||
);
 | 
			
		||||
const realBox = templateRef<HTMLElement | null>(
 | 
			
		||||
  `realBox${classOption["key"]}`,
 | 
			
		||||
  `realBox${props.classOption["key"]}`,
 | 
			
		||||
  null
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
@ -107,7 +108,7 @@ const defaultOption = computed(() => {
 | 
			
		||||
 | 
			
		||||
const options = computed(() => {
 | 
			
		||||
  // @ts-expect-error
 | 
			
		||||
  return copyObj({}, unref(defaultOption), classOption);
 | 
			
		||||
  return copyObj({}, unref(defaultOption), props.classOption);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const leftSwitchClass = computed(() => {
 | 
			
		||||
@ -495,7 +496,7 @@ defineExpose({
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div :ref="'wrap' + classOption['key']">
 | 
			
		||||
  <div :ref="'wrap' + props.classOption['key']">
 | 
			
		||||
    <div
 | 
			
		||||
      :style="leftSwitch"
 | 
			
		||||
      v-if="navigation"
 | 
			
		||||
@ -513,7 +514,7 @@ defineExpose({
 | 
			
		||||
      <slot name="right-switch" />
 | 
			
		||||
    </div>
 | 
			
		||||
    <div
 | 
			
		||||
      :ref="'realBox' + classOption['key']"
 | 
			
		||||
      :ref="'realBox' + props.classOption['key']"
 | 
			
		||||
      :style="pos"
 | 
			
		||||
      @mouseenter="enter"
 | 
			
		||||
      @mouseleave="leave"
 | 
			
		||||
@ -522,7 +523,7 @@ defineExpose({
 | 
			
		||||
      @touchend="touchEnd"
 | 
			
		||||
      @mousewheel.passive="wheel"
 | 
			
		||||
    >
 | 
			
		||||
      <div :ref="'slotList' + classOption['key']" :style="float">
 | 
			
		||||
      <div :ref="'slotList' + props.classOption['key']" :style="float">
 | 
			
		||||
        <slot />
 | 
			
		||||
      </div>
 | 
			
		||||
      <div v-html="copyHtml" :style="float" />
 | 
			
		||||
 | 
			
		||||
@ -164,7 +164,7 @@ onKeyStroke("ArrowDown", handleDown);
 | 
			
		||||
      </template>
 | 
			
		||||
    </el-input>
 | 
			
		||||
    <div class="search-result-container">
 | 
			
		||||
      <el-scrollbar ref="scrollbarRef" max-height="600px">
 | 
			
		||||
      <el-scrollbar ref="scrollbarRef" max-height="calc(90vh - 140px)">
 | 
			
		||||
        <el-empty
 | 
			
		||||
          v-if="resultOptions.length === 0"
 | 
			
		||||
          description="暂无搜索结果"
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,9 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { useI18n } from "vue-i18n";
 | 
			
		||||
import { computed, getCurrentInstance } from "vue";
 | 
			
		||||
import { useResizeObserver } from "@vueuse/core";
 | 
			
		||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
 | 
			
		||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
			
		||||
import { ref, computed, getCurrentInstance, onMounted } from "vue";
 | 
			
		||||
import enterOutlined from "@/assets/svg/enter_outlined.svg?component";
 | 
			
		||||
import Bookmark2Line from "@iconify-icons/ri/bookmark-2-line";
 | 
			
		||||
 | 
			
		||||
@ -26,6 +27,8 @@ interface Emits {
 | 
			
		||||
  (e: "enter"): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const resultRef = ref();
 | 
			
		||||
const innerHeight = ref();
 | 
			
		||||
const props = withDefaults(defineProps<Props>(), {});
 | 
			
		||||
const emit = defineEmits<Emits>();
 | 
			
		||||
const instance = getCurrentInstance()!;
 | 
			
		||||
@ -59,19 +62,32 @@ function handleTo() {
 | 
			
		||||
  emit("enter");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function resizeResult() {
 | 
			
		||||
  // el-scrollbar max-height="calc(90vh - 140px)"
 | 
			
		||||
  innerHeight.value = window.innerHeight - window.innerHeight / 10 - 140;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
useResizeObserver(resultRef, () => {
 | 
			
		||||
  resizeResult();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function handleScroll(index: number) {
 | 
			
		||||
  const curInstance = instance?.proxy?.$refs[`resultItemRef${index}`];
 | 
			
		||||
  if (!curInstance) return 0;
 | 
			
		||||
  const curRef = curInstance[0] as ElRef;
 | 
			
		||||
  const scrollTop = curRef.offsetTop + 128; // 128 两个result-item(56px+56px=112px)高度加上下margin(8px+8px=16px)
 | 
			
		||||
  return scrollTop > 600 ? scrollTop - 600 : 0; // 600 el-scrollbar max-height="600px"
 | 
			
		||||
  return scrollTop > innerHeight.value ? scrollTop - innerHeight.value : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  resizeResult();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
defineExpose({ handleScroll });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="result">
 | 
			
		||||
  <div ref="resultRef" class="result">
 | 
			
		||||
    <div
 | 
			
		||||
      v-for="(item, index) in options"
 | 
			
		||||
      :key="item.path"
 | 
			
		||||
 | 
			
		||||
@ -218,7 +218,6 @@ watch($storage, ({ layout }) => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onBeforeMount(() => {
 | 
			
		||||
  dataThemeChange();
 | 
			
		||||
  /* 初始化项目配置 */
 | 
			
		||||
  nextTick(() => {
 | 
			
		||||
    settings.greyVal &&
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,15 @@ import { useLayout } from "./hooks/useLayout";
 | 
			
		||||
import { useAppStoreHook } from "@/store/modules/app";
 | 
			
		||||
import { useSettingStoreHook } from "@/store/modules/settings";
 | 
			
		||||
import { deviceDetection, useDark, useGlobal } from "@pureadmin/utils";
 | 
			
		||||
import { h, reactive, computed, onMounted, defineComponent } from "vue";
 | 
			
		||||
import { useDataThemeChange } from "@/layout/hooks/useDataThemeChange";
 | 
			
		||||
import {
 | 
			
		||||
  h,
 | 
			
		||||
  reactive,
 | 
			
		||||
  computed,
 | 
			
		||||
  onMounted,
 | 
			
		||||
  onBeforeMount,
 | 
			
		||||
  defineComponent
 | 
			
		||||
} from "vue";
 | 
			
		||||
 | 
			
		||||
import navbar from "./components/navbar.vue";
 | 
			
		||||
import tag from "./components/tag/index.vue";
 | 
			
		||||
@ -102,6 +110,10 @@ onMounted(() => {
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
onBeforeMount(() => {
 | 
			
		||||
  useDataThemeChange().dataThemeChange();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const layoutHeader = defineComponent({
 | 
			
		||||
  render() {
 | 
			
		||||
    return h(
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ import {
 | 
			
		||||
  formatFlatteningRoutes
 | 
			
		||||
} from "./utils";
 | 
			
		||||
import { buildHierarchyTree } from "@/utils/tree";
 | 
			
		||||
import { isUrl, openLink, storageSession } from "@pureadmin/utils";
 | 
			
		||||
import { isUrl, openLink, storageSession, isAllEmpty } from "@pureadmin/utils";
 | 
			
		||||
 | 
			
		||||
import remainingRouter from "./modules/remaining";
 | 
			
		||||
 | 
			
		||||
@ -158,11 +158,22 @@ router.beforeEach((to: toRouteType, _from, next) => {
 | 
			
		||||
            getTopMenu(true);
 | 
			
		||||
            // query、params模式路由传参数的标签页不在此处处理
 | 
			
		||||
            if (route && route.meta?.title) {
 | 
			
		||||
              useMultiTagsStoreHook().handleTags("push", {
 | 
			
		||||
                path: route.path,
 | 
			
		||||
                name: route.name,
 | 
			
		||||
                meta: route.meta
 | 
			
		||||
              });
 | 
			
		||||
              if (isAllEmpty(route.parentId) && route.meta?.backstage) {
 | 
			
		||||
                // 此处为动态顶级路由(目录)
 | 
			
		||||
                const { path, name, meta } = route.children[0];
 | 
			
		||||
                useMultiTagsStoreHook().handleTags("push", {
 | 
			
		||||
                  path,
 | 
			
		||||
                  name,
 | 
			
		||||
                  meta
 | 
			
		||||
                });
 | 
			
		||||
              } else {
 | 
			
		||||
                const { path, name, meta } = route;
 | 
			
		||||
                useMultiTagsStoreHook().handleTags("push", {
 | 
			
		||||
                  path,
 | 
			
		||||
                  name,
 | 
			
		||||
                  meta
 | 
			
		||||
                });
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          router.push(to.fullPath);
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,7 @@ import { components } from "@/router/enums";
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  path: "/components",
 | 
			
		||||
  redirect: "/components/video",
 | 
			
		||||
  redirect: "/components/dialog",
 | 
			
		||||
  meta: {
 | 
			
		||||
    icon: "menu",
 | 
			
		||||
    title: $t("menus.hscomponents"),
 | 
			
		||||
 | 
			
		||||
@ -54,14 +54,14 @@ export function useColumns() {
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      label: "QQ交流群",
 | 
			
		||||
      label: "精简版",
 | 
			
		||||
      cellRenderer: () => {
 | 
			
		||||
        return (
 | 
			
		||||
          <a
 | 
			
		||||
            href="https://yiming_chang.gitee.io/pure-admin-doc/pages/support/#qq-%E4%BA%A4%E6%B5%81%E7%BE%A4"
 | 
			
		||||
            href="https://github.com/pure-admin/pure-admin-thin"
 | 
			
		||||
            target="_blank"
 | 
			
		||||
          >
 | 
			
		||||
            <span style="color: var(--el-color-primary)">点击加群</span>
 | 
			
		||||
            <span style="color: var(--el-color-primary)">精简版</span>
 | 
			
		||||
          </a>
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -2,9 +2,14 @@
 | 
			
		||||
import { useRouter } from "vue-router";
 | 
			
		||||
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";
 | 
			
		||||
import { cloneDeep, debounce } from "@pureadmin/utils";
 | 
			
		||||
import {
 | 
			
		||||
  addDialog,
 | 
			
		||||
  closeDialog,
 | 
			
		||||
  updateDialog,
 | 
			
		||||
  closeAllDialog
 | 
			
		||||
} from "@/components/ReDialog";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "DialogPage"
 | 
			
		||||
@ -60,13 +65,16 @@ function onStyleClick() {
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function onoOpenDelayClick() {
 | 
			
		||||
  addDialog({
 | 
			
		||||
    title: "延时2秒打开弹框",
 | 
			
		||||
    openDelay: 2000,
 | 
			
		||||
    contentRenderer: () => <p>弹框内容-延时2秒打开弹框</p>
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
// 添加 600ms 防抖
 | 
			
		||||
const onoOpenDelayClick = debounce(
 | 
			
		||||
  () =>
 | 
			
		||||
    addDialog({
 | 
			
		||||
      title: "延时2秒打开弹框",
 | 
			
		||||
      openDelay: 2000 - 600,
 | 
			
		||||
      contentRenderer: () => <p>弹框内容-延时2秒打开弹框</p>
 | 
			
		||||
    }),
 | 
			
		||||
  600
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
function onCloseDelayClick() {
 | 
			
		||||
  addDialog({
 | 
			
		||||
@ -240,6 +248,35 @@ function onNestingClick() {
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 满足在 contentRenderer 内容区更改弹框自身属性值的场景
 | 
			
		||||
function onUpdateClick() {
 | 
			
		||||
  const curPage = ref(1);
 | 
			
		||||
  addDialog({
 | 
			
		||||
    title: `第${curPage.value}页`,
 | 
			
		||||
    contentRenderer: () => (
 | 
			
		||||
      <>
 | 
			
		||||
        <el-button
 | 
			
		||||
          disabled={curPage.value > 1 ? false : true}
 | 
			
		||||
          onClick={() => {
 | 
			
		||||
            curPage.value -= 1;
 | 
			
		||||
            updateDialog(`第${curPage.value}页`);
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          上一页
 | 
			
		||||
        </el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          onClick={() => {
 | 
			
		||||
            curPage.value += 1;
 | 
			
		||||
            updateDialog(`第${curPage.value}页`);
 | 
			
		||||
          }}
 | 
			
		||||
        >
 | 
			
		||||
          下一页
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </>
 | 
			
		||||
    )
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 结合Form表单(第一种方式,弹框关闭立刻恢复初始值)通过 props 属性接收子组件的 prop 并赋值
 | 
			
		||||
function onFormOneClick() {
 | 
			
		||||
  addDialog({
 | 
			
		||||
@ -421,6 +458,7 @@ function onBeforeSureClick() {
 | 
			
		||||
      <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-space>
 | 
			
		||||
    <el-divider />
 | 
			
		||||
    <el-space wrap>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										56
									
								
								src/views/editor/components/base.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,56 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import "@wangeditor/editor/dist/css/style.css";
 | 
			
		||||
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
 | 
			
		||||
import { onBeforeUnmount, ref, shallowRef, onMounted } from "vue";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "BaseEditor"
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mode = "default";
 | 
			
		||||
// 编辑器实例,必须用 shallowRef
 | 
			
		||||
const editorRef = shallowRef();
 | 
			
		||||
 | 
			
		||||
// 内容 HTML
 | 
			
		||||
const valueHtml = ref("<p>你好</p>");
 | 
			
		||||
 | 
			
		||||
// 模拟 ajax 异步获取内容
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    valueHtml.value = "<p>我是模拟的异步数据</p>";
 | 
			
		||||
  }, 1500);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const toolbarConfig: any = { excludeKeys: "fullScreen" };
 | 
			
		||||
const editorConfig = { placeholder: "请输入内容..." };
 | 
			
		||||
 | 
			
		||||
const handleCreated = editor => {
 | 
			
		||||
  // 记录 editor 实例,重要!
 | 
			
		||||
  editorRef.value = editor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 组件销毁时,也及时销毁编辑器
 | 
			
		||||
onBeforeUnmount(() => {
 | 
			
		||||
  const editor = editorRef.value;
 | 
			
		||||
  if (editor == null) return;
 | 
			
		||||
  editor.destroy();
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="wangeditor">
 | 
			
		||||
    <Toolbar
 | 
			
		||||
      :editor="editorRef"
 | 
			
		||||
      :defaultConfig="toolbarConfig"
 | 
			
		||||
      :mode="mode"
 | 
			
		||||
      style="border-bottom: 1px solid #ccc"
 | 
			
		||||
    />
 | 
			
		||||
    <Editor
 | 
			
		||||
      v-model="valueHtml"
 | 
			
		||||
      :defaultConfig="editorConfig"
 | 
			
		||||
      :mode="mode"
 | 
			
		||||
      style="height: 500px; overflow-y: hidden"
 | 
			
		||||
      @onCreated="handleCreated"
 | 
			
		||||
    />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
							
								
								
									
										9
									
								
								src/views/editor/components/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,9 @@
 | 
			
		||||
import base from "./base.vue";
 | 
			
		||||
import multi from "./multi.vue";
 | 
			
		||||
import picUpload from "./picUpload.vue";
 | 
			
		||||
 | 
			
		||||
const Base = base;
 | 
			
		||||
const Multi = multi;
 | 
			
		||||
const PicUpload = picUpload;
 | 
			
		||||
 | 
			
		||||
export { Base, Multi, PicUpload };
 | 
			
		||||
							
								
								
									
										76
									
								
								src/views/editor/components/multi.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,76 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import ReCol from "@/components/ReCol";
 | 
			
		||||
import { onBeforeUnmount, ref, shallowRef } from "vue";
 | 
			
		||||
import "@wangeditor/editor/dist/css/style.css";
 | 
			
		||||
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "MultiEditor"
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 模拟后端返回多个编辑器的数据
 | 
			
		||||
const endEditorList = [
 | 
			
		||||
  {
 | 
			
		||||
    value: "<p>测试一</p>"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    value: "<p>测试二</p>"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    value: "<p>测试三</p>"
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    value: "<p>测试四</p>"
 | 
			
		||||
  }
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
// 多个编辑器的情况下,前端必须进行处理,满足 Toolbar 组件的 editor 属性 所需的 shallowRef 格式
 | 
			
		||||
const editorList = ref([]);
 | 
			
		||||
endEditorList.forEach(edit => {
 | 
			
		||||
  editorList.value.push({
 | 
			
		||||
    value: edit.value,
 | 
			
		||||
    // 编辑器实例,必须用 shallowRef
 | 
			
		||||
    editorRef: shallowRef()
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mode = "default";
 | 
			
		||||
 | 
			
		||||
const toolbarConfig: any = { excludeKeys: "fullScreen" };
 | 
			
		||||
const editorConfig = { placeholder: "请输入内容..." };
 | 
			
		||||
 | 
			
		||||
const handleCreated = (editor, index) => {
 | 
			
		||||
  // 记录 editor 实例,重要!
 | 
			
		||||
  editorList.value[index].editorRef = editor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 组件销毁时,也及时销毁编辑器
 | 
			
		||||
onBeforeUnmount(() => {
 | 
			
		||||
  return editorList.value.map(edit => {
 | 
			
		||||
    if (edit.editorRef == null) return;
 | 
			
		||||
    edit.editorRef.destroy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <el-row :gutter="30" justify="space-around">
 | 
			
		||||
    <re-col :value="11" v-for="(edit, index) in editorList" :key="index">
 | 
			
		||||
      <div class="wangeditor">
 | 
			
		||||
        <Toolbar
 | 
			
		||||
          :editor="edit.editorRef"
 | 
			
		||||
          :defaultConfig="toolbarConfig"
 | 
			
		||||
          :mode="mode"
 | 
			
		||||
          style="border-bottom: 1px solid #ccc"
 | 
			
		||||
        />
 | 
			
		||||
        <Editor
 | 
			
		||||
          v-model="edit.value"
 | 
			
		||||
          :defaultConfig="editorConfig"
 | 
			
		||||
          :mode="mode"
 | 
			
		||||
          style="height: 300px; overflow-y: hidden"
 | 
			
		||||
          @onCreated="editor => handleCreated(editor, index)"
 | 
			
		||||
        />
 | 
			
		||||
      </div>
 | 
			
		||||
    </re-col>
 | 
			
		||||
  </el-row>
 | 
			
		||||
</template>
 | 
			
		||||
							
								
								
									
										70
									
								
								src/views/editor/components/picUpload.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@ -0,0 +1,70 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { onBeforeUnmount, ref, shallowRef } from "vue";
 | 
			
		||||
import "@wangeditor/editor/dist/css/style.css";
 | 
			
		||||
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "picUpload"
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mode = "default";
 | 
			
		||||
// 编辑器实例,必须用 shallowRef
 | 
			
		||||
const editorRef = shallowRef();
 | 
			
		||||
 | 
			
		||||
// 内容 HTML
 | 
			
		||||
const valueHtml = ref(
 | 
			
		||||
  "<p>仅提供代码参考,暂不可上传图片,可根据实际业务改写</p>"
 | 
			
		||||
);
 | 
			
		||||
const toolbarConfig: any = { excludeKeys: "fullScreen" };
 | 
			
		||||
const editorConfig = { placeholder: "请输入内容...", MENU_CONF: {} };
 | 
			
		||||
 | 
			
		||||
// 更多详细配置看 https://www.wangeditor.com/v5/menu-config.html#%E4%B8%8A%E4%BC%A0%E5%9B%BE%E7%89%87
 | 
			
		||||
editorConfig.MENU_CONF["uploadImage"] = {
 | 
			
		||||
  // 服务端上传地址,根据实际业务改写
 | 
			
		||||
  server: "",
 | 
			
		||||
  // form-data 的 fieldName,根据实际业务改写
 | 
			
		||||
  fieldName: "file",
 | 
			
		||||
  // 选择文件时的类型限制,根据实际业务改写
 | 
			
		||||
  allowedFileTypes: ["image/png", "image/jpg", "image/jpeg"],
 | 
			
		||||
  // 自定义插入图片
 | 
			
		||||
  customInsert(res: any, insertFn) {
 | 
			
		||||
    // res.data.url是后端返回的图片地址,根据实际业务改写
 | 
			
		||||
    if (res.data.url) {
 | 
			
		||||
      setTimeout(() => {
 | 
			
		||||
        // insertFn插入图片进编辑器
 | 
			
		||||
        insertFn(res.data.url);
 | 
			
		||||
      }, 2000);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handleCreated = editor => {
 | 
			
		||||
  // 记录 editor 实例,重要!
 | 
			
		||||
  editorRef.value = editor;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 组件销毁时,也及时销毁编辑器
 | 
			
		||||
onBeforeUnmount(() => {
 | 
			
		||||
  const editor = editorRef.value;
 | 
			
		||||
  if (editor == null) return;
 | 
			
		||||
  editor.destroy();
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="wangeditor">
 | 
			
		||||
    <Toolbar
 | 
			
		||||
      :editor="editorRef"
 | 
			
		||||
      :defaultConfig="toolbarConfig"
 | 
			
		||||
      :mode="mode"
 | 
			
		||||
      style="border-bottom: 1px solid #ccc"
 | 
			
		||||
    />
 | 
			
		||||
    <Editor
 | 
			
		||||
      v-model="valueHtml"
 | 
			
		||||
      :defaultConfig="editorConfig"
 | 
			
		||||
      :mode="mode"
 | 
			
		||||
      style="height: 500px; overflow-y: hidden"
 | 
			
		||||
      @onCreated="handleCreated"
 | 
			
		||||
    />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
@ -1,41 +1,12 @@
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
 | 
			
		||||
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
 | 
			
		||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
 | 
			
		||||
import { onBeforeUnmount, ref, shallowRef, onMounted } from "vue";
 | 
			
		||||
import Edit from "@iconify-icons/ep/edit";
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import { Base, Multi, PicUpload } from "./components";
 | 
			
		||||
 | 
			
		||||
defineOptions({
 | 
			
		||||
  name: "Editor"
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const mode = "default";
 | 
			
		||||
// 编辑器实例,必须用 shallowRef
 | 
			
		||||
const editorRef = shallowRef();
 | 
			
		||||
 | 
			
		||||
// 内容 HTML
 | 
			
		||||
const valueHtml = ref("<p>hello</p>");
 | 
			
		||||
 | 
			
		||||
// 模拟 ajax 异步获取内容
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  setTimeout(() => {
 | 
			
		||||
    valueHtml.value = "<p>模拟 Ajax 异步设置内容</p>";
 | 
			
		||||
  }, 1500);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const toolbarConfig: any = { excludeKeys: "fullScreen" };
 | 
			
		||||
const editorConfig = { placeholder: "请输入内容..." };
 | 
			
		||||
 | 
			
		||||
// 组件销毁时,也及时销毁编辑器
 | 
			
		||||
onBeforeUnmount(() => {
 | 
			
		||||
  const editor = editorRef.value;
 | 
			
		||||
  if (editor == null) return;
 | 
			
		||||
  editor.destroy();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const handleCreated = editor => {
 | 
			
		||||
  editorRef.value = editor; // 记录 editor 实例,重要!
 | 
			
		||||
};
 | 
			
		||||
const activeNames = ref(["1"]);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
@ -47,7 +18,6 @@ const handleCreated = editor => {
 | 
			
		||||
          <el-link
 | 
			
		||||
            href="https://www.wangeditor.com"
 | 
			
		||||
            target="_blank"
 | 
			
		||||
            :icon="useRenderIcon(Edit)"
 | 
			
		||||
            style="margin: 0 4px 5px; font-size: 16px"
 | 
			
		||||
          >
 | 
			
		||||
            Wangeditor
 | 
			
		||||
@ -55,20 +25,22 @@ const handleCreated = editor => {
 | 
			
		||||
        </span>
 | 
			
		||||
      </div>
 | 
			
		||||
    </template>
 | 
			
		||||
    <div class="wangeditor">
 | 
			
		||||
      <Toolbar
 | 
			
		||||
        style="border-bottom: 1px solid #ccc"
 | 
			
		||||
        :editor="editorRef"
 | 
			
		||||
        :defaultConfig="toolbarConfig"
 | 
			
		||||
        :mode="mode"
 | 
			
		||||
      />
 | 
			
		||||
      <Editor
 | 
			
		||||
        style="height: 500px; overflow-y: hidden"
 | 
			
		||||
        v-model="valueHtml"
 | 
			
		||||
        :defaultConfig="editorConfig"
 | 
			
		||||
        :mode="mode"
 | 
			
		||||
        @onCreated="handleCreated"
 | 
			
		||||
      />
 | 
			
		||||
    </div>
 | 
			
		||||
    <el-collapse v-model="activeNames" accordion>
 | 
			
		||||
      <el-collapse-item title="基础用法" name="1">
 | 
			
		||||
        <Base />
 | 
			
		||||
      </el-collapse-item>
 | 
			
		||||
      <el-collapse-item title="多个富文本" name="2">
 | 
			
		||||
        <Multi />
 | 
			
		||||
      </el-collapse-item>
 | 
			
		||||
      <el-collapse-item title="自定义图片上传" name="3">
 | 
			
		||||
        <PicUpload />
 | 
			
		||||
      </el-collapse-item>
 | 
			
		||||
    </el-collapse>
 | 
			
		||||
  </el-card>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style lang="scss" scoped>
 | 
			
		||||
:deep(.el-collapse-item__header) {
 | 
			
		||||
  padding-left: 10px;
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
 | 
			
		||||