A:剩余diamagnetic提交
This commit is contained in:
1 parent
04bb8099ac
commit
0981ef5d3e
8 files changed
+541
No files matched your search
@@ -0,0 +1,213 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Data;
|
||||||
|
using Data.Models;
|
||||||
|
|
||||||
|
namespace Shell.Utils;
|
||||||
|
|
||||||
|
public static class NetworkApiHelper
|
||||||
|
{
|
||||||
|
private static readonly Dictionary<string, object> _networkInterfaceCache = new();
|
||||||
|
private static DateTime _cacheLastUpdateTime = DateTime.MinValue;
|
||||||
|
private static readonly TimeSpan _cacheExpireTime = TimeSpan.FromMinutes(5);
|
||||||
|
|
||||||
|
public static Dictionary<string, object> NetworkInterfaceCache => _networkInterfaceCache;
|
||||||
|
public static DateTime CacheLastUpdateTime => _cacheLastUpdateTime;
|
||||||
|
public static TimeSpan CacheExpireTime => _cacheExpireTime;
|
||||||
|
|
||||||
|
public static void UpdateCacheTime() => _cacheLastUpdateTime = DateTime.Now;
|
||||||
|
|
||||||
|
public static async Task<List<GlobalNetworkAggregatedBase>> GetAllNetworkCardsHourlyDataAsync(int hours)
|
||||||
|
{
|
||||||
|
var result = new List<GlobalNetworkAggregatedBase>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var allHourlyData = await DatabaseManager.Instance.Networks.GetGlobalNetworkByHourAsync("", hours);
|
||||||
|
var networkGuids = allHourlyData.Select(x => "").Distinct();
|
||||||
|
|
||||||
|
foreach (var guid in networkGuids)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(guid))
|
||||||
|
result.Add(new GlobalNetworkHourly { NetworkCardGuid = guid });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 如果出错,返回空列表
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<List<GlobalNetworkAggregatedBase>> GetAllNetworkCardsDailyDataAsync(int days)
|
||||||
|
{
|
||||||
|
var result = new List<GlobalNetworkAggregatedBase>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var allDailyData = await DatabaseManager.Instance.Networks.GetGlobalNetworkByDayAsync("", days);
|
||||||
|
var networkGuids = allDailyData.Select(x => "").Distinct();
|
||||||
|
|
||||||
|
foreach (var guid in networkGuids)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(guid))
|
||||||
|
result.Add(new GlobalNetworkDaily { NetworkCardGuid = guid });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 如果出错,返回空列表
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<bool> HasNetworkDataInTimeRangeAsync(string dataType, long startTime)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (dataType)
|
||||||
|
{
|
||||||
|
case "hourly":
|
||||||
|
var hourlyData = await DatabaseManager.Instance.Networks.GetGlobalNetworkByHourAsync("", 1);
|
||||||
|
return hourlyData.Any();
|
||||||
|
case "daily":
|
||||||
|
var dailyData = await DatabaseManager.Instance.Networks.GetGlobalNetworkByDayAsync("", 1);
|
||||||
|
return dailyData.Any();
|
||||||
|
default:
|
||||||
|
var networkData = await DatabaseManager.Instance.Networks.GetGlobalNetworkHistoryAsync("", 1);
|
||||||
|
return networkData.Any();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task<List<object>> GetTrafficTrendsAsync(string timeRange, string interfaceId, long startTime, long endTime)
|
||||||
|
{
|
||||||
|
var points = new List<object>();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (timeRange == "hour")
|
||||||
|
{
|
||||||
|
if (interfaceId == "all")
|
||||||
|
{
|
||||||
|
var allData = await DatabaseManager.Instance.Networks
|
||||||
|
.GetGlobalNetworkByTimeRangeAsync("", startTime, endTime);
|
||||||
|
var groupedData = allData.GroupBy(d => d.Timestep).Select(g => new
|
||||||
|
{
|
||||||
|
timestamp = g.Key.ToString(),
|
||||||
|
uploadSpeed = g.Sum(x => x.Upload),
|
||||||
|
downloadSpeed = g.Sum(x => x.Download)
|
||||||
|
});
|
||||||
|
|
||||||
|
points.AddRange(groupedData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var data = await DatabaseManager.Instance.Networks.GetGlobalNetworkByTimeRangeAsync(interfaceId,
|
||||||
|
startTime, endTime);
|
||||||
|
points.AddRange(data.Select(d => new
|
||||||
|
{
|
||||||
|
timestamp = d.Timestep.ToString(),
|
||||||
|
uploadSpeed = d.Upload,
|
||||||
|
downloadSpeed = d.Download
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (timeRange == "day")
|
||||||
|
{
|
||||||
|
if (interfaceId == "all")
|
||||||
|
{
|
||||||
|
var allData = await DatabaseManager.Instance.Networks.GetGlobalNetworkByHourAsync("", 24);
|
||||||
|
var groupedData = allData.GroupBy(d => d.HourTimestamp).Select(g => new
|
||||||
|
{
|
||||||
|
timestamp = g.Key.ToString(),
|
||||||
|
uploadSpeed = g.Sum(x => x.AvgUpload),
|
||||||
|
downloadSpeed = g.Sum(x => x.AvgDownload)
|
||||||
|
});
|
||||||
|
|
||||||
|
points.AddRange(groupedData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var data = await DatabaseManager.Instance.Networks.GetGlobalNetworkByHourAsync(interfaceId, 24);
|
||||||
|
points.AddRange(data.Select(d => new
|
||||||
|
{
|
||||||
|
timestamp = d.HourTimestamp.ToString(),
|
||||||
|
uploadSpeed = d.AvgUpload,
|
||||||
|
downloadSpeed = d.AvgDownload
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int days = timeRange == "week" ? 7 : 30;
|
||||||
|
if (interfaceId == "all")
|
||||||
|
{
|
||||||
|
var allData = await DatabaseManager.Instance.Networks.GetGlobalNetworkByDayAsync("", days);
|
||||||
|
var groupedData = allData.GroupBy(d => d.DayTimestamp).Select(g => new
|
||||||
|
{
|
||||||
|
timestamp = g.Key.ToString(),
|
||||||
|
uploadSpeed = g.Sum(x => x.AvgUpload),
|
||||||
|
downloadSpeed = g.Sum(x => x.AvgDownload)
|
||||||
|
});
|
||||||
|
|
||||||
|
points.AddRange(groupedData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var data = await DatabaseManager.Instance.Networks.GetGlobalNetworkByDayAsync(interfaceId, days);
|
||||||
|
points.AddRange(data.Select(d => new
|
||||||
|
{
|
||||||
|
timestamp = d.DayTimestamp.ToString(),
|
||||||
|
uploadSpeed = d.AvgUpload,
|
||||||
|
downloadSpeed = d.AvgDownload
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// 如果出错,返回空数据
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetPortServiceName(int port)
|
||||||
|
{
|
||||||
|
return port switch
|
||||||
|
{
|
||||||
|
21 => "FTP",
|
||||||
|
22 => "SSH",
|
||||||
|
23 => "Telnet",
|
||||||
|
25 => "SMTP",
|
||||||
|
53 => "DNS",
|
||||||
|
80 => "HTTP",
|
||||||
|
110 => "POP3",
|
||||||
|
123 => "NTP",
|
||||||
|
143 => "IMAP",
|
||||||
|
443 => "HTTPS",
|
||||||
|
993 => "IMAPS",
|
||||||
|
995 => "POP3S",
|
||||||
|
1433 => "SQL Server",
|
||||||
|
3306 => "MySQL",
|
||||||
|
3389 => "RDP",
|
||||||
|
5432 => "PostgreSQL",
|
||||||
|
6379 => "Redis",
|
||||||
|
8080 => "HTTP-Alt",
|
||||||
|
8443 => "HTTPS-Alt",
|
||||||
|
_ when port >= 1024 && port <= 5000 => "User Port",
|
||||||
|
_ when port > 5000 && port < 32768 => "Service Port",
|
||||||
|
_ when port >= 32768 => "Dynamic Port",
|
||||||
|
_ => "Unknown"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
using Microsoft.Win32;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using Common.Logger;
|
||||||
|
|
||||||
|
namespace Shell.Utils;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Windows开机自启动辅助类
|
||||||
|
/// </summary>
|
||||||
|
public static class WindowsStartupHelper
|
||||||
|
{
|
||||||
|
private const string REGISTRY_KEY = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
|
||||||
|
private const string APP_NAME = "NetVizor";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置开机自启动
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="enable">是否启用自启动</param>
|
||||||
|
/// <returns>操作是否成功</returns>
|
||||||
|
public static bool SetStartup(bool enable)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var key = Registry.CurrentUser.OpenSubKey(REGISTRY_KEY, true);
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
Log.Error4Ctx("无法打开注册表项");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
// 获取当前执行文件的路径
|
||||||
|
var executablePath = Assembly.GetExecutingAssembly().Location;
|
||||||
|
|
||||||
|
// 如果是.NET Core/.NET 5+应用,使用exe文件路径
|
||||||
|
if (executablePath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
executablePath = Path.ChangeExtension(executablePath, ".exe");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果exe文件不存在,尝试从当前目录查找
|
||||||
|
if (!File.Exists(executablePath))
|
||||||
|
{
|
||||||
|
var currentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
||||||
|
var exeName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().Location) + ".exe";
|
||||||
|
executablePath = Path.Combine(currentDir ?? "", exeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(executablePath))
|
||||||
|
{
|
||||||
|
Log.Error4Ctx($"找不到可执行文件: {executablePath}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加自启动项
|
||||||
|
key.SetValue(APP_NAME, $"\"{executablePath}\"");
|
||||||
|
Log.Info($"已设置开机自启动: {executablePath}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 删除自启动项
|
||||||
|
if (key.GetValue(APP_NAME) != null)
|
||||||
|
{
|
||||||
|
key.DeleteValue(APP_NAME);
|
||||||
|
Log.Info("已取消开机自启动");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Error4Ctx($"设置开机自启动失败: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查是否已设置开机自启动
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>是否已设置自启动</returns>
|
||||||
|
public static bool IsStartupEnabled()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var key = Registry.CurrentUser.OpenSubKey(REGISTRY_KEY, false);
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = key.GetValue(APP_NAME)?.ToString();
|
||||||
|
return !string.IsNullOrEmpty(value);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warning($"检查开机自启动状态失败: {ex.Message}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前设置的启动路径
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>启动路径,如果未设置则返回null</returns>
|
||||||
|
public static string? GetStartupPath()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var key = Registry.CurrentUser.OpenSubKey(REGISTRY_KEY, false);
|
||||||
|
if (key == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = key.GetValue(APP_NAME)?.ToString();
|
||||||
|
return value?.Trim('"'); // 移除引号
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Warning($"获取开机自启动路径失败: {ex.Message}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import { globalIgnores } from 'eslint/config';
|
||||||
|
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript';
|
||||||
|
import pluginVue from 'eslint-plugin-vue';
|
||||||
|
import pluginVitest from '@vitest/eslint-plugin';
|
||||||
|
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting';
|
||||||
|
import tsParser from '@typescript-eslint/parser';
|
||||||
|
import vuePlugin from 'eslint-plugin-vue';
|
||||||
|
import tsPlugin from '@typescript-eslint/eslint-plugin';
|
||||||
|
import prettier from 'eslint-config-prettier';
|
||||||
|
export default defineConfigWithVueTs({
|
||||||
|
name: 'app/files-to-lint',
|
||||||
|
files: ['**/*.{ts,mts,tsx,vue}']
|
||||||
|
}, globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']), pluginVue.configs['flat/essential'], vueTsConfigs.recommended,
|
||||||
|
// 重要:确保自定义规则配置优先级更高
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
// 完全禁用未使用变量的检查 - 更强力的方式
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'no-unused-vars': 'off'
|
||||||
|
// 或者使用你之前的配置(二选一)
|
||||||
|
/*
|
||||||
|
'@typescript-eslint/no-unused-vars': ['warn', {
|
||||||
|
'varsIgnorePattern': '^_',
|
||||||
|
'argsIgnorePattern': '^_',
|
||||||
|
// 添加更多宽松配置
|
||||||
|
'ignoreRestSiblings': true,
|
||||||
|
'caughtErrors': 'none'
|
||||||
|
}],
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
...pluginVitest.configs.recommended,
|
||||||
|
files: ['src/**/__tests__/*'],
|
||||||
|
languageOptions: {
|
||||||
|
parser: tsParser,
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
globals: {
|
||||||
|
window: 'readonly',
|
||||||
|
document: 'readonly'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
vue: vuePlugin,
|
||||||
|
'@typescript-eslint': tsPlugin
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// ❗ 严重错误(保留)
|
||||||
|
'no-undef': 'error',
|
||||||
|
'vue/no-unused-components': 'warn',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'warn',
|
||||||
|
// ✅ 风格类(宽松)
|
||||||
|
'vue/multi-word-component-names': 'off',
|
||||||
|
'vue/max-attributes-per-line': 'off',
|
||||||
|
'@typescript-eslint/no-non-null-assertion': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
// ✅ 开发方便
|
||||||
|
'no-console': 'off',
|
||||||
|
'no-debugger': 'warn'
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
...prettier
|
||||||
|
}, skipFormatting);
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import type { IBridge, LogParam, MessagePayload } from './IBridge'
|
||||||
|
|
||||||
|
export class CSharpBridge implements IBridge {
|
||||||
|
private eventListeners = new Map<string, Set<(...args: any[]) => void>>()
|
||||||
|
|
||||||
|
log(param: LogParam): void {
|
||||||
|
console.log(`[${param.level.toUpperCase()}] ${param.message}`, param.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
async invokeMethod(methodName: string, ...args: any[]): Promise<any> {
|
||||||
|
// 默认实现
|
||||||
|
console.warn(`CSharpBridge.invokeMethod not implemented: ${methodName}`, args)
|
||||||
|
return Promise.resolve(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener(eventName: string, callback: (...args: any[]) => void): void {
|
||||||
|
if (!this.eventListeners.has(eventName)) {
|
||||||
|
this.eventListeners.set(eventName, new Set())
|
||||||
|
}
|
||||||
|
this.eventListeners.get(eventName)!.add(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeEventListener(eventName: string, callback: (...args: any[]) => void): void {
|
||||||
|
const listeners = this.eventListeners.get(eventName)
|
||||||
|
if (listeners) {
|
||||||
|
listeners.delete(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected emit(eventName: string, ...args: any[]): void {
|
||||||
|
const listeners = this.eventListeners.get(eventName)
|
||||||
|
if (listeners) {
|
||||||
|
listeners.forEach(callback => callback(...args))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// 桥接接口定义
|
||||||
|
export interface IBridge {
|
||||||
|
log(param: LogParam): void
|
||||||
|
invokeMethod(methodName: string, ...args: any[]): Promise<any>
|
||||||
|
addEventListener(eventName: string, callback: (...args: any[]) => void): void
|
||||||
|
removeEventListener(eventName: string, callback: (...args: any[]) => void): void
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LogParam {
|
||||||
|
level: 'info' | 'warn' | 'error' | 'debug'
|
||||||
|
message: string
|
||||||
|
data?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessagePayload<T = any> {
|
||||||
|
type: string
|
||||||
|
data: T
|
||||||
|
timestamp?: number
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
import { CSharpBridge } from './CSharpBridge'
|
||||||
|
import type { LogParam } from './IBridge'
|
||||||
|
|
||||||
|
export class TauriBridge extends CSharpBridge {
|
||||||
|
async invokeMethod(methodName: string, ...args: any[]): Promise<any> {
|
||||||
|
try {
|
||||||
|
// 如果运行在 Tauri 环境中
|
||||||
|
if (window.__TAURI__) {
|
||||||
|
const { invoke } = window.__TAURI__.tauri
|
||||||
|
return await invoke(methodName, ...args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 否则使用父类的默认实现
|
||||||
|
return super.invokeMethod(methodName, ...args)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`TauriBridge.invokeMethod error:`, error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log(param: LogParam): void {
|
||||||
|
// 在 Tauri 环境中,可以使用更高级的日志记录
|
||||||
|
super.log(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扩展 Window 接口
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
__TAURI__?: {
|
||||||
|
tauri: {
|
||||||
|
invoke: (cmd: string, ...args: any[]) => Promise<any>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
declare const _default: import("vite").UserConfigFnObject;
|
||||||
|
export default _default;
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { fileURLToPath, URL } from 'node:url';
|
||||||
|
import { defineConfig, loadEnv } from 'vite';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
import AutoImport from 'unplugin-auto-import/vite';
|
||||||
|
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers';
|
||||||
|
import Components from 'unplugin-vue-components/vite';
|
||||||
|
export default defineConfig(({ mode }) => {
|
||||||
|
const env = loadEnv(mode, process.cwd());
|
||||||
|
return {
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
AutoImport({
|
||||||
|
imports: [
|
||||||
|
'vue',
|
||||||
|
{
|
||||||
|
'naive-ui': [
|
||||||
|
'useDialog',
|
||||||
|
'useMessage',
|
||||||
|
'useNotification',
|
||||||
|
'useLoadingBar'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
Components({
|
||||||
|
resolvers: [NaiveUiResolver()]
|
||||||
|
})
|
||||||
|
],
|
||||||
|
// 防止 Vite 掩盖 Rust 错误
|
||||||
|
clearScreen: false,
|
||||||
|
server: {
|
||||||
|
port: 3000,
|
||||||
|
strictPort: true,
|
||||||
|
host: "0.0.0.0",
|
||||||
|
watch: {},
|
||||||
|
},
|
||||||
|
build: {},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
Reference in new issue
Block a user