perf: 代码预览

This commit is contained in:
pan 2024-03-21 17:47:46 +08:00
parent 96dbb57862
commit 163aef4b83
7 changed files with 352 additions and 77 deletions

View File

@ -48,6 +48,11 @@
"url": "https://github.com/xiaoxian521"
},
"dependencies": {
"@codemirror/lang-html": "^6.4.8",
"@codemirror/lang-java": "^6.0.1",
"@codemirror/lang-javascript": "^6.2.2",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/theme-one-dark": "^6.1.2",
"@pureadmin/descriptions": "^1.2.0",
"@pureadmin/table": "^3.1.2",
"@pureadmin/utils": "^2.4.5",
@ -58,6 +63,7 @@
"@zxcvbn-ts/core": "^3.0.4",
"animate.css": "^4.1.1",
"axios": "^1.6.7",
"codemirror": "^6.0.1",
"cropperjs": "^1.6.1",
"dayjs": "^1.11.10",
"echarts": "^5.5.0",
@ -76,6 +82,7 @@
"sortablejs": "^1.15.2",
"typeit": "8.7.1",
"vue": "^3.4.21",
"vue-codemirror": "^6.1.1",
"vue-i18n": "^9.10.1",
"vue-router": "^4.3.0",
"vue-tippy": "^6.4.1",

244
pnpm-lock.yaml generated
View File

@ -5,6 +5,21 @@ settings:
excludeLinksFromLockfile: false
dependencies:
'@codemirror/lang-html':
specifier: ^6.4.8
version: 6.4.8
'@codemirror/lang-java':
specifier: ^6.0.1
version: 6.0.1
'@codemirror/lang-javascript':
specifier: ^6.2.2
version: 6.2.2
'@codemirror/lang-xml':
specifier: ^6.1.0
version: 6.1.0
'@codemirror/theme-one-dark':
specifier: ^6.1.2
version: 6.1.2
'@pureadmin/descriptions':
specifier: ^1.2.0
version: 1.2.0(element-plus@2.6.0)(typescript@5.3.3)
@ -35,6 +50,9 @@ dependencies:
axios:
specifier: ^1.6.7
version: 1.6.7
codemirror:
specifier: ^6.0.1
version: 6.0.1(@lezer/common@1.2.1)
cropperjs:
specifier: ^1.6.1
version: 1.6.1
@ -89,6 +107,9 @@ dependencies:
vue:
specifier: ^3.4.21
version: 3.4.21(typescript@5.3.3)
vue-codemirror:
specifier: ^6.1.1
version: 6.1.1(codemirror@6.0.1)(vue@3.4.21)
vue-i18n:
specifier: ^9.10.1
version: 9.10.1(vue@3.4.21)
@ -574,6 +595,133 @@ packages:
'@babel/helper-validator-identifier': 7.22.20
to-fast-properties: 2.0.0
/@codemirror/autocomplete@6.15.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.0)(@lezer/common@1.2.1):
resolution: {integrity: sha512-G2Zm0mXznxz97JhaaOdoEG2cVupn4JjPaS4AcNvZzhOsnnG9YVN68VzfoUw6dYTsIxT6a/cmoFEN47KAWhXaOg==}
peerDependencies:
'@codemirror/language': ^6.0.0
'@codemirror/state': ^6.0.0
'@codemirror/view': ^6.0.0
'@lezer/common': ^1.0.0
dependencies:
'@codemirror/language': 6.10.1
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
'@lezer/common': 1.2.1
dev: false
/@codemirror/commands@6.3.3:
resolution: {integrity: sha512-dO4hcF0fGT9tu1Pj1D2PvGvxjeGkbC6RGcZw6Qs74TH+Ed1gw98jmUgd2axWvIZEqTeTuFrg1lEB1KV6cK9h1A==}
dependencies:
'@codemirror/language': 6.10.1
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
'@lezer/common': 1.2.1
dev: false
/@codemirror/lang-css@6.2.1(@codemirror/view@6.26.0):
resolution: {integrity: sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==}
dependencies:
'@codemirror/autocomplete': 6.15.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.0)(@lezer/common@1.2.1)
'@codemirror/language': 6.10.1
'@codemirror/state': 6.4.1
'@lezer/common': 1.2.1
'@lezer/css': 1.1.8
transitivePeerDependencies:
- '@codemirror/view'
dev: false
/@codemirror/lang-html@6.4.8:
resolution: {integrity: sha512-tE2YK7wDlb9ZpAH6mpTPiYm6rhfdQKVDa5r9IwIFlwwgvVaKsCfuKKZoJGWsmMZIf3FQAuJ5CHMPLymOtg1hXw==}
dependencies:
'@codemirror/autocomplete': 6.15.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.0)(@lezer/common@1.2.1)
'@codemirror/lang-css': 6.2.1(@codemirror/view@6.26.0)
'@codemirror/lang-javascript': 6.2.2
'@codemirror/language': 6.10.1
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
'@lezer/common': 1.2.1
'@lezer/css': 1.1.8
'@lezer/html': 1.3.9
dev: false
/@codemirror/lang-java@6.0.1:
resolution: {integrity: sha512-OOnmhH67h97jHzCuFaIEspbmsT98fNdhVhmA3zCxW0cn7l8rChDhZtwiwJ/JOKXgfm4J+ELxQihxaI7bj7mJRg==}
dependencies:
'@codemirror/language': 6.10.1
'@lezer/java': 1.1.1
dev: false
/@codemirror/lang-javascript@6.2.2:
resolution: {integrity: sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==}
dependencies:
'@codemirror/autocomplete': 6.15.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.0)(@lezer/common@1.2.1)
'@codemirror/language': 6.10.1
'@codemirror/lint': 6.5.0
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
'@lezer/common': 1.2.1
'@lezer/javascript': 1.4.13
dev: false
/@codemirror/lang-xml@6.1.0:
resolution: {integrity: sha512-3z0blhicHLfwi2UgkZYRPioSgVTo9PV5GP5ducFH6FaHy0IAJRg+ixj5gTR1gnT/glAIC8xv4w2VL1LoZfs+Jg==}
dependencies:
'@codemirror/autocomplete': 6.15.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.0)(@lezer/common@1.2.1)
'@codemirror/language': 6.10.1
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
'@lezer/common': 1.2.1
'@lezer/xml': 1.0.5
dev: false
/@codemirror/language@6.10.1:
resolution: {integrity: sha512-5GrXzrhq6k+gL5fjkAwt90nYDmjlzTIJV8THnxNFtNKWotMIlzzN+CpqxqwXOECnUdOndmSeWntVrVcv5axWRQ==}
dependencies:
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
'@lezer/common': 1.2.1
'@lezer/highlight': 1.2.0
'@lezer/lr': 1.4.0
style-mod: 4.1.2
dev: false
/@codemirror/lint@6.5.0:
resolution: {integrity: sha512-+5YyicIaaAZKU8K43IQi8TBy6mF6giGeWAH7N96Z5LC30Wm5JMjqxOYIE9mxwMG1NbhT2mA3l9hA4uuKUM3E5g==}
dependencies:
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
crelt: 1.0.6
dev: false
/@codemirror/search@6.5.6:
resolution: {integrity: sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==}
dependencies:
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
crelt: 1.0.6
dev: false
/@codemirror/state@6.4.1:
resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==}
dev: false
/@codemirror/theme-one-dark@6.1.2:
resolution: {integrity: sha512-F+sH0X16j/qFLMAfbciKTxVOwkdAS336b7AXTKOZhy8BR3eH/RelsnLgLFINrpST63mmN2OuwUt0W2ndUgYwUA==}
dependencies:
'@codemirror/language': 6.10.1
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
'@lezer/highlight': 1.2.0
dev: false
/@codemirror/view@6.26.0:
resolution: {integrity: sha512-nSSmzONpqsNzshPOxiKhK203R6BvABepugAe34QfQDbNDslyjkqBuKgrK5ZBvqNXpfxz5iLrlGTmEfhbQyH46A==}
dependencies:
'@codemirror/state': 6.4.1
style-mod: 4.1.2
w3c-keyname: 2.2.8
dev: false
/@commitlint/cli@18.6.1(@types/node@20.11.24)(typescript@5.3.3):
resolution: {integrity: sha512-5IDE0a+lWGdkOvKH892HHAZgbAjcj1mT5QrfA/SVbLJV/BbBMGyKN0W5mhgjekPJJwEQdVNvhl9PwUacY58Usw==}
engines: {node: '>=v18'}
@ -1210,6 +1358,62 @@ packages:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.4.15
/@lezer/common@1.2.1:
resolution: {integrity: sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==}
dev: false
/@lezer/css@1.1.8:
resolution: {integrity: sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==}
dependencies:
'@lezer/common': 1.2.1
'@lezer/highlight': 1.2.0
'@lezer/lr': 1.4.0
dev: false
/@lezer/highlight@1.2.0:
resolution: {integrity: sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==}
dependencies:
'@lezer/common': 1.2.1
dev: false
/@lezer/html@1.3.9:
resolution: {integrity: sha512-MXxeCMPyrcemSLGaTQEZx0dBUH0i+RPl8RN5GwMAzo53nTsd/Unc/t5ZxACeQoyPUM5/GkPLRUs2WliOImzkRA==}
dependencies:
'@lezer/common': 1.2.1
'@lezer/highlight': 1.2.0
'@lezer/lr': 1.4.0
dev: false
/@lezer/java@1.1.1:
resolution: {integrity: sha512-mt3dX13fRlpY7RlWELYRakanXgmwXsLRCrhstrn+c1sZd7jR2xle46/3heoxGd+oHxnuTnpoyXTyxcLJQs9+mQ==}
dependencies:
'@lezer/common': 1.2.1
'@lezer/highlight': 1.2.0
'@lezer/lr': 1.4.0
dev: false
/@lezer/javascript@1.4.13:
resolution: {integrity: sha512-5IBr8LIO3xJdJH1e9aj/ZNLE4LSbdsx25wFmGRAZsj2zSmwAYjx26JyU/BYOCpRQlu1jcv1z3vy4NB9+UkfRow==}
dependencies:
'@lezer/common': 1.2.1
'@lezer/highlight': 1.2.0
'@lezer/lr': 1.4.0
dev: false
/@lezer/lr@1.4.0:
resolution: {integrity: sha512-Wst46p51km8gH0ZUmeNrtpRYmdlRHUpN1DQd3GFAyKANi8WVz8c2jHYTf1CVScFaCjQw1iO3ZZdqGDxQPRErTg==}
dependencies:
'@lezer/common': 1.2.1
dev: false
/@lezer/xml@1.0.5:
resolution: {integrity: sha512-VFouqOzmUWfIg+tfmpcdV33ewtK+NSwd4ngSe1aG7HFb4BN0ExyY1b8msp+ndFrnlG4V4iC8yXacjFtrwERnaw==}
dependencies:
'@lezer/common': 1.2.1
'@lezer/highlight': 1.2.0
'@lezer/lr': 1.4.0
dev: false
/@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
@ -2586,6 +2790,20 @@ packages:
hasBin: true
dev: true
/codemirror@6.0.1(@lezer/common@1.2.1):
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
dependencies:
'@codemirror/autocomplete': 6.15.0(@codemirror/language@6.10.1)(@codemirror/state@6.4.1)(@codemirror/view@6.26.0)(@lezer/common@1.2.1)
'@codemirror/commands': 6.3.3
'@codemirror/language': 6.10.1
'@codemirror/lint': 6.5.0
'@codemirror/search': 6.5.6
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
transitivePeerDependencies:
- '@lezer/common'
dev: false
/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
@ -2754,6 +2972,10 @@ packages:
typescript: 5.3.3
dev: true
/crelt@1.0.6:
resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==}
dev: false
/cropperjs@1.6.1:
resolution: {integrity: sha512-F4wsi+XkDHCOMrHMYjrTEE4QBOrsHHN5/2VsVAaRq8P7E5z7xQpT75S+f/9WikmBEailas3+yo+6zPIomW+NOA==}
dev: false
@ -6372,6 +6594,10 @@ packages:
dev: false
optional: true
/style-mod@4.1.2:
resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==}
dev: false
/style-value-types@5.1.2:
resolution: {integrity: sha512-Vs9fNreYF9j6W2VvuDTP7kepALi7sk0xtk2Tu8Yxi9UoajJdEVpNpCov0HsLTqXvNGKX+Uv09pkozVITi1jf3Q==}
dependencies:
@ -7052,6 +7278,20 @@ packages:
fsevents: 2.3.3
dev: true
/vue-codemirror@6.1.1(codemirror@6.0.1)(vue@3.4.21):
resolution: {integrity: sha512-rTAYo44owd282yVxKtJtnOi7ERAcXTeviwoPXjIc6K/IQYUsoDkzPvw/JDFtSP6T7Cz/2g3EHaEyeyaQCKoDMg==}
peerDependencies:
codemirror: 6.x
vue: 3.x
dependencies:
'@codemirror/commands': 6.3.3
'@codemirror/language': 6.10.1
'@codemirror/state': 6.4.1
'@codemirror/view': 6.26.0
codemirror: 6.0.1(@lezer/common@1.2.1)
vue: 3.4.21(typescript@5.3.3)
dev: false
/vue-demi@0.14.7(vue@3.4.21):
resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==}
engines: {node: '>=12'}
@ -7161,6 +7401,10 @@ packages:
'@vue/shared': 3.4.21
typescript: 5.3.3
/w3c-keyname@2.2.8:
resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
dev: false
/webpack-sources@3.2.3:
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
engines: {node: '>=10.13.0'}

