Browse Source

新增页面缓存管理功能和模板页面

- 在 `src/renderer/src/store/module/page.ts` 中新增 `usePageStore`,实现页面缓存管理功能,包括添加和移除缓存视图的操作。
- 创建模板页面 `src/renderer/src/pages/Template.vue`,并实现页面结构和路由逻辑。
- 新增多个模板相关组件和文件,包括 `IPhone.vue`、`MeCode` 组件及其相关逻辑,支持代码编辑和占位符功能。
- 更新导航栏,添加模板页面的导航链接。
develop
dash 1 month ago
parent
commit
063cf3e0be
  1. 2
      electron.vite.config.ts
  2. 4
      src/renderer/auto-imports.d.ts
  3. 2
      src/renderer/components.d.ts
  4. 31
      src/renderer/src/components/CodeEditor/PlaceholderContentWidget.ts
  5. 4
      src/renderer/src/components/CodeEditor/code-editor-plus.vue
  6. 6
      src/renderer/src/components/CodeEditor/hook.ts
  7. 14
      src/renderer/src/components/IPhone.vue
  8. 59
      src/renderer/src/components/MeCode/PlaceholderContentWidget.ts
  9. 211
      src/renderer/src/components/MeCode/hook.ts
  10. 107
      src/renderer/src/components/MeCode/index.vue
  11. 19
      src/renderer/src/components/MeCode/monaco.ts
  12. 33
      src/renderer/src/components/MeCode/utils.ts
  13. 38
      src/renderer/src/pages/Template.vue
  14. 5
      src/renderer/src/pages/Template/Canvas/index.vue
  15. 4
      src/renderer/src/pages/Template/Canvas/params.json
  16. 15
      src/renderer/src/pages/Template/all.ts
  17. 27
      src/renderer/src/pages/index/index copy 2.vue
  18. 53
      src/renderer/src/pages/index/index copy 3.vue
  19. 14
      src/renderer/src/pages/index/index.vue
  20. 24
      src/renderer/src/store/module/page.ts
  21. 6
      src/renderer/src/ui/NavBar.vue
  22. 4
      src/renderer/typed-router.d.ts

2
electron.vite.config.ts

@ -104,7 +104,7 @@ export default defineConfig({
"vue-i18n",
],
dts: true,
dirs: ["src/composables/**/*.ts", "!src/composables/**/_/**/*.ts"],
dirs: ["src/composables/**/*.ts", "!src/composables/**/_/**/*.ts", "src/store/module/**/*.ts"],
vueTemplate: true,
}),
// https://github.com/antfu/vite-plugin-components

4
src/renderer/auto-imports.d.ts

