mirror of
https://github.com/putyy/res-downloader.git
synced 2026-01-12 06:04:55 +08:00
perf: Install certificates and optimize proxy settings
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"])
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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
|
||||
})
|
||||
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
4
frontend/src/types/app.d.ts
vendored
4
frontend/src/types/app.d.ts
vendored
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
@@ -176,7 +176,7 @@
|
||||
<HelpCircleOutline/>
|
||||
</NIcon>
|
||||
</template>
|
||||
拦截规则JSON配置,不清楚请勿改动
|
||||
拦截规则,json格式,不清楚请勿改动
|
||||
</NTooltip>
|
||||
</NFormItem>
|
||||
</NForm>
|
||||
|
||||
Reference in New Issue
Block a user