perf: Install certificates and optimize proxy settings

This commit is contained in:
putyy
2025-05-09 17:56:11 +08:00
parent 29cc879b85
commit 7793f83ea3
24 changed files with 381 additions and 193 deletions

View File

@@ -1,10 +1,12 @@
<template>
<NConfigProvider class="h-full" :theme="theme" :locale="zhCN">
<NaiveProvider>
<RouterView />
<RouterView/>
<ShowLoading :isLoading="loading"/>
<Password v-model:showModal="showPassword" @submit="handlePassword"/>
</NaiveProvider>
<NGlobalStyle />
<NModalProvider />
<NGlobalStyle/>
<NModalProvider/>
</NConfigProvider>
</template>
@@ -12,12 +14,17 @@
import NaiveProvider from '@/components/NaiveProvider.vue'
import {darkTheme, lightTheme, zhCN} from 'naive-ui'
import {useIndexStore} from "@/stores"
import {computed, onMounted} from "vue"
import {computed, onMounted, ref} from "vue"
import {useEventStore} from "@/stores/event"
import {appType} from "@/types/app";
import type {appType} from "@/types/app"
import appApi from "@/api/app"
import ShowLoading from "@/components/ShowLoading.vue"
import Password from "@/components/Password.vue"
const store = useIndexStore()
const eventStore = useEventStore()
const loading = ref(false)
const showPassword = ref(false)
const theme = computed(() => {
if (store.globalConfig.Theme === "darkTheme") {
@@ -30,28 +37,57 @@ const theme = computed(() => {
onMounted(async () => {
await store.init()
loading.value = true
handleInstall().then((is: boolean)=>{
loading.value = false
})
eventStore.init()
eventStore.addHandle({
type: "message",
event: (res: appType.Message)=>{
event: (res: appType.Message) => {
switch (res?.code) {
case 0:
window?.$message?.error(res.message)
window.$message?.error(res.message)
break
case 1:
window?.$message?.success(res.message)
window.$message?.success(res.message)
break
}
}
})
})
eventStore.addHandle({
type: "updateProxyStatus",
event: (res: any)=>{
store.updateProxyStatus(res)
const handleInstall = async () => {
const res = await appApi.install()
if (res.code === 1) {
store.globalConfig.AutoProxy && store.openProxy()
return true
}
window.$message?.error(res.message, {duration: 5000})
if (store.envInfo.platform === 'windows' && res.message.includes('Access is denied')) {
window.$message?.error('首次启用本软件,请使用鼠标右键选择以管理员身份运行')
} else if (['darwin', 'linux'].includes(store.envInfo.platform)) {
showPassword.value = true
}
return false
}
const handlePassword = async (password: string, isCache: boolean) => {
const res = await appApi.setSystemPassword({password, isCache})
if (res.code === 0) {
window.$message?.error(res.message)
return
}
handleInstall().then((is: boolean)=>{
if (is) {
showPassword.value = false
}
})
})
}
</script>
<style scoped>

View File

@@ -1,6 +1,12 @@
import request from '@/api/request'
export default {
install() {
return request({
url: '/api/install',
method: 'post'
})
},
setSystemPassword(data: object) {
return request({
url: 'api/set-system-password',

View File

@@ -1,5 +1,5 @@
import axios from 'axios';
import type {AxiosResponse, InternalAxiosRequestConfig} from 'axios';
import type {AxiosResponse, InternalAxiosRequestConfig} from 'axios'
import axios from 'axios'
interface RequestOptions {
url: string;

View File

@@ -60,6 +60,7 @@
<script lang="ts" setup>
import {useIndexStore} from "@/stores"
import {BrowserOpenURL} from "../../wailsjs/runtime"
const store = useIndexStore()
const props = defineProps(["showModal"])
const emits = defineEmits(["update:showModal"])

View File

@@ -7,40 +7,55 @@
title="管理员授权"
content=""
:show-icon="false"
:closable="false"
:mask-closable="false"
:close-on-esc="false"
class="rounded-lg"
>
<n-form>
<div>
<div class="text-red-500 text-base">
操作需要管理员授权仅对本次运行期间有效
次输入的密码仅在本次运行期间有效用于安装证书或设置系统代理
</div>
<n-form-item path="password" label="">
<div class="mt-3">
<n-input
v-model:value="password"
v-model:value="formValue.password"
type="password"
placeholder="请输入你的电脑密码"
class="w-full"
/>
</n-form-item>
</n-form>
<template #action>
<div class="flex justify-end gap-4">
<n-button @click="emits('update:showModal', false)">取消操作</n-button>
<n-button type="primary" @click="emits('submit', password)">确认操作</n-button>
</div>
<div class="mt-3 text-base">
<label>是否缓存</label>
<NSwitch class="pl-1" v-model:value="formValue.cache" aria-placeholder="是否缓存"/>
</div>
</div>
<template #action>
<n-button type="primary" @click="submit">确认</n-button>
</template>
</n-modal>
</template>
<script setup lang="ts">
import {ref, computed} from 'vue'
import {NModal, NForm, NFormItem, NInput, NButton} from 'naive-ui'
import {reactive} from 'vue'
import {NButton, NInput, NModal} from 'naive-ui'
const props = defineProps({
defineProps({
showModal: Boolean,
})
const password = ref("")
const formValue = reactive({
password: "",
cache: false,
})
const emits = defineEmits(["update:showModal", "submit"])
const changeShow = (value: boolean) => emits("update:showModal", value)
const submit = () => {
if (!formValue.password) {
window.$message?.error("密码不能为空")
return
}
emits('submit', formValue.password, formValue.cache)
}
</script>

View File

@@ -1,15 +1,19 @@
<template>
<div class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50 z-50" v-if="isLoading">
<div class="flex flex-col items-center">
<svg class="animate-spin h-10 w-10 text-white mb-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<svg class="animate-spin h-10 w-10 text-white mb-4" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z"></path>
</svg>
<span class="text-white">{{ loadingText }}</span>
<span class="text-white" v-if="loadingText">{{ loadingText }}</span>
</div>
</div>
</template>
<script lang="ts" setup>
const props = defineProps(["isLoading", "loadingText"])
defineProps<{
isLoading: boolean
loadingText?: string
}>()
</script>

View File

@@ -59,8 +59,8 @@ import {
} from "@vicons/ionicons5"
import {useIndexStore} from "@/stores"
import Footer from "@/components/Footer.vue"
import Screen from "@/components/Screen.vue";
import {BrowserOpenURL} from "../../../wailsjs/runtime";
import Screen from "@/components/Screen.vue"
import {BrowserOpenURL} from "../../../wailsjs/runtime"
const route = useRoute()
const router = useRouter()
@@ -72,7 +72,7 @@ const store = useIndexStore()
const envInfo = store.envInfo
const globalConfig = computed(()=>{
const globalConfig = computed(() => {
return store.globalConfig
})

View File

@@ -1,7 +1,7 @@
import './assets/css/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import {createApp} from 'vue'
import {createPinia} from 'pinia'
import App from './App.vue'
import router from './router'

View File

@@ -6,7 +6,7 @@ import {appType} from "@/types/app"
export const useEventStore = defineStore('ws-store', () => {
const handles = ref<any>({})
const init = ()=>{
const init = () => {
EventsOn("event", (res: any) => {
const data = JSON.parse(res)
if (handles.value.hasOwnProperty(data.type)) {

View File

@@ -49,11 +49,7 @@ export const useIndexStore = defineStore("index-store", () => {
await appApi.getConfig().then((res) => {
globalConfig.value = Object.assign({}, globalConfig.value, res.data)
})
setTimeout(() => {
appApi.isProxy().then((res: any) => {
isProxy.value = res.data.isProxy
})
}, 150)
window.addEventListener("resize", handleResize);
handleResize()
}
@@ -73,9 +69,32 @@ export const useIndexStore = defineStore("index-store", () => {
tableHeight.value = document.documentElement.clientHeight || window.innerHeight
}
const updateProxyStatus = (res: any) => {
isProxy.value = res.isProxy
const openProxy = async () => {
return appApi.openSystemProxy().then(handleProxy)
}
return {appInfo, globalConfig, tableHeight, isProxy, envInfo, init, getAppInfo, setConfig, updateProxyStatus}
const unsetProxy = async () => {
return appApi.unsetSystemProxy().then(handleProxy)
}
const handleProxy = (res: appType.Res) => {
isProxy.value = res.data.value
if (res.code === 0) {
window?.$message?.error(res.message)
}
return res
}
return {
appInfo,
globalConfig,
tableHeight,
isProxy,
envInfo,
init,
getAppInfo,
setConfig,
openProxy,
unsetProxy
}
})

View File

@@ -27,7 +27,7 @@ export namespace appType {
TaskNumber: number
UserAgent: string
UseHeaders: string
MimeMap: {[key: string]: MimeMap}
MimeMap: { [key: string]: MimeMap }
}
interface MediaInfo {
@@ -44,7 +44,7 @@ export namespace appType {
DecodeKey: string
Description: string
ContentType: string
OtherData: {[key: string]: string}
OtherData: { [key: string]: string }
}
interface DownloadProgress {

View File

@@ -61,7 +61,7 @@ const tableHeight = computed(() => {
return store.tableHeight - 132
})
const resourcesType = ref<string[]>(["all"])
const classifyAlias: {[key: string]: string} = {
const classifyAlias: { [key: string]: string } = {
image: "图片",
audio: "音频",
video: "视频",
@@ -269,9 +269,9 @@ onMounted(() => {
})
})
watch(()=>{
watch(() => {
return store.globalConfig.MimeMap
}, ()=>{
}, () => {
buildClassify()
})
@@ -280,7 +280,7 @@ watch(resourcesType, (n, o) => {
appApi.setType(resourcesType.value)
})
const buildClassify = ()=>{
const buildClassify = () => {
const mimeMap = store.globalConfig.MimeMap ?? {}
const seen = new Set()
classify.value = [
@@ -373,7 +373,7 @@ const batchDown = async () => {
}
}
const batchImport = ()=>{
const batchImport = () => {
if (checkedRowKeysValue.value.length <= 0) {
window?.$message?.error('请选择需要导出的数据')
return
@@ -431,7 +431,10 @@ const download = (row: appType.MediaInfo, index: number) => {
loading.value = true
downIndex.value = index
if (row.DecodeKey) {
appApi.download({...row, decodeStr: uint8ArrayToBase64(getDecryptionArray(row.DecodeKey))}).then((res: appType.Res) => {
appApi.download({
...row,
decodeStr: uint8ArrayToBase64(getDecryptionArray(row.DecodeKey))
}).then((res: appType.Res) => {
if (res.code === 0) {
loading.value = false
window?.$message?.error(res.message)
@@ -448,27 +451,18 @@ const download = (row: appType.MediaInfo, index: number) => {
}
const open = () => {
appApi.openSystemProxy().then((res: appType.Res) => {
if (res.code === 0 ){
if (store.envInfo.platform === "darwin") {
showPassword.value = true
return
}
window?.$message?.error(res.message)
store.openProxy().then((res: appType.Res) => {
if (res.code === 1) {
return
}
store.updateProxyStatus(res.data)
if (store.envInfo.platform === "darwin" || store.envInfo.platform === "linux") {
showPassword.value = true
}
})
}
const close = () => {
appApi.unsetSystemProxy().then((res: appType.Res) => {
if (res.code === 0 ){
window?.$message?.error(res.message)
return
}
store.updateProxyStatus(res.data)
})
store.unsetProxy()
}
const clear = () => {
@@ -509,7 +503,7 @@ const decodeWxFile = (row: appType.MediaInfo, index: number) => {
})
}
const handleImport = (content: string)=>{
const handleImport = (content: string) => {
content.split("\n").forEach((line, index) => {
try {
let res = JSON.parse(decodeURIComponent(line))
@@ -519,7 +513,7 @@ const handleImport = (content: string)=>{
res.Status = "ready"
data.value.unshift(res)
}
}catch (e) {
} catch (e) {
console.log(e)
}
});
@@ -527,13 +521,14 @@ const handleImport = (content: string)=>{
showImport.value = false
}
const handlePassword = (password: string)=>{
appApi.setSystemPassword({password: password}).then((res: appType.Res)=>{
const handlePassword = (password: string, isCache: boolean) => {
appApi.setSystemPassword({password: password, isCache: isCache}).then((res: appType.Res) => {
if (res.code === 0) {
window?.$message?.error(res.message)
return
}
open()
showPassword.value = false
store.openProxy()
})
}
</script>

View File

@@ -176,7 +176,7 @@
<HelpCircleOutline/>
</NIcon>
</template>
拦截规则JSON配置不清楚请勿改动
拦截规则json格式不清楚请勿改动
</NTooltip>
</NFormItem>
</NForm>