From d8a283dd89f4efa94290ba75a577976c8b7eaacd Mon Sep 17 00:00:00 2001 From: Miao_Spring <539943419@qq.com> Date: Sun, 19 Jan 2025 12:33:41 +0800 Subject: [PATCH 1/9] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96collapse=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/miaoCollapse.vue | 56 +++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/components/miaoCollapse.vue b/components/miaoCollapse.vue index 0c83650..b24cb49 100644 --- a/components/miaoCollapse.vue +++ b/components/miaoCollapse.vue @@ -15,9 +15,7 @@ const props = defineProps({ }) const cwRef = ref() const cRef = ref() -const cwStyle = ref<{ [key: string]: string | number }>({ - maxHeight: '99999vh', -}) +const cwStyle = ref<{ [key: string]: string | number }>({}) const cStyle = ref<{ [key: string]: string | number }>({}) let originHeight = -1 @@ -33,19 +31,28 @@ const clearTimer = () => { const handleHide = () => { clearTimer() + calcOriginHeight(); cwStyle.value = { - maxHeight: 0, - opacity: 0, + maxHeight: `${originHeight}px`, + opacity: 1, transition: "all 0.2s ease-in-out, opacity 0.1s ease-out", - pointerEvents: 'none', } timer.push(setTimeout(() => { cwStyle.value = { maxHeight: 0, - display: 'none', opacity: 0, + transition: "all 0.2s ease-in-out, opacity 0.1s ease-out", + pointerEvents: 'none', } - }, 300)) + timer.push(setTimeout(() => { + cwStyle.value = { + maxHeight: 0, + display: 'none', + opacity: 0, + pointerEvents: 'none', + } + }, 300)) + })) } const handleShow = () => { @@ -53,13 +60,31 @@ const handleShow = () => { cwStyle.value = { maxHeight: 0, opacity: 0, + pointerEvents: 'none', } timer.push(setTimeout(() => { + calcOriginHeight(); cwStyle.value = { - maxHeight: `${originHeight}px`, - opacity: 1, - transition: "all 0.2s ease-in-out, opacity 0.3s ease-in" + maxHeight: 0, + opacity: 0, + transition: "all 0.2s ease-in-out, opacity 0.3s ease-in", + pointerEvents: 'none', } + timer.push(setTimeout(() => { + cwStyle.value = { + maxHeight: `${originHeight}px`, + opacity: 1, + transition: "all 0.2s ease-in-out, opacity 0.3s ease-in" + } + timer.push(setTimeout(() => { + cwStyle.value = { + opacity: 1, + } + nextTick(() => { + calcOriginHeight() + }) + }, 300)) + })) })) } @@ -73,11 +98,12 @@ watch(() => props.show, (newVal) => { } }) +const calcOriginHeight = () => { + originHeight = cRef.value!.clientHeight +} + onMounted(() => { - originHeight = cwRef.value!.clientHeight - cwStyle.value = { - maxHeight: `${originHeight}px`, - } + calcOriginHeight() }) From 63206e71b8c5c2d6c96bc0695846c5b23c2d41b7 Mon Sep 17 00:00:00 2001 From: Miao_Spring <539943419@qq.com> Date: Mon, 20 Jan 2025 01:15:38 +0800 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96markdown=E6=B8=B2?= =?UTF-8?q?=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .node-version | 2 +- components/codeMirror.vue | 69 +++++++++++++ components/markdownRender.vue | 57 +++++++++-- package.json | 3 + pnpm-lock.yaml | 149 +++++++++++++++++++++++++++ utils/html2VNode.ts | 188 ++++++++++++++++++++++++++++++++++ 6 files changed, 460 insertions(+), 8 deletions(-) create mode 100644 components/codeMirror.vue create mode 100644 utils/html2VNode.ts diff --git a/.node-version b/.node-version index e8aa644..c12134b 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -v20.18.1 +v20.15.0 diff --git a/components/codeMirror.vue b/components/codeMirror.vue new file mode 100644 index 0000000..6b3f583 --- /dev/null +++ b/components/codeMirror.vue @@ -0,0 +1,69 @@ + + + + + \ No newline at end of file diff --git a/components/markdownRender.vue b/components/markdownRender.vue index d0a18b7..00c2759 100644 --- a/components/markdownRender.vue +++ b/components/markdownRender.vue @@ -2,12 +2,15 @@ - \ No newline at end of file diff --git a/package.json b/package.json index 52bf516..f132eac 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,13 @@ "postinstall": "nuxt prepare" }, "dependencies": { + "@codemirror/lang-javascript": "^6.2.2", + "@codemirror/state": "^6.5.1", "@pinia/nuxt": "^0.9.0", "@types/node": "^22.10.5", "bcryptjs": "^2.4.3", "better-sqlite3": "11.3.0", + "codemirror": "^6.0.1", "dayjs": "^1.11.13", "jsonwebtoken": "^9.0.2", "markdown-it": "^14.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a197e0b..9701c85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,12 @@ importers: .: dependencies: + '@codemirror/lang-javascript': + specifier: ^6.2.2 + version: 6.2.2 + '@codemirror/state': + specifier: ^6.5.1 + version: 6.5.1 '@pinia/nuxt': specifier: ^0.9.0 version: 0.9.0(magicast@0.3.5)(pinia@2.3.0(typescript@5.7.3)(vue@3.5.13(typescript@5.7.3)))(rollup@4.30.1) @@ -20,6 +26,9 @@ importers: better-sqlite3: specifier: 11.3.0 version: 11.3.0 + codemirror: + specifier: ^6.0.1 + version: 6.0.1 dayjs: specifier: ^1.11.13 version: 1.11.13 @@ -226,6 +235,30 @@ packages: resolution: {integrity: sha512-YLPHc8yASwjNkmcDMQMY35yiWjoKAKnhUbPRszBRS0YgH+IXtsMp61j+yTcnCE3oO2DgP0U3iejLC8FTtKDC8Q==} engines: {node: '>=16.13'} + '@codemirror/autocomplete@6.18.4': + resolution: {integrity: sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==} + + '@codemirror/commands@6.8.0': + resolution: {integrity: sha512-q8VPEFaEP4ikSlt6ZxjB3zW72+7osfAYW9i8Zu943uqbKuz6utc1+F170hyLUCUltXORjQXRyYQNfkckzA/bPQ==} + + '@codemirror/lang-javascript@6.2.2': + resolution: {integrity: sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==} + + '@codemirror/language@6.10.8': + resolution: {integrity: sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==} + + '@codemirror/lint@6.8.4': + resolution: {integrity: sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==} + + '@codemirror/search@6.5.8': + resolution: {integrity: sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==} + + '@codemirror/state@6.5.1': + resolution: {integrity: sha512-3rA9lcwciEB47ZevqvD8qgbzhM9qMb8vCcQCNmDfVRPQG4JT9mSb0Jg8H7YjKGGQcFnLN323fj9jdnG59Kx6bg==} + + '@codemirror/view@6.36.2': + resolution: {integrity: sha512-DZ6ONbs8qdJK0fdN7AB82CgI6tYXf4HWk1wSVa0+9bhVznCuuvhQtX8bFBoy3dv8rZSQqUd8GvhVAcielcidrA==} + '@ctrl/tinycolor@3.6.1': resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} engines: {node: '>=10'} @@ -576,11 +609,26 @@ packages: '@kwsites/promise-deferred@1.1.1': resolution: {integrity: sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==} + '@lezer/common@1.2.3': + resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} + + '@lezer/highlight@1.2.1': + resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==} + + '@lezer/javascript@1.4.21': + resolution: {integrity: sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==} + + '@lezer/lr@1.4.2': + resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==} + '@mapbox/node-pre-gyp@2.0.0-rc.0': resolution: {integrity: sha512-nhSMNprz3WmeRvd8iUs5JqkKr0Ncx46JtPxM3AhXes84XpSJfmIwKeWXRpsr53S7kqPkQfPhzrMFUxSNb23qSA==} engines: {node: '>=18'} hasBin: true + '@marijn/find-cluster-break@1.0.2': + resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + '@netlify/functions@2.8.2': resolution: {integrity: sha512-DeoAQh8LuNPvBE4qsKlezjKj0PyXDryOFJfJKo3Z1qZLKzQ21sT314KQKPVjfvw6knqijj+IO+0kHXy/TJiqNA==} engines: {node: '>=14.0.0'} @@ -1314,6 +1362,9 @@ packages: resolution: {integrity: sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==} engines: {node: '>=0.10.0'} + codemirror@6.0.1: + resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -1380,6 +1431,9 @@ packages: resolution: {integrity: sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==} engines: {node: '>= 14'} + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + croner@9.0.0: resolution: {integrity: sha512-onMB0OkDjkXunhdW9htFjEhqrD54+M94i6ackoUkjHKbRnXdyEyKRelp4nJ1kAz32+s27jP1FsebpJCVl0BsvA==} engines: {node: '>=18.0'} @@ -2954,6 +3008,9 @@ packages: strip-literal@2.1.1: resolution: {integrity: sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==} + style-mod@4.1.2: + resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} + stylehacks@7.0.4: resolution: {integrity: sha512-i4zfNrGMt9SB4xRK9L83rlsFCgdGANfeDAYacO1pkqcE7cRHPdWHwnKZVz7WY17Veq/FvyYsRAU++Ga+qDFIww==} engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} @@ -3411,6 +3468,9 @@ packages: typescript: optional: true + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + web-streams-polyfill@3.3.3: resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} engines: {node: '>= 8'} @@ -3698,6 +3758,61 @@ snapshots: dependencies: mime: 3.0.0 + '@codemirror/autocomplete@6.18.4': + dependencies: + '@codemirror/language': 6.10.8 + '@codemirror/state': 6.5.1 + '@codemirror/view': 6.36.2 + '@lezer/common': 1.2.3 + + '@codemirror/commands@6.8.0': + dependencies: + '@codemirror/language': 6.10.8 + '@codemirror/state': 6.5.1 + '@codemirror/view': 6.36.2 + '@lezer/common': 1.2.3 + + '@codemirror/lang-javascript@6.2.2': + dependencies: + '@codemirror/autocomplete': 6.18.4 + '@codemirror/language': 6.10.8 + '@codemirror/lint': 6.8.4 + '@codemirror/state': 6.5.1 + '@codemirror/view': 6.36.2 + '@lezer/common': 1.2.3 + '@lezer/javascript': 1.4.21 + + '@codemirror/language@6.10.8': + dependencies: + '@codemirror/state': 6.5.1 + '@codemirror/view': 6.36.2 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + style-mod: 4.1.2 + + '@codemirror/lint@6.8.4': + dependencies: + '@codemirror/state': 6.5.1 + '@codemirror/view': 6.36.2 + crelt: 1.0.6 + + '@codemirror/search@6.5.8': + dependencies: + '@codemirror/state': 6.5.1 + '@codemirror/view': 6.36.2 + crelt: 1.0.6 + + '@codemirror/state@6.5.1': + dependencies: + '@marijn/find-cluster-break': 1.0.2 + + '@codemirror/view@6.36.2': + dependencies: + '@codemirror/state': 6.5.1 + style-mod: 4.1.2 + w3c-keyname: 2.2.8 + '@ctrl/tinycolor@3.6.1': {} '@element-plus/icons-vue@2.3.1(vue@3.5.13(typescript@5.7.3))': @@ -3916,6 +4031,22 @@ snapshots: '@kwsites/promise-deferred@1.1.1': {} + '@lezer/common@1.2.3': {} + + '@lezer/highlight@1.2.1': + dependencies: + '@lezer/common': 1.2.3 + + '@lezer/javascript@1.4.21': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/lr@1.4.2': + dependencies: + '@lezer/common': 1.2.3 + '@mapbox/node-pre-gyp@2.0.0-rc.0': dependencies: consola: 3.3.3 @@ -3929,6 +4060,8 @@ snapshots: - encoding - supports-color + '@marijn/find-cluster-break@1.0.2': {} + '@netlify/functions@2.8.2': dependencies: '@netlify/serverless-functions-api': 1.26.1 @@ -4845,6 +4978,16 @@ snapshots: cluster-key-slot@1.1.2: {} + codemirror@6.0.1: + dependencies: + '@codemirror/autocomplete': 6.18.4 + '@codemirror/commands': 6.8.0 + '@codemirror/language': 6.10.8 + '@codemirror/lint': 6.8.4 + '@codemirror/search': 6.5.8 + '@codemirror/state': 6.5.1 + '@codemirror/view': 6.36.2 + color-convert@2.0.1: dependencies: color-name: 1.1.4 @@ -4896,6 +5039,8 @@ snapshots: crc-32: 1.2.2 readable-stream: 4.7.0 + crelt@1.0.6: {} + croner@9.0.0: {} cronstrue@2.52.0: {} @@ -6676,6 +6821,8 @@ snapshots: dependencies: js-tokens: 9.0.1 + style-mod@4.1.2: {} + stylehacks@7.0.4(postcss@8.4.49): dependencies: browserslist: 4.24.4 @@ -7119,6 +7266,8 @@ snapshots: optionalDependencies: typescript: 5.7.3 + w3c-keyname@2.2.8: {} + web-streams-polyfill@3.3.3: {} webidl-conversions@3.0.1: {} diff --git a/utils/html2VNode.ts b/utils/html2VNode.ts new file mode 100644 index 0000000..b73752a --- /dev/null +++ b/utils/html2VNode.ts @@ -0,0 +1,188 @@ +import type { VNode } from "vue"; + +// 未完成 +export default class Html2VNode { + private middlewareList: middlewareType[] = [] + + constructor() { + this.use(this.defaultMiddleware) + } + + public use(middleware: middlewareType) { + this.middlewareList.push(middleware) + } + public rander(htmlString: string) { + const html2ObjResult = this.html2Obj(htmlString); + const middlewareMap = this.buildMiddlewareMap(html2ObjResult); + const wrinklesResult = this.wrinkles(html2ObjResult) + const vnodes = this.rander2VNode(wrinklesResult, middlewareMap) + return vnodes; + } + + private buildMiddlewareMap(objs: (TagType | miaoVNodeType)[]) { + const tagNameSet = new Set() + const middlewareMap = new Map() + for (const item of objs) { + const { tagName = '' } = this.parseTag(item.tag); + tagNameSet.add(tagName) + } + for (const tagName of tagNameSet) { + for (const middleware of this.middlewareList) { + if (middleware.filter(tagName)) { + middlewareMap.set(tagName, middleware) + } + } + } + return middlewareMap; + } + + private rander2VNode = ( + wrinklesResult: (miaoVNodeType | string)[], + middlewareMap: Map + ): (VNode | string)[] => { + return wrinklesResult.map((item: miaoVNodeType | string): VNode | string => { + if (typeof item === 'string') { + return item; + } + const { tagName = '', tagAttrs } = this.parseTag(item.tag); + return middlewareMap.get(tagName)!.rander({ + item, tagName, tagAttrs, middlewareMap + }) + }) + } + + private defaultMiddleware: middlewareType = { + filter: (_: string) => { + return true; + }, + rander: ({ + item, tagName, tagAttrs, middlewareMap + }) => { + if (!tagName) { + return item.children as string; + } + let child: string | (string | VNode)[] = item.children as string + if (typeof item.children !== 'string') { + child = this.rander2VNode(item.children, middlewareMap) + } + return h(tagName ?? 'span', tagAttrs, child) + } + } + + private html2Obj = (htmlString: string) => { + const html2ObjResult: (TagType | miaoVNodeType)[] = [] + let currhtml = htmlString; + while (true) { + const nextTag = this.getNextHtmlTag(currhtml); + if (!nextTag) { + break; + } + const middleChild = currhtml.slice(0, nextTag.Index); + if (middleChild) { + html2ObjResult.push({ + tag: '', + children: middleChild, + // html: middleContent + }) + } + currhtml = currhtml.slice(nextTag.Index + nextTag.tag.length); + html2ObjResult.push(nextTag) + } + return html2ObjResult; + } + + private check = (html2ObjResult: (TagType | miaoVNodeType)[]) => { + const stack = [] + for (const item of html2ObjResult) { + if (!item.tag) { + continue; + } + // @ts-ignore + if (item?.isClose && item.isClose == true) { + const last = stack.pop(); + if (last !== this.parseTag(item.tag).tagName) { + return false; + } + } else { + stack.push(this.parseTag(item.tag).tagName) + } + } + return true; + } + + // 想必是flat的反义词吧 + private wrinkles = (target: (TagType | miaoVNodeType)[]) => { + const res: miaoVNodeType[] = [] + const resStack = [res] + for (const item of target) { + if (!item.tag) { + // @ts-ignore + resStack[resStack.length - 1].push(item) + // @ts-ignore + } else if (item.isClose) { + resStack.pop() + } else { + const _childRes: any = [] + resStack[resStack.length - 1].push({ + tag: item.tag, + // tag: this.getTagName(item.tag), + children: _childRes, + }) + resStack.push(_childRes) + } + } + return res; + } + + private getNextHtmlTag = (htmlString: string): { + tag: string, + Index: number, + isClose: boolean + } | null => { + let startIndex = 0; + let tagRegex = /<("[^"]*"|'[^']*'|[^'">])*>/; + let tagMatch = tagRegex.exec(htmlString.slice(startIndex)); + if (tagMatch) { + const isClose = tagMatch[0].startsWith(' { + const tagStr = tag.replace(/<\s*\/*\s*|\s*>/g, ''); + const tagArr = tagStr.split(' ').filter(item => item.trim()); + const tagName = tagArr.shift(); + const tagAttrs = tagArr.map(v => v.trim().split('=')).reduce((pre, cur) => { + pre[cur[0]] = cur[1]; + return pre; + }, {} as { [key: string]: string }) + return { tagName, tagAttrs }; + } +} + +type miaoVNodeType = { + tag: string, + children: string | miaoVNodeType[], +} + +type TagType = { + tag: string; + Index: number; + isClose: boolean; +} + +export type middlewareType = { + filter: (tagName: string) => boolean, + rander: (option: { + item: miaoVNodeType, + tagName: string, + tagAttrs: { [key: string]: string }, + middlewareMap: Map + } + ) => VNode | string +} \ No newline at end of file From 72ba1691fbcf0285733f224b151df083757e7fab Mon Sep 17 00:00:00 2001 From: Miao_Spring <539943419@qq.com> Date: Mon, 20 Jan 2025 23:42:33 +0800 Subject: [PATCH 3/9] =?UTF-8?q?md=E6=B7=BB=E5=8A=A0hightlight=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/codeMirror.vue | 103 ++++++++++++++-- components/markdownRender.vue | 15 ++- components/miaoCollapse.vue | 4 +- package.json | 9 ++ pnpm-lock.yaml | 224 ++++++++++++++++++++++++++++++++++ utils/html2VNode.ts | 60 +++++++-- 6 files changed, 391 insertions(+), 24 deletions(-) diff --git a/components/codeMirror.vue b/components/codeMirror.vue index 6b3f583..961c932 100644 --- a/components/codeMirror.vue +++ b/components/codeMirror.vue @@ -12,6 +12,7 @@
+
@@ -23,29 +24,116 @@ import { EditorState } from "@codemirror/state" // import {javascript} from "@codemirror/lang-javascript" const props = defineProps<{ - data: string + data: string, + type?: string, }>() const show = ref(true) const cmRootRef = ref() -onMounted(() => { - if (!cmRootRef.value) { - return +const isLoading = ref(true) + +const rows = computed(() => { + if (!props.data) { + return 5 } - new EditorView({ + const lines = props.data.split('\n') + console.log({ + L: lines.length, + }) + return lines.length - 2 > 0 ? lines.length - 2 : 1 +}) + +const useLangExtensions = async () => { + const ext = props.type + switch (ext) { + case 'js': + case 'jsx': + case 'ts': + case 'tsx': + const { javascript } = await import('@codemirror/lang-javascript') + return [ + javascript({ + jsx: ext.substring(2, 3) === 'x', + typescript: ext.substring(0, 2) === 'js' + }) + ] + break + case 'css': + case 'scss': + const { sass } = await import('@codemirror/lang-sass') + return [sass()] + break + case 'html': + const { html } = await import('@codemirror/lang-html') + return [html()] + break + case 'py': + const { python } = await import('@codemirror/lang-python') + return [python()] + break + case 'go': + const { go } = await import('@codemirror/lang-go') + return [go()] + break + case 'json': + const { json } = await import('@codemirror/lang-json') + return [json()] + break + case 'md': + const { markdown } = await import('@codemirror/lang-markdown') + return [markdown()] + break + case 'yaml': + const { yaml } = await import('@codemirror/lang-yaml') + return [yaml()] + break + case 'vue': + const { vue } = await import('@codemirror/lang-vue') + return [vue()] + break + case 'xml': + const { xml } = await import('@codemirror/lang-xml') + return [xml()] + break + default: + return [] + } +} + +let cm: EditorView + +onMounted(async () => { + const langExtensions = await useLangExtensions() + cm = new EditorView({ parent: cmRootRef.value, doc: props.data, extensions: [ basicSetup, EditorState.readOnly.of(true), + ...langExtensions ], }) + isLoading.value = false +}) + +onUpdated(() => { + cm.dispatch({ + changes: { + from: 0, + to: cm.state.doc.length, + insert: props.data, + }, + }) +}) + +onBeforeUnmount(() => { + cm.destroy() }) - \ No newline at end of file diff --git a/package.json b/package.json index 876493d..57a7e3e 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "codemirror": "^6.0.1", "dayjs": "^1.11.13", "jsonwebtoken": "^9.0.2", + "jsqr": "^1.4.0", "markdown-it": "^14.1.0", "node-fetch": "^3.3.2", "nuxt": "^3.15.1", diff --git a/pages/tools/QRScanner.vue b/pages/tools/QRScanner.vue new file mode 100644 index 0000000..d17bce2 --- /dev/null +++ b/pages/tools/QRScanner.vue @@ -0,0 +1,19 @@ + + + + + \ No newline at end of file diff --git a/pages/tools/fucksq.vue b/pages/tools/fucksq.vue index 187ba6a..b901460 100644 --- a/pages/tools/fucksq.vue +++ b/pages/tools/fucksq.vue @@ -4,11 +4,17 @@
- + + + + 扫码 + @@ -35,15 +41,22 @@
+
+ +
- \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4626b9e..202a4f4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,9 @@ importers: jsonwebtoken: specifier: ^9.0.2 version: 9.0.2 + jsqr: + specifier: ^1.4.0 + version: 1.4.0 markdown-it: specifier: ^14.1.0 version: 14.1.0 @@ -2174,6 +2177,9 @@ packages: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} + jsqr@1.4.0: + resolution: {integrity: sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==} + jwa@1.4.1: resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} @@ -5944,6 +5950,8 @@ snapshots: ms: 2.1.3 semver: 7.6.3 + jsqr@1.4.0: {} + jwa@1.4.1: dependencies: buffer-equal-constant-time: 1.0.1 From f3af29f04cf812271f05a24f008b47bed16cf06b Mon Sep 17 00:00:00 2001 From: Miao_Spring <539943419@qq.com> Date: Tue, 21 Jan 2025 14:27:46 +0800 Subject: [PATCH 5/9] =?UTF-8?q?style:=20=E4=BC=98=E5=8C=96=E5=88=B7?= =?UTF-8?q?=E8=B5=9E=E6=89=AB=E7=A0=81=E7=9A=84=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/miaoQRScanner.vue | 7 +- nuxt.config.ts | 8 +- package.json | 3 +- pages/tools/fucksq.vue | 3 +- pnpm-lock.yaml | 221 +++++++++++++++++++++++++++++++++++ 5 files changed, 235 insertions(+), 7 deletions(-) diff --git a/components/miaoQRScanner.vue b/components/miaoQRScanner.vue index b359133..858bdce 100644 --- a/components/miaoQRScanner.vue +++ b/components/miaoQRScanner.vue @@ -1,7 +1,7 @@ @@ -13,7 +13,7 @@ const emit = defineEmits<{ }>() const scannerDisplayRef = ref() -const testCtx = ref() +// const testCtx = ref() const result = reactive([]) let stream: MediaStream | null = null @@ -75,6 +75,7 @@ onMounted(async () => { } if (stream) { scannerDisplayRef.value!.srcObject = stream + scannerDisplayRef.value!.play() const videoTrack = stream.getVideoTracks()[0] handleVideoTrack(videoTrack) } diff --git a/nuxt.config.ts b/nuxt.config.ts index 38c12b3..b6c9f02 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -1,6 +1,8 @@ // import AutoImport from "unplugin-auto-import/vite"; // import Components from "unplugin-vue-components/vite"; // import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' +import mkcert from "vite-plugin-mkcert"; + // https://nuxt.com/docs/api/configuration/nuxt-config // @ts-ignore @@ -16,8 +18,10 @@ export default defineNuxtConfig({ } }, vite: { - server: {}, - plugins: [], + server: { + https: true, + }, + plugins: [mkcert()], }, modules: ["@pinia/nuxt", '@element-plus/nuxt'], compatibilityDate: "2025-01-12", diff --git a/package.json b/package.json index 57a7e3e..2d27d18 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "@types/jsonwebtoken": "^9.0.7", "@types/markdown-it": "^14.1.2", "element-plus": "^2.9.3", - "sass": "^1.83.1" + "sass": "^1.83.1", + "vite-plugin-mkcert": "^1.17.6" }, "packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a" } diff --git a/pages/tools/fucksq.vue b/pages/tools/fucksq.vue index b901460..6dd13b4 100644 --- a/pages/tools/fucksq.vue +++ b/pages/tools/fucksq.vue @@ -207,8 +207,9 @@ watchEffect(() => { display: flex; justify-content: center; align-items: center; + z-index: 3000; &-scanner { - width: 80%; + // width: 80%; height: 80%; object-fit: contain; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 202a4f4..2a5b23f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,6 +111,9 @@ importers: sass: specifier: ^1.83.1 version: 1.83.1 + vite-plugin-mkcert: + specifier: ^1.17.6 + version: 1.17.6(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass@1.83.1)(terser@5.37.0)(yaml@2.7.0)) packages: @@ -777,6 +780,58 @@ packages: peerDependencies: vue: ^3.3.4 + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + + '@octokit/core@5.2.0': + resolution: {integrity: sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==} + engines: {node: '>= 18'} + + '@octokit/endpoint@9.0.5': + resolution: {integrity: sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==} + engines: {node: '>= 18'} + + '@octokit/graphql@7.1.0': + resolution: {integrity: sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==} + engines: {node: '>= 18'} + + '@octokit/openapi-types@23.0.1': + resolution: {integrity: sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==} + + '@octokit/plugin-paginate-rest@11.3.1': + resolution: {integrity: sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/plugin-request-log@4.0.1': + resolution: {integrity: sha512-GihNqNpGHorUrO7Qa9JbAl0dbLnqJVrV8OXe2Zm5/Y4wFkZQDfTreBzVmiRfJVfE4mClXdihHnbpyyO9FSX4HA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/plugin-rest-endpoint-methods@13.2.2': + resolution: {integrity: sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': ^5 + + '@octokit/request-error@5.1.0': + resolution: {integrity: sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==} + engines: {node: '>= 18'} + + '@octokit/request@8.4.0': + resolution: {integrity: sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==} + engines: {node: '>= 18'} + + '@octokit/rest@20.1.1': + resolution: {integrity: sha512-MB4AYDsM5jhIHro/dq4ix1iWTLGToIGk6cWF5L6vanFaMble5jTX/UBQyiv05HsWnwUtY8JrfHy2LWfKwihqMw==} + engines: {node: '>= 18'} + + '@octokit/types@13.7.0': + resolution: {integrity: sha512-BXfRP+3P3IN6fd4uF3SniaHKOO4UXWBfkdR3vA8mIvaoO/wLjGN5qivUtW0QRitBHHMcfC41SLhNVYIZZE+wkA==} + '@parcel/watcher-android-arm64@2.5.0': resolution: {integrity: sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==} engines: {node: '>= 10.0.0'} @@ -1314,6 +1369,9 @@ packages: async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + autoprefixer@10.4.20: resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} @@ -1321,6 +1379,9 @@ packages: peerDependencies: postcss: ^8.1.0 + axios@1.7.9: + resolution: {integrity: sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==} + b4a@1.6.7: resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} @@ -1336,6 +1397,9 @@ packages: bcryptjs@2.4.3: resolution: {integrity: sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==} + before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + better-sqlite3@11.3.0: resolution: {integrity: sha512-iHt9j8NPYF3oKCNOO5ZI4JwThjt3Z6J6XrcwG85VNMVzv1ByqrHWv5VILEbCMFWDsoHhXvQ7oC8vgRXFAKgl9w==} @@ -1465,6 +1529,10 @@ packages: colorette@1.4.0: resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -1662,6 +1730,10 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + denque@2.1.0: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} @@ -1670,6 +1742,9 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + destr@2.0.3: resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} @@ -1860,10 +1935,23 @@ packages: flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + foreground-child@3.3.0: resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} engines: {node: '>=14'} + form-data@4.0.1: + resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} + engines: {node: '>= 6'} + formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} @@ -2315,6 +2403,14 @@ packages: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mime@1.6.0: resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} engines: {node: '>=4'} @@ -2838,6 +2934,9 @@ packages: protocols@2.0.1: resolution: {integrity: sha512-/XJ368cyBJ7fzLMwLKv1e4vLxOju2MNAIokcr7meSaNcVbWz/CPcW22cP04mwxOErdA5mwjA8Q6w/cdAQxVn7Q==} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -3237,6 +3336,9 @@ packages: unimport@3.14.5: resolution: {integrity: sha512-tn890SwFFZxqaJSKQPPd+yygfKSATbM8BZWW1aCR2TJBTs1SDrmLamBueaFtYsGjHtQaRgqEbQflOjN2iW12gA==} + universal-user-agent@6.0.1: + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -3428,6 +3530,12 @@ packages: '@nuxt/kit': optional: true + vite-plugin-mkcert@1.17.6: + resolution: {integrity: sha512-4JR1RN0HEg/w17eRQJ/Ve2pSa6KCVQcQO6yKtIaKQCFDyd63zGfXHWpygBkvvRSpqa0GcqNKf0fjUJ0HiJQXVQ==} + engines: {node: '>=v16.7.0'} + peerDependencies: + vite: '>=3' + vite-plugin-vue-inspector@5.3.1: resolution: {integrity: sha512-cBk172kZKTdvGpJuzCCLg8lJ909wopwsu3Ve9FsL1XsnLBiRT9U3MePcqrgGHgCX2ZgkqZmAGR8taxw+TV6s7A==} peerDependencies: @@ -4501,6 +4609,69 @@ snapshots: - vue-tsc - yaml + '@octokit/auth-token@4.0.0': {} + + '@octokit/core@5.2.0': + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.1.0 + '@octokit/request': 8.4.0 + '@octokit/request-error': 5.1.0 + '@octokit/types': 13.7.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.1 + + '@octokit/endpoint@9.0.5': + dependencies: + '@octokit/types': 13.7.0 + universal-user-agent: 6.0.1 + + '@octokit/graphql@7.1.0': + dependencies: + '@octokit/request': 8.4.0 + '@octokit/types': 13.7.0 + universal-user-agent: 6.0.1 + + '@octokit/openapi-types@23.0.1': {} + + '@octokit/plugin-paginate-rest@11.3.1(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 13.7.0 + + '@octokit/plugin-request-log@4.0.1(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + + '@octokit/plugin-rest-endpoint-methods@13.2.2(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 13.7.0 + + '@octokit/request-error@5.1.0': + dependencies: + '@octokit/types': 13.7.0 + deprecation: 2.3.1 + once: 1.4.0 + + '@octokit/request@8.4.0': + dependencies: + '@octokit/endpoint': 9.0.5 + '@octokit/request-error': 5.1.0 + '@octokit/types': 13.7.0 + universal-user-agent: 6.0.1 + + '@octokit/rest@20.1.1': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/plugin-paginate-rest': 11.3.1(@octokit/core@5.2.0) + '@octokit/plugin-request-log': 4.0.1(@octokit/core@5.2.0) + '@octokit/plugin-rest-endpoint-methods': 13.2.2(@octokit/core@5.2.0) + + '@octokit/types@13.7.0': + dependencies: + '@octokit/openapi-types': 23.0.1 + '@parcel/watcher-android-arm64@2.5.0': optional: true @@ -5051,6 +5222,8 @@ snapshots: async@3.2.6: {} + asynckit@0.4.0: {} + autoprefixer@10.4.20(postcss@8.4.49): dependencies: browserslist: 4.24.4 @@ -5061,6 +5234,14 @@ snapshots: postcss: 8.4.49 postcss-value-parser: 4.2.0 + axios@1.7.9(debug@4.4.0): + dependencies: + follow-redirects: 1.15.9(debug@4.4.0) + form-data: 4.0.1 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + b4a@1.6.7: {} balanced-match@1.0.2: {} @@ -5072,6 +5253,8 @@ snapshots: bcryptjs@2.4.3: {} + before-after-hook@2.2.3: {} + better-sqlite3@11.3.0: dependencies: bindings: 1.5.0 @@ -5228,6 +5411,10 @@ snapshots: colorette@1.4.0: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@2.20.3: {} commander@7.2.0: {} @@ -5400,10 +5587,14 @@ snapshots: defu@6.1.4: {} + delayed-stream@1.0.0: {} + denque@2.1.0: {} depd@2.0.0: {} + deprecation@2.3.1: {} + destr@2.0.3: {} destroy@1.2.0: {} @@ -5638,11 +5829,21 @@ snapshots: flatted@3.3.2: {} + follow-redirects@1.15.9(debug@4.4.0): + optionalDependencies: + debug: 4.4.0(supports-color@9.4.0) + foreground-child@3.3.0: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data@4.0.1: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + formdata-polyfill@4.0.10: dependencies: fetch-blob: 3.2.0 @@ -6094,6 +6295,12 @@ snapshots: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mime@1.6.0: {} mime@3.0.0: {} @@ -6764,6 +6971,8 @@ snapshots: protocols@2.0.1: {} + proxy-from-env@1.1.0: {} + pump@3.0.2: dependencies: end-of-stream: 1.4.4 @@ -7221,6 +7430,8 @@ snapshots: transitivePeerDependencies: - rollup + universal-user-agent@6.0.1: {} + universalify@2.0.1: {} unplugin-auto-import@19.0.0(@nuxt/kit@3.15.1(magicast@0.3.5)(rollup@4.30.1))(@vueuse/core@9.13.0(vue@3.5.13(typescript@5.7.3)))(rollup@4.30.1): @@ -7411,6 +7622,16 @@ snapshots: - rollup - supports-color + vite-plugin-mkcert@1.17.6(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass@1.83.1)(terser@5.37.0)(yaml@2.7.0)): + dependencies: + '@octokit/rest': 20.1.1 + axios: 1.7.9(debug@4.4.0) + debug: 4.4.0(supports-color@9.4.0) + picocolors: 1.1.1 + vite: 6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass@1.83.1)(terser@5.37.0)(yaml@2.7.0) + transitivePeerDependencies: + - supports-color + vite-plugin-vue-inspector@5.3.1(vite@6.0.7(@types/node@22.10.5)(jiti@2.4.2)(sass@1.83.1)(terser@5.37.0)(yaml@2.7.0)): dependencies: '@babel/core': 7.26.0 From f8fba79d550988ee6489840eef44171bdfebe37c Mon Sep 17 00:00:00 2001 From: Miao_Spring <539943419@qq.com> Date: Tue, 21 Jan 2025 19:14:40 +0800 Subject: [PATCH 6/9] =?UTF-8?q?feat:=20=E5=88=B7=E8=B5=9E=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=9B=BE=E7=89=87=E8=AF=86=E5=88=AB=E4=BA=8C=E7=BB=B4?= =?UTF-8?q?=E7=A0=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- components/miaoQRScanner.vue | 23 ++++---- pages/tools/fucksq.vue | 69 ++++++++++++++++------- utils/filePicker.ts | 105 +++++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+), 32 deletions(-) create mode 100644 utils/filePicker.ts diff --git a/.gitignore b/.gitignore index ea8ee76..fd3777d 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,6 @@ logs .pnpm-lock.yaml -userData \ No newline at end of file +userData + +test/* \ No newline at end of file diff --git a/components/miaoQRScanner.vue b/components/miaoQRScanner.vue index 858bdce..bd60dc0 100644 --- a/components/miaoQRScanner.vue +++ b/components/miaoQRScanner.vue @@ -42,18 +42,17 @@ const handleVideoTrack = (track: MediaStreamTrack) => { let errCount = 0 // @ts-ignore const imageCapture = new ImageCapture(track) - timer = setInterval(() => { + timer = setInterval(async () => { try { - imageCapture.grabFrame().then((videoFrame: VideoFrame) => { - const data = getQRData(videoFrame) - if (data &&!scannerResult.has(data)) { - console.log(data) - scannerResult.add(data) - result.push(data) - emit('onResult', data) - } - videoFrame.close() - }) + const videoFrame = await imageCapture.grabFrame() + const data = getQRData(videoFrame) + if (data && !scannerResult.has(data)) { + console.log(data) + scannerResult.add(data) + result.push(data) + emit('onResult', data) + } + videoFrame.close() } catch (e) { errCount++ if (errCount > 10) { @@ -96,6 +95,8 @@ onBeforeUnmount(() => { video { height: inherit; width: inherit; + max-height: inherit; + max-width: inherit; object-fit: contain; } } diff --git a/pages/tools/fucksq.vue b/pages/tools/fucksq.vue index 6dd13b4..faf7c60 100644 --- a/pages/tools/fucksq.vue +++ b/pages/tools/fucksq.vue @@ -4,14 +4,14 @@
- + - + 扫码 @@ -22,11 +22,12 @@ - 开始 + 开始 - 清空输出 + 清空输出
@@ -48,8 +49,11 @@ + + \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2a5b23f..19389f6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -50,6 +50,9 @@ importers: pinia: specifier: ^2.3.0 version: 2.3.0(typescript@5.7.3)(vue@3.5.13(typescript@5.7.3)) + qrcode: + specifier: ^1.5.4 + version: 1.5.4 unplugin-auto-import: specifier: ^19.0.0 version: 19.0.0(@nuxt/kit@3.15.1(magicast@0.3.5)(rollup@4.30.1))(@vueuse/core@9.13.0(vue@3.5.13(typescript@5.7.3)))(rollup@4.30.1) @@ -105,6 +108,9 @@ importers: '@types/markdown-it': specifier: ^14.1.2 version: 14.1.2 + '@types/qrcode': + specifier: ^1.5.5 + version: 1.5.5 element-plus: specifier: ^2.9.3 version: 2.9.3(vue@3.5.13(typescript@5.7.3)) @@ -1172,6 +1178,9 @@ packages: '@types/parse-path@7.0.3': resolution: {integrity: sha512-LriObC2+KYZD3FzCrgWGv/qufdUy4eXrxcLgQMfYXgPbLIecKIsVBaQgUPmxSSLcjmYbDTQbMgr6qr6l/eb7Bg==} + '@types/qrcode@1.5.5': + resolution: {integrity: sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg==} + '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} @@ -1466,6 +1475,10 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} @@ -1505,6 +1518,9 @@ packages: resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} engines: {node: '>=18'} + cliui@6.0.0: + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -1699,6 +1715,10 @@ packages: supports-color: optional: true + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -1768,6 +1788,9 @@ packages: resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==} engines: {node: '>=0.3.1'} + dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -1932,6 +1955,10 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} @@ -2310,6 +2337,10 @@ packages: resolution: {integrity: sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==} engines: {node: '>=14'} + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} @@ -2647,6 +2678,18 @@ packages: peerDependencies: typescript: ^5.x + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -2675,6 +2718,10 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -2734,6 +2781,10 @@ packages: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} + pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + postcss-calc@10.1.0: resolution: {integrity: sha512-uQ/LDGsf3mgsSUEXmAt3VsCSHR3aKqtEIkmB+4PhzYwRYOW5MZs/GhCCFpsOtJJkP6EC6uGipbrnaTjqaJZcJw==} engines: {node: ^18.12 || ^20.9 || >=22.0} @@ -2944,6 +2995,11 @@ packages: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} + qrcode@1.5.4: + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} + hasBin: true + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -3005,6 +3061,9 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} + require-main-filename@2.0.0: + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} @@ -3087,6 +3146,9 @@ packages: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} + set-blocking@2.0.0: + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -3682,6 +3744,9 @@ packages: whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-module@2.0.1: + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3692,6 +3757,10 @@ packages: engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} hasBin: true + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -3715,6 +3784,9 @@ packages: utf-8-validate: optional: true + y18n@4.0.3: + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -3737,10 +3809,18 @@ packages: engines: {node: '>= 14'} hasBin: true + yargs-parser@18.1.3: + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} + yargs@15.4.1: + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} + yargs@17.7.2: resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} engines: {node: '>=12'} @@ -4939,6 +5019,10 @@ snapshots: '@types/parse-path@7.0.3': {} + '@types/qrcode@1.5.5': + dependencies: + '@types/node': 22.10.5 + '@types/resolve@1.20.2': {} '@types/web-bluetooth@0.0.16': {} @@ -5335,6 +5419,8 @@ snapshots: cac@6.7.14: {} + camelcase@5.3.1: {} + caniuse-api@3.0.0: dependencies: browserslist: 4.24.4 @@ -5383,6 +5469,12 @@ snapshots: is-wsl: 3.1.0 is64bit: 2.0.0 + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + cliui@8.0.1: dependencies: string-width: 4.2.3 @@ -5566,6 +5658,8 @@ snapshots: optionalDependencies: supports-color: 9.4.0 + decamelize@1.2.0: {} + decompress-response@6.0.0: dependencies: mimic-response: 3.1.0 @@ -5607,6 +5701,8 @@ snapshots: diff@7.0.0: {} + dijkstrajs@1.0.3: {} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -5827,6 +5923,11 @@ snapshots: dependencies: to-regex-range: 5.0.1 + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + flatted@3.3.2: {} follow-redirects@1.15.9(debug@4.4.0): @@ -6213,6 +6314,10 @@ snapshots: mlly: 1.7.4 pkg-types: 1.3.0 + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + lodash-es@4.17.21: {} lodash-unified@1.0.3(@types/lodash-es@4.17.12)(lodash-es@4.17.21)(lodash@4.17.21): @@ -6703,6 +6808,16 @@ snapshots: transitivePeerDependencies: - encoding + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} package-manager-detector@0.2.8: {} @@ -6731,6 +6846,8 @@ snapshots: parseurl@1.3.3: {} + path-exists@4.0.0: {} + path-is-absolute@1.0.1: {} path-key@3.1.1: {} @@ -6776,6 +6893,8 @@ snapshots: pluralize@8.0.0: {} + pngjs@5.0.0: {} + postcss-calc@10.1.0(postcss@8.4.49): dependencies: postcss: 8.4.49 @@ -6980,6 +7099,12 @@ snapshots: punycode.js@2.3.1: {} + qrcode@1.5.4: + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + queue-microtask@1.2.3: {} queue-tick@1.0.1: {} @@ -7048,6 +7173,8 @@ snapshots: require-from-string@2.0.2: {} + require-main-filename@2.0.0: {} + resolve-from@5.0.0: {} resolve@1.22.10: @@ -7157,6 +7284,8 @@ snapshots: transitivePeerDependencies: - supports-color + set-blocking@2.0.0: {} + setprototypeof@1.2.0: {} shebang-command@2.0.0: @@ -7732,6 +7861,8 @@ snapshots: tr46: 0.0.3 webidl-conversions: 3.0.1 + which-module@2.0.1: {} + which@2.0.2: dependencies: isexe: 2.0.0 @@ -7740,6 +7871,12 @@ snapshots: dependencies: isexe: 2.0.0 + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 @@ -7756,6 +7893,8 @@ snapshots: ws@8.18.0: {} + y18n@4.0.3: {} + y18n@5.0.8: {} yallist@3.1.1: {} @@ -7768,8 +7907,27 @@ snapshots: yaml@2.7.0: {} + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + yargs-parser@21.1.1: {} + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + yargs@17.7.2: dependencies: cliui: 8.0.1 diff --git a/server/api/posts/getPostContent.ts b/server/api/posts/getPostContent.ts index b8a090b..d9bbdef 100644 --- a/server/api/posts/getPostContent.ts +++ b/server/api/posts/getPostContent.ts @@ -1,5 +1,4 @@ // @ts-ignore -import testData from "~/public/testData/test.md" import DB from 'better-sqlite3'; import { postItem } from "~/types/post"; diff --git a/server/api/tools/imgBed/download/[hash].ts b/server/api/tools/imgBed/download/[hash].ts new file mode 100644 index 0000000..cd744a9 --- /dev/null +++ b/server/api/tools/imgBed/download/[hash].ts @@ -0,0 +1,39 @@ +// @ts-ignore +import DB from 'better-sqlite3'; +import { defineEventHandler, getRouterParam } from 'h3'; +import fs from 'fs'; +import { sendStream } from 'h3'; + +export default defineEventHandler(async (event) => { + try { + const hash = getRouterParam(event, 'hash'); + if (!hash) { + return { code: 400, msg: 'Invalid hash parameter' }; + } + const db = new DB('./userData/db/imgBed.db'); + // 从数据库中查询文件信息 + const fileInfo = db.prepare(` + SELECT name, expire FROM imgBed WHERE hash =? + `).get(hash) as { name: string, expire: number }; + db.close(); + + if (!fileInfo) { + return { code: 404, msg: 'File not found' }; + } + + const fileName = fileInfo.name; + const filePath = `./userData/imgBed/${hash}`; + // 检查文件是否存在 + if (!fs.existsSync(filePath)) { + return { code: 404, msg: 'File not found on disk' }; + } + const fileStream = fs.createReadStream(filePath); + + setResponseHeader(event, 'Content-Disposition', `attachment; filename="${fileName}"`); + // 发送文件流 + return sendStream(event, fileStream); + } catch (error) { + console.error(error); + return { code: 500, msg: 'Internal Server Error' }; + } +}); \ No newline at end of file diff --git a/server/api/tools/imgBed/upload.ts b/server/api/tools/imgBed/upload.ts new file mode 100644 index 0000000..e2de398 --- /dev/null +++ b/server/api/tools/imgBed/upload.ts @@ -0,0 +1,39 @@ +// @ts-ignore +import DB from 'better-sqlite3'; +import { defineEventHandler, readBody } from 'h3'; +import crypto from 'crypto'; +import fs from 'fs'; + +export default defineEventHandler(async (event) => { + try { + const data = await readFormData(event) + const file = data.get('file') as File + const expire = data.get('expire') as string + console.log({ + file: file.name, + expire, + }) + const fileBuffer = Buffer.from(await file.arrayBuffer()); + // 计算文件的 MD5 哈希值 + const hash = crypto.createHash('md5').update(fileBuffer).digest('hex'); + const fileName = file.name; + const filePath = `./userData/imgBed/${hash}`; + // 将文件写入磁盘 + await fs.promises.writeFile(filePath, fileBuffer); + // 获取文件大小 + const fileSize = fileBuffer.length; + + const db = new DB('./userData/db/imgBed.db'); + // 插入数据到数据库 + db.prepare(` + INSERT INTO imgBed (name, hash, size, expire) + VALUES (?,?,?,?) + `).run([fileName, hash, fileSize, expire]); + db.close(); + + return { code: 200, hash, fileName, fileSize, expire: Number(expire) + Date.now() }; + } catch (error) { + console.error(error); + return { code: 500, msg: 'Internal Server Error' }; + } +}); \ No newline at end of file diff --git a/server/middleware/auth.ts b/server/middleware/auth.ts index 810cc93..0258cfa 100644 --- a/server/middleware/auth.ts +++ b/server/middleware/auth.ts @@ -7,12 +7,10 @@ const pathNeedAuth = serverConfig.auth.api export default defineEventHandler(async (event) => { const path = getRequestURL(event).pathname - // console.log(path) if (pathNeedAuth.has(path)) { const key = getKey() // @ts-ignore const authHeader = event.headers.get('authorization'); - // console.log(authHeader) if (!authHeader || !authHeader.startsWith('Bearer ')) { throw createError({ statusCode: 401, statusMessage: 'Unauthorized' }) } @@ -20,7 +18,6 @@ export default defineEventHandler(async (event) => { try { const decoded = jwt.verify(token, key) as { userId: number, password: string, username: string, exp: number } if (decoded.exp > Date.now()) { - // console.log('token expired') throw createError({ statusCode: 401, statusMessage: 'Token invalid or expired', data: { err: 'token expired', token } }) } // console.log(decoded) diff --git a/server/utils/initUserData.ts b/server/utils/initUserData.ts index 0b59e65..8c91e74 100644 --- a/server/utils/initUserData.ts +++ b/server/utils/initUserData.ts @@ -1,5 +1,6 @@ import mkfileIfNotExist from "./mkfileIfNotExist" -import db from 'better-sqlite3' +import DB from 'better-sqlite3' +import fs from 'fs' let checked = false @@ -14,6 +15,7 @@ function checkUserData() { const dirList = [ './userData/', './userData/db/', + './userData/imgBed/', ] dirList.forEach(mkdirIfNotExist) @@ -24,9 +26,14 @@ function checkUserData() { } function createDB() { - const userDB = new db('./userData/db/user.db'); - const postsDB = new db('./userData/db/posts.db'); + createUserDB(); + createPostsDB(); + createImgBedDB(); +} + +const createUserDB = () => { + const userDB = new DB('./userData/db/user.db'); userDB.exec(` CREATE TABLE IF NOT EXISTS user ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -36,7 +43,11 @@ function createDB() { lastLoginTime INTEGER NOT NULL ); `); + userDB.close(); +} +const createPostsDB = () => { + const postsDB = new DB('./userData/db/posts.db'); postsDB.exec(` CREATE TABLE IF NOT EXISTS posts ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -49,14 +60,12 @@ function createDB() { FOREIGN KEY(tag_id) REFERENCES tags(id) ); `); - postsDB.exec(` CREATE TABLE IF NOT EXISTS postContent ( id INTEGER PRIMARY KEY AUTOINCREMENT, content TEXT NOT NULL ); `); - postsDB.exec(` CREATE TABLE IF NOT EXISTS tags ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -77,9 +86,56 @@ function createDB() { tag15 TEXT ); `); - postsDB.close(); - userDB.close(); } +const createImgBedDB = () => { + const imgBedDB = new DB('./userData/db/imgBed.db'); + imgBedDB.exec(` + CREATE TABLE IF NOT EXISTS imgBed ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + hash TEXT NOT NULL, + size INTEGER NOT NULL, + expire INTEGER NOT NULL + ); + `); + imgBedDB.close(); + setInterval(cleanExpiredFiles_imgBed, 1000 * 30 * 60 ); + // cleanExpiredFiles_imgBed() +} + +const cleanExpiredFiles_imgBed = async () => { + try { + const db = new DB('./userData/db/imgBed.db'); + const currentTime = Date.now(); + // 从数据库中查询过期文件的哈希 + const expiredFiles = db.prepare(` + SELECT hash FROM imgBed WHERE expire Date: Wed, 22 Jan 2025 11:21:53 +0800 Subject: [PATCH 8/9] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BA=86=E5=9B=BE?= =?UTF-8?q?=E5=BA=8A=E6=97=A0=E6=B3=95=E6=AD=A3=E7=A1=AE=E6=B8=85=E7=90=86?= =?UTF-8?q?=E8=BF=87=E6=9C=9F=E6=95=B0=E6=8D=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/utils/initUserData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/utils/initUserData.ts b/server/utils/initUserData.ts index 8c91e74..2673224 100644 --- a/server/utils/initUserData.ts +++ b/server/utils/initUserData.ts @@ -119,7 +119,7 @@ const cleanExpiredFiles_imgBed = async () => { for (const file of expiredFiles) { const hash = file.hash; - const filePath = useRuntimeConfig().public.userDataPath + `/imgBed/${hash}`; + const filePath = `./userData/imgBed/${hash}`; // 检查文件是否存在 if (fs.existsSync(filePath)) { // 删除文件 From 46b1da589f5d9aaabf8c87631bba5670e7caa9a0 Mon Sep 17 00:00:00 2001 From: Miao_Spring <539943419@qq.com> Date: Mon, 27 Jan 2025 20:51:37 +0800 Subject: [PATCH 9/9] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E4=B8=80?= =?UTF-8?q?=E4=B8=AAqrgb=E7=9A=84demo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/miaoQRScanner.vue | 5 +- components/tools/miaoQRGBCode.vue | 81 ++++++++++++++++ pages/index.vue | 10 ++ pages/tools/QRGB.vue | 15 +++ pages/tools/QRGB/code.vue | 21 +++++ pages/tools/QRGB/scanner.vue | 149 ++++++++++++++++++++++++++++++ 6 files changed, 278 insertions(+), 3 deletions(-) create mode 100644 components/tools/miaoQRGBCode.vue create mode 100644 pages/tools/QRGB.vue create mode 100644 pages/tools/QRGB/code.vue create mode 100644 pages/tools/QRGB/scanner.vue diff --git a/components/miaoQRScanner.vue b/components/miaoQRScanner.vue index bd60dc0..39e4645 100644 --- a/components/miaoQRScanner.vue +++ b/components/miaoQRScanner.vue @@ -21,12 +21,10 @@ let timer: any | undefined = undefined const scannerResult = new Set() -const getQRData = (videoFrame: VideoFrame): string | undefined => { +const getQRData = (videoFrame: ImageBitmap ): string | undefined => { const canvas = document.createElement('canvas') // const canvas = testCtx.value! - // @ts-ignore canvas.width = videoFrame.width - // @ts-ignore canvas.height = videoFrame.height // console.log(canvas.width, canvas.height) const ctx = canvas.getContext('2d') @@ -82,6 +80,7 @@ onMounted(async () => { onBeforeUnmount(() => { stream?.getTracks().forEach(track => track.stop()) + clearInterval(timer) }) diff --git a/components/tools/miaoQRGBCode.vue b/components/tools/miaoQRGBCode.vue new file mode 100644 index 0000000..704a371 --- /dev/null +++ b/components/tools/miaoQRGBCode.vue @@ -0,0 +1,81 @@ + + + + + \ No newline at end of file diff --git a/pages/index.vue b/pages/index.vue index 5b5c147..98e266e 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -148,6 +148,16 @@ const PageContent = reactive([ } ] }, + { + name: 'QRGB', + description: '把三个二维码叠在一起,真是创创又新新啊', + nuxtLinks: [ + { + name: 'link', + to: `/tools/QRGB` + } + ] + }, ] }, { subTitle: '学习资料', diff --git a/pages/tools/QRGB.vue b/pages/tools/QRGB.vue new file mode 100644 index 0000000..a70119a --- /dev/null +++ b/pages/tools/QRGB.vue @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/pages/tools/QRGB/code.vue b/pages/tools/QRGB/code.vue new file mode 100644 index 0000000..a848d2b --- /dev/null +++ b/pages/tools/QRGB/code.vue @@ -0,0 +1,21 @@ + + + + + \ No newline at end of file diff --git a/pages/tools/QRGB/scanner.vue b/pages/tools/QRGB/scanner.vue new file mode 100644 index 0000000..f040e58 --- /dev/null +++ b/pages/tools/QRGB/scanner.vue @@ -0,0 +1,149 @@ + + + + + \ No newline at end of file