Compare commits

..

13 Commits

Author SHA1 Message Date
xiaoxian521
ab1c7f8bcc refactor: 升级tailwindcssv4版本,带来更快的构建速度、更简化的安装和配置、提供专属vite插件 2025-03-16 19:46:35 +08:00
xiaoxian521
b87eb6fd0a chore: 升级依赖 2025-01-15 12:10:39 +08:00
xiaoxian521
a0246e31df feat: 添加tagOnClick标签切换全局公共事件 2025-01-09 16:20:31 +08:00
xiaoxian521
e1cd14a946 chore: 升级依赖,相关兼容处理(主要是typescriptvue-tsc升级最新版) 2025-01-09 15:55:45 +08:00
xiaoxian521
02380f69e1 chore: 优化src/style/dark.scss语法 2025-01-07 17:21:00 +08:00
可能
5208272456 chore: 优化登录传参 (#1197) 2025-01-06 14:30:43 +08:00
xiaoming
551292078e fix: 修复aria-hidden报错 (#1192) 2025-01-04 02:19:38 +08:00
XiaoYue
79cd159154 chore: 使用keydown替换keypresskeypress事件已弃用 (#1195) 2024-12-27 09:55:28 +08:00
xiaoming
6d26300181 feat: 添加代码编辑器示例 (#1194) 2024-12-24 09:14:43 +08:00
xiaoming
0dd6665b2a feat: 添加Markdown示例 (#1193) 2024-12-23 13:57:37 +08:00
xiaoxian521
bbdd44a917 feat: 添加滑块示例 2024-12-19 17:29:45 +08:00
xiaoxian521
f8690a0b73 fix: 修复使用this语法时无法显示代码提示的问题并更新pinia相关语法 2024-12-15 23:29:37 +08:00
xiaoxian521
b843eda26f style: update 2024-12-14 11:20:45 +08:00
128 changed files with 2726 additions and 1963 deletions

2
.nvmrc
View File

@@ -1 +1 @@
v22.12.0
v22.13.0

View File

@@ -11,6 +11,7 @@ const include = [
"dayjs",
"axios",
"pinia",
"vditor",
"typeit",
"swiper",
"qrcode",
@@ -22,6 +23,7 @@ const include = [
"vue-tippy",
"cropperjs",
"jsbarcode",
"codemirror",
"pinyin-pro",
"sortablejs",
"swiper/vue",
@@ -42,6 +44,7 @@ const include = [
"@howdyjs/mouse-menu",
"@logicflow/extension",
"vue-virtual-scroller",
"codemirror-editor-vue3",
"@amap/amap-jsapi-loader",
"el-table-infinite-scroll",
"vue-waterfall-plugin-next",

View File

@@ -5,6 +5,7 @@ import { viteBuildInfo } from "./info";
import svgLoader from "vite-svg-loader";
import type { PluginOption } from "vite";
import vueJsx from "@vitejs/plugin-vue-jsx";
import tailwindcss from "@tailwindcss/vite";
import { configCompressPlugin } from "./compress";
import removeNoMatch from "vite-plugin-router-warn";
import { visualizer } from "rollup-plugin-visualizer";
@@ -19,6 +20,7 @@ export function getPluginsList(
): PluginOption[] {
const lifecycle = process.env.npm_lifecycle_event;
return [
tailwindcss(),
vue(),
// jsx、tsx语法支持
vueJsx(),

View File

@@ -10,9 +10,6 @@
/>
<title>vue-pure-admin</title>
<link rel="icon" href="/favicon.ico" />
<script>
window.process = {};
</script>
</head>
<body>

View File

@@ -76,6 +76,8 @@ menus:
pureLoginLog: Login Log
pureOperationLog: Operation Log
pureSystemLog: System Log
pureCodeMirror: CodeMirror
pureMarkdown: Markdown
pureEditor: Editor
pureAbnormal: Abnormal Page
pureFourZeroFour: "404"
@@ -92,6 +94,7 @@ menus:
pureDraggable: Draggable
pureSplitPane: Split Pane
pureText: Text Ellipsis
pureSlider: Slider
pureElButton: Button
pureButton: Button Animation
pureCheckButton: Check Button

View File

@@ -76,6 +76,8 @@ menus:
pureLoginLog: 登录日志
pureOperationLog: 操作日志
pureSystemLog: 系统日志
pureCodeMirror: 代码编辑器
pureMarkdown: Markdown
pureEditor: 编辑器
pureAbnormal: 异常页面
pureFourZeroFour: "404"
@@ -92,6 +94,7 @@ menus:
pureDraggable: 拖拽
pureSplitPane: 切割面板
pureText: 文本省略
pureSlider: 滑块
pureElButton: 按钮
pureCheckButton: 可选按钮
pureButton: 按钮动效

View File

@@ -56,8 +56,8 @@
"@pureadmin/table": "^3.2.1",
"@pureadmin/utils": "^2.5.0",
"@vue-flow/background": "^1.3.2",
"@vue-flow/core": "^1.41.6",
"@vueuse/core": "^12.0.0",
"@vue-flow/core": "^1.42.0",
"@vueuse/core": "^12.4.0",
"@vueuse/motion": "^2.2.6",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^5.1.12",
@@ -65,11 +65,13 @@
"animate.css": "^4.1.1",
"axios": "^1.7.9",
"china-area-data": "^5.0.1",
"codemirror": "^5.65.18",
"codemirror-editor-vue3": "^2.8.0",
"cropperjs": "^1.6.2",
"dayjs": "^1.11.13",
"echarts": "^5.5.1",
"echarts": "^5.6.0",
"el-table-infinite-scroll": "^3.0.6",
"element-plus": "^2.9.0",
"element-plus": "^2.9.3",
"intro.js": "^7.2.0",
"js-cookie": "^3.0.5",
"jsbarcode": "^3.11.6",
@@ -81,94 +83,96 @@
"path-browserify": "^1.0.1",
"pinia": "^2.3.0",
"pinyin-pro": "^3.26.0",
"plus-pro-components": "^0.1.18",
"plus-pro-components": "^0.1.20",
"qrcode": "^1.5.4",
"qs": "^6.13.1",
"qs": "^6.14.0",
"responsive-storage": "^2.2.0",
"sortablejs": "^1.15.6",
"swiper": "^11.1.15",
"swiper": "^11.2.1",
"typeit": "^8.8.7",
"v-contextmenu": "^3.2.0",
"v3-infinite-loading": "^1.3.2",
"vditor": "^3.10.8",
"version-rocket": "^1.7.4",
"vue": "^3.5.13",
"vue-i18n": "^10.0.5",
"vue-i18n": "^11.0.1",
"vue-json-pretty": "^2.4.0",
"vue-pdf-embed": "^2.1.1",
"vue-router": "^4.5.0",
"vue-tippy": "^6.5.0",
"vue-tippy": "^6.6.0",
"vue-types": "^5.1.3",
"vue-virtual-scroller": "2.0.0-beta.8",
"vue-waterfall-plugin-next": "^2.6.4",
"vue-waterfall-plugin-next": "^2.6.5",
"vue3-danmaku": "^1.6.1",
"vue3-puzzle-vcode": "^1.1.7",
"vuedraggable": "^4.1.0",
"vxe-table": "4.6.25",
"wavesurfer.js": "^7.8.10",
"wavesurfer.js": "^7.8.16",
"xgplayer": "^3.0.20",
"xlsx": "^0.18.5"
},
"devDependencies": {
"@commitlint/cli": "^19.6.0",
"@commitlint/cli": "^19.6.1",
"@commitlint/config-conventional": "^19.6.0",
"@commitlint/types": "^19.5.0",
"@eslint/js": "^9.16.0",
"@eslint/js": "^9.18.0",
"@faker-js/faker": "^9.3.0",
"@iconify-icons/ep": "^1.2.12",
"@iconify-icons/ri": "^1.2.10",
"@iconify/vue": "^4.2.0",
"@intlify/unplugin-vue-i18n": "^6.0.1",
"@iconify/vue": "4.2.0",
"@intlify/unplugin-vue-i18n": "^6.0.3",
"@tailwindcss/vite": "^4.0.13",
"@types/codemirror": "^5.60.15",
"@types/dagre": "^0.7.52",
"@types/intro.js": "^5.1.5",
"@types/js-cookie": "^3.0.6",
"@types/node": "^20.17.9",
"@types/node": "^20.17.13",
"@types/nprogress": "^0.2.3",
"@types/path-browserify": "^1.0.3",
"@types/qrcode": "^1.5.5",
"@types/qs": "^6.9.17",
"@types/qs": "^6.9.18",
"@types/sortablejs": "^1.15.8",
"@typescript-eslint/eslint-plugin": "^8.18.0",
"@typescript-eslint/parser": "^8.18.0",
"@typescript-eslint/eslint-plugin": "^8.20.0",
"@typescript-eslint/parser": "^8.20.0",
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"autoprefixer": "^10.4.20",
"boxen": "^8.0.1",
"code-inspector-plugin": "^0.18.2",
"code-inspector-plugin": "^0.19.2",
"cssnano": "^7.0.6",
"dagre": "^0.8.5",
"eslint": "^9.16.0",
"eslint-config-prettier": "^9.1.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-define-config": "^2.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-vue": "^9.32.0",
"gradient-string": "^3.0.0",
"husky": "^9.1.7",
"lint-staged": "^15.2.10",
"postcss": "^8.4.49",
"postcss-html": "^1.7.0",
"postcss-import": "^16.1.0",
"lint-staged": "^15.3.0",
"postcss": "^8.5.1",
"postcss-html": "^1.8.0",
"postcss-load-config": "^6.0.1",
"postcss-scss": "^4.0.9",
"prettier": "^3.4.2",
"rimraf": "^6.0.1",
"rollup-plugin-visualizer": "^5.12.0",
"sass": "^1.82.0",
"stylelint": "^16.11.0",
"rollup-plugin-visualizer": "^5.14.0",
"sass": "^1.83.4",
"stylelint": "^16.13.2",
"stylelint-config-recess-order": "^5.1.1",
"stylelint-config-recommended-vue": "^1.5.0",
"stylelint-config-standard-scss": "^13.1.0",
"stylelint-config-standard-scss": "^14.0.0",
"stylelint-prettier": "^5.0.2",
"svgo": "^3.3.2",
"tailwindcss": "^3.4.16",
"typescript": "5.6.3",
"vite": "^6.0.3",
"tailwindcss": "^4.0.13",
"typescript": "^5.7.3",
"vite": "^6.0.7",
"vite-plugin-cdn-import": "^1.0.1",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-fake-server": "^2.1.4",
"vite-plugin-fake-server": "^2.2.0",
"vite-plugin-remove-console": "^2.2.0",
"vite-plugin-router-warn": "^1.0.0",
"vite-svg-loader": "^5.1.0",
"vue-eslint-parser": "^9.4.3",
"vue-tsc": "^2.1.10"
"vue-tsc": "^2.2.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=22.0.0",

3364
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,10 +3,6 @@
/** @type {import('postcss-load-config').Config} */
export default {
plugins: {
"postcss-import": {},
"tailwindcss/nesting": {},
tailwindcss: {},
autoprefixer: {},
...(process.env.NODE_ENV === "production" ? { cssnano: {} } : {})
}
};

View File

@@ -28,8 +28,7 @@
c = document.createElement("div");
(c.innerHTML = e._iconfont_svg_string_2208059),
(c = c.getElementsByTagName("svg")[0]) &&
(c.setAttribute("aria-hidden", "true"),
(c.style.position = "absolute"),
((c.style.position = "absolute"),
(c.style.width = 0),
(c.style.height = 0),
(c.style.overflow = "hidden"),

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" aria-hidden="true" class="iconify iconify--ant-design" viewBox="0 0 1024 1024"><path fill="currentColor" d="M864 170h-60c-4.4 0-8 3.6-8 8v518H310v-73c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 0 0 0 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-75h498c35.3 0 64-28.7 64-64V178c0-4.4-3.6-8-8-8"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" class="iconify iconify--ant-design" viewBox="0 0 1024 1024"><path fill="currentColor" d="M864 170h-60c-4.4 0-8 3.6-8 8v518H310v-73c0-6.7-7.8-10.5-13-6.3l-141.9 112a8 8 0 0 0 0 12.6l141.9 112c5.3 4.2 13 .4 13-6.3v-75h498c35.3 0 64-28.7 64-64V178c0-4.4-3.6-8-8-8"/></svg>

Before

Width:  |  Height:  |  Size: 351 B

After

Width:  |  Height:  |  Size: 332 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" aria-hidden="true" class="re-screen" color="#00000073" viewBox="0 0 16 16"><path fill="currentColor" d="M3.5 4H1V3h2V1h1v2.5zM13 3V1h-1v2.5l.5.5H15V3zm-1 9.5V15h1v-2h2v-1h-2.5zM1 12v1h2v2h1v-2.5l-.5-.5zm11-1.5-.5.5h-7l-.5-.5v-5l.5-.5h7l.5.5zM10 7H6v2h4z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" class="re-screen" color="#00000073" viewBox="0 0 16 16"><path fill="currentColor" d="M3.5 4H1V3h2V1h1v2.5zM13 3V1h-1v2.5l.5.5H15V3zm-1 9.5V15h1v-2h2v-1h-2.5zM1 12v1h2v2h1v-2.5l-.5-.5zm11-1.5-.5.5h-7l-.5-.5v-5l.5-.5h7l.5.5zM10 7H6v2h4z"/></svg>

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 308 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" aria-hidden="true" class="re-screen" color="#00000073" viewBox="0 0 16 16"><path fill="currentColor" d="M3 12h10V4H3zm2-6h6v4H5zM2 6H1V2.5l.5-.5H5v1H2zm13-3.5V6h-1V3h-3V2h3.5zM14 10h1v3.5l-.5.5H11v-1h3zM2 13h3v1H1.5l-.5-.5V10h1z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" class="re-screen" color="#00000073" viewBox="0 0 16 16"><path fill="currentColor" d="M3 12h10V4H3zm2-6h6v4H5zM2 6H1V2.5l.5-.5H5v1H2zm13-3.5V6h-1V3h-3V2h3.5zM14 10h1v3.5l-.5.5H11v-1h3zM2 13h3v1H1.5l-.5-.5V10h1z"/></svg>

Before

Width:  |  Height:  |  Size: 302 B

After

Width:  |  Height:  |  Size: 283 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" aria-hidden="true" class="globalization" viewBox="0 0 512 512"><path fill="currentColor" d="m478.33 433.6-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362 368 281.65 401.17 362zm-66.99-19.08a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73 39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93.92 1.19 1.83 2.35 2.74 3.51-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59 22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" class="globalization" viewBox="0 0 512 512"><path fill="currentColor" d="m478.33 433.6-90-218a22 22 0 0 0-40.67 0l-90 218a22 22 0 1 0 40.67 16.79L316.66 406h102.67l18.33 44.39A22 22 0 0 0 458 464a22 22 0 0 0 20.32-30.4zM334.83 362 368 281.65 401.17 362zm-66.99-19.08a22 22 0 0 0-4.89-30.7c-.2-.15-15-11.13-36.49-34.73 39.65-53.68 62.11-114.75 71.27-143.49H330a22 22 0 0 0 0-44H214V70a22 22 0 0 0-44 0v20H54a22 22 0 0 0 0 44h197.25c-9.52 26.95-27.05 69.5-53.79 108.36-31.41-41.68-43.08-68.65-43.17-68.87a22 22 0 0 0-40.58 17c.58 1.38 14.55 34.23 52.86 83.93.92 1.19 1.83 2.35 2.74 3.51-39.24 44.35-77.74 71.86-93.85 80.74a22 22 0 1 0 21.07 38.63c2.16-1.18 48.6-26.89 101.63-85.59 22.52 24.08 38 35.44 38.93 36.1a22 22 0 0 0 30.75-4.9z"/></svg>

Before

Width:  |  Height:  |  Size: 826 B

After

Width:  |  Height:  |  Size: 807 B

View File

@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" aria-hidden="true" class="iconify iconify--mdi" viewBox="0 0 24 24"><path fill="currentColor" d="M1 7h6v2H3v2h4v2H3v2h4v2H1zm10 0h4v2h-4v2h2a2 2 0 0 1 2 2v2c0 1.11-.89 2-2 2H9v-2h4v-2h-2a2 2 0 0 1-2-2V9c0-1.1.9-2 2-2m8 0h2a2 2 0 0 1 2 2v1h-2V9h-2v6h2v-1h2v1c0 1.11-.89 2-2 2h-2a2 2 0 0 1-2-2V9c0-1.1.9-2 2-2"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" class="iconify iconify--mdi" viewBox="0 0 24 24"><path fill="currentColor" d="M1 7h6v2H3v2h4v2H3v2h4v2H1zm10 0h4v2h-4v2h2a2 2 0 0 1 2 2v2c0 1.11-.89 2-2 2H9v-2h4v-2h-2a2 2 0 0 1-2-2V9c0-1.1.9-2 2-2m8 0h2a2 2 0 0 1 2 2v1h-2V9h-2v6h2v-1h2v1c0 1.11-.89 2-2 2h-2a2 2 0 0 1-2-2V9c0-1.1.9-2 2-2"/></svg>

Before

Width:  |  Height:  |  Size: 379 B

After

Width:  |  Height:  |  Size: 360 B

View File

@@ -1 +1 @@
<svg width="32" height="32" fill="currentColor" aria-hidden="true" data-icon="holder" viewBox="64 64 896 896"><path d="M300 276.5a56 56 0 1 0 56-97 56 56 0 0 0-56 97m0 284a56 56 0 1 0 56-97 56 56 0 0 0-56 97M640 228a56 56 0 1 0 112 0 56 56 0 0 0-112 0m0 284a56 56 0 1 0 112 0 56 56 0 0 0-112 0M300 844.5a56 56 0 1 0 56-97 56 56 0 0 0-56 97M640 796a56 56 0 1 0 112 0 56 56 0 0 0-112 0"/></svg>
<svg width="32" height="32" fill="currentColor" data-icon="holder" viewBox="64 64 896 896"><path d="M300 276.5a56 56 0 1 0 56-97 56 56 0 0 0-56 97m0 284a56 56 0 1 0 56-97 56 56 0 0 0-56 97M640 228a56 56 0 1 0 112 0 56 56 0 0 0-112 0m0 284a56 56 0 1 0 112 0 56 56 0 0 0-112 0M300 844.5a56 56 0 1 0 56-97 56 56 0 0 0-56 97M640 796a56 56 0 1 0 112 0 56 56 0 0 0-112 0"/></svg>

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 373 B

View File

@@ -119,7 +119,7 @@ export default defineComponent({
"p-[6px]",
"h-[30px]",
"w-[30px]",
"outline-none",
"outline-hidden",
"rounded-[4px]",
"cursor-pointer",
"hover:bg-[rgba(0,0,0,0.06)]"

View File

@@ -79,7 +79,7 @@ const fullscreenClass = computed(() => {
"el-dialog__close",
"-translate-x-2",
"cursor-pointer",
"hover:!text-[red]"
"hover:text-[red]!"
];
});

View File

@@ -28,8 +28,7 @@
((o = document.createElement("div")).innerHTML = i),
(i = null),
(e = o.getElementsByTagName("svg")[0]) &&
(e.setAttribute("aria-hidden", "true"),
(e.style.position = "absolute"),
((e.style.position = "absolute"),
(e.style.width = 0),
(e.style.height = 0),
(e.style.overflow = "hidden"),

View File

@@ -27,8 +27,7 @@ export default defineComponent({
return h(
"svg",
{
class: "icon-svg",
"aria-hidden": true
class: "icon-svg"
},
{
default: () => [

View File

@@ -17,6 +17,7 @@ export default defineComponent({
IconifyIcon,
{
icon: this.icon,
"aria-hidden": false,
style: attrs?.style
? Object.assign(attrs.style, { outline: "none" })
: { outline: "none" },

View File

@@ -17,6 +17,7 @@ export default defineComponent({
IconifyIcon,
{
icon: `${this.icon}`,
"aria-hidden": false,
style: attrs?.style
? Object.assign(attrs.style, { outline: "none" })
: { outline: "none" },

View File

@@ -87,9 +87,9 @@ export default defineComponent({
"text-black",
"dark:text-white",
"duration-100",
"hover:!text-primary",
"hover:text-primary!",
"cursor-pointer",
"outline-none"
"outline-hidden"
];
});
@@ -255,12 +255,12 @@ export default defineComponent({
<div
{...attrs}
class={[
"w-[99/100]",
"w-99/100",
"px-2",
"pb-2",
"bg-bg_color",
isFullscreen.value
? ["!w-full", "!h-full", "z-[2002]", "fixed", "inset-0"]
? ["w-full!", "h-full!", "z-2002", "fixed", "inset-0"]
: "mt-2"
]}
>
@@ -317,7 +317,7 @@ export default defineComponent({
>
<div class={[topClass.value]}>
<el-checkbox
class="!-mr-1"
class="-mr-1!"
label="列展示"
v-model={checkAll.value}
indeterminate={isIndeterminate.value}
@@ -347,8 +347,8 @@ export default defineComponent({
class={[
"drag-btn w-[16px] mr-2",
isFixedColumn(item)
? "!cursor-no-drop"
: "!cursor-grab"
? "cursor-no-drop!"
: "cursor-grab!"
]}
onMouseenter={(event: {
preventDefault: () => void;

View File

@@ -39,8 +39,7 @@
(t.innerHTML = i),
(i = null),
(t = t.getElementsByTagName("svg")[0]) &&
(t.setAttribute("aria-hidden", "true"),
(t.style.position = "absolute"),
((t.style.position = "absolute"),
(t.style.width = 0),
(t.style.height = 0),
(t.style.overflow = "hidden"),

View File

@@ -1,6 +1,6 @@
<script lang="ts" setup>
import { h, onMounted, ref, useSlots } from "vue";
import { type TippyOptions, useTippy } from "vue-tippy";
<script setup lang="ts">
import { h, onMounted, ref } from "vue";
import { type TippyOptions, type TippyContent, useTippy } from "vue-tippy";
defineOptions({
name: "ReText"
@@ -17,7 +17,10 @@ const props = defineProps({
}
});
const $slots = useSlots();
const slots = defineSlots<{
content: () => TippyContent;
default: () => any;
}>();
const textRef = ref();
const tippyFunc = ref();
@@ -33,7 +36,7 @@ const isTextEllipsis = (el: HTMLElement) => {
};
const getTippyProps = () => ({
content: h($slots.content || $slots.default),
content: h(slots.content || slots.default),
...props.tippyProps
});

View File

@@ -90,9 +90,9 @@ export default defineComponent({
];
// 取得每一层的当前节点是不是在当前层级列表的最后一个
const lastnodeArr = [];
let currentNode = this.node;
let currentNode: any = this.node;
while (currentNode) {
let parentNode = currentNode.parent;
let parentNode: any = currentNode.parent;
// 兼容element-plus的 el-tree-v2 (Virtualized Tree 虚拟树)
if (currentNode.level === 1 && !currentNode.parent) {
// el-tree-v2的第一层node是没有parent的必需 treeData 创建一个parent

View File

@@ -80,9 +80,9 @@ export default defineComponent({
"text-black",
"dark:text-white",
"duration-100",
"hover:!text-primary",
"hover:text-primary!",
"cursor-pointer",
"outline-none"
"outline-hidden"
];
});
@@ -248,12 +248,12 @@ export default defineComponent({
<div
{...attrs}
class={[
"w-[99/100]",
"w-99/100",
"px-2",
"pb-2",
"bg-bg_color",
isFullscreen.value
? ["!w-full", "!h-full", "z-[2002]", "fixed", "inset-0"]
? ["w-full!", "h-full!", "z-2002", "fixed", "inset-0"]
: "mt-2"
]}
>
@@ -310,7 +310,7 @@ export default defineComponent({
>
<div class={[topClass.value]}>
<el-checkbox
class="!-mr-1"
class="-mr-1!"
label="列展示"
v-model={checkAll.value}
indeterminate={isIndeterminate.value}
@@ -340,8 +340,8 @@ export default defineComponent({
class={[
"drag-btn w-[16px] mr-2",
isFixedColumn(item)
? "!cursor-no-drop"
: "!cursor-grab"
? "cursor-no-drop!"
: "cursor-grab!"
]}
onMouseenter={(event: {
preventDefault: () => void;

View File

@@ -1,4 +1,4 @@
<script lang="ts" setup>
<script setup lang="ts">
import { getConfig } from "@/config";
const TITLE = getConfig("Title");

View File

@@ -33,7 +33,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
</script>
<template>
<div class="navbar bg-[#fff] shadow-sm shadow-[rgba(0,21,41,0.08)]">
<div class="navbar bg-[#fff] shadow-xs shadow-[rgba(0,21,41,0.08)]">
<LaySidebarTopCollapse
v-if="device === 'mobile'"
class="hamburger-container"
@@ -54,13 +54,13 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
<!-- 国际化 -->
<el-dropdown id="header-translation" trigger="click">
<GlobalizationIcon
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none"
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-hidden"
/>
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
:class="['dark:text-white!', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<IconifyIconOffline
@@ -72,7 +72,7 @@ const { t, locale, translationCh, translationEn } = useTranslationLang();
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
:class="['dark:text-white!', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span v-show="locale === 'en'" class="check-en">

View File

@@ -112,7 +112,7 @@ function hoverDescription(event, description) {
max-width: 238px;
}
</style>
<style scoped lang="scss">
<style lang="scss" scoped>
.notice-container {
display: flex;
align-items: flex-start;

View File

@@ -16,7 +16,7 @@ const iconClass = computed(() => {
"flex",
"justify-center",
"items-center",
"outline-none",
"outline-hidden",
"rounded-[4px]",
"cursor-pointer",
"transition-colors",

View File

@@ -429,7 +429,7 @@ onUnmounted(() => removeMatchMedia);
height="20"
/>
<div
class="flex-grow border-b border-dashed"
class="grow border-b border-dashed"
style="border-color: var(--el-color-primary)"
/>
<IconifyIconOffline

View File

@@ -84,13 +84,13 @@ onMounted(() => {
<!-- 国际化 -->
<el-dropdown id="header-translation" trigger="click">
<GlobalizationIcon
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none"
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-hidden"
/>
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
:class="['dark:text-white!', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<span v-show="locale === 'zh'" class="check-zh">
@@ -100,7 +100,7 @@ onMounted(() => {
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
:class="['dark:text-white!', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span v-show="locale === 'en'" class="check-en">

View File

@@ -105,13 +105,13 @@ watch(
<!-- 国际化 -->
<el-dropdown id="header-translation" trigger="click">
<GlobalizationIcon
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-none"
class="navbar-bg-hover w-[40px] h-[48px] p-[11px] cursor-pointer outline-hidden"
/>
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
:class="['dark:text-white!', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<span v-show="locale === 'zh'" class="check-zh">
@@ -121,7 +121,7 @@ watch(
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
:class="['dark:text-white!', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span v-show="locale === 'en'" class="check-en">

View File

@@ -105,12 +105,12 @@ watch(
</script>
<template>
<el-breadcrumb class="!leading-[50px] select-none" separator="/">
<el-breadcrumb class="leading-[50px]! select-none" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item
v-for="item in levelList"
:key="item.path"
class="!inline !items-stretch"
class="inline! items-stretch!"
>
<a @click.prevent="handleLink(item)">
{{ transformI18n(item.meta.title) }}

View File

@@ -144,7 +144,7 @@ function resolvePath(routePath) {
item?.pathList?.length === 2)
"
truncated
class="!w-full !pl-4 !text-inherit"
class="w-full! pl-4! text-inherit!"
>
{{ transformI18n(onlyOneChild.meta.title) }}
</el-text>
@@ -156,7 +156,7 @@ function resolvePath(routePath) {
offset: [0, -10],
theme: tooltipEffect
}"
class="!w-full !text-inherit"
class="w-full! text-inherit!"
>
{{ transformI18n(onlyOneChild.meta.title) }}
</ReText>
@@ -196,9 +196,9 @@ function resolvePath(routePath) {
theme: tooltipEffect
}"
:class="{
'!w-full': true,
'!text-inherit': true,
'!pl-4':
'w-full!': true,
'text-inherit!': true,
'pl-4!':
layout !== 'horizontal' &&
isCollapse &&
!toRaw(item.meta.icon) &&

View File

@@ -32,7 +32,7 @@ const toggleClick = () => {
>
<IconifyIconOffline
:icon="isActive ? MenuFold : MenuUnfold"
class="inline-block align-middle hover:text-primary dark:hover:!text-white"
class="inline-block align-middle hover:text-primary dark:hover:text-white!"
/>
</div>
</template>

View File

@@ -511,6 +511,7 @@ function tagOnClick(item) {
} else {
router.push({ path });
}
emitter.emit("tagOnClick", item);
}
onClickOutside(contextmenuRef, closeMenu, {
@@ -588,7 +589,7 @@ onBeforeUnmount(() => {
>
<template v-if="showModel !== 'chrome'">
<span
class="tag-title dark:!text-text_color_primary dark:hover:!text-primary"
class="tag-title dark:text-text_color_primary! dark:hover:text-primary!"
>
{{ transformI18n(item.meta.title) }}
</span>

View File

@@ -64,7 +64,7 @@ export function useNav() {
const getDropdownItemClass = computed(() => {
return (locale, t) => {
return locale === t ? "" : "dark:hover:!text-primary";
return locale === t ? "" : "dark:hover:text-primary!";
};
});

View File

@@ -17,14 +17,16 @@ const home = 0, // 平台规定只有 home 路由的 rank 才能为 0 ,所以
monitor = 14,
tabs = 15,
about = 16,
editor = 17,
flowchart = 18,
formdesign = 19,
board = 20,
ppt = 21,
mind = 22,
guide = 23,
menuoverflow = 24;
codemirror = 17,
markdown = 18,
editor = 19,
flowchart = 20,
formdesign = 21,
board = 22,
ppt = 23,
mind = 24,
guide = 25,
menuoverflow = 26;
export {
home,
@@ -44,6 +46,8 @@ export {
monitor,
tabs,
about,
codemirror,
markdown,
editor,
flowchart,
formdesign,

View File

@@ -15,8 +15,7 @@ export default {
name: "MqttClient",
component: () => import("@/views/able/mqtt-client.vue"),
meta: {
title: $t("menus.pureMqtt"),
extraIcon: "IF-pure-iconfont-new svg"
title: $t("menus.pureMqtt")
}
},
{

View File

@@ -0,0 +1,23 @@
import { $t } from "@/plugins/i18n";
import { codemirror } from "@/router/enums";
export default {
path: "/codemirror",
redirect: "/codemirror/index",
meta: {
icon: "ri:code-box-line",
title: $t("menus.pureCodeMirror"),
rank: codemirror
},
children: [
{
path: "/codemirror/index",
name: "CodeMirror",
component: () => import("@/views/codemirror/index.vue"),
meta: {
title: $t("menus.pureCodeMirror"),
extraIcon: "IF-pure-iconfont-new svg"
}
}
]
} satisfies RouteConfigsTable;

View File

@@ -47,8 +47,7 @@ export default {
name: "CheckCard",
component: () => import("@/views/components/check-card.vue"),
meta: {
title: $t("menus.pureCheckCard"),
extraIcon: "IF-pure-iconfont-new svg"
title: $t("menus.pureCheckCard")
}
},
{
@@ -112,7 +111,15 @@ export default {
name: "PureText",
component: () => import("@/views/components/text.vue"),
meta: {
title: $t("menus.pureText"),
title: $t("menus.pureText")
}
},
{
path: "/components/slider",
name: "PureSlider",
component: () => import("@/views/components/slider/index.vue"),
meta: {
title: $t("menus.pureSlider"),
extraIcon: "IF-pure-iconfont-new svg"
}
},
@@ -129,8 +136,7 @@ export default {
name: "CheckButton",
component: () => import("@/views/components/check-button.vue"),
meta: {
title: $t("menus.pureCheckButton"),
extraIcon: "IF-pure-iconfont-new svg"
title: $t("menus.pureCheckButton")
}
},
{

View File

@@ -15,8 +15,7 @@ export default {
name: "SchemaForm",
component: () => import("@/views/schema-form/index.vue"),
meta: {
title: $t("menus.pureSchemaForm"),
extraIcon: "IF-pure-iconfont-new svg"
title: $t("menus.pureSchemaForm")
}
}
]

View File

@@ -15,8 +15,7 @@ export default {
name: "Ganttastic",
component: () => import("@/views/ganttastic/index.vue"),
meta: {
title: $t("menus.pureGanttastic"),
extraIcon: "IF-pure-iconfont-new svg"
title: $t("menus.pureGanttastic")
}
}
]

View File

@@ -0,0 +1,23 @@
import { $t } from "@/plugins/i18n";
import { markdown } from "@/router/enums";
export default {
path: "/markdown",
redirect: "/markdown/index",
meta: {
icon: "ri:markdown-line",
title: $t("menus.pureMarkdown"),
rank: markdown
},
children: [
{
path: "/markdown/index",
name: "Markdown",
component: () => import("@/views/markdown/index.vue"),
meta: {
title: $t("menus.pureMarkdown"),
extraIcon: "IF-pure-iconfont-new svg"
}
}
]
} satisfies RouteConfigsTable;

View File

@@ -31,8 +31,7 @@ export default {
name: "PureTableEdit",
component: () => import("@/views/table/edit.vue"),
meta: {
title: $t("menus.pureTableEdit"),
extraIcon: "IF-pure-iconfont-new svg"
title: $t("menus.pureTableEdit")
}
},
{
@@ -40,8 +39,7 @@ export default {
name: "VxeTable",
component: () => import("@/views/table/virtual.vue"),
meta: {
title: $t("menus.pureVxeTable"),
extraIcon: "IF-pure-iconfont-new svg"
title: $t("menus.pureVxeTable")
}
}
]

View File

@@ -14,8 +14,7 @@ export default {
name: "VueFlow",
component: () => import("@/views/vue-flow/layouting/index.vue"),
meta: {
title: "vue-flow",
extraIcon: "IF-pure-iconfont-new svg"
title: "vue-flow"
}
}
]

View File

@@ -8,8 +8,7 @@ import {
responsiveStorageNameSpace
} from "../utils";
export const useAppStore = defineStore({
id: "pure-app",
export const useAppStore = defineStore("pure-app", {
state: (): appType => ({
sidebar: {
opened:

View File

@@ -6,8 +6,7 @@ import {
responsiveStorageNameSpace
} from "../utils";
export const useEpThemeStore = defineStore({
id: "pure-epTheme",
export const useEpThemeStore = defineStore("pure-epTheme", {
state: () => ({
epThemeColor:
storageLocal().getItem<StorageConfigs>(

View File

@@ -14,8 +14,7 @@ import {
} from "../utils";
import { usePermissionStoreHook } from "./permission";
export const useMultiTagsStore = defineStore({
id: "pure-multiTags",
export const useMultiTagsStore = defineStore("pure-multiTags", {
state: () => ({
// 存储标签页信息(路由信息)
multiTags: storageLocal().getItem<StorageConfigs>(
@@ -24,12 +23,12 @@ export const useMultiTagsStore = defineStore({
? storageLocal().getItem<StorageConfigs>(
`${responsiveStorageNameSpace()}tags`
)
: [
: ([
...routerArrays,
...usePermissionStoreHook().flatteningRoutes.filter(
v => v?.meta?.fixedTag
)
],
] as any),
multiTagsCache: storageLocal().getItem<StorageConfigs>(
`${responsiveStorageNameSpace()}configure`
)?.multiTagsCache

View File

@@ -12,8 +12,7 @@ import {
} from "../utils";
import { useMultiTagsStoreHook } from "./multiTags";
export const usePermissionStore = defineStore({
id: "pure-permission",
export const usePermissionStore = defineStore("pure-permission", {
state: () => ({
// 静态路由生成的菜单
constantMenus,
@@ -31,7 +30,7 @@ export const usePermissionStore = defineStore({
filterTree(ascending(this.constantMenus.concat(routes)))
);
this.flatteningRoutes = formatFlatteningRoutes(
this.constantMenus.concat(routes)
this.constantMenus.concat(routes) as any
);
},
cacheOperate({ mode, name }: cacheType) {

View File

@@ -1,8 +1,7 @@
import { defineStore } from "pinia";
import { type setType, store, getConfig } from "../utils";
export const useSettingStore = defineStore({
id: "pure-setting",
export const useSettingStore = defineStore("pure-setting", {
state: (): setType => ({
title: getConfig().Title,
fixedHeader: getConfig().FixedHeader,

View File

@@ -16,8 +16,7 @@ import {
import { useMultiTagsStoreHook } from "./multiTags";
import { type DataInfo, setToken, removeToken, userKey } from "@/utils/auth";
export const useUserStore = defineStore({
id: "pure-user",
export const useUserStore = defineStore("pure-user", {
state: (): userType => ({
// 头像
avatar: storageLocal().getItem<DataInfo<number>>(userKey)?.avatar ?? "",

View File

@@ -1,3 +1,4 @@
@use "sass:color";
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;
/* 整体暗色风格适配 */

View File

@@ -1,7 +1,5 @@
/* $sideBarWidth: vertical 模式下主体内容距离网页文档左侧的距离 */
@mixin merge-style($sideBarWidth) {
$menuActiveText: #7a80b4;
@media screen and (width >= 150px) and (width <= 420px) {
.app-main-nofixed-header {
overflow-y: hidden;
@@ -94,7 +92,7 @@
height: 100%;
overflow: visible;
font-size: 0;
background: var(--pure-theme-menu-bg);
background: var(--pure-theme-menu-bg) !important;
border-right: 1px solid var(--pure-border-color);
/* 展开动画 */
@@ -415,7 +413,7 @@
justify-content: space-around;
width: 100%;
height: 48px;
background: var(--pure-theme-menu-bg);
background: var(--pure-theme-menu-bg) !important;
.horizontal-header-left {
display: flex;
@@ -533,7 +531,7 @@
.el-sub-menu__title {
height: 48px;
line-height: 48px;
background: var(--pure-theme-menu-bg);
background: var(--pure-theme-menu-bg) !important;
svg {
position: static !important;

View File

@@ -1,21 +1,44 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "tailwindcss";
@layer components {
.flex-c {
@custom-variant dark (&:is(.dark *));
@theme {
--color-bg_color: var(--el-bg-color);
--color-primary: var(--el-color-primary);
--color-text_color_primary: var(--el-text-color-primary);
--color-text_color_regular: var(--el-text-color-regular);
}
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}
@utility flex-c {
@apply flex justify-center items-center;
}
.flex-ac {
@utility flex-ac {
@apply flex justify-around items-center;
}
.flex-bc {
@utility flex-bc {
@apply flex justify-between items-center;
}
.navbar-bg-hover {
@apply dark:text-white dark:hover:!bg-[#242424];
}
@utility navbar-bg-hover {
@apply dark:text-white dark:hover:bg-[#242424]!;
}

View File

@@ -4,10 +4,11 @@ import mitt from "mitt";
/** 全局公共事件需要在此处添加类型 */
type Events = {
openPanel: string;
tagViewsChange: string;
tagViewsShowModel: string;
tagOnClick: string;
logoChange: boolean;
tagViewsChange: string;
changLayoutRoute: string;
tagViewsShowModel: string;
imageInfo: {
img: HTMLImageElement;
height: number;

View File

@@ -9,6 +9,7 @@ const Print = function (dom, options?: object): PrintFunction {
options = options || {};
// @ts-expect-error
if (!(this instanceof Print)) return new Print(dom, options);
// @ts-expect-error
this.conf = {
styleStr: "",
// Elements that need to dynamically get and set the height
@@ -18,19 +19,26 @@ const Print = function (dom, options?: object): PrintFunction {
// Callback after printing
printDoneCallBack: null
};
// @ts-expect-error
for (const key in this.conf) {
if (key && options.hasOwnProperty(key)) {
// @ts-expect-error
this.conf[key] = options[key];
}
}
if (typeof dom === "string") {
// @ts-expect-error
this.dom = document.querySelector(dom);
} else {
// @ts-expect-error
this.dom = this.isDOM(dom) ? dom : dom.$el;
}
// @ts-expect-error
if (this.conf.setDomHeightArr && this.conf.setDomHeightArr.length) {
// @ts-expect-error
this.setDomHeight(this.conf.setDomHeightArr);
}
// @ts-expect-error
this.init();
};

View File

@@ -76,7 +76,7 @@ function onReset() {
immediate: true,
timeout: 1000
}"
class="!w-[200px]"
class="w-[200px]!"
clearable
@clear="onInput"
/>
@@ -86,7 +86,7 @@ function onReset() {
<el-input
v-model="searchTwo"
v-optimize="{ event: 'input', fn: onInputTwo, timeout: 400 }"
class="!w-[200px]"
class="w-[200px]!"
clearable
/>
</div>
@@ -100,7 +100,7 @@ function onReset() {
timeout: 400,
params: { name: '小明', sex: '男' }
}"
class="!w-[200px]"
class="w-[200px]!"
clearable
/>
</div>
@@ -112,7 +112,7 @@ function onReset() {
<el-input
v-model="searchFour"
v-optimize:throttle="{ event: 'input', fn: onInputFour, timeout: 1000 }"
class="!w-[200px]"
class="w-[200px]!"
clearable
/>
</div>
@@ -125,7 +125,7 @@ function onReset() {
fn: onInputFive,
params: { name: '小明', sex: '男' }
}"
class="!w-[200px]"
class="w-[200px]!"
clearable
/>
</div>
@@ -134,7 +134,7 @@ function onReset() {
<div class="mb-2">
文本复制指令(双击输入框内容即可复制)
<el-input v-model="searchSix" v-copy="searchSix" class="!w-[200px]" />
<el-input v-model="searchSix" v-copy="searchSix" class="w-[200px]!" />
</div>
<div>
文本复制指令(自定义触发事件,单击复制)

View File

@@ -83,7 +83,7 @@ const tableData: User[] = [
<span class="font-medium">打印功能报表图表图片</span>
<el-select
v-model="value"
class="!w-[100px] mr-2"
class="w-[100px]! mr-2"
placeholder="Select"
size="small"
>

View File

@@ -170,7 +170,7 @@ onBeforeUnmount(() => {
</el-card>
</template>
<style scoped lang="scss">
<style lang="scss" scoped>
::v-deep(.el-upload-dragger) {
display: flex;
align-items: center;

View File

@@ -53,7 +53,7 @@ onBeforeUnmount(() => {
代码位置 src/views/able/watermark.vue
</el-link>
</template>
<el-space wrap class="!mb-2">
<el-space wrap class="mb-2!">
<span> 请输入要创建水印的值</span>
<el-input v-model="value" class="mr-4" style="width: 200px" clearable />
<span>请选择要创建水印的颜色</span>

View File

@@ -103,7 +103,7 @@ onBeforeUnmount(() => {
</template>
<div
v-loading="loading"
class="w-8/12 !m-auto !mt-[20px]"
class="w-8/12 m-auto! mt-[20px]!"
element-loading-background="transparent"
>
<div ref="wavesurferRef" />

View File

@@ -7,7 +7,7 @@ export function useColumns() {
minWidth: 100,
cellRenderer: () => {
return (
<el-tag size="large" class="!text-base">
<el-tag size="large" class="text-base!">
{version}
</el-tag>
);
@@ -18,7 +18,7 @@ export function useColumns() {
minWidth: 120,
cellRenderer: () => {
return (
<el-tag size="large" class="!text-base">
<el-tag size="large" class="text-base!">
{lastBuildTime}
</el-tag>
);
@@ -29,7 +29,7 @@ export function useColumns() {
minWidth: 140,
cellRenderer: () => {
return (
<el-tag size="large" class="!text-base">
<el-tag size="large" class="text-base!">
{engines.node}
</el-tag>
);
@@ -40,7 +40,7 @@ export function useColumns() {
minWidth: 140,
cellRenderer: () => {
return (
<el-tag size="large" class="!text-base">
<el-tag size="large" class="text-base!">
{engines.pnpm}
</el-tag>
);

View File

@@ -70,12 +70,12 @@ getMine().then(res => {
<el-container class="h-full">
<el-aside
v-if="isOpen"
class="pure-account-settings overflow-hidden px-2 dark:!bg-[var(--el-bg-color)] border-r-[1px] border-[var(--pure-border-color)]"
class="pure-account-settings overflow-hidden px-2 dark:bg-(--el-bg-color)! border-r-[1px] border-[var(--pure-border-color)]"
:width="deviceDetection() ? '180px' : '240px'"
>
<el-menu :default-active="witchPane" class="pure-account-settings-menu">
<el-menu-item
class="hover:!transition-all hover:!duration-200 hover:!text-base !h-[50px]"
class="hover:transition-all! hover:duration-200! hover:text-base! h-[50px]!"
@click="router.go(-1)"
>
<div class="flex items-center">
@@ -86,10 +86,10 @@ getMine().then(res => {
<div class="flex items-center ml-8 mt-4 mb-4">
<el-avatar :size="48" :src="userInfo.avatar" />
<div class="ml-4 flex flex-col max-w-[130px]">
<ReText class="font-bold !self-baseline">
<ReText class="font-bold self-baseline!">
{{ userInfo.nickname }}
</ReText>
<ReText class="!self-baseline" type="info">
<ReText class="self-baseline!" type="info">
{{ userInfo.username }}
</ReText>
</div>
@@ -131,7 +131,7 @@ getMine().then(res => {
<style lang="scss">
.pure-account-settings {
background: var(--pure-theme-menu-bg);
background: var(--pure-theme-menu-bg) !important;
}
.pure-account-settings-menu {

View File

@@ -0,0 +1,96 @@
<script setup lang="ts">
import "codemirror/theme/material-darker.css";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/addon/hint/show-hint";
import "codemirror/addon/hint/javascript-hint.js";
import "codemirror/mode/javascript/javascript.js";
import { useDark } from "@pureadmin/utils";
import Codemirror from "codemirror-editor-vue3";
import { ref, reactive, watch, nextTick } from "vue";
import type { Editor, EditorConfiguration } from "codemirror";
const { isDark } = useDark();
const cminstance = ref<Editor | null>(null);
const cmOptions: EditorConfiguration = reactive({
mode: "javascript",
theme: isDark.value ? "material-darker" : "default",
tabSize: 4,
readOnly: false,
autofocus: true,
autoRefresh: true,
lineNumbers: true,
lineWiseCopyCut: true,
gutters: ["CodeMirror-lint-markers"],
lint: true,
extraKeys: {
Ctrl: "autocomplete",
Tab: "autocomplete"
},
hintOptions: {
completeSingle: false
}
});
const code = ref(`function sayHello() {
console.log("Hello, World!");
}
sayHello();`);
const onReady = (cm: Editor) => {
cminstance.value = cm;
cm.on("keypress", () => cm.showHint());
// console.log(cm.getValue());
};
watch(
() => isDark.value,
async newVal => {
await nextTick();
newVal
? cminstance.value.setOption("theme", "material-darker")
: cminstance.value.setOption("theme", "default");
}
);
</script>
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">
代码编辑器组件采用开源的
<el-link
href="https://rennzhang.github.io/codemirror-editor-vue3/zh-CN/guide/getting-started"
target="_blank"
style="margin: 0 4px 5px; font-size: 16px"
>
codemirror-editor-vue3
</el-link>
</span>
</div>
<el-link
class="mt-2"
href="https://github.com/pure-admin/vue-pure-admin/blob/main/src/views/codemirror/index.vue"
target="_blank"
>
代码位置 src/views/codemirror/index.vue
</el-link>
</template>
<Codemirror
v-model:value="code"
width="100%"
height="400px"
:options="cmOptions"
:border="true"
@ready="onReady"
/>
</el-card>
</template>
<style lang="scss" scoped>
.codemirror-container.bordered {
border: 1px solid var(--pure-border-color);
}
</style>

View File

@@ -36,6 +36,6 @@ watch(animate, () => {
代码位置 src/views/components/animatecss.vue
</el-link>
</template>
<ReAnimateSelector v-model="animate" class="!w-[200px]" />
<ReAnimateSelector v-model="animate" class="w-[200px]!" />
</el-card>
</template>

View File

@@ -221,7 +221,7 @@ watch(size, val =>
<p>可控制间距的按钮样式</p>
<el-slider
v-model="spaceSize"
class="mb-2 !w-[300px]"
class="mb-2 w-[300px]!"
:show-tooltip="false"
:disabled="size === 'disabled'"
/>

View File

@@ -164,7 +164,7 @@ watch(size, val =>
<el-date-picker
v-model="value"
type="date"
class="!w-[160px]"
class="w-[160px]!"
placeholder="请选择"
:disabled-date="disabledDate"
:shortcuts="shortcuts"
@@ -180,7 +180,7 @@ watch(size, val =>
<el-date-picker
v-model="value1"
type="week"
class="!w-[160px]"
class="w-[160px]!"
format="YYYY年第ww周"
placeholder="选择某年中的某周"
:size="dynamicSize"
@@ -189,7 +189,7 @@ watch(size, val =>
<el-date-picker
v-model="value2"
type="month"
class="!w-[160px]"
class="w-[160px]!"
placeholder="选择某月"
:size="dynamicSize"
:disabled="size === 'disabled'"
@@ -197,7 +197,7 @@ watch(size, val =>
<el-date-picker
v-model="value3"
type="year"
class="!w-[160px]"
class="w-[160px]!"
placeholder="选择某年"
:size="dynamicSize"
:disabled="size === 'disabled'"
@@ -205,7 +205,7 @@ watch(size, val =>
<el-date-picker
v-model="value4"
type="dates"
class="!w-[160px]"
class="w-[160px]!"
placeholder="选择多个日期"
:size="dynamicSize"
:disabled="size === 'disabled'"
@@ -216,7 +216,7 @@ watch(size, val =>
<el-date-picker
v-model="value5"
type="daterange"
class="!w-[240px]"
class="w-[240px]!"
unlink-panels
range-separator="至"
start-placeholder="开始时间"
@@ -261,7 +261,7 @@ watch(size, val =>
<el-date-picker
v-model="value7"
type="date"
class="!w-[160px]"
class="w-[160px]!"
placeholder="请选择日期"
format="YYYY/MM/DD"
:value-format="dateFormat"
@@ -275,7 +275,7 @@ watch(size, val =>
<el-date-picker
v-model="value8"
type="date"
class="!w-[160px]"
class="w-[160px]!"
placeholder="请选择日期"
:prefix-icon="useRenderIcon('twemoji:spiral-calendar')"
:size="dynamicSize"

View File

@@ -190,7 +190,7 @@ watch(size, val =>
<el-date-picker
v-model="value"
type="datetime"
class="!w-[200px]"
class="w-[200px]!"
placeholder="请选择日期时间"
:shortcuts="shortcuts"
:size="dynamicSize"
@@ -213,7 +213,7 @@ watch(size, val =>
<el-date-picker
v-model="value1"
type="datetime"
class="!w-[200px]"
class="w-[200px]!"
placeholder="请选择日期时间"
format="YYYY/MM/DD hh:mm:ss"
:value-format="datetimeFormat"

View File

@@ -28,14 +28,14 @@ const newFormInline = ref(props.formInline);
<el-form-item label="姓名">
<el-input
v-model="newFormInline.user"
class="!w-[220px]"
class="w-[220px]!"
placeholder="请输入姓名"
/>
</el-form-item>
<el-form-item label="城市">
<el-select
v-model="newFormInline.region"
class="!w-[220px]"
class="w-[220px]!"
placeholder="请选择城市"
>
<el-option label="上海" value="上海" />

View File

@@ -18,5 +18,5 @@ const data = useVModel(props, "data", emit);
</script>
<template>
<el-input v-model="data" class="!w-[220px]" placeholder="请输入内容" />
<el-input v-model="data" class="w-[220px]!" placeholder="请输入内容" />
</template>

View File

@@ -28,14 +28,14 @@ const newFormInline = ref(props.formInline);
<el-form-item label="姓名">
<el-input
v-model="newFormInline.user"
class="!w-[220px]"
class="w-[220px]!"
placeholder="请输入姓名"
/>
</el-form-item>
<el-form-item label="城市">
<el-select
v-model="newFormInline.region"
class="!w-[220px]"
class="w-[220px]!"
placeholder="请选择城市"
>
<el-option label="上海" value="上海" />

View File

@@ -18,5 +18,5 @@ const data = useVModel(props, "data", emit);
</script>
<template>
<el-input v-model="data" class="!w-[220px]" placeholder="请输入内容" />
<el-input v-model="data" class="w-[220px]!" placeholder="请输入内容" />
</template>

View File

@@ -84,17 +84,7 @@ watch(
>
vue-json-pretty
</el-link>
支持大数据量
</span>
<span class="font-medium">
当然还有一款代码编辑器推荐这里就不做演示了采用开源的
<el-link
href="https://github.com/surmon-china/vue-codemirror"
target="_blank"
style="margin: 0 4px 5px; font-size: 16px"
>
codemirror6
</el-link>
支持大数据量
</span>
</div>
<el-link

View File

@@ -0,0 +1,64 @@
<script setup lang="ts">
import { ref } from "vue";
const value1 = ref(0);
const value2 = ref(10);
const value3 = ref(0);
const value4 = ref(0);
const value5 = ref(0);
const formatTooltip = (val: number) => {
return val / 100;
};
</script>
<template>
<div class="slider-demo-block">
<span class="demonstration">默认值</span>
<el-slider v-model="value1" />
</div>
<div class="slider-demo-block">
<span class="demonstration">自定义初始值</span>
<el-slider v-model="value2" />
</div>
<div class="slider-demo-block">
<span class="demonstration">隐藏 Tooltip 提示</span>
<el-slider v-model="value3" :show-tooltip="false" />
</div>
<div class="slider-demo-block">
<span class="demonstration">格式化 Tooltip 提示</span>
<el-slider v-model="value4" :format-tooltip="formatTooltip" />
</div>
<div class="slider-demo-block">
<span class="demonstration">禁用</span>
<el-slider v-model="value5" disabled />
</div>
</template>
<style lang="scss" scoped>
.slider-demo-block {
display: flex;
align-items: center;
max-width: 600px;
}
.slider-demo-block .el-slider {
margin-top: 0;
margin-left: 12px;
}
.slider-demo-block .demonstration {
flex: 1;
margin-bottom: 0;
overflow: hidden;
font-size: 14px;
line-height: 44px;
color: var(--el-text-color-secondary);
text-overflow: ellipsis;
white-space: nowrap;
}
.slider-demo-block .demonstration + .el-slider {
flex: 0 0 70%;
}
</style>

View File

@@ -0,0 +1,24 @@
<script setup lang="ts">
import { ref } from "vue";
const value = ref(0);
</script>
<template>
<div class="slider-demo-block">
<el-slider v-model="value" show-input />
</div>
</template>
<style lang="scss" scoped>
.slider-demo-block {
display: flex;
align-items: center;
max-width: 600px;
}
.slider-demo-block .el-slider {
margin-top: 0;
margin-left: 12px;
}
</style>

View File

@@ -0,0 +1,43 @@
<script setup lang="ts">
import { reactive, ref } from "vue";
import type { CSSProperties } from "vue";
interface Mark {
style: CSSProperties;
label: string;
}
type Marks = Record<number, Mark | string>;
const value = ref([30, 60]);
const marks = reactive<Marks>({
0: "0°C",
8: "8°C",
37: "37°C",
50: {
style: {
color: "#1989FA"
},
label: "50%"
}
});
</script>
<template>
<div class="slider-demo-block">
<el-slider v-model="value" range :marks="marks" />
</div>
</template>
<style lang="scss" scoped>
.slider-demo-block {
display: flex;
align-items: center;
max-width: 600px;
}
.slider-demo-block .el-slider {
margin-top: 0;
margin-left: 12px;
}
</style>

View File

@@ -0,0 +1,40 @@
<script setup lang="ts">
import { ref } from "vue";
const value1 = ref(0);
const value2 = ref(0);
const value3 = ref(0);
const value4 = ref(0);
</script>
<template>
<div class="slider-demo-block">
<span class="mr-2"></span>
<el-slider v-model="value1" />
</div>
<div class="slider-demo-block">
<span class="mr-2"></span>
<el-slider v-model="value2" placement="bottom" />
</div>
<div class="slider-demo-block">
<span class="mr-2"></span>
<el-slider v-model="value4" placement="left" />
</div>
<div class="slider-demo-block">
<span class="mr-2"></span>
<el-slider v-model="value3" placement="right" />
</div>
</template>
<style lang="scss" scoped>
.slider-demo-block {
display: flex;
align-items: center;
max-width: 600px;
}
.slider-demo-block .el-slider {
margin-top: 0;
margin-left: 12px;
}
</style>

View File

@@ -0,0 +1,24 @@
<script setup lang="ts">
import { ref } from "vue";
const value = ref([4, 8]);
</script>
<template>
<div class="slider-demo-block">
<el-slider v-model="value" range show-stops :max="10" />
</div>
</template>
<style lang="scss" scoped>
.slider-demo-block {
display: flex;
align-items: center;
max-width: 600px;
}
.slider-demo-block .el-slider {
margin-top: 0;
margin-left: 12px;
}
</style>

View File

@@ -0,0 +1,23 @@
<script setup lang="ts">
import { ref } from "vue";
const value = ref(0);
</script>
<template>
<div class="max-w-[600px] ml-4">
<el-slider v-model="value" show-input size="large" />
<el-slider v-model="value" show-input />
<el-slider v-model="value" show-input size="small" />
</div>
</template>
<style lang="scss" scoped>
.el-slider {
margin-top: 20px;
}
.el-slider:first-child {
margin-top: 0;
}
</style>

View File

@@ -0,0 +1,45 @@
<script setup lang="ts">
import { ref } from "vue";
const value1 = ref(0);
const value2 = ref(0);
</script>
<template>
<div class="slider-demo-block">
<span class="demonstration">不显示断点</span>
<el-slider v-model="value1" :step="10" />
</div>
<div class="slider-demo-block">
<span class="demonstration">显示断点</span>
<el-slider v-model="value2" :step="10" show-stops />
</div>
</template>
<style lang="scss" scoped>
.slider-demo-block {
display: flex;
align-items: center;
max-width: 600px;
}
.slider-demo-block .el-slider {
margin-top: 0;
margin-left: 12px;
}
.slider-demo-block .demonstration {
flex: 1;
margin-bottom: 0;
overflow: hidden;
font-size: 14px;
line-height: 44px;
color: var(--el-text-color-secondary);
text-overflow: ellipsis;
white-space: nowrap;
}
.slider-demo-block .demonstration + .el-slider {
flex: 0 0 70%;
}
</style>

View File

@@ -0,0 +1,24 @@
<script setup lang="ts">
import { ref } from "vue";
const value = ref(0);
</script>
<template>
<div class="slider-demo-block">
<el-slider v-model="value" vertical height="200px" />
</div>
</template>
<style lang="scss" scoped>
.slider-demo-block {
display: flex;
align-items: center;
max-width: 600px;
}
.slider-demo-block .el-slider {
margin-top: 0;
margin-left: 12px;
}
</style>

View File

@@ -0,0 +1,8 @@
export { default as Base } from "./Base.vue";
export { default as Step } from "./Step.vue";
export { default as Size } from "./Size.vue";
export { default as Input } from "./Input.vue";
export { default as Range } from "./Range.vue";
export { default as Marks } from "./Marks.vue";
export { default as Vertical } from "./Vertical.vue";
export { default as Placement } from "./Placement.vue";

View File

@@ -0,0 +1,56 @@
<script setup lang="ts">
import {
Base,
Step,
Input,
Size,
Placement,
Range,
Vertical,
Marks
} from "./components";
defineOptions({
name: "PureSlider"
});
</script>
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<p class="font-medium">滑块</p>
<el-link
class="mt-2"
href="https://github.com/pure-admin/vue-pure-admin/blob/main/src/views/components/slider/index.vue"
target="_blank"
>
代码位置 src/views/components/slider/index.vue
</el-link>
</div>
</template>
<p class="mb-2">基础用法</p>
<Base />
<el-divider />
<p class="mb-2">离散值</p>
<Step />
<el-divider />
<p class="mb-2">带有输入框的滑块</p>
<Input />
<el-divider />
<p class="mb-2">不同尺寸</p>
<Size />
<el-divider />
<p class="mb-2">位置</p>
<Placement />
<el-divider />
<p class="mb-2">范围选择</p>
<Range />
<el-divider />
<p class="mb-2">垂直模式</p>
<Vertical />
<el-divider />
<p class="mb-2">显示标记</p>
<Marks class="mb-6" />
</el-card>
</template>

View File

@@ -121,7 +121,7 @@ const swiperExample: any[] = [
</el-card>
</template>
<style scoped lang="scss">
<style lang="scss" scoped>
:deep(.el-card__body) {
padding-top: 0;
}

View File

@@ -156,7 +156,7 @@ const handleInputConfirm = () => {
v-if="inputVisible"
ref="InputRef"
v-model="inputValue"
class="ml-1 !w-20"
class="ml-1 w-20!"
size="small"
@keyup.enter="handleInputConfirm"
@blur="handleInputConfirm"

View File

@@ -1,4 +1,4 @@
<script lang="ts" setup>
<script setup lang="ts">
import dayjs from "dayjs";
import { ref } from "vue";
import { ReText } from "@/components/ReText";

View File

@@ -91,7 +91,7 @@ const endTime = ref("");
<el-time-picker
v-model="value"
placeholder="请选择时间"
class="!w-[140px]"
class="w-[140px]!"
:size="dynamicSize"
:disabled="size === 'disabled'"
/>
@@ -100,7 +100,7 @@ const endTime = ref("");
v-model="value1"
arrow-control
placeholder="请选择时间"
class="!w-[140px]"
class="w-[140px]!"
:size="dynamicSize"
:disabled="size === 'disabled'"
/>
@@ -110,7 +110,7 @@ const endTime = ref("");
<p class="mb-2">限制时间选择范围</p>
<el-time-picker
v-model="value2"
class="!w-[140px]"
class="w-[140px]!"
:disabled-hours="disabledHours"
:disabled-minutes="disabledMinutes"
:disabled-seconds="disabledSeconds"
@@ -123,7 +123,7 @@ const endTime = ref("");
<p class="mb-2">任意时间范围</p>
<el-time-picker
v-model="value3"
class="!w-[220px]"
class="w-[220px]!"
is-range
range-separator="至"
start-placeholder="开始时间"
@@ -153,7 +153,7 @@ const endTime = ref("");
<el-time-select
v-model="value4"
placeholder="请选择时间"
class="!w-[140px]"
class="w-[140px]!"
start="08:30"
step="00:15"
end="18:30"
@@ -165,7 +165,7 @@ const endTime = ref("");
<el-time-select
v-model="value5"
placeholder="请选择时间"
class="!w-[140px]"
class="w-[140px]!"
start="00:00"
step="00:30"
end="23:59"
@@ -179,7 +179,7 @@ const endTime = ref("");
<el-time-select
v-model="startTime"
placeholder="开始时间"
class="!w-[140px]"
class="w-[140px]!"
:max-time="endTime"
start="08:30"
step="00:15"
@@ -190,7 +190,7 @@ const endTime = ref("");
<el-time-select
v-model="endTime"
placeholder="结束时间"
class="!w-[140px]"
class="w-[140px]!"
:min-time="startTime"
start="08:30"
step="00:15"

View File

@@ -1,4 +1,4 @@
<script lang="ts" setup>
<script setup lang="ts">
import { reactive, ref } from "vue";
import { formUpload } from "@/api/mock";
import { message } from "@/utils/message";
@@ -58,7 +58,7 @@ const resetForm = formEl => {
drag
multiple
action="#"
class="!w-[200px]"
class="w-[200px]!"
:auto-upload="false"
>
<div class="el-upload__text">
@@ -79,7 +79,7 @@ const resetForm = formEl => {
<el-date-picker
v-model="validateForm.date"
type="datetime"
class="!w-[200px]"
class="w-[200px]!"
placeholder="请选择日期时间"
value-format="YYYY-MM-DD HH:mm:ss"
/>

View File

@@ -173,7 +173,7 @@ const onDownload = () => {
id="pure-upload-item"
:class="[
'el-upload-list__item-actions',
fileList.length > 1 && '!cursor-move'
fileList.length > 1 && 'cursor-move!'
]"
>
<span

View File

@@ -24,7 +24,7 @@ const filteredItems = computed(() => {
水平模式 horizontal
<el-input
v-model="search"
class="mr-2 !w-[1/1.5]"
class="mr-2 w-[1/1.5]!"
clearable
placeholder="Filter..."
style="width: 300px"

View File

@@ -24,7 +24,7 @@ const filteredItems = computed(() => {
垂直模式 vertical
<el-input
v-model="search"
class="!w-[350px]"
class="w-[350px]!"
clearable
placeholder="Filter..."
/>

View File

@@ -89,7 +89,7 @@ const cardLogoClass = computed(() => [
</div>
</template>
<style scoped lang="scss">
<style lang="scss" scoped>
.list-card-item {
display: flex;
flex-direction: column;

View File

@@ -68,7 +68,10 @@ const onLogin = async (formEl: FormInstance | undefined) => {
if (valid) {
loading.value = true;
useUserStoreHook()
.loginByUsername({ username: ruleForm.username, password: "admin123" })
.loginByUsername({
username: ruleForm.username,
password: ruleForm.password
})
.then(res => {
if (res.success) {
// 获取后端路由
@@ -96,7 +99,7 @@ const immediateDebounce: any = debounce(
true
);
useEventListener(document, "keypress", ({ code }) => {
useEventListener(document, "keydown", ({ code }) => {
if (
["Enter", "NumpadEnter"].includes(code) &&
!disabled.value &&
@@ -131,13 +134,13 @@ watch(loginDay, value => {
<!-- 国际化 -->
<el-dropdown trigger="click">
<globalization
class="hover:text-primary hover:!bg-[transparent] w-[20px] h-[20px] ml-1.5 cursor-pointer outline-none duration-300"
class="hover:text-primary hover:bg-[transparent]! w-[20px] h-[20px] ml-1.5 cursor-pointer outline-hidden duration-300"
/>
<template #dropdown>
<el-dropdown-menu class="translation">
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'zh')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'zh')]"
:class="['dark:text-white!', getDropdownItemClass(locale, 'zh')]"
@click="translationCh"
>
<IconifyIconOffline
@@ -149,7 +152,7 @@ watch(loginDay, value => {
</el-dropdown-item>
<el-dropdown-item
:style="getDropdownItemStyle(locale, 'en')"
:class="['dark:!text-white', getDropdownItemClass(locale, 'en')]"
:class="['dark:text-white!', getDropdownItemClass(locale, 'en')]"
@click="translationEn"
>
<span v-show="locale === 'en'" class="check-en">
@@ -169,7 +172,7 @@ watch(loginDay, value => {
<div class="login-form">
<avatar class="avatar" />
<Motion>
<h2 class="outline-none">
<h2 class="outline-hidden">
<TypeIt
:options="{ strings: [title], cursor: false, speed: 100 }"
/>

View File

@@ -0,0 +1,105 @@
<script setup lang="ts">
import "vditor/dist/index.css";
import Vditor from "vditor";
import { useDark } from "@pureadmin/utils";
import { useIntervalFn } from "@vueuse/core";
import { onMounted, ref, watch, toRaw, onUnmounted } from "vue";
const emit = defineEmits([
"update:modelValue",
"after",
"focus",
"blur",
"esc",
"ctrlEnter",
"select"
]);
const props = defineProps({
options: {
type: Object,
default() {
return {};
}
},
modelValue: {
type: String,
default: ""
}
});
const { isDark } = useDark();
const editor = ref<Vditor | null>(null);
const markdownRef = ref<HTMLElement | null>(null);
onMounted(() => {
editor.value = new Vditor(markdownRef.value as HTMLElement, {
...props.options,
value: props.modelValue,
cache: {
enable: false
},
fullscreen: {
index: 10000
},
after() {
emit("after", toRaw(editor.value));
},
input(value: string) {
emit("update:modelValue", value);
},
focus(value: string) {
emit("focus", value);
},
blur(value: string) {
emit("blur", value);
},
esc(value: string) {
emit("esc", value);
},
ctrlEnter(value: string) {
emit("ctrlEnter", value);
},
select(value: string) {
emit("select", value);
}
});
});
watch(
() => props.modelValue,
newVal => {
if (newVal !== editor.value?.getValue()) {
editor.value?.setValue(newVal);
}
}
);
watch(
() => isDark.value,
newVal => {
const { pause } = useIntervalFn(() => {
if (editor.value.vditor) {
newVal
? editor.value.setTheme("dark", "dark", "rose-pine")
: editor.value.setTheme("classic", "light", "github");
pause();
}
}, 20);
}
);
onUnmounted(() => {
const editorInstance = editor.value;
if (!editorInstance) return;
try {
editorInstance?.destroy?.();
} catch (error) {
console.log(error);
}
});
</script>
<template>
<div ref="markdownRef" />
</template>

View File

@@ -0,0 +1,59 @@
<script setup lang="ts">
import { ref } from "vue";
import Vditor from "./components/Vditor.vue";
defineOptions({
name: "Markdown"
});
const text = ref(`
\`\`\`ts
function sayHello(): void {
\tconsole.log("Hello, World!");
}
sayHello();
\`\`\`
# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题
`);
</script>
<template>
<el-card shadow="never">
<template #header>
<div class="card-header">
<span class="font-medium">
Markdown组件采用开源的
<el-link
href="https://b3log.org/vditor/"
target="_blank"
style="margin: 0 4px 5px; font-size: 16px"
>
Vditor
</el-link>
</span>
</div>
<el-link
class="mt-2"
href="https://github.com/pure-admin/vue-pure-admin/blob/main/src/views/markdown"
target="_blank"
>
代码位置 src/views/markdown
</el-link>
</template>
<h1 class="mb-2">
双向绑定<span class="text-red-500">{{ text }}</span>
</h1>
<Vditor
v-model="text"
:options="{
height: 560, // 高度
outline: { enable: true, position: 'right' } // 大纲
}"
/>
</el-card>
</template>

View File

@@ -39,14 +39,14 @@ const {
ref="formRef"
:inline="true"
:model="form"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto"
class="search-form bg-bg_color w-99/100 pl-8 pt-[12px] overflow-auto"
>
<el-form-item label="用户名" prop="username">
<el-input
v-model="form.username"
placeholder="请输入用户名"
clearable
class="!w-[150px]"
class="w-[150px]!"
/>
</el-form-item>
<el-form-item label="登录状态" prop="status">
@@ -54,7 +54,7 @@ const {
v-model="form.status"
placeholder="请选择"
clearable
class="!w-[150px]"
class="w-[150px]!"
>
<el-option label="成功" value="1" />
<el-option label="失败" value="0" />
@@ -147,7 +147,7 @@ const {
</div>
</template>
<style scoped lang="scss">
<style lang="scss" scoped>
:deep(.el-dropdown-menu__item i) {
margin: 0;
}

View File

@@ -39,14 +39,14 @@ const {
ref="formRef"
:inline="true"
:model="form"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px] overflow-auto"
class="search-form bg-bg_color w-99/100 pl-8 pt-[12px] overflow-auto"
>
<el-form-item label="所属模块" prop="module">
<el-input
v-model="form.module"
placeholder="请输入所属模块"
clearable
class="!w-[170px]"
class="w-[170px]!"
/>
</el-form-item>
<el-form-item label="操作状态" prop="status">
@@ -54,7 +54,7 @@ const {
v-model="form.status"
placeholder="请选择"
clearable
class="!w-[150px]"
class="w-[150px]!"
>
<el-option label="成功" value="1" />
<el-option label="失败" value="0" />
@@ -147,7 +147,7 @@ const {
</div>
</template>
<style scoped lang="scss">
<style lang="scss" scoped>
:deep(.el-dropdown-menu__item i) {
margin: 0;
}

Some files were not shown because too many files have changed in this diff Show More