mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-27 21:28:12 +00:00
perf: 优化本地资源
This commit is contained in:
parent
9bc3e56c79
commit
9f00047fdd
68
electron/electron.js
vendored
68
electron/electron.js
vendored
@ -1,7 +1,7 @@
|
||||
const fs = require('fs')
|
||||
const os = require("os");
|
||||
const path = require('path')
|
||||
const {app, BrowserWindow, ipcMain, dialog, clipboard, nativeImage, shell, Tray, Menu, globalShortcut, Notification, BrowserView, nativeTheme} = require('electron')
|
||||
const {app, BrowserWindow, ipcMain, dialog, clipboard, nativeImage, shell, Tray, Menu, globalShortcut, Notification, BrowserView, nativeTheme, protocol} = require('electron')
|
||||
const {autoUpdater} = require("electron-updater")
|
||||
const log = require("electron-log");
|
||||
const electronConf = require('electron-config')
|
||||
@ -52,6 +52,70 @@ if (fs.existsSync(devloadCachePath)) {
|
||||
devloadUrl = fs.readFileSync(devloadCachePath, 'utf8')
|
||||
}
|
||||
|
||||
// 在最开始就注册协议为特权协议
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
{
|
||||
scheme: 'dootask-resources',
|
||||
privileges: {
|
||||
standard: true,
|
||||
secure: true,
|
||||
supportFetchAPI: true,
|
||||
corsEnabled: true
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
/**
|
||||
* 创建协议
|
||||
*/
|
||||
function createProtocol() {
|
||||
protocol.handle('dootask-resources', async (request) => {
|
||||
const url = request.url.replace(/^dootask-resources:\/\//, '')
|
||||
|
||||
if (url.includes('..')) {
|
||||
return new Response('Access Denied', { status: 403 })
|
||||
}
|
||||
|
||||
try {
|
||||
const filePath = path.join(__dirname, devloadUrl ? '..' : '.', url)
|
||||
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return new Response('Not Found', { status: 404 })
|
||||
}
|
||||
|
||||
const data = await fs.promises.readFile(filePath)
|
||||
const mimeType = getMimeType(filePath)
|
||||
|
||||
return new Response(data, {
|
||||
headers: {
|
||||
'Content-Type': mimeType
|
||||
}
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Protocol handler error:', error)
|
||||
return new Response('Internal Error', { status: 500 })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* MIME类型判断
|
||||
* @param filePath
|
||||
* @returns {*|string}
|
||||
*/
|
||||
function getMimeType(filePath) {
|
||||
const ext = path.extname(filePath).toLowerCase()
|
||||
const mimeTypes = {
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.png': 'image/png',
|
||||
'.gif': 'image/gif',
|
||||
'.svg': 'image/svg+xml',
|
||||
'.webp': 'image/webp'
|
||||
}
|
||||
return mimeTypes[ext] || 'application/octet-stream'
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建主窗口
|
||||
*/
|
||||
@ -596,6 +660,8 @@ if (!getTheLock) {
|
||||
isReady = true
|
||||
// SameSite
|
||||
utils.useCookie()
|
||||
// 创建协议
|
||||
createProtocol()
|
||||
// 创建主窗口
|
||||
createMainWindow()
|
||||
// 创建托盘
|
||||
|
||||
2
resources/assets/js/app.js
vendored
2
resources/assets/js/app.js
vendored
@ -62,6 +62,7 @@ import TagInput from './components/TagInput.vue'
|
||||
import TableAction from './components/TableAction.vue'
|
||||
import QuickEdit from './components/QuickEdit.vue'
|
||||
import UserAvatar from './components/UserAvatar'
|
||||
import Imgs from './components/Replace/Imgs'
|
||||
import ImgView from './components/ImgView.vue'
|
||||
import Scrollbar from './components/Scrollbar'
|
||||
|
||||
@ -72,6 +73,7 @@ Vue.component('TagInput', TagInput)
|
||||
Vue.component('TableAction', TableAction);
|
||||
Vue.component('QuickEdit', QuickEdit);
|
||||
Vue.component('UserAvatar', UserAvatar);
|
||||
Vue.component('Imgs', Imgs);
|
||||
Vue.component('ImgView', ImgView);
|
||||
Vue.component('Scrollbar', Scrollbar);
|
||||
|
||||
|
||||
26
resources/assets/js/components/Replace/Imgs.vue
Normal file
26
resources/assets/js/components/Replace/Imgs.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<img :src="processedSrc" :alt="alt">
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {publicImageResources} from "./utils";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
src: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
alt: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
processedSrc({src}) {
|
||||
return publicImageResources(src)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
62
resources/assets/js/components/Replace/utils.js
vendored
Normal file
62
resources/assets/js/components/Replace/utils.js
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
const publicImageResources = (() => {
|
||||
let initialized = false
|
||||
let appPreUrl = null
|
||||
let serverPreUrl = null
|
||||
let urlRegex = null
|
||||
|
||||
// 将 escapeRegExp 移到闭包内部
|
||||
const escapeRegExp = (string) => {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
}
|
||||
|
||||
// 初始化函数
|
||||
const initialize = () => {
|
||||
if (initialized) return
|
||||
|
||||
// 设置应用前缀URL
|
||||
if ($A.isEEUiApp) {
|
||||
appPreUrl = $A.eeuiAppRewriteUrl('../public/')
|
||||
} else if ($A.Electron) {
|
||||
appPreUrl = "dootask-resources://public/"
|
||||
}
|
||||
|
||||
// 如果没有特殊前缀,提前返回
|
||||
if (!appPreUrl) return
|
||||
|
||||
// 获取服务器URL
|
||||
serverPreUrl = $A.mainUrl()
|
||||
const escapedPreUrl = escapeRegExp(serverPreUrl)
|
||||
|
||||
// 固定的模式
|
||||
const patterns = [
|
||||
'images/',
|
||||
// 可以继续添加其他路径...
|
||||
]
|
||||
|
||||
// 计算转义后的模式
|
||||
const escapedPatterns = patterns.map(pattern => escapeRegExp(pattern))
|
||||
|
||||
// 编译正则表达式
|
||||
urlRegex = new RegExp(`${escapedPreUrl}(${escapedPatterns.join('|')})`)
|
||||
|
||||
initialized = true
|
||||
}
|
||||
|
||||
// 返回实际的处理函数
|
||||
return (url) => {
|
||||
// 第一次调用时初始化
|
||||
initialize()
|
||||
|
||||
// 如果没有特殊前缀,直接返回原URL
|
||||
if (!appPreUrl) {
|
||||
return url
|
||||
}
|
||||
|
||||
if (urlRegex.test(url)) {
|
||||
return url.replace(serverPreUrl, appPreUrl)
|
||||
}
|
||||
return url
|
||||
}
|
||||
})()
|
||||
|
||||
export {publicImageResources}
|
||||
3
resources/assets/js/functions/web.js
vendored
3
resources/assets/js/functions/web.js
vendored
@ -1,4 +1,5 @@
|
||||
import {MarkdownPreview} from "../store/markdown";
|
||||
import {publicImageResources} from "../components/Replace/utils";
|
||||
|
||||
/**
|
||||
* 页面专用
|
||||
@ -349,7 +350,7 @@ import {MarkdownPreview} from "../store/markdown";
|
||||
const value = item.original
|
||||
.replace(/\s+width=/, ` original-width=`)
|
||||
.replace(/\s+height=/, ` original-height=`)
|
||||
.replace(/\s+src=(["'])([^'"]*)\1/i, ` style="width:${data.width}px;height:${data.height}px" src="${data.src}"`)
|
||||
.replace(/\s+src=(["'])([^'"]*)\1/i, ` style="width:${data.width}px;height:${data.height}px" src="${publicImageResources(data.src)}"`)
|
||||
text = text.replace(item.original, value)
|
||||
} else {
|
||||
text = text.replace(item.original, `<div class="no-size-image-box">${item.original}</div>`);
|
||||
|
||||
@ -17,7 +17,7 @@
|
||||
<Scrollbar>
|
||||
<ul :class="[type, 'no-dark-content']">
|
||||
<li v-for="item in list" @click="onSelect($event, item)">
|
||||
<img v-if="item.type === 'emoticon'" :src="item.src" :title="item.name" :alt="item.name"/>
|
||||
<Imgs v-if="item.type === 'emoticon'" :src="item.src" :title="item.name" :alt="item.name"/>
|
||||
<span v-else v-html="item.html" :title="item.name"></span>
|
||||
</li>
|
||||
</ul>
|
||||
@ -32,7 +32,7 @@
|
||||
<span class="no-dark-content">😀</span>
|
||||
</li>
|
||||
<li v-for="item in emoticonData" :class="{active: type === 'emoticon' && emoticonPath == item.path}" @click="onEmoticon(item.path)">
|
||||
<img :title="item.name" :alt="item.name" :src="item.src"/>
|
||||
<Imgs :title="item.name" :alt="item.name" :src="item.src"/>
|
||||
</li>
|
||||
<li v-if="showEmojiMenuScrollRightBtn" @click="onEmojiMenuScroll('right')" class="right-btn"><i class="taskfont"></i></li>
|
||||
</ul>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user