@ -69,6 +69,7 @@ declare global {
const onUnmounted: typeof import('vue')['onUnmounted']
const onUpdated: typeof import('vue')['onUpdated']
const onWatcherCleanup: typeof import('vue')['onWatcherCleanup']
const page: typeof import('./src/store/module/page')['default']
const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
const provide: typeof import('vue')['provide']
const provideLocal: typeof import('@vueuse/core')['provideLocal']
@ -213,6 +214,7 @@ declare global {
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
const useOnline: typeof import('@vueuse/core')['useOnline']
const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
const usePageStore: typeof import('./src/store/module/page')['usePageStore']
const useParallax: typeof import('@vueuse/core')['useParallax']
const useParentElement: typeof import('@vueuse/core')['useParentElement']
const usePerformanceObserver: typeof import('@vueuse/core')['usePerformanceObserver']
@ -374,6 +376,7 @@ declare module 'vue' {
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']>
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']>
readonly onWatcherCleanup: UnwrapRef<typeof import('vue')['onWatcherCleanup']>
readonly page: UnwrapRef<typeof import('./src/store/module/page')['default']>
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']>
readonly provide: UnwrapRef<typeof import('vue')['provide']>
readonly provideLocal: UnwrapRef<typeof import('@vueuse/core')['provideLocal']>
@ -518,6 +521,7 @@ declare module 'vue' {
readonly useOffsetPagination: UnwrapRef<typeof import('@vueuse/core')['useOffsetPagination']>
readonly useOnline: UnwrapRef<typeof import('@vueuse/core')['useOnline']>
readonly usePageLeave: UnwrapRef<typeof import('@vueuse/core')['usePageLeave']>
readonly usePageStore: UnwrapRef<typeof import('./src/store/module/page')['usePageStore']>
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']>
readonly useParentElement: UnwrapRef<typeof import('@vueuse/core')['useParentElement']>
readonly usePerformanceObserver: UnwrapRef<typeof import('@vueuse/core')['usePerformanceObserver']>

2
src/renderer/components.d.ts

@ -17,6 +17,8 @@ declare module 'vue' {
'IconIx:reset': typeof import('~icons/ix/reset')['default']
'IconMaterialSymbols:save': typeof import('~icons/material-symbols/save')['default']
'IconStash:arrowReplyDuotone': typeof import('~icons/stash/arrow-reply-duotone')['default']
IPhone: typeof import('./src/components/IPhone.vue')['default']
MeCode: typeof import('./src/components/MeCode/index.vue')['default']
NavBar: typeof import('./src/ui/NavBar.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']

31
src/renderer/src/components/CodeEditor/PlaceholderContentWidget.ts

@ -10,7 +10,7 @@ export class PlaceholderContentWidget implements monaco.editor.IContentWidget {
private domNode: HTMLElement | undefined
constructor(
private readonly placeholder: string,
private readonly placeholder: (() => Node) | string,
private readonly editor: monaco.editor.ICodeEditor,
) {
// register a listener for editor code changes
@ -39,34 +39,7 @@ export class PlaceholderContentWidget implements monaco.editor.IContentWidget {
this.domNode.style.fontStyle = "italic"
this.domNode.style.opacity = "0.6" // 添加透明度,更像 placeholder
// 创建文本节点
const textNode = document.createTextNode(this.placeholder + " ")
this.domNode.appendChild(textNode)
// 创建链接
const link = document.createElement("a")
link.href = "https://baidu.com"
link.textContent = "AA"
link.style.pointerEvents = "auto" // 只对链接启用指针事件
link.style.color = "#0066cc" // 设置链接颜色
link.style.textDecoration = "underline"
link.style.cursor = "pointer"
link.target = "_blank" // 在新标签页打开
link.rel = "noopener noreferrer" // 安全属性
// 阻止点击链接时编辑器获得焦点
link.addEventListener("mousedown", e => {
e.preventDefault()
e.stopPropagation()
})
link.addEventListener("click", e => {
e.preventDefault()
e.stopPropagation()
// window.open(link.href, "_blank", "noopener,noreferrer")
})
this.domNode.appendChild(link)
this.domNode.appendChild(typeof this.placeholder === "function" ? this.placeholder() : document.createTextNode(this.placeholder))
this.editor.applyFontInfo(this.domNode)
}

4
src/renderer/src/components/CodeEditor/code-editor-plus.vue

@ -6,7 +6,7 @@
readonly?: boolean
modelValue?: string
filename?: string
placeholder?: string
placeholder?: (() => Node) | string
modelOptions?: IOptions["modelOptions"]
editorOptions?: IOptions["editorOptions"]
}>(),
@ -25,7 +25,7 @@
const editorRef = ref<HTMLDivElement>()
const { updateOption, setValue } = useMonacoEditor(editorRef, {
placeholder: "请输入一些文本测试",
placeholder: props.placeholder,
content: props.modelValue,
filename: props.filename,
modelOptions: props.modelOptions,

6
src/renderer/src/components/CodeEditor/hook.ts

@ -40,7 +40,7 @@ function useResizeObserver(el: HTMLDivElement, callback: ResizeObserverCallback)
}
export interface IOptions {
placeholder: string
placeholder: (() => Node) | string | undefined
filename: string
content: string
editorOptions: monaco.editor.IEditorOptions & monaco.editor.IGlobalEditorOptions
@ -50,7 +50,7 @@ export interface IOptions {
}
const defaultOptions: IOptions = {
placeholder: "请输入文本",
placeholder: undefined,
filename: "temp",
content: "",
editorOptions: {
@ -175,7 +175,7 @@ export function useMonacoEditor(editorElement: Ref<HTMLDivElement | undefined>,
curOption.onCursorChange?.(e)
})
if (!curOption.content) {
placeholderWidget = new PlaceholderContentWidget(curOption.placeholder, editor)
placeholderWidget = new PlaceholderContentWidget(curOption.placeholder || "", editor)
} else {
if (isInnerChange === "waitting") {
isInnerChange = "out"

14
src/renderer/src/components/IPhone.vue

@ -0,0 +1,14 @@
<script lang="ts" setup>
</script>
<template>
<div class="w-full h-full bg-[#E9ECEF] grid place-content-center place-items-center">
<div shadow="lg" bg="light-100"
style="width: 375px; height: 667px; transform: scale(1); transform-origin: center center;">
<slot></slot>
</div>
</div>
</template>
<style lang="scss" scoped></style>

59
src/renderer/src/components/MeCode/PlaceholderContentWidget.ts

@ -0,0 +1,59 @@
import { monaco } from "./monaco"
/**
* Represents a placeholder renderer for monaco editor
* Roughly based on https://github.com/microsoft/vscode/blob/main/src/vs/workbench/contrib/codeEditor/browser/untitledTextEditorHint/untitledTextEditorHint.ts
*/
export class PlaceholderContentWidget implements monaco.editor.IContentWidget {
private static readonly ID = "editor.widget.placeholderHint"
private domNode: HTMLElement | undefined
constructor(
private readonly placeholder: (() => Node) | string,
private readonly editor: monaco.editor.ICodeEditor,
) {
// register a listener for editor code changes
editor.onDidChangeModelContent(() => this.onDidChangeModelContent())
// ensure that on initial load the placeholder is shown
this.onDidChangeModelContent()
}
private onDidChangeModelContent(): void {
if (this.editor.getValue() === "") {
this.editor.addContentWidget(this)
} else {
this.editor.removeContentWidget(this)
}
}
getId(): string {
return PlaceholderContentWidget.ID
}
getDomNode(): HTMLElement {
if (!this.domNode) {
this.domNode = document.createElement("div")
this.domNode.style.width = "max-content"
this.domNode.style.pointerEvents = "none" // 整个容器禁用指针事件
this.domNode.style.fontStyle = "italic"
this.domNode.style.opacity = "0.6" // 添加透明度,更像 placeholder
this.domNode.appendChild(typeof this.placeholder === "function" ? this.placeholder() : document.createTextNode(this.placeholder))
this.editor.applyFontInfo(this.domNode)
}
return this.domNode
}
getPosition(): monaco.editor.IContentWidgetPosition | null {
return {
position: { lineNumber: 1, column: 1 },
preference: [monaco.editor.ContentWidgetPositionPreference.EXACT],
}
}
dispose(): void {
this.editor.removeContentWidget(this)
}
}

211
src/renderer/src/components/MeCode/hook.ts

@ -0,0 +1,211 @@
import { monaco } from "./monaco"
import { PlaceholderContentWidget } from "./PlaceholderContentWidget"
import { judgeFile } from "./utils"
import type { Ref } from "vue"
function useResizeObserver(el: HTMLDivElement, callback: ResizeObserverCallback) {
const isSupported = window && "ResizeObserver" in window
let observer: ResizeObserver | undefined
const cleanup = () => {
if (observer) {
observer.disconnect()
observer = undefined
}
}
const stopWatch = watch(
() => el,
el => {
cleanup()
if (isSupported && window && el) {
observer = new ResizeObserver(callback)
observer!.observe(el, {})
}
},
{ immediate: true },
)
const stop = () => {
cleanup()
stopWatch()
}
function tryOnScopeDispose(fn: () => void) {
if (getCurrentScope()) {
onScopeDispose(fn)
return true
}
return false
}
tryOnScopeDispose(() => {
stop()
})
}
export interface IOptions {
placeholder: (() => Node) | string | undefined
filename: string
extendsExt?: {language: string, ext?: string, pre?: string}[]
content: string
editorOptions: monaco.editor.IEditorOptions & monaco.editor.IGlobalEditorOptions
modelOptions: monaco.editor.ITextModelUpdateOptions
onCursorChange?: (e: monaco.editor.ICursorPositionChangedEvent) => void
onDidChangeContent?: (str: string) => void
}
const defaultOptions: IOptions = {
placeholder: undefined,
filename: "temp",
extendsExt: [],
content: "",
editorOptions: {
fontSize: 14,
readOnly: false,
theme: "vs-light",
fontFamily: "Cascadia Mono, Consolas, 'Courier New', monospace",
scrollBeyondLastLine: false,
lineHeight: 22,
automaticLayout: true,
minimap: {
enabled: false,
},
},
modelOptions: {},
}
const assign = (curOpt, opt, parenyKey: string[] = [], config = { arrayExtend: "concat" }) => {
for (const key in opt) {
if (opt[key] !== undefined) {
if (typeof opt[key] === "function" && curOpt[key] !== undefined && typeof curOpt[key] !== "function") {
opt[key] = opt[key](curOpt[key])
}
if (typeof opt[key] === "object" && !Array.isArray(opt[key]) && !Array.isArray(curOpt[key])) {
parenyKey.push(key)
assign(curOpt[key], opt[key], parenyKey, config)
} else if (typeof opt[key] === "object" && Array.isArray(opt[key]) && Array.isArray(curOpt[key])) {
if (config.arrayExtend === "concat") {
curOpt[key] = curOpt[key].concat(opt[key])
} else {
curOpt[key] = opt[key]
}
} else if (curOpt[key] !== undefined && typeof curOpt[key] !== typeof opt[key]) {
throw new Error(`Type of ${parenyKey.join(",") + "." + key} is not match`)
} else {
curOpt[key] = opt[key]
}
}
}
return curOpt
}
function getOptions(opt = {}, config = { arrayExtend: "concat" }): IOptions {
const curOptions = structuredClone(defaultOptions)
assign(curOptions, opt, [], config)
return curOptions
}
export function useMonacoEditor(editorElement: Ref<HTMLDivElement | undefined>, opts: Partial<IOptions>) {
let curOption = getOptions(opts) as IOptions
let editor: monaco.editor.IStandaloneCodeEditor | null = null
let placeholderWidget: PlaceholderContentWidget | null = null
const updateOption = (opts: Partial<IOptions>) => {
if (!editor) return
curOption = assign(curOption, opts)
if (Object.hasOwn(opts, "placeholder")) {
if (placeholderWidget) {
placeholderWidget.dispose()
placeholderWidget = null
}
if (opts.placeholder) {
placeholderWidget = new PlaceholderContentWidget(opts.placeholder, editor)
}
}
if (Object.hasOwn(opts, "modelOptions") && opts.modelOptions) {
const model = editor.getModel()
model?.updateOptions(opts.modelOptions)
}
if (Object.hasOwn(opts, "editorOptions") && opts.editorOptions) {
editor.updateOptions(opts.editorOptions)
}
if (Object.hasOwn(opts, "filename")) {
updateModel(curOption.filename, curOption.content)
}
if (Object.hasOwn(opts, "content")) {
console.log("无法通过updateOption修改content")
}
}
let isInnerChange = "waitting" // waitting, out, in
const setValue = (content: string) => {
if (isInnerChange === "waitting") {
isInnerChange = "out"
}
if (editor && isInnerChange === "out") {
editor.setValue(content)
} else {
isInnerChange = "waitting"
}
}
function updateModel(name: string, content: string) {
if (editor) {
const oldModel = editor.getModel() //获取旧模型
const file = judgeFile(name, curOption.extendsExt || [])
// 这样定义的话model无法清除
// monaco.editor.createModel("const a = 111","typescript", monaco.Uri.parse('file://root/file3.ts'))
const model: monaco.editor.ITextModel = monaco.editor.createModel(content ?? "", file?.language ?? "txt")
model.updateOptions(curOption.modelOptions)
model.onDidChangeContent(() => {
if (model) {
if (isInnerChange === "out") {
isInnerChange = "waitting"
return
}
isInnerChange = "in"
const code = model.getValue()
curOption.onDidChangeContent?.(code)
}
})
if (oldModel) {
oldModel.dispose()
}
editor.setModel(model)
}
}
tryOnMounted(() => {
if (editorElement.value && !editor) {
editor = monaco.editor.create(editorElement.value, curOption.editorOptions) as monaco.editor.IStandaloneCodeEditor
editor.onDidChangeCursorPosition(e => {
curOption.onCursorChange?.(e)
})
if (!curOption.content) {
placeholderWidget = new PlaceholderContentWidget(curOption.placeholder || "", editor)
} else {
if (isInnerChange === "waitting") {
isInnerChange = "out"
}
}
updateModel(curOption.filename, curOption.content)
useResizeObserver(editorElement.value, () => {
editor!.layout()
})
}
})
tryOnUnmounted(() => {
if (editor) {
const oldModel = editor.getModel()
if (oldModel) {
oldModel.dispose()
}
editor.dispose()
editor = null
}
})
return {
setValue,
scrollTop() {
editor?.setScrollTop(0)
},
updateOption,
}
}

107
src/renderer/src/components/MeCode/index.vue

@ -0,0 +1,107 @@
<script lang="ts" setup>
import { useMonacoEditor, IOptions } from "./hook"
const props = withDefaults(
defineProps<{
readonly?: boolean
modelValue?: string
filename?: string
placeholder?: (() => Node) | string
extendsExt?: {language: string, ext?: string, pre?: string}[]
modelOptions?: IOptions["modelOptions"]
editorOptions?: IOptions["editorOptions"]
}>(),
{
readonly: false,
modelValue: "",
filename: "",
},
)
const emit = defineEmits<{
(e: "update:modelValue", code: string): void
(e: "change", code: string): void
(e: "cursor:position", position: [number, number]): void
}>()
const editorRef = ref<HTMLDivElement>()
const { updateOption, setValue } = useMonacoEditor(editorRef, {
placeholder: props.placeholder,
content: props.modelValue,
filename: props.filename,
extendsExt: props.extendsExt,
modelOptions: props.modelOptions,
editorOptions: props.editorOptions,
onCursorChange(e) {
emit("cursor:position", [e.position.lineNumber, e.position.column])
},
onDidChangeContent(code) {
emit("update:modelValue", code)
emit("change", code)
},
})
watch(
() => props.modelValue,
() => {
setValue(props.modelValue)
},
)
watch(
() => props.filename,
() => {
updateOption({
filename: props.filename,
})
},
)
watch(
() => props.editorOptions,
() => {
updateOption({
editorOptions: props.editorOptions,
})
},
{ deep: true },
)
watch(
() => props.modelOptions,
() => {
updateOption({
modelOptions: props.modelOptions,
})
},
{ deep: true },
)
</script>
<template>
<div class="monaco-wrapper">
<div ref="editorRef" class="monaco-editor"></div>
</div>
</template>
<style lang="scss" scoped>
.monaco-wrapper {
height: 100%;
position: relative;
.monaco-editor {
height: 100%;
}
.monaco-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
pointer-events: none;
opacity: 0.1;
overflow: hidden;
.monaco-logo {
@apply absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2;
}
}
}
</style>

19
src/renderer/src/components/MeCode/monaco.ts

@ -0,0 +1,19 @@
// import 'monaco-editor/esm/vs/editor/editor.all.js';
// import 'monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js';
// import 'monaco-editor/esm/vs/basic-languages/monaco.contribution.js';
// import 'monaco-editor/esm/vs/basic-languages/typescript/typescript.contribution.js';
// import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution.js';
// import 'monaco-editor/esm/vs/basic-languages/html/html.contribution.js';
// import 'monaco-editor/esm/vs/basic-languages/css/css.contribution.js';
// import 'monaco-editor/esm/vs/basic-languages/java/java.contribution.js';
// 导入全部特性
import * as monaco from "monaco-editor"
// import * as monaco from "monaco-editor/esm/vs/editor/editor.api"
// import "monaco-editor/esm/vs/basic-languages/monaco.contribution.js"
export { monaco }

33
src/renderer/src/components/MeCode/utils.ts

@ -0,0 +1,33 @@
export function judgeFile(filename: string, extendsExt?: {language: string, ext?: string, pre?: string}[]) {
if (!filename) return
const ext = [
{ language: "vue", ext: ".vue", index: -1 },
{ language: "javascript", ext: ".js", index: -1 },
{ language: "css", ext: ".css", index: -1 },
{ language: "html", ext: ".html", index: -1 },
{ language: "tsx", ext: ".tsx", index: -1 },
{ language: "typescript", ext: ".ts", index: -1 },
{ language: "markdown", ext: ".md", index: -1 },
{ language: "json", ext: ".json", index: -1 },
{ language: "web", ext: ".web", index: -1 },
{ language: "dot", pre: ".", index: -1 },
...(extendsExt || []).map(e => ({ ...e, index: -1 })),
]
let cur
for (let i = 0; i < ext.length; i++) {
const e = ext[i]
if (e.ext && filename.endsWith(e.ext)) {
const index = filename.lastIndexOf(e.ext)
e.index = index
cur = e
break
}
if (e.pre && filename.startsWith(e.pre)) {
const index = filename.indexOf(e.pre)
e.index = index
cur = e
break
}
}
return cur
}

38
src/renderer/src/pages/Template.vue

@ -0,0 +1,38 @@
<script lang="ts" setup>
import { moduleArray } from "./Template/all"
let store = usePageStore()
const cacheList = computed(() => store.cache)
</script>
<template>
<div class="flex h-full dev-filetree">
<div class="w-200px px-5 py-5 flex flex-col gap-1 bg-white relative" style="border-right: 1px solid #e5e8ea">
<router-link to="/Template">
首页
</router-link>
<router-link class="truncate" :title="item.title" :to="item.url" v-for="item in moduleArray"
:key="item.title">
{{ item.title }}
</router-link>
<AdjustLine></AdjustLine>
</div>
<div class="flex-1 w-0 relative">
<router-view v-slot="{ Component, route }">
<!-- 缓存界面 -->
<keep-alive :include="cacheList">
<component :key="route.meta.parentPath ? route.meta.parentPath : route.fullPath" :is="Component" />
</keep-alive>
<div class="flex items-center justify-center h-full text-2xl" v-if="!Component">请选中侧边栏查看详情</div>
</router-view>
</div>
</div>
</template>
<style lang="scss" scoped>
.dev-filetree {
:deep(.router-link-exact-active) {
color: red;
}
}
</style>

5
src/renderer/src/pages/Template/Canvas/index.vue

@ -0,0 +1,5 @@
<template>
<IPhone>
asdd
</IPhone>
</template>

4
src/renderer/src/pages/Template/Canvas/params.json

@ -0,0 +1,4 @@
{
"url": "/Template/Canvas",
"title": "Canvas"
}

15
src/renderer/src/pages/Template/all.ts

@ -0,0 +1,15 @@
const allModules = import.meta.glob("./*/params.json", { eager: true })
export const moduleArray: any[] = []
for (const key in allModules) {
const m = allModules[key] as any
const mod = m.default || m
moduleArray.push(mod)
}
console.log(moduleArray);
export {
allModules,
}

27
src/renderer/src/pages/index/index copy 2.vue

@ -0,0 +1,27 @@
<script setup lang="ts">
// import { useUpdaterStore } from "common/event/Updater/hook"
// const UpdaterStore = useUpdaterStore()
const code = ref("")
const aa = ref(true)
</script>
<template>
<div gap="20px" h-full>
<input type="text" v-model="code" placeholder="请输入文本" class="input" />
<input type="checkbox" v-model="aa" />
{{ aa }}
<div h-300px>
<code-editor-plus :editorOptions="{ readOnly: aa }" filename="test.js" v-model="code" placeholder="请输入文本"></code-editor-plus>
</div>
<div p="20px" flex flex-wrap items-start gap="20px" justify-start rounded>
<Card v-for="i in 20" :key="i"></Card>
<button class="button">Button</button>
<!-- <button @click="UpdaterStore.checkForUpdates()">更新</button> -->
<button @click="$router.push('/browser')">浏览器</button>
</div>
</div>
</template>
<style lang="scss" scoped></style>

53
src/renderer/src/pages/index/index copy 3.vue

@ -0,0 +1,53 @@
<script setup lang="ts">
// import { useUpdaterStore } from "common/event/Updater/hook"
// const UpdaterStore = useUpdaterStore()
const code = ref("")
const aa = ref(true)
const placeholder = function(){
const fragment = document.createDocumentFragment()
//
const textNode = document.createTextNode("请输入文本" + " ")
fragment.appendChild(textNode)
//
const link = document.createElement("a")
link.href = "https://baidu.com"
link.textContent = "AA阿松大"
link.style.pointerEvents = "auto" //
link.style.color = "#0066cc" //
link.style.textDecoration = "underline"
link.style.cursor = "pointer"
link.target = "_blank" //
link.rel = "noopener noreferrer" //
//
link.addEventListener("mousedown", e => {
e.preventDefault()
e.stopPropagation()
})
link.addEventListener("click", e => {
e.preventDefault()
e.stopPropagation()
// window.open(link.href, "_blank", "noopener,noreferrer")
})
fragment.appendChild(link)
return fragment
}
</script>
<template>
<div gap="20px" h-full>
<input type="text" v-model="code" placeholder="请输入文本" class="input" />
<input type="checkbox" v-model="aa" />
{{ aa }}📁
<div h-300px>
<me-code :editorOptions="{ readOnly: aa }" filename="test.ts" v-model="code" :placeholder="placeholder"></me-code>
</div>
</div>
</template>
<style lang="scss" scoped></style>

14
src/renderer/src/pages/index/index.vue

@ -4,23 +4,11 @@
// const UpdaterStore = useUpdaterStore()
const code = ref("")
const aa = ref(true)
</script>
<template>
<div gap="20px" h-full>
<input type="text" v-model="code" placeholder="请输入文本" class="input" />
<input type="checkbox" v-model="aa" />
{{ aa }}
<div h-300px>
<code-editor-plus :editorOptions="{ readOnly: aa }" filename="test.js" v-model="code" placeholder="请输入文本"></code-editor-plus>
</div>
<div p="20px" flex flex-wrap items-start gap="20px" justify-start rounded>
<Card v-for="i in 20" :key="i"></Card>
<button class="button">Button</button>
<!-- <button @click="UpdaterStore.checkForUpdates()">更新</button> -->
<button @click="$router.push('/browser')">浏览器</button>
</div>
阿松大
</div>
</template>

24
src/renderer/src/store/module/page.ts

@ -0,0 +1,24 @@
import { defineStore } from "pinia"
export const usePageStore = defineStore("page", {
state: (): { _cache: string[] } => ({
_cache: [],
}),
getters: {
cache: state => state._cache,
},
actions: {
addCacheView(name: string) {
if (!this._cache.includes(name)) {
this._cache.push(name)
}
},
removeCacheView(name: string) {
let index = this.cache.indexOf(name)
if (index > -1) {
this._cache.splice(index, 1)
}
},
},
})
export default usePageStore

6
src/renderer/src/ui/NavBar.vue

@ -82,6 +82,12 @@
},
},
{
label: "模板",
async click() {
router.push("/Template")
},
},
{
label: t("browser.navbar.menu.toggleDevTools"),
async click() {
PlatForm.power.toggleDevTools()

4
src/renderer/typed-router.d.ts

@ -20,6 +20,8 @@ declare module 'vue-router/auto-routes' {
export interface RouteNamedMap {
'//': RouteRecordInfo<'//', '/', Record<never, never>, Record<never, never>>,
'//index copy': RouteRecordInfo<'//index copy', '/index copy', Record<never, never>, Record<never, never>>,
'//index copy 2': RouteRecordInfo<'//index copy 2', '/index copy 2', Record<never, never>, Record<never, never>>,
'//index copy 3': RouteRecordInfo<'//index copy 3', '/index copy 3', Record<never, never>, Record<never, never>>,
'/[...all]': RouteRecordInfo<'/[...all]', '/:all(.*)', { all: ParamValue<true> }, { all: ParamValue<false> }>,
'about': RouteRecordInfo<'about', '/about', Record<never, never>, Record<never, never>>,
'/browser': RouteRecordInfo<'/browser', '/browser', Record<never, never>, Record<never, never>>,
@ -28,5 +30,7 @@ declare module 'vue-router/auto-routes' {
'/setting/': RouteRecordInfo<'/setting/', '/setting', Record<never, never>, Record<never, never>>,
'/setting/dev': RouteRecordInfo<'/setting/dev', '/setting/dev', Record<never, never>, Record<never, never>>,
'/setting/update': RouteRecordInfo<'/setting/update', '/setting/update', Record<never, never>, Record<never, never>>,
'/Template': RouteRecordInfo<'/Template', '/Template', Record<never, never>, Record<never, never>>,
'/Template/Canvas/': RouteRecordInfo<'/Template/Canvas/', '/Template/Canvas', Record<never, never>, Record<never, never>>,
}
}

Loading…
Cancel
Save