This commit is contained in:
2025-03-03 13:47:34 +08:00
parent 586727cb99
commit f01f8a174d
16 changed files with 212 additions and 133 deletions

2
components.d.ts vendored
View File

@@ -14,10 +14,12 @@ declare module 'vue' {
NAlert: typeof import('naive-ui')['NAlert'] NAlert: typeof import('naive-ui')['NAlert']
NButton: typeof import('naive-ui')['NButton'] NButton: typeof import('naive-ui')['NButton']
NConfigProvider: typeof import('naive-ui')['NConfigProvider'] NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDropdown: typeof import('naive-ui')['NDropdown']
NFlex: typeof import('naive-ui')['NFlex'] NFlex: typeof import('naive-ui')['NFlex']
NForm: typeof import('naive-ui')['NForm'] NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem'] NFormItem: typeof import('naive-ui')['NFormItem']
NInput: typeof import('naive-ui')['NInput'] NInput: typeof import('naive-ui')['NInput']
NMessageProvider: typeof import('naive-ui')['NMessageProvider']
NModal: typeof import('naive-ui')['NModal'] NModal: typeof import('naive-ui')['NModal']
NModalProvider: typeof import('naive-ui')['NModalProvider'] NModalProvider: typeof import('naive-ui')['NModalProvider']
NSplit: typeof import('naive-ui')['NSplit'] NSplit: typeof import('naive-ui')['NSplit']

143
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "webpreview", "name": "web",
"version": "0.1.0", "version": "0.2.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "webpreview", "name": "web",
"version": "0.1.0", "version": "0.2.0",
"dependencies": { "dependencies": {
"@codemirror/lang-css": "^6.3.1", "@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-html": "^6.4.9", "@codemirror/lang-html": "^6.4.9",
@@ -29,12 +29,12 @@
}, },
"devDependencies": { "devDependencies": {
"@iconify/vue": "^4.3.0", "@iconify/vue": "^4.3.0",
"@rsbuild/core": "^1.2.11", "@rsbuild/core": "^1.2.14",
"@rsbuild/plugin-vue": "^1.0.6", "@rsbuild/plugin-vue": "^1.0.6",
"@vue/tsconfig": "^0.7.0", "@vue/tsconfig": "^0.7.0",
"prettier": "^3.5.2", "prettier": "^3.5.3",
"typescript": "^5.7.3", "typescript": "^5.8.2",
"unplugin-vue-components": "^28.4.0" "unplugin-vue-components": "^28.4.1"
} }
}, },
"node_modules/@babel/helper-string-parser": { "node_modules/@babel/helper-string-parser": {
@@ -450,16 +450,17 @@
} }
}, },
"node_modules/@rsbuild/core": { "node_modules/@rsbuild/core": {
"version": "1.2.11", "version": "1.2.14",
"resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-1.2.11.tgz", "resolved": "https://registry.npmjs.org/@rsbuild/core/-/core-1.2.14.tgz",
"integrity": "sha512-bsTtXlqJKoqnHwOZ05NePGpBf/neuwHTzJtQegQ9GA8YLyjow1wn8vPXFiRtYL0UqASEDtFtAm2bcaieg7r/TQ==", "integrity": "sha512-G8AqvCHBhs8Yt7pOQuS5YYjdYozp436ohaLr1iAMB/Jw01VNFh4u1tpShudRnw3NPmHhJ82wBaEu1zNaJ0VsKg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@rspack/core": "1.2.3", "@rspack/core": "1.2.5",
"@rspack/lite-tapable": "~1.0.1", "@rspack/lite-tapable": "~1.0.1",
"@swc/helpers": "^0.5.15", "@swc/helpers": "^0.5.15",
"core-js": "~3.40.0" "core-js": "~3.40.0",
"jiti": "^2.4.2"
}, },
"bin": { "bin": {
"rsbuild": "bin/rsbuild.js" "rsbuild": "bin/rsbuild.js"
@@ -483,27 +484,27 @@
} }
}, },
"node_modules/@rspack/binding": { "node_modules/@rspack/binding": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding/-/binding-1.2.5.tgz",
"integrity": "sha512-enpOXZPQOJO800wdWcR7H5Dx5UZfwkaT0D0xsHD53WbpI09Z2KJbLX7I/i1FLLy3K1KQTB+2FIHLVdRikasXZA==", "integrity": "sha512-q9vQmGDFZyFVMULwOFL7488WNSgn4ue94R/njDLMMIPF4K0oEJP2QT02elfG4KVGv2CbP63D7vEFN4ZNreo/Rw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"optionalDependencies": { "optionalDependencies": {
"@rspack/binding-darwin-arm64": "1.2.3", "@rspack/binding-darwin-arm64": "1.2.5",
"@rspack/binding-darwin-x64": "1.2.3", "@rspack/binding-darwin-x64": "1.2.5",
"@rspack/binding-linux-arm64-gnu": "1.2.3", "@rspack/binding-linux-arm64-gnu": "1.2.5",
"@rspack/binding-linux-arm64-musl": "1.2.3", "@rspack/binding-linux-arm64-musl": "1.2.5",
"@rspack/binding-linux-x64-gnu": "1.2.3", "@rspack/binding-linux-x64-gnu": "1.2.5",
"@rspack/binding-linux-x64-musl": "1.2.3", "@rspack/binding-linux-x64-musl": "1.2.5",
"@rspack/binding-win32-arm64-msvc": "1.2.3", "@rspack/binding-win32-arm64-msvc": "1.2.5",
"@rspack/binding-win32-ia32-msvc": "1.2.3", "@rspack/binding-win32-ia32-msvc": "1.2.5",
"@rspack/binding-win32-x64-msvc": "1.2.3" "@rspack/binding-win32-x64-msvc": "1.2.5"
} }
}, },
"node_modules/@rspack/binding-darwin-arm64": { "node_modules/@rspack/binding-darwin-arm64": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.2.5.tgz",
"integrity": "sha512-xuwYzhPgNCr4BtKXCU3xe4249TFsXAZglIlbxv8Qs3PeIarrZMRddcqH2zUXi+nJavNw3yN12sCYEzk1f+O4FQ==", "integrity": "sha512-ou0NXMLp6RxY9Bx8P9lA8ArVjz/WAI/gSu5kKrdKKtMs6WKutl4vvP9A4HHZnISd9Tn00dlvDwNeNSUR7fjoDQ==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -515,9 +516,9 @@
] ]
}, },
"node_modules/@rspack/binding-darwin-x64": { "node_modules/@rspack/binding-darwin-x64": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-darwin-x64/-/binding-darwin-x64-1.2.5.tgz",
"integrity": "sha512-afiIN8elcrO2EtO27UN0qyZqu5FXGUdclud56DrhvEfnWS3GGxJEdjA8XUYVXkfCYakdXHucIJKlkkgaAjEvHg==", "integrity": "sha512-RdvH9YongQlDE9+T2Xh5D2+dyiLHx2Gz38Af1uObyBRNWjF1qbuR51hOas0f2NFUdyA03j1+HWZCbE7yZrmI3w==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -529,9 +530,9 @@
] ]
}, },
"node_modules/@rspack/binding-linux-arm64-gnu": { "node_modules/@rspack/binding-linux-arm64-gnu": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.5.tgz",
"integrity": "sha512-K2u/fPUmKujlKSWL3q2zaUu8/6ZK/bOGKcqJSib8jdanQQ/GFKwKtPAFOOa/vvqbzhDocqKOobFR10FhgJqCHg==", "integrity": "sha512-jznk/CI/wN93fr8I1j3la/CAiGf8aG7ZHIpRBtT4CkNze0c5BcF3AaJVSBHVNQqgSv0qddxMt3SADpzV8rWZ6g==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -543,9 +544,9 @@
] ]
}, },
"node_modules/@rspack/binding-linux-arm64-musl": { "node_modules/@rspack/binding-linux-arm64-musl": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.5.tgz",
"integrity": "sha512-mgovdzGb6cH9hQsjTyzDbfZWCPhTcoHcLro1P7UbiqcLPMDJp/k3Io9xV2/EJhaDA1aynIdq7XfY0fuk4+6Irw==", "integrity": "sha512-oYzcaJ0xjb1fWbbtPmjjPXeehExEgwJ8fEGYQ5TikB+p9oCLkAghnNjsz9evUhgjByxi+NTZ1YmUNwxRuQDY1Q==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -557,9 +558,9 @@
] ]
}, },
"node_modules/@rspack/binding-linux-x64-gnu": { "node_modules/@rspack/binding-linux-x64-gnu": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.5.tgz",
"integrity": "sha512-542lwJzB1RMGuVdBdA3cOWTlmL9okpOppHUBWcNCjmJM+9zTI+0jwjVe8HaqOqtuR8XzNsoCwT9QonU/GLcuhg==", "integrity": "sha512-dzEKs8oi86Vi+TFRCPpgmfF5ANL0VmlZN45e1An7HipeI2C5B1xrz/H8V43vPy8XEvQuMmkXO6Sp82A0zlHvIA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -571,9 +572,9 @@
] ]
}, },
"node_modules/@rspack/binding-linux-x64-musl": { "node_modules/@rspack/binding-linux-x64-musl": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.5.tgz",
"integrity": "sha512-dJromiREDcTWqzfCOI5y1IVoYmUnCv7vCp63AEq0+13fJJdk7+pcNN3VV2jOKpk9VECSvjg1c01wl+UzXAXFMw==", "integrity": "sha512-4ENeVPVSD97rRRGr6kJSm4sIPf1tKJ8vlr9hJi4sSvF7eMLWipSwIVmqRXJ2riVMRjYD2einmJ9KzI8rqQ2OwA==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -585,9 +586,9 @@
] ]
}, },
"node_modules/@rspack/binding-win32-arm64-msvc": { "node_modules/@rspack/binding-win32-arm64-msvc": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.5.tgz",
"integrity": "sha512-S8ZKddMMQDGy8jx/R0i2m1XrmfY2CpI+t6lIEpsuZuKUR4MbOGKN2DuL4MDnT3m8JaYvC8ihsvQjBXQCy3SNxQ==", "integrity": "sha512-WUoJvX/z43MWeW1JKAQIxdvqH02oLzbaGMCzIikvniZnakQovYLPH6tCYh7qD3p7uQsm+IafFddhFxTtogC3pg==",
"cpu": [ "cpu": [
"arm64" "arm64"
], ],
@@ -599,9 +600,9 @@
] ]
}, },
"node_modules/@rspack/binding-win32-ia32-msvc": { "node_modules/@rspack/binding-win32-ia32-msvc": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.2.5.tgz",
"integrity": "sha512-74lqSMKQJcJcgfFaxm+G9YVJSl2KK9/v4fRoMsWApztNy2qNgee+UguNBCOU6JLa3rVSj8Z5OVVDtJkGFrSvVg==", "integrity": "sha512-YzPvmt/gpiacE6aAacz4dxgEbNWwoKYPaT4WYy/oITobnAui++iCFXC4IICSmlpoA1y7O8K3Qb9jbaB/lLhbwA==",
"cpu": [ "cpu": [
"ia32" "ia32"
], ],
@@ -613,9 +614,9 @@
] ]
}, },
"node_modules/@rspack/binding-win32-x64-msvc": { "node_modules/@rspack/binding-win32-x64-msvc": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.5.tgz",
"integrity": "sha512-fcU532PgFdd5Bil8jwQW0Dcb/80oM6V0qSstGIxZ4M77t4t8e/PcukXfORTL71FfNQ64Rd4Dp6XRl1NHNJVxeg==", "integrity": "sha512-QDDshfteMZiglllm7WUh/ITemFNuexwn1Yul7cHBFGQu6HqtqKNAR0kGR8J3e15MPMlinSaygVpfRE4A0KPmjQ==",
"cpu": [ "cpu": [
"x64" "x64"
], ],
@@ -627,14 +628,14 @@
] ]
}, },
"node_modules/@rspack/core": { "node_modules/@rspack/core": {
"version": "1.2.3", "version": "1.2.5",
"resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.2.3.tgz", "resolved": "https://registry.npmjs.org/@rspack/core/-/core-1.2.5.tgz",
"integrity": "sha512-BFgdUYf05/hjjY9Nlwq8DpWaRJN5w2kTl8ZJi20SRL60oAx+ZD2ABT+fsPhBiFSmfTZDdvGGIq5e3vfRzoIuqg==", "integrity": "sha512-x/riOl05gOVGgGQFimBqS5i8XbUpBxPIKUC+tDX4hmNNkzxRaGpspZfNtcL+1HBMyYuoM6fOWGyCp2R290Uy6g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@module-federation/runtime-tools": "0.8.4", "@module-federation/runtime-tools": "0.8.4",
"@rspack/binding": "1.2.3", "@rspack/binding": "1.2.5",
"@rspack/lite-tapable": "1.0.1", "@rspack/lite-tapable": "1.0.1",
"caniuse-lite": "^1.0.30001616" "caniuse-lite": "^1.0.30001616"
}, },
@@ -2047,6 +2048,16 @@
"url": "https://github.com/chalk/supports-color?sponsor=1" "url": "https://github.com/chalk/supports-color?sponsor=1"
} }
}, },
"node_modules/jiti": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz",
"integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==",
"dev": true,
"license": "MIT",
"bin": {
"jiti": "lib/jiti-cli.mjs"
}
},
"node_modules/json-loose": { "node_modules/json-loose": {
"version": "1.2.4", "version": "1.2.4",
"resolved": "https://registry.npmjs.org/json-loose/-/json-loose-1.2.4.tgz", "resolved": "https://registry.npmjs.org/json-loose/-/json-loose-1.2.4.tgz",
@@ -2368,9 +2379,9 @@
} }
}, },
"node_modules/prettier": { "node_modules/prettier": {
"version": "3.5.2", "version": "3.5.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
"integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
@@ -2649,9 +2660,9 @@
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.7.3", "version": "5.8.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz",
"integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==",
"devOptional": true, "devOptional": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {
@@ -2708,9 +2719,9 @@
} }
}, },
"node_modules/unplugin-vue-components": { "node_modules/unplugin-vue-components": {
"version": "28.4.0", "version": "28.4.1",
"resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-28.4.0.tgz", "resolved": "https://registry.npmjs.org/unplugin-vue-components/-/unplugin-vue-components-28.4.1.tgz",
"integrity": "sha512-fnamX2RiKM30nPK4tihEas+bHnbLICo6MmOiP4jGg7fAlgNEuaLvN9yx96JwZDOYfLQcrNzikDdPhZ8k6pkhMg==", "integrity": "sha512-niGSc0vJD9ueAnsqcfAldmtpkppZ09B6p2G1dL7X5S8KPdgbk1P+txPwaaDCe7N+eZh2VG1aAypLXkuJs3OSUg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
@@ -2719,7 +2730,7 @@
"local-pkg": "^1.0.0", "local-pkg": "^1.0.0",
"magic-string": "^0.30.17", "magic-string": "^0.30.17",
"mlly": "^1.7.4", "mlly": "^1.7.4",
"tinyglobby": "^0.2.10", "tinyglobby": "^0.2.12",
"unplugin": "^2.2.0", "unplugin": "^2.2.0",
"unplugin-utils": "^0.2.4" "unplugin-utils": "^0.2.4"
}, },

