mirror of
https://github.com/kuaifan/dootask.git
synced 2026-01-29 15:58:14 +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 fs = require('fs')
|
||||||
const os = require("os");
|
const os = require("os");
|
||||||
const path = require('path')
|
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 {autoUpdater} = require("electron-updater")
|
||||||
const log = require("electron-log");
|
const log = require("electron-log");
|
||||||
const electronConf = require('electron-config')
|
const electronConf = require('electron-config')
|
||||||
@ -52,6 +52,70 @@ if (fs.existsSync(devloadCachePath)) {
|
|||||||
devloadUrl = fs.readFileSync(devloadCachePath, 'utf8')
|
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
|
isReady = true
|
||||||
// SameSite
|
// SameSite
|
||||||
utils.useCookie()
|
utils.useCookie()
|
||||||
|
// 创建协议
|
||||||
|
createProtocol()
|
||||||
// 创建主窗口
|
// 创建主窗口
|
||||||
createMainWindow()
|
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 TableAction from './components/TableAction.vue'
|
||||||
import QuickEdit from './components/QuickEdit.vue'
|
import QuickEdit from './components/QuickEdit.vue'
|
||||||
import UserAvatar from './components/UserAvatar'
|
import UserAvatar from './components/UserAvatar'
|
||||||
|
import Imgs from './components/Replace/Imgs'
|
||||||
import ImgView from './components/ImgView.vue'
|
import ImgView from './components/ImgView.vue'
|
||||||
import Scrollbar from './components/Scrollbar'
|
import Scrollbar from './components/Scrollbar'
|
||||||
|
|
||||||
@ -72,6 +73,7 @@ Vue.component('TagInput', TagInput)
|
|||||||
Vue.component('TableAction', TableAction);
|
Vue.component('TableAction', TableAction);
|
||||||
Vue.component('QuickEdit', QuickEdit);
|
Vue.component('QuickEdit', QuickEdit);
|
||||||
Vue.component('UserAvatar', UserAvatar);
|
Vue.component('UserAvatar', UserAvatar);
|
||||||
|
Vue.component('Imgs', Imgs);
|
||||||
Vue.component('ImgView', ImgView);
|
Vue.component('ImgView', ImgView);
|
||||||
Vue.component('Scrollbar', Scrollbar);
|
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 {MarkdownPreview} from "../store/markdown";
|
||||||
|
import {publicImageResources} from "../components/Replace/utils";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面专用
|
* 页面专用
|
||||||
@ -349,7 +350,7 @@ import {MarkdownPreview} from "../store/markdown";
|
|||||||
const value = item.original
|
const value = item.original
|
||||||
.replace(/\s+width=/, ` original-width=`)
|
.replace(/\s+width=/, ` original-width=`)
|
||||||
.replace(/\s+height=/, ` original-height=`)
|
.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)
|
text = text.replace(item.original, value)
|
||||||
} else {
|
} else {
|
||||||
text = text.replace(item.original, `<div class="no-size-image-box">${item.original}</div>`);
|
text = text.replace(item.original, `<div class="no-size-image-box">${item.original}</div>`);
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
<Scrollbar>
|
<Scrollbar>
|
||||||
<ul :class="[type, 'no-dark-content']">
|
<ul :class="[type, 'no-dark-content']">
|
||||||
<li v-for="item in list" @click="onSelect($event, item)">
|
<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>
|
<span v-else v-html="item.html" :title="item.name"></span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -32,7 +32,7 @@
|
|||||||
<span class="no-dark-content">😀</span>
|
<span class="no-dark-content">😀</span>
|
||||||
</li>
|
</li>
|
||||||
<li v-for="item in emoticonData" :class="{active: type === 'emoticon' && emoticonPath == item.path}" @click="onEmoticon(item.path)">
|
<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>
|
||||||
<li v-if="showEmojiMenuScrollRightBtn" @click="onEmojiMenuScroll('right')" class="right-btn"><i class="taskfont"></i></li>
|
<li v-if="showEmojiMenuScrollRightBtn" @click="onEmojiMenuScroll('right')" class="right-btn"><i class="taskfont"></i></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user