View File

@ -1,57 +0,0 @@
<script setup lang="ts">
import "@wangeditor/editor/dist/css/style.css";
import { IEditorConfig } from "@wangeditor/editor";
import { Editor } from "@wangeditor/editor-for-vue";
import {
onMounted,
onBeforeUnmount,
shallowRef,
defineProps,
defineEmits,
ref
} from "vue";
defineOptions({
name: "BaseEditor"
});
const content = defineProps({
content: {
type: String,
default: ""
}
});
const emits = defineEmits(["update:content"]);
const mode = "default";
// shallowRef
const editorRef = shallowRef();
// HTML
const editorConfig: Partial<IEditorConfig> = { MENU_CONF: {} };
console.log("content", content.content);
const htmlText = ref(content.content);
onMounted(() => {});
const handleCreated = editor => {
// editor
editorRef.value = editor;
};
//
onBeforeUnmount(() => {
const editor = editorRef.value;
if (editor == null) return;
editor.destroy();
});
</script>
<template>
<div>
<Editor
v-model="htmlText"
:defaultConfig="editorConfig"
:mode="mode"
style="height: 100%; overflow-y: hidden"
@onCreated="handleCreated"
/>
</div>
</template>

View File

@ -1,5 +1,5 @@
import base from "./base.vue";
import code from "./index.vue";
const Base = base;
const Code = code;
export { Base };
export { Code };

