Merge remote-tracking branch 'origin/feature/refactor' into feature/refactor
@@ -1,6 +1,7 @@
|
||||
import * as https from 'https'
|
||||
import * as fs from 'fs'
|
||||
import { BrowserWindow } from 'electron'
|
||||
import * as http from 'http'
|
||||
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
|
||||
@@ -8,51 +9,55 @@ export function setMainWindow(window: BrowserWindow) {
|
||||
mainWindow = window
|
||||
}
|
||||
|
||||
// 下载文件的通用函数
|
||||
export function downloadFile(url: string, outputPath: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
console.log(`开始下载文件: ${url}`)
|
||||
console.log(`保存路径: ${outputPath}`)
|
||||
|
||||
|
||||
const file = fs.createWriteStream(outputPath)
|
||||
|
||||
https.get(url, (response) => {
|
||||
const totalSize = parseInt(response.headers['content-length'] || '0', 10)
|
||||
let downloadedSize = 0
|
||||
// 创建HTTP客户端,兼容https和http
|
||||
const client = url.startsWith('https') ? https : http
|
||||
|
||||
console.log(`文件大小: ${totalSize} bytes`)
|
||||
|
||||
response.pipe(file)
|
||||
client
|
||||
.get(url, response => {
|
||||
const totalSize = parseInt(response.headers['content-length'] || '0', 10)
|
||||
let downloadedSize = 0
|
||||
|
||||
response.on('data', (chunk) => {
|
||||
downloadedSize += chunk.length
|
||||
const progress = Math.round((downloadedSize / totalSize) * 100)
|
||||
|
||||
console.log(`下载进度: ${progress}% (${downloadedSize}/${totalSize})`)
|
||||
|
||||
if (mainWindow) {
|
||||
mainWindow.webContents.send('download-progress', {
|
||||
progress,
|
||||
status: 'downloading',
|
||||
message: `下载中... ${progress}%`
|
||||
})
|
||||
}
|
||||
console.log(`文件大小: ${totalSize} bytes`)
|
||||
|
||||
response.pipe(file)
|
||||
|
||||
response.on('data', chunk => {
|
||||
downloadedSize += chunk.length
|
||||
const progress = totalSize ? Math.round((downloadedSize / totalSize) * 100) : 0
|
||||
|
||||
console.log(`下载进度: ${progress}% (${downloadedSize}/${totalSize})`)
|
||||
|
||||
if (mainWindow) {
|
||||
mainWindow.webContents.send('download-progress', {
|
||||
progress,
|
||||
status: 'downloading',
|
||||
message: `下载中... ${progress}%`,
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
file.on('finish', () => {
|
||||
file.close()
|
||||
console.log(`文件下载完成: ${outputPath}`)
|
||||
resolve()
|
||||
})
|
||||
|
||||
file.on('error', err => {
|
||||
console.error(`文件写入错误: ${err.message}`)
|
||||
fs.unlink(outputPath, () => {}) // 删除不完整的文件
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
|
||||
file.on('finish', () => {
|
||||
file.close()
|
||||
console.log(`文件下载完成: ${outputPath}`)
|
||||
resolve()
|
||||
})
|
||||
|
||||
file.on('error', (err) => {
|
||||
console.error(`文件写入错误: ${err.message}`)
|
||||
fs.unlink(outputPath, () => {}) // 删除不完整的文件
|
||||
.on('error', err => {
|
||||
console.error(`下载错误: ${err.message}`)
|
||||
reject(err)
|
||||
})
|
||||
}).on('error', (err) => {
|
||||
console.error(`下载错误: ${err.message}`)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export function setMainWindow(window: BrowserWindow) {
|
||||
mainWindow = window
|
||||
}
|
||||
|
||||
const gitDownloadUrl = 'https://alist-automaa.fearr.xyz/d/AUTO_MAA/git.zip'
|
||||
const gitDownloadUrl = 'http://221.236.27.82:10197/d/AUTO_MAA/git.zip'
|
||||
|
||||
// 递归复制目录,包括文件和隐藏文件
|
||||
function copyDirSync(src: string, dest: string) {
|
||||
|
||||
@@ -64,7 +64,7 @@ async function installPip(pythonPath: string, appRoot: string): Promise<void> {
|
||||
console.log('pip未安装,开始安装...')
|
||||
|
||||
const getPipPath = path.join(pythonPath, 'get-pip.py')
|
||||
const getPipUrl = 'https://alist-automaa.fearr.xyz/d/AUTO_MAA/get-pip.py'
|
||||
const getPipUrl = 'http://221.236.27.82:10197/d/AUTO_MAA/get-pip.py'
|
||||
|
||||
console.log(`Python可执行文件路径: ${pythonExe}`)
|
||||
console.log(`get-pip.py下载URL: ${getPipUrl}`)
|
||||
@@ -203,7 +203,7 @@ export async function downloadPython(appRoot: string, mirror = 'ustc'): Promise<
|
||||
// Python 3.12.0嵌入式版本应该大约30MB,如果小于5MB可能是无效文件
|
||||
if (stats.size < 5 * 1024 * 1024) { // 5MB
|
||||
fs.unlinkSync(zipPath) // 删除无效文件
|
||||
throw new Error(`Python下载文件大小异常: ${stats.size} bytes (${(stats.size / 1024).toFixed(2)} KB),可能是镜像站返回的错误页面或无效文件`)
|
||||
throw new Error(`Python下载文件大小异常: ${stats.size} bytes (${(stats.size / 1024).toFixed(2)} KB),可能是镜像站返回的错误页面或无效文件。请选择一个其他可用镜像源进行下载!`)
|
||||
}
|
||||
|
||||
if (mainWindow) {
|
||||
|
||||
@@ -10,6 +10,7 @@ export type { OpenAPIConfig } from './core/OpenAPI';
|
||||
export type { ComboBoxItem } from './models/ComboBoxItem';
|
||||
export type { ComboBoxOut } from './models/ComboBoxOut';
|
||||
export type { DispatchIn } from './models/DispatchIn';
|
||||
export { GetStageIn } from './models/GetStageIn';
|
||||
export type { GlobalConfig } from './models/GlobalConfig';
|
||||
export type { GlobalConfig_Function } from './models/GlobalConfig_Function';
|
||||
export type { GlobalConfig_Notify } from './models/GlobalConfig_Notify';
|
||||
|
||||
100
frontend/src/api/mirrors.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 镜像源 API 接口
|
||||
* 用于从后端获取最新的镜像源配置
|
||||
*/
|
||||
|
||||
import { OpenAPI } from '@/api'
|
||||
import type { MirrorConfig } from '@/config/mirrors'
|
||||
|
||||
export interface MirrorApiResponse {
|
||||
git?: MirrorConfig[]
|
||||
python?: MirrorConfig[]
|
||||
pip?: MirrorConfig[]
|
||||
apiEndpoints?: {
|
||||
local?: string
|
||||
production?: string
|
||||
proxy?: string
|
||||
}
|
||||
downloadLinks?: {
|
||||
[category: string]: {
|
||||
[key: string]: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取镜像源配置
|
||||
*/
|
||||
export async function fetchMirrorConfig(): Promise<MirrorApiResponse> {
|
||||
try {
|
||||
const response = await fetch(`${OpenAPI.BASE}/api/mirrors`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
return await response.json()
|
||||
} catch (error) {
|
||||
console.warn('获取镜像源配置失败,使用默认配置:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试镜像源连通性
|
||||
*/
|
||||
export async function testMirrorConnectivity(url: string, timeout: number = 5000): Promise<{
|
||||
success: boolean
|
||||
speed: number
|
||||
error?: string
|
||||
}> {
|
||||
try {
|
||||
const startTime = Date.now()
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), timeout)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'HEAD',
|
||||
signal: controller.signal,
|
||||
cache: 'no-cache',
|
||||
mode: 'no-cors' // 避免 CORS 问题
|
||||
})
|
||||
|
||||
clearTimeout(timeoutId)
|
||||
const speed = Date.now() - startTime
|
||||
|
||||
return {
|
||||
success: true,
|
||||
speed
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
speed: 9999,
|
||||
error: error instanceof Error ? error.message : String(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量测试镜像源
|
||||
*/
|
||||
export async function batchTestMirrors(mirrors: MirrorConfig[]): Promise<MirrorConfig[]> {
|
||||
const promises = mirrors.map(async (mirror) => {
|
||||
const result = await testMirrorConnectivity(mirror.url)
|
||||
return {
|
||||
...mirror,
|
||||
speed: result.speed
|
||||
}
|
||||
})
|
||||
|
||||
const results = await Promise.all(promises)
|
||||
|
||||
// 按速度排序
|
||||
return results.sort((a, b) => (a.speed || 9999) - (b.speed || 9999))
|
||||
}
|
||||
@@ -10,6 +10,6 @@ export type ComboBoxItem = {
|
||||
/**
|
||||
* 实际值
|
||||
*/
|
||||
value: string;
|
||||
value: (string | null);
|
||||
};
|
||||
|
||||
|
||||
27
frontend/src/api/models/GetStageIn.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
/* generated using openapi-typescript-codegen -- do not edit */
|
||||
/* istanbul ignore file */
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
export type GetStageIn = {
|
||||
/**
|
||||
* 选择的日期类型, Today为当天, ALL为包含当天未开放关卡在内的所有项
|
||||
*/
|
||||
type: GetStageIn.type;
|
||||
};
|
||||
export namespace GetStageIn {
|
||||
/**
|
||||
* 选择的日期类型, Today为当天, ALL为包含当天未开放关卡在内的所有项
|
||||
*/
|
||||
export enum type {
|
||||
TODAY = 'Today',
|
||||
ALL = 'ALL',
|
||||
MONDAY = 'Monday',
|
||||
TUESDAY = 'Tuesday',
|
||||
WEDNESDAY = 'Wednesday',
|
||||
THURSDAY = 'Thursday',
|
||||
FRIDAY = 'Friday',
|
||||
SATURDAY = 'Saturday',
|
||||
SUNDAY = 'Sunday',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,6 @@ export type TaskCreateOut = {
|
||||
/**
|
||||
* 新创建的任务ID
|
||||
*/
|
||||
taskId: string;
|
||||
websocketId: string;
|
||||
};
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
/* eslint-disable */
|
||||
import type { ComboBoxOut } from '../models/ComboBoxOut';
|
||||
import type { DispatchIn } from '../models/DispatchIn';
|
||||
import type { GetStageIn } from '../models/GetStageIn';
|
||||
import type { InfoOut } from '../models/InfoOut';
|
||||
import type { OutBase } from '../models/OutBase';
|
||||
import type { PlanCreateIn } from '../models/PlanCreateIn';
|
||||
@@ -49,14 +50,22 @@ import { OpenAPI } from '../core/OpenAPI';
|
||||
import { request as __request } from '../core/request';
|
||||
export class Service {
|
||||
/**
|
||||
* 获取关卡号信息
|
||||
* @returns InfoOut Successful Response
|
||||
* 获取关卡号下拉框信息
|
||||
* @param requestBody
|
||||
* @returns ComboBoxOut Successful Response
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static getStageInfoApiInfoStagePost(): CancelablePromise<InfoOut> {
|
||||
public static getStageComboxApiInfoComboxStagePost(
|
||||
requestBody: GetStageIn,
|
||||
): CancelablePromise<ComboBoxOut> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'POST',
|
||||
url: '/api/info/stage',
|
||||
url: '/api/info/combox/stage',
|
||||
body: requestBody,
|
||||
mediaType: 'application/json',
|
||||
errors: {
|
||||
422: `Validation Error`,
|
||||
},
|
||||
});
|
||||
}
|
||||
/**
|
||||
@@ -70,6 +79,17 @@ export class Service {
|
||||
url: '/api/info/combox/script',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取可选任务下拉框信息
|
||||
* @returns ComboBoxOut Successful Response
|
||||
* @throws ApiError
|
||||
*/
|
||||
public static getTaskComboxApiInfoComboxTaskPost(): CancelablePromise<ComboBoxOut> {
|
||||
return __request(OpenAPI, {
|
||||
method: 'POST',
|
||||
url: '/api/info/combox/task',
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 获取通知信息
|
||||
* @returns InfoOut Successful Response
|
||||
|
||||
BIN
frontend/src/assets/materials/2024感谢庆典物资补给.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/32h战略配给.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 21 KiB |
BIN
frontend/src/assets/materials/KFC积分.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/“勇气”胸章.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/“印象”.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/“应急物资”蓝图芯片.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
frontend/src/assets/materials/“我反对!”.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
frontend/src/assets/materials/“战略家”点数.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/“战略家”点数_1.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/“探索者”兑换点数.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/“生香”.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/《“黄金拍档”》.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/《假日终结》.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/《奇谈怪论》复印本.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/《鬼虎双星》.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/《龙鼠相争》.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/中坚寻访凭证.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 17 KiB |
BIN
frontend/src/assets/materials/主播U的直播切片.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
frontend/src/assets/materials/乐之节符.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/乐谱草稿.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/事相碎片.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/事相结晶.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/二次认证徽记.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
frontend/src/assets/materials/二次认证徽记_1.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/今日食谱.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 13 KiB |
BIN
frontend/src/assets/materials/信用.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
frontend/src/assets/materials/借阅证.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/元宵通宝.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 16 KiB |
BIN
frontend/src/assets/materials/先锋芯片组印刻仪.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/光谱行动物资补给.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 15 KiB |
BIN
frontend/src/assets/materials/利刃行动物资补给.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/制式器械零件.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/加急许可.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/劣质燃料.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 17 KiB |
BIN
frontend/src/assets/materials/医疗芯片组印刻仪.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/匿名邀请函.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
frontend/src/assets/materials/十连中坚寻访凭证.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/十连寻访凭证.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/卫戍认证.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/卷宗管理员的钥匙.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/参赛纪念.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
frontend/src/assets/materials/参赛认证-S1.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 12 KiB |
BIN
frontend/src/assets/materials/合作限定十连寻访凭证.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/合成玉.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
frontend/src/assets/materials/合约赏金.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/合约赏金_1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/后勤特别许可证.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/哀之节符.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/商业联合会声望.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 17 KiB |
BIN
frontend/src/assets/materials/圣像碎片.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 15 KiB |
BIN
frontend/src/assets/materials/基础加固建材.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
frontend/src/assets/materials/声望.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/夕墨.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/天桩.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
frontend/src/assets/materials/奇景明信片.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/好好吃饭寻访凭证.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/好看的蘑菇.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/如死亦终十连寻访凭证.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/如死亦终寻访凭证.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
frontend/src/assets/materials/宠物营养罐头.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/家具零件.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
frontend/src/assets/materials/寻昼行动物资补给.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
frontend/src/assets/materials/寻访凭证.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
frontend/src/assets/materials/寻访参数模型.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/寻访数据契约.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
frontend/src/assets/materials/寻访数据契约_1.png
Normal file
|
After Width: | Height: | Size: 20 KiB |