View File

@@ -1,7 +1,7 @@
{ {
"name": "webpreview", "name": "web",
"private": true, "private": true,
"version": "0.1.0", "version": "0.2.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"start": "rsbuild dev", "start": "rsbuild dev",
@@ -30,11 +30,11 @@
}, },
"devDependencies": { "devDependencies": {
"@iconify/vue": "^4.3.0", "@iconify/vue": "^4.3.0",
"@rsbuild/core": "^1.2.11", "@rsbuild/core": "^1.2.14",
"@rsbuild/plugin-vue": "^1.0.6", "@rsbuild/plugin-vue": "^1.0.6",
"@vue/tsconfig": "^0.7.0", "@vue/tsconfig": "^0.7.0",
"prettier": "^3.5.2", "prettier": "^3.5.3",
"typescript": "^5.7.3", "typescript": "^5.8.2",
"unplugin-vue-components": "^28.4.0" "unplugin-vue-components": "^28.4.1"
} }
} }

View File

@@ -1,30 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import { dateZhCN, zhCN } from "naive-ui" import { dateZhCN, zhCN } from "naive-ui"
import { useMagicKeys, whenever } from "@vueuse/core"
import Login from "./components/Login.vue" import Login from "./components/Login.vue"
import { onMounted, watch } from "vue" import { onMounted, watch } from "vue"
import { getMyProfile } from "./api" import { getMyProfile } from "./api"
import { authed, username } from "./store/user" import { authed, user } from "./store/user"
const { ctrl_s } = useMagicKeys({
passive: false,
onEventFired(e) {
if (e.ctrlKey && e.key === "s" && e.type === "keydown") e.preventDefault()
},
})
const { ctrl_r } = useMagicKeys({
passive: false,
onEventFired(e) {
if (e.ctrlKey && e.key === "r" && e.type === "keydown") e.preventDefault()
},
})
whenever(ctrl_s, () => {})
whenever(ctrl_r, () => {})
onMounted(async () => { onMounted(async () => {
const data = await getMyProfile() const data = await getMyProfile()
username.value = data user.loaded = true
user.username = data.username
user.role = data.role
}) })
watch(authed, (v) => { watch(authed, (v) => {
@@ -39,8 +24,10 @@ watch(authed, (v) => {
<template> <template>
<n-config-provider class="myContainer" :locale="zhCN" :date-locale="dateZhCN"> <n-config-provider class="myContainer" :locale="zhCN" :date-locale="dateZhCN">
<n-modal-provider> <n-modal-provider>
<router-view></router-view> <n-message-provider>
<Login /> <router-view></router-view>
<Login />
</n-message-provider>
</n-modal-provider> </n-modal-provider>
</n-config-provider> </n-config-provider>
</template> </template>

View File

@@ -68,11 +68,20 @@
</n-tab-pane> </n-tab-pane>
<template #suffix> <template #suffix>
<n-flex align="center" class="suffix"> <n-flex align="center" class="suffix">
<span>{{ username }}</span> <template v-if="user.loaded && authed">
<n-button v-if="!authed" @click="handleLogin" secondary type="primary"> <n-button type="primary" secondary @click="submit">提交</n-button>
<n-dropdown :options="menu" @select="clickMenu">
<n-button>{{ user.username }}</n-button>
</n-dropdown>
</template>
<n-button
v-if="user.loaded && !authed"
@click="handleLogin"
secondary
type="primary"
>
登录 登录
</n-button> </n-button>
<n-button v-else @click="handleLogout">退出</n-button>
</n-flex> </n-flex>
</template> </template>
</n-tabs> </n-tabs>
@@ -81,9 +90,46 @@
import { Icon } from "@iconify/vue" import { Icon } from "@iconify/vue"
import Editor from "./Editor.vue" import Editor from "./Editor.vue"
import { html, css, js, tab, size, reset } from "../store/editors" import { html, css, js, tab, size, reset } from "../store/editors"
import { username, authed } from "../store/user" import { user, authed, roleNormal } from "../store/user"
import { loginModal } from "../store/modal" import { loginModal } from "../store/modal"
import { logout } from "../api" import { logout } from "../api"
import { Role } from "../utils/type"
import { router } from "../router"
import { computed, h } from "vue"
import { useMessage } from "naive-ui"
const message = useMessage()
const menu = computed(() => [
{
label: "后台",
key: "dashboard",
show: !roleNormal.value,
icon: () =>
h(Icon, {
icon: "streamline-emojis:robot-face-1",
}),
},
{
label: "退出",
key: "logout",
icon: () =>
h(Icon, {
icon: "streamline-emojis:hot-beverage-2",
}),
},
])
function clickMenu(name: string) {
switch (name) {
case "dashboard":
router.push({ name: "dashboard" })
break
case "logout":
handleLogout()
break
}
}
function changeTab(name: string) { function changeTab(name: string) {
tab.value = name tab.value = name
@@ -99,7 +145,12 @@ function handleLogin() {
async function handleLogout() { async function handleLogout() {
await logout() await logout()
username.value = "" user.username = ""
user.role = Role.Normal
}
function submit() {
message.error("未实装")
} }
</script> </script>
<style scoped> <style scoped>

View File

@@ -32,7 +32,7 @@
import { ref } from "vue" import { ref } from "vue"
import { login } from "../api" import { login } from "../api"
import { loginModal } from "../store/modal" import { loginModal } from "../store/modal"
import { username } from "../store/user" import { user } from "../store/user"
const name = ref("") const name = ref("")
const password = ref("") const password = ref("")
@@ -42,7 +42,9 @@ const showMeesage = ref(false)
async function submit() { async function submit() {
try { try {
const data = await login(name.value, password.value) const data = await login(name.value, password.value)
username.value = data user.username = data.username
user.role = data.role
user.loaded = true
loginModal.value = false loginModal.value = false
} catch (err) { } catch (err) {
showMeesage.value = true showMeesage.value = true

View File

@@ -4,9 +4,6 @@
<Icon icon="noto:eyes" :width="20"></Icon> <Icon icon="noto:eyes" :width="20"></Icon>
<n-text class="titleText">预览</n-text> <n-text class="titleText">预览</n-text>
</n-flex> </n-flex>
<n-flex>
<!-- <n-button>提交</n-button> -->
</n-flex>
</n-flex> </n-flex>
<iframe class="iframe" ref="iframe"></iframe> <iframe class="iframe" ref="iframe"></iframe>
</template> </template>

View File

@@ -11,7 +11,7 @@ import { marked } from "marked"
import alert from "marked-alert" import alert from "marked-alert"
import { markedHighlight } from "marked-highlight" import { markedHighlight } from "marked-highlight"
import preview from "marked-code-preview" import preview from "marked-code-preview"
import { alertVariants } from "./utils" import { alertVariants } from "./utils/const"
import hljs from "highlight.js/lib/core" import hljs from "highlight.js/lib/core"
import xml from "highlight.js/lib/languages/xml" import xml from "highlight.js/lib/languages/xml"

View File

@@ -1 +0,0 @@
<template>秘密花园</template>

1
src/pages/Dashboard.vue Normal file
View File

@@ -0,0 +1 @@
<template>秘密花园</template>

View File

@@ -1,22 +1,39 @@
<template> <template>
<n-split :default-size="1 / 3" min="300px" max="800px"> <n-split :default-size="1 / 3" min="300px" max="800px">
<template #1> <template #1>
<Tutorial /> <Tutorial />
</template> </template>
<template #2> <template #2>
<n-split direction="vertical" min="200px"> <n-split direction="vertical" min="200px">
<template #1> <template #1>
<Editors /> <Editors />
</template> </template>
<template #2> <template #2>
<Preview /> <Preview />
</template> </template>
</n-split> </n-split>
</template> </template>
</n-split> </n-split>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useMagicKeys, whenever } from "@vueuse/core"
import Editors from "../components/Editors.vue" import Editors from "../components/Editors.vue"
import Preview from "../components/Preview.vue" import Preview from "../components/Preview.vue"
import Tutorial from "../components/Tutorial.vue" import Tutorial from "../components/Tutorial.vue"
</script>
const { ctrl_s } = useMagicKeys({
passive: false,
onEventFired(e) {
if (e.ctrlKey && e.key === "s" && e.type === "keydown") e.preventDefault()
},
})
const { ctrl_r } = useMagicKeys({
passive: false,
onEventFired(e) {
if (e.ctrlKey && e.key === "r" && e.type === "keydown") e.preventDefault()
},
})
whenever(ctrl_s, () => {})
whenever(ctrl_r, () => {})
</script>

View File

@@ -2,15 +2,14 @@ import { createWebHistory, createRouter } from "vue-router"
import { loginModal } from "./store/modal" import { loginModal } from "./store/modal"
import Home from "./pages/Home.vue" import Home from "./pages/Home.vue"
import Protected from "./pages/Protected.vue"
const routes = [ const routes = [
{ path: "/", component: Home }, { path: "/", component: Home },
{ {
path: "/protected", path: "/dashboard",
name: "protected", name: "dashboard",
component: Protected, component: () => import("./pages/Dashboard.vue"),
meta: { requiresAuth: true }, meta: { auth: true },
}, },
] ]
@@ -21,10 +20,10 @@ export const router = createRouter({
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
const isLoggedIn = localStorage.getItem("web-isloggedin") === "true" const isLoggedIn = localStorage.getItem("web-isloggedin") === "true"
if (to.meta.requiresAuth && !isLoggedIn) { if (to.meta.auth && !isLoggedIn) {
loginModal.value = true loginModal.value = true
next(false) next(false)
} else { } else {
next() // 允许访问 next()
} }
}) })

View File

@@ -1,3 +1,3 @@
import { ref } from "vue"; import { ref } from "vue"
export const loginModal = ref(false) export const loginModal = ref(false)

View File

@@ -1,4 +1,12 @@
import { computed, ref } from "vue" import { computed, reactive } from "vue"
import { Role } from "../utils/type"
export const username = ref("") export const user = reactive({
export const authed = computed(() => !!username.value) loaded: false,
username: "",
role: Role.Normal,
})
export const authed = computed(() => !!user.username)
export const roleNormal = computed(() => user.role === Role.Normal)
export const roleAdmin = computed(() => user.role === Role.Admin)
export const roleSuper = computed(() => user.role !== Role.Super)

5
src/utils/type.ts Normal file
View File

@@ -0,0 +1,5 @@
export enum Role {
Super = "super",
Admin = "admin",
Normal = "normal",
}