View File

@ -0,0 +1,79 @@
<template>
<codemirror
v-model="myCode"
placeholder="Code goes here..."
:style="{ height: '100%' }"
:autofocus="true"
:indent-with-tab="true"
:tab-size="2"
:extensions="extensions"
@ready="handleReady"
/>
</template>
<script setup lang="ts">
import { shallowRef, defineProps, defineEmits, ref, watch } from "vue";
import { Codemirror } from "vue-codemirror";
import { javascript } from "@codemirror/lang-javascript";
import { java } from "@codemirror/lang-java";
import { xml } from "@codemirror/lang-xml";
import { html } from "@codemirror/lang-html";
import { oneDark } from "@codemirror/theme-one-dark";
defineOptions({
name: "Codemirror"
});
const code = defineProps({
code: {
type: String,
default: ""
},
type: {
type: String,
default: "java"
}
});
const emits = defineEmits(["update:code", "update:type"]);
const extensions = ref([]);
const myCode = ref(code.code);
extensions.value = [java(), oneDark];
watch(
() => code.type,
newValue => {
if (newValue === "javascript") {
extensions.value[0] = javascript();
} else if (newValue === "xml") {
extensions.value[0] = xml();
} else if (newValue === "html") {
extensions.value[0] = html();
} else {
extensions.value[0] = java();
}
}
);
watch(
() => code.code,
newValue => {
myCode.value = newValue;
}
);
// Codemirror EditorView instance ref
const view = shallowRef();
const handleReady = payload => {
view.value = payload.view;
};
// Status is available at all times via Codemirror EditorView
const getCodemirrorStates = () => {
const state = view.value.state;
const ranges = state.selection.ranges;
const selected = ranges.reduce((r, range) => r + range.to - range.from, 0);
const cursor = ranges[0].anchor;
const length = state.doc.length;
const lines = state.doc.lines;
// more state info ...
// return ...
};
</script>

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref } from "vue";
import { Base } from "./components";
import { Code } from "./components";
defineOptions({
name: "Editor"
@ -27,7 +27,7 @@ const activeNames = ref("1");
</template>
<el-collapse v-model="activeNames" accordion>
<el-collapse-item title="基础用法" name="1">
<Base v-if="activeNames === '1'" />
<Code v-if="activeNames === '1'" />
</el-collapse-item>
</el-collapse>
</el-card>

View File

@ -1,8 +1,8 @@
<script setup lang="ts">
import { useDetail } from "./hook";
import { onMounted, ref, reactive } from "vue";
import { onMounted, ref } from "vue";
import { get, type Generator } from "@/api/generator/generator";
import { Base } from "@/views/editor/components";
import { Code } from "@/views/editor/components";
defineOptions({
name: "TabQueryDetail"
@ -12,31 +12,33 @@ const { initToDetail, getParameter } = useDetail();
initToDetail("query");
const datas = ref([]);
const content = ref("");
const type = ref("java");
onMounted(() => {
get(getParameter.id, 1).then(data => {
console.log("data", data);
datas.value = data.data;
content.value =
'<pre><code class="language-java">' +
data.data[0].content +
"</code></pre>";
content.value = data.data[0].content;
});
});
const clickFn = (item: String) => {
content.value = '<pre><code class="language-java">' + item + "</code></pre>";
const clickFn = (item: Generator) => {
if (item.name.indexOf("Xml") > -1) {
type.value = "xml";
} else if (item.name.indexOf("api") > -1) {
type.value = "javascript";
} else if (item.name.indexOf("index") > -1) {
type.value = "html";
} else {
type.value = "java";
}
content.value = item.content;
};
</script>
<template>
<div>
<span
v-for="(item, index) in datas"
:key="index"
@click="clickFn(item.content)"
>
<span v-for="(item, index) in datas" :key="index" @click="clickFn(item)">
{{ item.name }} &nbsp;
</span>
<Base v-model:content="content" />
<Code v-model:code="content" v-model:type="type" />
</div>
</template>