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
|
# https://cn.vitejs.dev/guide/env-and-mode.html#modes
|
||||||
NODE_ENV=production
|
# NODE_ENV = development
|
||||||
|
|
||||||
VITE_PUBLIC_PATH = /
|
VITE_PUBLIC_PATH = /
|
||||||
|
|
||||||
|
10
.vscode/vue3.0.code-snippets
vendored
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"Vue3.0快速生成模板": {
|
"Vue3.0快速生成模板": {
|
||||||
|
"scope": "vue",
|
||||||
"prefix": "Vue3.0",
|
"prefix": "Vue3.0",
|
||||||
"body": [
|
"body": [
|
||||||
"<template>",
|
"<template>",
|
||||||
"\t<div>\n",
|
"\t<div>test</div>",
|
||||||
"\t</div>",
|
|
||||||
"</template>\n",
|
"</template>\n",
|
||||||
"<script lang='ts'>",
|
"<script lang='ts'>",
|
||||||
"export default {",
|
"export default {",
|
||||||
"\tsetup() {",
|
"\tsetup() {",
|
||||||
"\t\treturn{\n\n\t\t}",
|
"\t\treturn {}",
|
||||||
"\t},",
|
"\t}",
|
||||||
"}",
|
"}",
|
||||||
"</script>\n",
|
"</script>\n",
|
||||||
"<style scoped>\n",
|
"<style lang='scss' scoped>\n",
|
||||||
"</style>",
|
"</style>",
|
||||||
"$2"
|
"$2"
|
||||||
],
|
],
|
||||||
|
6
.vscode/vue3.2.code-snippets
vendored
@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"Vue3.2+快速生成模板": {
|
"Vue3.2+快速生成模板": {
|
||||||
|
"scope": "vue",
|
||||||
"prefix": "Vue3.2+",
|
"prefix": "Vue3.2+",
|
||||||
"body": [
|
"body": [
|
||||||
"<script setup lang='ts'>",
|
"<script setup lang='ts'>",
|
||||||
"</script>\n",
|
"</script>\n",
|
||||||
"<template>",
|
"<template>",
|
||||||
"\t<div>\n",
|
"\t<div>test</div>",
|
||||||
"\t</div>",
|
|
||||||
"</template>\n",
|
"</template>\n",
|
||||||
"<style scoped>\n",
|
"<style lang='scss' scoped>\n",
|
||||||
"</style>",
|
"</style>",
|
||||||
"$2"
|
"$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 Tutorial](https://www.bilibili.com/video/BV1kg411v7QT)
|
||||||
- [Click Watch UI Design](https://www.bilibili.com/video/BV17g411T7rq)
|
- [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 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)
|
- [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)
|
[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
|
## 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)
|
[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`
|
## `Star`
|
||||||
|
|
||||||
Many thanks to the kind individuals who leave a star. Your support is much appreciated :heart:
|
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)
|
- [点我查看快速开发教程](https://www.bilibili.com/video/BV1kg411v7QT)
|
||||||
- [点我查看 UI 设计](https://www.bilibili.com/video/BV17g411T7rq)
|
- [点我查看 UI 设计](https://www.bilibili.com/video/BV17g411T7rq)
|
||||||
|
|
||||||
## 配套保姆级文档(支持 `PWA` 快速、离线访问)
|
## 配套保姆级文档
|
||||||
|
|
||||||
- [点我查看国内文档站](https://yiming_chang.gitee.io/pure-admin-doc)
|
- [点我查看国内文档站](https://yiming_chang.gitee.io/pure-admin-doc)
|
||||||
- [点我查看国外文档站](https://pure-admin.github.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)
|
[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)
|
[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`
|
## `Star`
|
||||||
|
|
||||||
非常感谢留下星星的好心人,感谢您的支持 :heart:
|
非常感谢留下星星的好心人,感谢您的支持 :heart:
|
||||||
|
20
package.json
@ -56,7 +56,7 @@
|
|||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"pinia": "^2.1.1",
|
"pinia": "^2.1.3",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"qs": "^6.11.1",
|
"qs": "^6.11.1",
|
||||||
"responsive-storage": "^2.2.0",
|
"responsive-storage": "^2.2.0",
|
||||||
@ -69,7 +69,7 @@
|
|||||||
"vue-i18n": "^9.2.2",
|
"vue-i18n": "^9.2.2",
|
||||||
"vue-json-pretty": "^2.2.4",
|
"vue-json-pretty": "^2.2.4",
|
||||||
"vue-pdf-embed": "^1.1.6",
|
"vue-pdf-embed": "^1.1.6",
|
||||||
"vue-router": "^4.2.0",
|
"vue-router": "^4.2.1",
|
||||||
"vue-types": "^5.0.3",
|
"vue-types": "^5.0.3",
|
||||||
"vue-virtual-scroller": "2.0.0-beta.7",
|
"vue-virtual-scroller": "2.0.0-beta.7",
|
||||||
"vue-waterfall-plugin-next": "^2.2.1",
|
"vue-waterfall-plugin-next": "^2.2.1",
|
||||||
@ -104,9 +104,9 @@
|
|||||||
"autoprefixer": "^10.4.14",
|
"autoprefixer": "^10.4.14",
|
||||||
"cloc": "^2.11.0",
|
"cloc": "^2.11.0",
|
||||||
"cssnano": "^6.0.1",
|
"cssnano": "^6.0.1",
|
||||||
"eslint": "^8.40.0",
|
"eslint": "^8.41.0",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-vue": "^9.13.0",
|
"eslint-plugin-vue": "^9.14.0",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"lint-staged": "^13.2.2",
|
"lint-staged": "^13.2.2",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.0",
|
||||||
@ -114,12 +114,12 @@
|
|||||||
"postcss-html": "^1.5.0",
|
"postcss-html": "^1.5.0",
|
||||||
"postcss-import": "^15.1.0",
|
"postcss-import": "^15.1.0",
|
||||||
"postcss-scss": "^4.0.6",
|
"postcss-scss": "^4.0.6",
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.8",
|
||||||
"pretty-quick": "3.1.1",
|
"pretty-quick": "^3.1.3",
|
||||||
"rimraf": "^5.0.0",
|
"rimraf": "^5.0.1",
|
||||||
"rollup-plugin-visualizer": "^5.9.0",
|
"rollup-plugin-visualizer": "^5.9.0",
|
||||||
"sass": "^1.62.1",
|
"sass": "^1.62.1",
|
||||||
"sass-loader": "^13.2.2",
|
"sass-loader": "^13.3.0",
|
||||||
"stylelint": "^15.6.2",
|
"stylelint": "^15.6.2",
|
||||||
"stylelint-config-html": "^1.1.0",
|
"stylelint-config-html": "^1.1.0",
|
||||||
"stylelint-config-recess-order": "^4.0.0",
|
"stylelint-config-recess-order": "^4.0.0",
|
||||||
@ -133,9 +133,9 @@
|
|||||||
"stylelint-scss": "^5.0.0",
|
"stylelint-scss": "^5.0.0",
|
||||||
"svgo": "^3.0.2",
|
"svgo": "^3.0.2",
|
||||||
"tailwindcss": "^3.3.2",
|
"tailwindcss": "^3.3.2",
|
||||||
"terser": "^5.17.4",
|
"terser": "^5.17.5",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"vite": "^4.3.7",
|
"vite": "^4.3.8",
|
||||||
"vite-plugin-cdn-import": "^0.3.5",
|
"vite-plugin-cdn-import": "^0.3.5",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.6",
|
||||||
|
8278
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 dialogStore = ref<Array<DialogOptions>>([]);
|
||||||
|
|
||||||
|
/** 打开弹框 */
|
||||||
const addDialog = (options: DialogOptions) => {
|
const addDialog = (options: DialogOptions) => {
|
||||||
const open = () =>
|
const open = () =>
|
||||||
dialogStore.value.push(Object.assign(options, { visible: true }));
|
dialogStore.value.push(Object.assign(options, { visible: true }));
|
||||||
@ -24,16 +25,40 @@ const addDialog = (options: DialogOptions) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** 关闭弹框 */
|
||||||
const closeDialog = (options: DialogOptions, index: number, args?: any) => {
|
const closeDialog = (options: DialogOptions, index: number, args?: any) => {
|
||||||
dialogStore.value.splice(index, 1);
|
dialogStore.value.splice(index, 1);
|
||||||
options.closeCallBack && options.closeCallBack({ options, index, args });
|
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 = () => {
|
const closeAllDialog = () => {
|
||||||
dialogStore.value = [];
|
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);
|
const ReDialog = withInstall(reDialog);
|
||||||
|
|
||||||
export type { EventType, ArgsType, DialogProps, ButtonProps, DialogOptions };
|
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 () => (
|
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">
|
<div class="flex justify-between w-full h-[60px] p-4">
|
||||||
|
{slots?.title ? (
|
||||||
|
slots.title()
|
||||||
|
) : (
|
||||||
<p class="font-bold truncate">{props.title}</p>
|
<p class="font-bold truncate">{props.title}</p>
|
||||||
|
)}
|
||||||
<div class="flex items-center justify-around">
|
<div class="flex items-center justify-around">
|
||||||
{slots?.buttons ? (
|
{slots?.buttons ? (
|
||||||
<div class="flex mr-4">{slots.buttons()}</div>
|
<div class="flex mr-4">{slots.buttons()}</div>
|
||||||
|
@ -51,20 +51,21 @@ let startPosX = null;
|
|||||||
let isHover = false;
|
let isHover = false;
|
||||||
let ease = "ease-in";
|
let ease = "ease-in";
|
||||||
|
|
||||||
// eslint-disable-next-line vue/no-setup-props-destructure
|
if (props.classOption["key"] === undefined) {
|
||||||
const { classOption } = props;
|
// eslint-disable-next-line vue/no-mutating-props
|
||||||
|
props.classOption["key"] = 0;
|
||||||
if (classOption["key"] === undefined) {
|
|
||||||
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>(
|
const slotList = templateRef<HTMLElement | null>(
|
||||||
`slotList${classOption["key"]}`,
|
`slotList${props.classOption["key"]}`,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
const realBox = templateRef<HTMLElement | null>(
|
const realBox = templateRef<HTMLElement | null>(
|
||||||
`realBox${classOption["key"]}`,
|
`realBox${props.classOption["key"]}`,
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -107,7 +108,7 @@ const defaultOption = computed(() => {
|
|||||||
|
|
||||||
const options = computed(() => {
|
const options = computed(() => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
return copyObj({}, unref(defaultOption), classOption);
|
return copyObj({}, unref(defaultOption), props.classOption);
|
||||||
});
|
});
|
||||||
|
|
||||||
const leftSwitchClass = computed(() => {
|
const leftSwitchClass = computed(() => {
|
||||||
@ -495,7 +496,7 @@ defineExpose({
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :ref="'wrap' + classOption['key']">
|
<div :ref="'wrap' + props.classOption['key']">
|
||||||
<div
|
<div
|
||||||
:style="leftSwitch"
|
:style="leftSwitch"
|
||||||
v-if="navigation"
|
v-if="navigation"
|
||||||
@ -513,7 +514,7 @@ defineExpose({
|
|||||||
<slot name="right-switch" />
|
<slot name="right-switch" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
:ref="'realBox' + classOption['key']"
|
:ref="'realBox' + props.classOption['key']"
|
||||||
:style="pos"
|
:style="pos"
|
||||||
@mouseenter="enter"
|
@mouseenter="enter"
|
||||||
@mouseleave="leave"
|
@mouseleave="leave"
|
||||||
@ -522,7 +523,7 @@ defineExpose({
|
|||||||
@touchend="touchEnd"
|
@touchend="touchEnd"
|
||||||
@mousewheel.passive="wheel"
|
@mousewheel.passive="wheel"
|
||||||
>
|
>
|
||||||
<div :ref="'slotList' + classOption['key']" :style="float">
|
<div :ref="'slotList' + props.classOption['key']" :style="float">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
<div v-html="copyHtml" :style="float" />
|
<div v-html="copyHtml" :style="float" />
|
||||||
|
@ -164,7 +164,7 @@ onKeyStroke("ArrowDown", handleDown);
|
|||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
<div class="search-result-container">
|
<div class="search-result-container">
|
||||||
<el-scrollbar ref="scrollbarRef" max-height="600px">
|
<el-scrollbar ref="scrollbarRef" max-height="calc(90vh - 140px)">
|
||||||
<el-empty
|
<el-empty
|
||||||
v-if="resultOptions.length === 0"
|
v-if="resultOptions.length === 0"
|
||||||
description="暂无搜索结果"
|
description="暂无搜索结果"
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
import { computed, getCurrentInstance } from "vue";
|
import { useResizeObserver } from "@vueuse/core";
|
||||||
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
import { useEpThemeStoreHook } from "@/store/modules/epTheme";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
|
import { ref, computed, getCurrentInstance, onMounted } from "vue";
|
||||||
import enterOutlined from "@/assets/svg/enter_outlined.svg?component";
|
import enterOutlined from "@/assets/svg/enter_outlined.svg?component";
|
||||||
import Bookmark2Line from "@iconify-icons/ri/bookmark-2-line";
|
import Bookmark2Line from "@iconify-icons/ri/bookmark-2-line";
|
||||||
|
|
||||||
@ -26,6 +27,8 @@ interface Emits {
|
|||||||
(e: "enter"): void;
|
(e: "enter"): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resultRef = ref();
|
||||||
|
const innerHeight = ref();
|
||||||
const props = withDefaults(defineProps<Props>(), {});
|
const props = withDefaults(defineProps<Props>(), {});
|
||||||
const emit = defineEmits<Emits>();
|
const emit = defineEmits<Emits>();
|
||||||
const instance = getCurrentInstance()!;
|
const instance = getCurrentInstance()!;
|
||||||
@ -59,19 +62,32 @@ function handleTo() {
|
|||||||
emit("enter");
|
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) {
|
function handleScroll(index: number) {
|
||||||
const curInstance = instance?.proxy?.$refs[`resultItemRef${index}`];
|
const curInstance = instance?.proxy?.$refs[`resultItemRef${index}`];
|
||||||
if (!curInstance) return 0;
|
if (!curInstance) return 0;
|
||||||
const curRef = curInstance[0] as ElRef;
|
const curRef = curInstance[0] as ElRef;
|
||||||
const scrollTop = curRef.offsetTop + 128; // 128 两个result-item(56px+56px=112px)高度加上下margin(8px+8px=16px)
|
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 });
|
defineExpose({ handleScroll });
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="result">
|
<div ref="resultRef" class="result">
|
||||||
<div
|
<div
|
||||||
v-for="(item, index) in options"
|
v-for="(item, index) in options"
|
||||||
:key="item.path"
|
:key="item.path"
|
||||||
|
@ -218,7 +218,6 @@ watch($storage, ({ layout }) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
dataThemeChange();
|
|
||||||
/* 初始化项目配置 */
|
/* 初始化项目配置 */
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
settings.greyVal &&
|
settings.greyVal &&
|
||||||
|
@ -8,7 +8,15 @@ import { useLayout } from "./hooks/useLayout";
|
|||||||
import { useAppStoreHook } from "@/store/modules/app";
|
import { useAppStoreHook } from "@/store/modules/app";
|
||||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||||
import { deviceDetection, useDark, useGlobal } from "@pureadmin/utils";
|
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 navbar from "./components/navbar.vue";
|
||||||
import tag from "./components/tag/index.vue";
|
import tag from "./components/tag/index.vue";
|
||||||
@ -102,6 +110,10 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onBeforeMount(() => {
|
||||||
|
useDataThemeChange().dataThemeChange();
|
||||||
|
});
|
||||||
|
|
||||||
const layoutHeader = defineComponent({
|
const layoutHeader = defineComponent({
|
||||||
render() {
|
render() {
|
||||||
return h(
|
return h(
|
||||||
|
@ -23,7 +23,7 @@ import {
|
|||||||
formatFlatteningRoutes
|
formatFlatteningRoutes
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
import { buildHierarchyTree } from "@/utils/tree";
|
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";
|
import remainingRouter from "./modules/remaining";
|
||||||
|
|
||||||
@ -158,11 +158,22 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
|||||||
getTopMenu(true);
|
getTopMenu(true);
|
||||||
// query、params模式路由传参数的标签页不在此处处理
|
// query、params模式路由传参数的标签页不在此处处理
|
||||||
if (route && route.meta?.title) {
|
if (route && route.meta?.title) {
|
||||||
|
if (isAllEmpty(route.parentId) && route.meta?.backstage) {
|
||||||
|
// 此处为动态顶级路由(目录)
|
||||||
|
const { path, name, meta } = route.children[0];
|
||||||
useMultiTagsStoreHook().handleTags("push", {
|
useMultiTagsStoreHook().handleTags("push", {
|
||||||
path: route.path,
|
path,
|
||||||
name: route.name,
|
name,
|
||||||
meta: route.meta
|
meta
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
const { path, name, meta } = route;
|
||||||
|
useMultiTagsStoreHook().handleTags("push", {
|
||||||
|
path,
|
||||||
|
name,
|
||||||
|
meta
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
router.push(to.fullPath);
|
router.push(to.fullPath);
|
||||||
|
@ -3,7 +3,7 @@ import { components } from "@/router/enums";
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: "/components",
|
path: "/components",
|
||||||
redirect: "/components/video",
|
redirect: "/components/dialog",
|
||||||
meta: {
|
meta: {
|
||||||
icon: "menu",
|
icon: "menu",
|
||||||
title: $t("menus.hscomponents"),
|
title: $t("menus.hscomponents"),
|
||||||
|
@ -54,14 +54,14 @@ export function useColumns() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "QQ交流群",
|
label: "精简版",
|
||||||
cellRenderer: () => {
|
cellRenderer: () => {
|
||||||
return (
|
return (
|
||||||
<a
|
<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"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<span style="color: var(--el-color-primary)">点击加群</span>
|
<span style="color: var(--el-color-primary)">精简版</span>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,14 @@
|
|||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { h, createVNode, ref } from "vue";
|
import { h, createVNode, ref } from "vue";
|
||||||
import { message } from "@/utils/message";
|
import { message } from "@/utils/message";
|
||||||
import { cloneDeep } from "@pureadmin/utils";
|
|
||||||
import forms, { type FormProps } from "./form.vue";
|
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({
|
defineOptions({
|
||||||
name: "DialogPage"
|
name: "DialogPage"
|
||||||
@ -60,13 +65,16 @@ function onStyleClick() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onoOpenDelayClick() {
|
// 添加 600ms 防抖
|
||||||
|
const onoOpenDelayClick = debounce(
|
||||||
|
() =>
|
||||||
addDialog({
|
addDialog({
|
||||||
title: "延时2秒打开弹框",
|
title: "延时2秒打开弹框",
|
||||||
openDelay: 2000,
|
openDelay: 2000 - 600,
|
||||||
contentRenderer: () => <p>弹框内容-延时2秒打开弹框</p>
|
contentRenderer: () => <p>弹框内容-延时2秒打开弹框</p>
|
||||||
});
|
}),
|
||||||
}
|
600
|
||||||
|
);
|
||||||
|
|
||||||
function onCloseDelayClick() {
|
function onCloseDelayClick() {
|
||||||
addDialog({
|
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 并赋值
|
// 结合Form表单(第一种方式,弹框关闭立刻恢复初始值)通过 props 属性接收子组件的 prop 并赋值
|
||||||
function onFormOneClick() {
|
function onFormOneClick() {
|
||||||
addDialog({
|
addDialog({
|
||||||
@ -421,6 +458,7 @@ function onBeforeSureClick() {
|
|||||||
<el-button @click="onOpenClick"> 打开后的回调 </el-button>
|
<el-button @click="onOpenClick"> 打开后的回调 </el-button>
|
||||||
<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-space>
|
</el-space>
|
||||||
<el-divider />
|
<el-divider />
|
||||||
<el-space wrap>
|
<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">
|
<script setup lang="ts">
|
||||||
import "@wangeditor/editor/dist/css/style.css"; // 引入 css
|
import { ref } from "vue";
|
||||||
import { Editor, Toolbar } from "@wangeditor/editor-for-vue";
|
import { Base, Multi, PicUpload } from "./components";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
|
||||||
import { onBeforeUnmount, ref, shallowRef, onMounted } from "vue";
|
|
||||||
import Edit from "@iconify-icons/ep/edit";
|
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "Editor"
|
name: "Editor"
|
||||||
});
|
});
|
||||||
|
|
||||||
const mode = "default";
|
const activeNames = ref(["1"]);
|
||||||
// 编辑器实例,必须用 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 实例,重要!
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -47,7 +18,6 @@ const handleCreated = editor => {
|
|||||||
<el-link
|
<el-link
|
||||||
href="https://www.wangeditor.com"
|
href="https://www.wangeditor.com"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
:icon="useRenderIcon(Edit)"
|
|
||||||
style="margin: 0 4px 5px; font-size: 16px"
|
style="margin: 0 4px 5px; font-size: 16px"
|
||||||
>
|
>
|
||||||
Wangeditor
|
Wangeditor
|
||||||
@ -55,20 +25,22 @@ const handleCreated = editor => {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="wangeditor">
|
<el-collapse v-model="activeNames" accordion>
|
||||||
<Toolbar
|
<el-collapse-item title="基础用法" name="1">
|
||||||
style="border-bottom: 1px solid #ccc"
|
<Base />
|
||||||
:editor="editorRef"
|
</el-collapse-item>
|
||||||
:defaultConfig="toolbarConfig"
|
<el-collapse-item title="多个富文本" name="2">
|
||||||
:mode="mode"
|
<Multi />
|
||||||
/>
|
</el-collapse-item>
|
||||||
<Editor
|
<el-collapse-item title="自定义图片上传" name="3">
|
||||||
style="height: 500px; overflow-y: hidden"
|
<PicUpload />
|
||||||
v-model="valueHtml"
|
</el-collapse-item>
|
||||||
:defaultConfig="editorConfig"
|
</el-collapse>
|
||||||
:mode="mode"
|
|
||||||
@onCreated="handleCreated"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:deep(.el-collapse-item__header) {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|