初始化

This commit is contained in:
2025-11-20 14:07:55 +08:00
commit b9b1ff5ed4
318 changed files with 42662 additions and 0 deletions

18
.gitignore vendored Normal file
View File

@@ -0,0 +1,18 @@
/AUTS_New.Server/bin
/AUTS_New.Server/obj
/auts_new.client/.github
/.vs
/auts_new.client/obj
/AUTS_New.Server/*.user
/ViewModels/bin
/ViewModels/obj
/auts_new_mobile.client/auts_new_mobile.client.esproj.user
/AUTS_New.slnLaunch.user
/AUTS_New.Server/.config
/AUTS_New.Server/Properties/PublishProfiles/FolderProfile.pubxml.user
/AUTS_New.Server/Properties/PublishProfiles/FolderProfile.pubxml
/WebAPIServer/obj
/WebAPIServer/WebAPIServer.csproj.user
/WebAPIServer/bin
/auts_new_mobile.client/obj

39
AUTS_New.sln Normal file
View File

@@ -0,0 +1,39 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35527.113
MinimumVisualStudioVersion = 10.0.40219.1
Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "auts_new_mobile.client", "auts_new_mobile.client\auts_new_mobile.client.esproj", "{26571D6C-BE81-77E9-E9F2-92AA4EF59DAE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ViewModels", "ViewModels\ViewModels.csproj", "{55936537-3749-C7DC-F15C-3531E8498743}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebAPIServer", "WebAPIServer\WebAPIServer.csproj", "{A9D49D8F-14C1-413E-AB94-87CF21F0B3B8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{26571D6C-BE81-77E9-E9F2-92AA4EF59DAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26571D6C-BE81-77E9-E9F2-92AA4EF59DAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26571D6C-BE81-77E9-E9F2-92AA4EF59DAE}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{26571D6C-BE81-77E9-E9F2-92AA4EF59DAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26571D6C-BE81-77E9-E9F2-92AA4EF59DAE}.Release|Any CPU.Build.0 = Release|Any CPU
{26571D6C-BE81-77E9-E9F2-92AA4EF59DAE}.Release|Any CPU.Deploy.0 = Release|Any CPU
{55936537-3749-C7DC-F15C-3531E8498743}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{55936537-3749-C7DC-F15C-3531E8498743}.Debug|Any CPU.Build.0 = Debug|Any CPU
{55936537-3749-C7DC-F15C-3531E8498743}.Release|Any CPU.ActiveCfg = Release|Any CPU
{55936537-3749-C7DC-F15C-3531E8498743}.Release|Any CPU.Build.0 = Release|Any CPU
{A9D49D8F-14C1-413E-AB94-87CF21F0B3B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9D49D8F-14C1-413E-AB94-87CF21F0B3B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9D49D8F-14C1-413E-AB94-87CF21F0B3B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A9D49D8F-14C1-413E-AB94-87CF21F0B3B8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3D0E4D8-C7F9-460C-9332-1F802FDBBE22}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using CSRedis;
namespace ViewModels.Common
{
/// <summary>
/// Redis缓存辅助类
/// </summary>
public class CSRedisCacheHelper
{
public static CSRedisClient redis;
private static int SessionExpireMinutes = int.Parse(ReadConfig.Instance.get_session_expire_minutes);
//private static int RedisMaxReadPool = int.Parse(ConfigurationManager.AppSettings["redis_max_read_pool"]);
//private static int RedisMaxWritePool = int.Parse(ConfigurationManager.AppSettings["redis_max_write_pool"]);
//private const string ip = "127.0.0.1";
//private const string port = "6379";
//private const string preheat = "100"; // 设置预热连接数
//private const string connectTimeout = "100"; // 设置连接超时时间
//private const string tryit = "1"; // 设置重试次数
//private const string prefix = "CSRedisTest."; // 设置前缀
//private static readonly string _connectString = $"{ip}:{port},preheat={preheat},connectTimeout={connectTimeout},tryit={tryit},prefix={prefix}";
static CSRedisCacheHelper()
{
//var redisHostStr = ConfigurationManager.AppSettings["redis_server_session"];
var redisHostStr = ReadConfig.Instance.get_redis_server_session;
if (!string.IsNullOrEmpty(redisHostStr))
{
//redis = new CSRedisClient(redisHostStr);//+ ",password=,defaultDatabase=0,poolsize=500,ssl=false,writeBuffer=10240,prefix=");
//RedisHelper.Initialization(redis);
//redis = new CSRedisClient[2];
redis = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=1");
//redis[1] = new CSRedisClient(redisHostStr + ",password=,defaultDatabase=1");
}
}
/// <summary>
/// 添加缓存
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
public static void Set<T>(string key, T value)
{
redis.Set(key, value, SessionExpireMinutes * 60);
}
public static T Get<T>(string key)
{
return redis.Get<T>(key);
}
public static void Forever<T>(string key, T value)
{
redis.Set(key, value, -1);
}
public static void Del(string key)
{
redis.Del(key);
}
/// <summary>
/// 判断是否存在
/// </summary>
/// <param name="key"></param>
/// <param name="mac"></param>
/// <returns></returns>
public static bool Contains(string key, string mac)
{
bool result = redis.Exists(mac);
if (!result)
{
result = redis.Exists(key);
}
return result;
}
public static bool Contains(string key)
{
bool result = redis.Exists(key);
return result;
}
/// <summary>
/// 添加Hash缓存
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <param name="value"></param>
public static void HMSet<T>(string key, T value)
{
redis.HMSet(key, value);
}
/// <summary>
/// 获取Hash缓存
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public static T[] HMGet<T>(string key)
{
return redis.HMGet<T>(key);
}
/// <summary>
/// 删除Hash缓存
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="key"></param>
/// <returns></returns>
public static long HDel<T>(string key)
{
return redis.HDel(key);
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ViewModels.Common
{
public class CacheKey
{
public static string RoomIP_Port_Prefix = "Log_IP_Port";
public static string Key = "monitor_host";
public static string MonitorLogPrefix = "AllLogKey";
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
namespace ViewModels.Common
{
public class ReadConfig
{
public static ReadConfig Instance = new ReadConfig();
public IConfiguration? Configuration { get; set; }
public string? MySQLConnectionString { get; set; }
public string? get_monitor_filter { get; set; }
public string? get_session_expire_minutes { get; set; }
public string? get_redis_server_session { get; set; }
public string? get_redis_max_read_pool { get; set; }
public string? get_redis_max_write_pool { get; set; }
public string? MQTT_ServerIP { get; set; }
public int? MQTT_ServerPort { get; set; }
public string? MQTT_User { get; set; }
public string? MQTT_PassWord { get; set; }
public ReadConfig()
{
Configuration = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("app.json").Build();
MySQLConnectionString = Configuration.GetConnectionString("SQLServerConnectionString");
get_session_expire_minutes = Configuration.GetSection("session_expire_minutes").Value;
get_redis_server_session = Configuration.GetSection("redis_server_session").Value;
get_redis_max_read_pool = Configuration.GetSection("redis_max_read_pool").Value;
get_redis_max_write_pool = Configuration.GetSection("redis_max_write_pool").Value;
MQTT_ServerIP = Configuration.GetSection("MQTT_ServerIP").Value;
int p = 1883;
int.TryParse(Configuration.GetSection("MQTT_ServerPort").Value, out p);
MQTT_ServerPort = p;
MQTT_User = Configuration.GetSection("MQTT_User").Value;
MQTT_PassWord = Configuration.GetSection("MQTT_PWD").Value;
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ViewModels.RequestData
{
public class LoginData
{
public string username { get; set; }
public string password { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ViewModels.ResponseData
{
public class ResLoginData
{
public int ID { get; set; }
public string UserName { get; set; }
public bool IsAdmin { get; set; }
public string AccessToken { get; set; }
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ViewModels
{
public class ReturnResult
{
public int Status { get; set; }
public string Message { get; set; }
}
public class QueryAll_Or_Single
{
public bool IsAll { get; set; }
public int ID { get; set; }
}
public class ReturnInfo
{
public bool isok { set; get; } // 是否成功true成功
public string message { set; get; } // 传递接口信息or报错信息
public int status { set; get; } // 服务器报错信息正确为200错误404/500等
public object response { set; get; } // 获取到的信息本体若报错则为null
}
public class ReturnInfoPage : ReturnInfo
{
public long total { set; get; } // 总条数
}
}

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CSRedisCore" Version="3.8.804" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.3" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.3" />
<PackageReference Include="RestSharp" Version="112.1.0" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "9.0.3",
"commands": [
"dotnet-ef"
],
"rollForward": false
}
}
}

View File

@@ -0,0 +1,13 @@
using Microsoft.Extensions.Caching.Memory;
namespace WebAPIServer.Common
{
public class MyMemoryCache
{
public MemoryCache Cache { get; } = new MemoryCache(
new MemoryCacheOptions
{
SizeLimit = 4096
});
}
}

View File

@@ -0,0 +1,16 @@
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
namespace WebAPIServer.Common
{
public class StaticData
{
public static ScriptEngine eng = Python.CreateEngine();
public static ScriptScope scope = eng.CreateScope();
public static void GetWebAPIMethod()
{
eng.ExecuteFile("ScriptConfig\\webapi.py", scope);
}
}
}

View File

@@ -0,0 +1,48 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ViewModels;
using WebAPIServer.Models;
namespace WebAPIServer.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class CompanyController : ControllerBase
{
[HttpPost()]
[Authorize()]
public ReturnInfo GetCompanyInfo([FromBody] QueryAll_Or_Single S)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
using (var q=new UtsManageContext())
{
if (S.IsAll)
{
returnInfo.isok = true;
returnInfo.response = q.TblUtsManageCompanies.ToList();
}
else
{
returnInfo.isok = true;
var a = q.TblUtsManageUsers.SingleOrDefault(A => A.Id == S.ID);
if (a != null)
{
returnInfo.response = a;
}
}
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
}
}

View File

@@ -0,0 +1,275 @@
using ClosedXML.Excel;
using IronPython.Hosting;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.Extensions.Caching.Memory;
using MySqlConnector;
using NLog;
using System.Data;
using System.Text;
using ViewModels;
using WebAPIServer.Common;
using WebAPIServer.Models;
namespace WebAPIServer.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class DataHandleController : ControllerBase
{
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
public readonly IMemoryCache _memoryCache;
public DataHandleController(IMemoryCache memoryCache)
{
this._memoryCache = memoryCache;
}
[HttpPost()]
public string NNN()
{
return "hello";
}
[HttpPost()]
[Authorize()]
public ReturnInfo R_InfoCommon([FromBody] PageQueryData S)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
string KKK = "";
if (S.DBQueryData.Count > 0)
{
KKK = string.Join('_', S.DBQueryData);
}
string NK = S.Key + S.CmdType??"" + KKK;
var ooo = _memoryCache.Get<List<Dictionary<string, object>>>(NK);
if (ooo != null)
{
list = ooo;
}
else
{
using (var q = new UtsManageContext())
{
using IDbConnection conn = q.Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
IDbCommand cmd = conn.CreateCommand();
string VariableName = S.Key;
string result = "";
if (S.isFunction)
{
if (S.FunParameters.Count == 1)
{
result = StaticData.scope.GetVariable(VariableName)(S.FunParameters[0]);
}
if (S.FunParameters.Count == 2)
{
result = StaticData.scope.GetVariable(VariableName)(S.FunParameters[0], S.FunParameters[1]);
}
if (S.FunParameters.Count == 3)
{
result = StaticData.scope.GetVariable(VariableName)(S.FunParameters[0], S.FunParameters[1], S.FunParameters[2]);
}
if (S.FunParameters.Count == 4)
{
result = StaticData.scope.GetVariable(VariableName)(S.FunParameters[0], S.FunParameters[1], S.FunParameters[2], S.FunParameters[3]);
}
if (S.FunParameters.Count == 5)
{
result = StaticData.scope.GetVariable(VariableName)(S.FunParameters[0], S.FunParameters[1], S.FunParameters[2], S.FunParameters[3], S.FunParameters[4]);
}
}
else
{
result = StaticData.scope.GetVariable(VariableName);
}
var Q = S.DBQueryData;
if (S.CmdType.Equals("sys"))
{
foreach (var item in Q)
{
result = result.Replace(item.Key, item.Value);
}
}
else
{
foreach (QueryString item in Q)
{
if (item.ValueType.Equals("string"))
{
MySqlParameter mmm = new MySqlParameter(item.Key, item.Value);
cmd.Parameters.Add(mmm);
}
else if (item.ValueType.Equals("number"))
{
decimal a = 0;
decimal.TryParse(item.Value, out a);
MySqlParameter mmm = new MySqlParameter(item.Key, a);
cmd.Parameters.Add(mmm);
}
}
}
cmd.CommandText = result;
cmd.CommandType = CommandType.Text;
MySqlCommand command = cmd as MySqlCommand;
MySqlDataAdapter adapter = new MySqlDataAdapter(command);
DataSet ds = new DataSet();
adapter.Fill(ds);
DataTable dt = ds.Tables[0];
//string str= System.Text.Json.JsonSerializer.Serialize(dt);
foreach (DataRow item in dt.Rows)
{
Dictionary<string, object> dic = new Dictionary<string, object>();
foreach (DataColumn item1 in dt.Columns)
{
string CName = item1.ColumnName;
dic.Add(CName, item[CName]);
}
list.Add(dic);
}
}
}
returnInfo.isok = true;
returnInfo.response = list;
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
[HttpPost()]
[Authorize()]
public ReturnInfo CUD_InfoCommon([FromBody] PageQueryData S)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
using (var q = new UtsManageContext())
{
using IDbConnection conn = q.Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
IDbCommand cmd = conn.CreateCommand();
string VariableName = S.Key;
string result = "";
if (S.isFunction)
{
var LG = S.FunParameters;
result = StaticData.scope.GetVariable(VariableName)(S.FunParameters);
}
else
{
result = StaticData.scope.GetVariable(VariableName);
}
var Q = S.DBQueryData;
if (S.CmdType.Equals("sys"))
{
foreach (var item in Q)
{
result = result.Replace(item.Key, item.Value);
}
}
else
{
foreach (QueryString item in Q)
{
if (item.ValueType.Equals("string"))
{
MySqlParameter mmm = new MySqlParameter(item.Key, item.Value);
cmd.Parameters.Add(mmm);
}
else if (item.ValueType.Equals("number"))
{
decimal a = 0;
decimal.TryParse(item.Value, out a);
MySqlParameter mmm = new MySqlParameter(item.Key, a);
cmd.Parameters.Add(mmm);
}
}
}
cmd.CommandText = result;
cmd.CommandType = CommandType.Text;
object ooo = cmd.ExecuteNonQuery();
returnInfo.response = ooo;
returnInfo.isok = true;
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
[HttpPost()]
public ReturnInfo III([FromBody] PageQueryData S)
{
var NNN = S.FunParameters;
var result = StaticData.scope.GetVariable("a")(NNN);
return null;
}
}
public record PageQueryData
{
public string Key { get; set; }
public bool isFunction { get; set; } = false;
/// <summary>
/// 参数最多直接5个参数
/// </summary>
public List<string>? FunParameters { get; set; }
//sys
//customer
public string? CmdType { get; set; }
public List<QueryString>? DBQueryData { get; set; }
}
public class FunParameter
{
public string PKey { get; set; }
public string PValue { get; set; }
}
public record QueryString
{
public string Key { get; set; }
public string Value { get; set; }
public string ValueType { get; set; }
}
}

View File

@@ -0,0 +1,395 @@
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using ViewModels;
using Microsoft.Extensions.Configuration;
using System;
using System.Linq;
using ViewModels.RequestData;
using ViewModels.ResponseData;
using WebAPIServer.Extensions;
using WebAPIServer.Models;
using System.Net;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using RestSharp;
using UAParser;
using UAParser.Objects;
using NLog;
namespace WebAPIServer.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class LoginController : ControllerBase
{
public IConfiguration? configuration { get; set; }
public LoginController(IConfiguration _configuration)
{
configuration = _configuration;
}
[Authorize()]
[HttpPost()]
public ReturnInfo TokenXuQi()
{
ReturnInfo r = new ReturnInfo();
r.isok = false;
try
{
var claims = HttpContext.AuthenticateAsync().Result?.Principal?.Claims;
if (claims != null && claims.Any())
{
var Name = claims.SingleOrDefault(A => A.Type == ClaimTypes.Name)?.Value;
var UUU = claims.SingleOrDefault(A => A.Type == ClaimTypes.Role)?.Value;
var TTT = claims.SingleOrDefault(A => A.Type == ClaimTypes.NameIdentifier)?.Value;
TblUtsManageUser? HH = new TblUtsManageUser();
int a = 0;
int.TryParse(TTT, out a);
HH.Id = a;
bool bl = false;
bool.TryParse(UUU, out bl);
HH.IsAdmin = bl;
HH.UserName = Name;
string TokenStr = GetToken(HH);
r.isok = true;
r.response = TokenStr;
}
}
catch (Exception ex)
{
r.isok = false;
r.message = ex.Message;
}
return r;
//var identity = HttpContext.User.Identity as ClaimsIdentity;
//if (identity != null)
//{
// var userClaims = identity.Claims;
//}
//return "hello world";
}
[HttpGet()] // 例如一个获取验证码的API端点
public IActionResult GetCaptcha()
{
string captchaText; // 这里使用上面任一版本的GenerateCaptchaImage方法生成的文本。例如captchaText = CaptchaHelperSkiaSharp.GenerateCaptchaImage(out captchaText); 或 captchaText = CaptchaHelper.GenerateCaptchaImage(out captchaText); 根据你的选择。
byte[] imageBytes = CaptchaHelperSkiaSharp.GenerateCaptchaImage(); // 或者使用System.Drawing的方法。确保你选择了
return Ok(new { CaptchaText = "1111", Image = Convert.ToBase64String(imageBytes) });
}
/// <summary>
/// 登录
/// </summary>
/// <param name="username">用户名</param>
/// <param name="password">密码</param>
/// <returns></returns>
[HttpPost]
public ReturnInfo Login([FromBody] LoginData data)
{
ReturnInfo res = new ReturnInfo();
try
{
string password = data.password;
string username = data.username;
TblUtsManageUser? entity = null;
string TokenString = "";
string pwd = password.ToMD5().ToMD5();
using (var q = new UtsManageContext())
{
entity = q.TblUtsManageUsers.SingleOrDefault(A => A.UserName.Equals(username) && A.Password.Equals(pwd));
if (entity != null)
{
TokenString = GetToken(entity);
res.isok = true;
ResLoginData r = new ResLoginData();
r.AccessToken = TokenString;
r.IsAdmin = entity.IsAdmin;
r.ID = entity.Id;
r.UserName = entity.UserName;
res.response = r;
}
else
{
res.isok = false;
res.message = "用户名或密码错误";
}
}
}
catch (Exception ex)
{
res.message = ex.Message;
res.isok = false;
}
return res;
}
private string GetToken(TblUtsManageUser? entity)
{
string TokenString;
var claims = new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, entity.Id.ToString()),
new Claim(ClaimTypes.Role, entity.IsAdmin.ToString()),
new Claim(ClaimTypes.Name, entity.UserName)
};
var secretByte = Encoding.UTF8.GetBytes(configuration["JwT:SecretKey"]);
var signingKey = new SymmetricSecurityKey(secretByte);
var a = SecurityAlgorithms.HmacSha256;
var signingCredentials = new SigningCredentials(signingKey, a);
var token = new JwtSecurityToken(
issuer: configuration["JwT:Issuer"],
audience: configuration["JwT:Audience"],//接收
claims: claims,//存放的用户信息
notBefore: DateTime.UtcNow,//发布时间
expires: DateTime.UtcNow.AddDays(3),//过期时间
signingCredentials: signingCredentials
//有效期设置为1天signingCredentials //数字名
);
TokenString = new JwtSecurityTokenHandler().WriteToken(token);
return TokenString;
}
public class LLLG
{
public string UserName { get; set; }
public string Database { get; set; }
}
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
[Authorize()]
[HttpPost()]
public ReturnInfo LogRecord([FromBody] LLLG data)
{
ReturnInfo res = new ReturnInfo();
try
{
string Device = "Unknown";
#region
var userAgent = Request.Headers["User-Agent"].ToString();
bool
_windows = userAgent.Contains("Windows NT"),
_mac = userAgent.Contains("Macintosh"),
_iphone = userAgent.Contains("iPhone"),
_android = userAgent.Contains("Android")
;
if (_windows)
{
Device = "windows";
}
else if (_mac)
{
Device = "Mac";
}
else if (_iphone)
{
Device = "ios";
}
else if (_android)
{
Device = "Android";
}
else
{
Device = "未知";
}
#endregion
//获得IP
string? ip = string.Empty;
string? NNN = HttpContext?.Request?.HttpContext?.Connection?.RemoteIpAddress?.ToString();
if (string.IsNullOrEmpty(NNN))
{
ip = HttpContext?.Request.Headers["HTTP_X_FORWARDED_FOR"];
}
else
{
ip = NNN;
}
var uaParser = Parser.GetDefault();
ClientInfo c = uaParser.Parse(userAgent);
using (var q = new UtsManageContext())
{
TblUtsUseroperation t = new TblUtsUseroperation();
t.CreationTime = DateTime.Now;
t.UserName = data.UserName;
t.Ip = ip;
t.Browser = c.Browser.Family + " " + c.Browser.Major + "." + c.Browser.Minor;
t.Operation = "登录";
t.Database = data.Database;
t.Device = Device;
if (ip.Equals("::1"))
{
t.Location = "本地";
}
else
{
t.Location = GetBaiduIp(ip);
}
q.TblUtsUseroperations.Add(t);
q.SaveChanges();
res.isok = true;
res.response = "sucess";
}
}
catch (Exception ex)
{
_logger.Error(ex.Message);
res.isok = false;
res.response = ex.Message;
}
return res;
}
public static void UserLog(string Openration, string Device)
{
}
[HttpPost()]
[Authorize()]
public string Helloooo()
{
return "hello";
}
[HttpGet()]
public string AccessDenied()
{
return "aaaa";
}
/// <summary>
/// 百度api
/// </summary>
/// <returns></returns>
public static string GetBaiduIp(string ip)
{
string location = "";
try
{
string url = $"https://sp0.baidu.com";
//WebClient client = new WebClient();
RestSharp.RestClient client1 = new RestSharp.RestClient(url);
RestSharp.RestRequest request = new RestSharp.RestRequest($"/8aQDcjqpAAV3otqbppnN2DJv/api.php?query={ip}&co=&resource_id=6006&oe=utf8", Method.Get);
var buffer = client1.DownloadData(request);
//var buffer = client.DownloadData(url);
string jsonText = Encoding.UTF8.GetString(buffer);
JObject jo = JObject.Parse(jsonText);
Root root = JsonConvert.DeserializeObject<Root>(jo.ToString());
foreach (var item in root.data)
{
location = item.location;
}
return location;
}
catch (Exception ex)
{
//Console.WriteLine(ex);
return location;
}
}
}
public class Root
{
public List<DataItem> data { get; set; }
}
public class DataItem
{
/// <summary>
///
/// </summary>
public string ExtendedLocation { get; set; }
/// <summary>
///
/// </summary>
public string OriginQuery { get; set; }
/// <summary>
///
/// </summary>
public string appinfo { get; set; }
/// <summary>
///
/// </summary>
public int disp_type { get; set; }
/// <summary>
///
/// </summary>
public string fetchkey { get; set; }
/// <summary>
/// 本地局域网
/// </summary>
public string location { get; set; }
/// <summary>
///
/// </summary>
public string origip { get; set; }
/// <summary>
///
/// </summary>
public string origipquery { get; set; }
/// <summary>
///
/// </summary>
public string resourceid { get; set; }
/// <summary>
///
/// </summary>
public int role_id { get; set; }
/// <summary>
///
/// </summary>
public int shareImage { get; set; }
/// <summary>
///
/// </summary>
public int showLikeShare { get; set; }
/// <summary>
///
/// </summary>
public string showlamp { get; set; }
/// <summary>
/// IP地址查询
/// </summary>
public string titlecont { get; set; }
/// <summary>
///
/// </summary>
public string tplt { get; set; }
}
}

View File

@@ -0,0 +1,515 @@
using ClosedXML.Excel;
using IronPython.Hosting;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
using Microsoft.IdentityModel.Tokens;
using MySqlConnector;
using NLog;
using System.Data;
using System.Text;
using ViewModels;
using WebAPIServer.Common;
using WebAPIServer.Models;
namespace WebAPIServer.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class TestLogsController : ControllerBase
{
/// <summary>
/// 每个步骤返回多条测试记录
/// </summary>
[HttpPost()]
[Authorize()]
public ReturnInfo GetLogListBySN([FromBody] TestLogsQueryModel T)
{
ReturnInfo returnInfo = new();
try
{
using (var q = new UtsManageContext())
{
using IDbConnection conn = q.Database.GetDbConnection();
conn.Open();
List<ReturnTestLogs> tl = [];
foreach (var item in T.DbList)
{
string tableName = $"{T.DBName}.tbl_{item.ProId}_{item.Step}_testlog";
// 修改点1移除了MAX聚合函数查询所有匹配记录
string sql = $"SELECT * FROM {tableName} WHERE DUT_SN = '{T.SnCode}'";
using MySqlCommand command = new(sql, (MySqlConnection)conn);
using MySqlDataAdapter adapter = new(command);
DataSet ds = new();
adapter.Fill(ds);
if (ds.Tables.Count == 0 || ds.Tables[0].Rows.Count == 0)
{
// 没有数据时仍创建空对象(保持原有结构)
tl.Add(new ReturnTestLogs
{
Step = item.Step,
ID = "",
StartTime = "",
UsedTime = "",
FailSteps = "",
FailMsg = "",
TestResult = "",
RObj = new List<Dictionary<string, string>>()
});
}
else
{
// 修改点2处理所有行数据
foreach (DataRow row in ds.Tables[0].Rows)
{
var log = new ReturnTestLogs
{
Step = item.Step,
ID = row["ID"]?.ToString() ?? "",
StartTime = row["StartTime"]?.ToString() ?? "",
UsedTime = row["UsedTime"]?.ToString() ?? "",
FailSteps = row["FailSteps"]?.ToString() ?? "",
FailMsg = row["FailMsg"]?.ToString() ?? "",
TestResult = row["TestResult"]?.ToString() ?? "",
RObj = []
};
// 修改点3每行数据单独创建字典
var rowData = new Dictionary<string, string>();
foreach (DataColumn col in ds.Tables[0].Columns)
{
rowData[col.ColumnName] = row[col]?.ToString() ?? "";
}
log.RObj.Add(rowData);
tl.Add(log);
}
}
}
returnInfo.isok = true;
returnInfo.response = tl;
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
/// <summary>
/// 测试总表Excel
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost()]
[Authorize()]
public IActionResult GetTestSummaryTableExcel([FromBody] TestLogExportRequest request)
{
try
{
string? dbName = request.dbName;
string? tbName = request.tbName;
string? startDate = request.StartTime;
string? endDate = request.EndTime;
string? testResult = request.TestResult;
List<string>? failSteps = request.FailSteps;
string? columnList = request.ColumnList;
string distinctType = request.DistinctType ?? "None"; // 获取去重类型
if (string.IsNullOrEmpty(startDate) || string.IsNullOrEmpty(endDate))
{
return BadRequest("开始时间或结束时间不能为空");
}
using (var q = new UtsManageContext())
{
using IDbConnection conn = q.Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
// 构建查询
StringBuilder dataQuery = new StringBuilder();
if (distinctType == "None")
{
// 不去重的情况
dataQuery.Append("SELECT ID, ServiceID AS SID, StartTime, DUT_SN, TestResult, Failsteps");
if (!string.IsNullOrEmpty(columnList))
{
dataQuery.Append(columnList);
}
dataQuery.Append($" FROM {dbName}.{tbName} ");
dataQuery.Append($"WHERE StartTime BETWEEN '{startDate} 00:00:00' AND '{endDate} 23:59:59' ");
}
else
{
// 去重的情况
string orderDirection = distinctType == "Latest" ? "DESC" : "ASC";
dataQuery.Append("SELECT ID, ServiceID AS SID, StartTime, DUT_SN, TestResult, Failsteps");
if (!string.IsNullOrEmpty(columnList))
{
dataQuery.Append(columnList);
}
dataQuery.Append(" FROM (");
dataQuery.Append("SELECT *, ROW_NUMBER() OVER (PARTITION BY DUT_SN ORDER BY StartTime ");
dataQuery.Append(orderDirection);
dataQuery.Append($") AS rn FROM {dbName}.{tbName} ");
dataQuery.Append($"WHERE StartTime BETWEEN '{startDate} 00:00:00' AND '{endDate} 23:59:59' ");
}
if (!string.IsNullOrEmpty(testResult))
{
dataQuery.Append($"AND TestResult = '{testResult}' ");
}
if (failSteps != null && failSteps.Count > 0)
{
string failStepsCondition = string.Join(",", failSteps.Select(f => $"'{MySqlHelper.EscapeString(f)}'"));
dataQuery.Append($"AND Failsteps IN ({failStepsCondition}) ");
}
if (distinctType != "None")
{
dataQuery.Append(") t WHERE rn = 1 ");
}
dataQuery.Append("ORDER BY StartTime DESC");
// 执行数据查询
IDbCommand dataCmd = conn.CreateCommand();
dataCmd.CommandText = dataQuery.ToString();
MySqlCommand command = dataCmd as MySqlCommand;
MySqlDataAdapter adapter = new(command);
DataSet ds = new();
adapter.Fill(ds);
DataTable dt = ds.Tables[0];
// 使用ClosedXML创建Excel
using (var workbook = new XLWorkbook())
{
var worksheet = workbook.Worksheets.Add(dt, "Sheet");
// 设置标题行样式
var headerRow = worksheet.Row(1);
headerRow.Style.Font.Bold = true;
// 自动调整列宽
worksheet.Columns().AdjustToContents();
using (var stream = new MemoryStream())
{
workbook.SaveAs(stream);
var content = stream.ToArray();
return File(content, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", $"{tbName}_Export.xlsx");
}
}
}
}
catch (Exception ex)
{
return StatusCode(500, $"导出失败: {ex.Message}");
}
}
public ReturnInfoPage GetTestSummaryTable([FromBody] TestLog T)
{
ReturnInfoPage returnInfo = new();
string? dbName = T.dbName;
string? tbName = T.tbName;
string? StartTime = T.StartTime;
string? EndTime = T.EndTime;
string? TestResult = T.TestResult;
List<string>? FailSteps = T.FailSteps;
string? ColumnList = T.ColumnList;
int page = T.Page;
int pageSize = T.PageSize;
string distinctType = T.DistinctType ?? "None"; // 获取去重类型,默认为不去重
if (string.IsNullOrEmpty(StartTime) || string.IsNullOrEmpty(EndTime))
{
returnInfo.isok = false;
returnInfo.message = "开始时间或结束时间不能为空";
return returnInfo;
}
try
{
using (var q = new UtsManageContext())
{
using IDbConnection conn = q.Database.GetDbConnection();
if (conn.State != ConnectionState.Open)
{
conn.Open();
}
// 1. 构建基础查询(总数查询)
StringBuilder baseQuery = new StringBuilder();
if (distinctType == "None")
{
// 不去重的情况
baseQuery.Append($"SELECT COUNT(*) AS Total FROM {dbName}.{tbName} ");
baseQuery.Append($"WHERE StartTime BETWEEN '{StartTime} 00:00:00' AND '{EndTime} 23:59:59' ");
}
else
{
// 去重的情况,需要计算去重后的总数
baseQuery.Append($"SELECT COUNT(DISTINCT DUT_SN) AS Total FROM {dbName}.{tbName} ");
baseQuery.Append($"WHERE StartTime BETWEEN '{StartTime} 00:00:00' AND '{EndTime} 23:59:59' ");
}
if (!string.IsNullOrEmpty(TestResult))
{
baseQuery.Append($"AND TestResult = '{TestResult}' ");
}
if (FailSteps != null && FailSteps.Count > 0)
{
// 使用IN语句查询多个失败步骤
string failStepsCondition = string.Join(",", FailSteps.Select(f => $"'{MySqlHelper.EscapeString(f)}'"));
baseQuery.Append($"AND Failsteps IN ({failStepsCondition}) ");
}
// 执行总数查询
IDbCommand countCmd = conn.CreateCommand();
countCmd.CommandText = baseQuery.ToString();
long totalCount = Convert.ToInt64(countCmd.ExecuteScalar());
// 2. 计算总通过数
long totalPassCount = 0;
StringBuilder totalPassQuery = new StringBuilder();
if (distinctType == "None")
{
// 不去重的情况:统计所有通过的记录
totalPassQuery.Append($"SELECT COUNT(*) FROM {dbName}.{tbName} ");
totalPassQuery.Append($"WHERE StartTime BETWEEN '{StartTime} 00:00:00' AND '{EndTime} 23:59:59' ");
totalPassQuery.Append($"AND TestResult = '1'");
if (!string.IsNullOrEmpty(TestResult))
{
totalPassQuery.Append($"AND TestResult = '{TestResult}' ");
}
if (FailSteps != null && FailSteps.Count > 0)
{
// 使用IN语句查询多个失败步骤
string failStepsCondition = string.Join(",", FailSteps.Select(f => $"'{MySqlHelper.EscapeString(f)}'"));
totalPassQuery.Append($"AND Failsteps IN ({failStepsCondition}) ");
}
}
else
{
// 去重的情况:统计去重后记录中通过的数量
string orderDirection = distinctType == "Latest" ? "DESC" : "ASC";
totalPassQuery.Append($"SELECT COUNT(*) FROM (");
totalPassQuery.Append($"SELECT *, ROW_NUMBER() OVER (PARTITION BY DUT_SN ORDER BY StartTime {orderDirection}) AS rn ");
totalPassQuery.Append($"FROM {dbName}.{tbName} ");
totalPassQuery.Append($"WHERE StartTime BETWEEN '{StartTime} 00:00:00' AND '{EndTime} 23:59:59' ");
if (!string.IsNullOrEmpty(TestResult))
{
totalPassQuery.Append($"AND TestResult = '{TestResult}' ");
}
if (FailSteps != null && FailSteps.Count > 0)
{
// 使用IN语句查询多个失败步骤
string failStepsCondition = string.Join(",", FailSteps.Select(f => $"'{MySqlHelper.EscapeString(f)}'"));
totalPassQuery.Append($"AND Failsteps IN ({failStepsCondition}) ");
}
totalPassQuery.Append($") as t WHERE rn = 1 AND TestResult = '1'");
}
IDbCommand totalPassCmd = conn.CreateCommand();
totalPassCmd.CommandText = totalPassQuery.ToString();
totalPassCount = Convert.ToInt64(totalPassCmd.ExecuteScalar());
// 3. 计算通过率
double passRate = totalCount > 0 ? Math.Round((double)totalPassCount / totalCount * 100, 2) : 0;
// 4. 构建数据查询
StringBuilder dataQuery = new StringBuilder();
if (distinctType == "None")
{
// 不去重的情况
dataQuery.Append("SELECT ID, ServiceID AS SID, StartTime, DUT_SN, TestResult, Failsteps");
if (!string.IsNullOrEmpty(ColumnList))
{
dataQuery.Append(ColumnList);
}
dataQuery.Append($" FROM {dbName}.{tbName} ");
dataQuery.Append($"WHERE StartTime BETWEEN '{StartTime} 00:00:00' AND '{EndTime} 23:59:59' ");
}
else
{
// 去重的情况
string orderDirection = distinctType == "Latest" ? "DESC" : "ASC";
dataQuery.Append("SELECT ID, ServiceID AS SID, StartTime, DUT_SN, TestResult, Failsteps");
if (!string.IsNullOrEmpty(ColumnList))
{
dataQuery.Append(ColumnList);
}
dataQuery.Append(" FROM (");
dataQuery.Append("SELECT *, ROW_NUMBER() OVER (PARTITION BY DUT_SN ORDER BY StartTime ");
dataQuery.Append(orderDirection);
dataQuery.Append($") AS rn FROM {dbName}.{tbName} ");
dataQuery.Append($"WHERE StartTime BETWEEN '{StartTime} 00:00:00' AND '{EndTime} 23:59:59' ");
if (!string.IsNullOrEmpty(TestResult))
{
dataQuery.Append($"AND TestResult = '{TestResult}' ");
}
if (FailSteps != null && FailSteps.Count > 0)
{
// 使用IN语句查询多个失败步骤
string failStepsCondition = string.Join(",", FailSteps.Select(f => $"'{MySqlHelper.EscapeString(f)}'"));
dataQuery.Append($"AND Failsteps IN ({failStepsCondition}) ");
}
dataQuery.Append(") t WHERE rn = 1 ");
}
if (distinctType == "None")
{
// 不去重的情况下添加条件
if (!string.IsNullOrEmpty(TestResult))
{
dataQuery.Append($"AND TestResult = '{TestResult}' ");
}
if (FailSteps != null && FailSteps.Count > 0)
{
// 使用IN语句查询多个失败步骤
string failStepsCondition = string.Join(",", FailSteps.Select(f => $"'{MySqlHelper.EscapeString(f)}'"));
dataQuery.Append($"AND Failsteps IN ({failStepsCondition}) ");
}
}
// 添加排序和分页
dataQuery.Append($"ORDER BY StartTime DESC LIMIT {pageSize} OFFSET {(page - 1) * pageSize}");
// 执行数据查询
IDbCommand dataCmd = conn.CreateCommand();
dataCmd.CommandText = dataQuery.ToString();
MySqlCommand command = dataCmd as MySqlCommand;
MySqlDataAdapter adapter = new(command);
DataSet ds = new();
adapter.Fill(ds);
DataTable dt = ds.Tables[0];
// 处理结果
List<Dictionary<string, string>> list = new List<Dictionary<string, string>>();
foreach (DataRow item in dt.Rows)
{
Dictionary<string, string> dic = new Dictionary<string, string>();
foreach (DataColumn col in dt.Columns)
{
dic.Add(col.ColumnName, item[col]?.ToString() ?? "");
}
list.Add(dic);
}
returnInfo.isok = true;
returnInfo.total = totalCount;
returnInfo.response = list;
returnInfo.passCount = totalPassCount; // 修改字段名
returnInfo.passRate = passRate;
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
}
public class TestLogExportRequest
{
public string? dbName { get; set; }
public string? tbName { get; set; }
public string StartTime { get; set; }
public string EndTime { get; set; }
public string? TestResult { get; set; }
public List<string>? FailSteps { get; set; }
public string? ColumnList { get; set; }
public string DistinctType { get; set; } = "None"; // 新增字段None-不去重, Latest-保留最新, Earliest-保留最早
}
public class ReturnTestLogs
{
public string Step { get; set; }
public string ID { get; set; }
public string StartTime { get; set; }
public string UsedTime { get; set; }
public string FailSteps { get; set; }
public string FailMsg { get; set; }
public string TestResult { get; set; }
public List<Dictionary<string, string>> RObj { get; set; }
}
public class TestLogsQueryModel
{
public string DBName { get; set; }
public string SnCode { get; set; }
public List<DBL> DbList { get; set; }
}
public class DBL
{
public string ProId { get; set; }
public string Step { get; set; }
}
public class TestLog : TestLogExportRequest
{
public int Page { get; set; }
public int PageSize { get; set; }
}
// 扩展ReturnInfoPage类以包含一次通过数和通过率
public class ReturnInfoPage
{
public bool isok { get; set; }
public string message { get; set; }
public long total { get; set; }
public object response { get; set; }
public long passCount { get; set; }
public double passRate { get; set; }
}
}

View File

@@ -0,0 +1,298 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ViewModels;
using WebAPIServer.Extensions;
using WebAPIServer.Models;
namespace WebAPIServer.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class UsersController : ControllerBase
{
/// <summary>
/// 删除用户
/// </summary>
/// <param name="LLL"></param>
/// <returns></returns>
[HttpPost()]
[Authorize()]
public ReturnInfo DelUser([FromBody] TblUtsManageUser LLL)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
using (var q = new UtsManageContext())
{
var FFF = q.TblUtsManageUsers.FirstOrDefault(A => A.Id == LLL.Id);
if (FFF != null)
{
FFF.IsValid = false;
q.TblUtsManageUsers.Update(FFF);
q.SaveChanges();
returnInfo.isok = true;
}
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
/// <summary>
/// 修改用户
/// </summary>
/// <param name="LLL"></param>
/// <returns></returns>
[HttpPost()]
[Authorize()]
public ReturnInfo EditUser([FromBody] ReturnUser LLL)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
using (var q = new UtsManageContext())
{
var lll = q.TblUtsManageUsers.SingleOrDefault(A => A.Id == LLL.Id);
if (lll != null)
{
string username = LLL.UserName;
int companyId = LLL.CompanyId;
string mobile = LLL.Mobile;
string weiXin = LLL.WeiXin;
string email = LLL.Email;
lll.UserName = username;
lll.CompanyId = companyId;
lll.Mobile = mobile;
lll.WeiXin = weiXin;
lll.Email = email;
lll.UpdateTime = DateTime.Now;
q.TblUtsManageUsers.Update(lll);
q.SaveChanges();
returnInfo.isok = true;
}
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
/// <summary>
/// 重置密码
/// </summary>
/// <param name="LLL"></param>
/// <returns></returns>
[HttpPost()]
[Authorize()]
public ReturnInfo ResetPassWord([FromBody] PWD_Reset LLL)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
using (var q = new UtsManageContext())
{
var QQQ = q.TblUtsManageUsers.SingleOrDefault(A => A.Id == LLL.Id);
if (QQQ != null)
{
QQQ.Password = LLL.PlaintextPwd.ToMD5().ToMD5();
QQQ.PlaintextPwd = LLL.PlaintextPwd;
q.TblUtsManageUsers.Update(QQQ);
q.SaveChanges();
returnInfo.isok = true;
}
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
/// <summary>
/// 新增密码为123456
/// </summary>
/// <param name="LLL"></param>
/// <returns></returns>
[HttpPost()]
[Authorize()]
public ReturnInfo NewPassWord([FromBody] PWD_Reset LLL)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
using (var q = new UtsManageContext())
{
var Q = q.TblUtsManageUsers.SingleOrDefault(A => A.Id == LLL.Id);
if (Q != null)
{
Q.Password = "123456".ToMD5().ToMD5();
Q.PlaintextPwd = "123456";
q.TblUtsManageUsers.Update(Q);
q.SaveChanges();
returnInfo.isok = true;
}
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
/// <summary>
/// 获取用户信息
/// </summary>
/// <param name="S"></param>
/// <returns></returns>
[HttpPost()]
[Authorize()]
public ReturnInfo GetUserInfo([FromBody] QueryAll_Or_Single S)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
using (var q = new UtsManageContext())
{
if (S.IsAll)
{
returnInfo.isok = true;
returnInfo.response = q.TblUtsManageUsers.Where(A => A.IsValid).Select(F => new ReturnUser
{
Id = F.Id,
UserName = F.UserName,
CompanyId = F.CompanyId,
Mobile = F.Mobile,
WeiXin = F.WeiXin,
Email = F.Email,
}).ToList();
}
else
{
returnInfo.isok = true;
var a = q.TblUtsManageUsers.SingleOrDefault(A => A.Id == S.ID);
if (a != null)
{
ReturnUser u = new ReturnUser();
u.Id = a.Id;
u.UserName = a.UserName;
u.CompanyId = a.CompanyId;
u.Mobile = a.Mobile;
u.WeiXin = a.WeiXin;
u.Email = a.Email;
returnInfo.response = u;
}
}
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
/// <summary>
/// 新增用户
/// </summary>
/// <param name="LLL"></param>
/// <returns></returns>
[HttpPost()]
[Authorize()]
public ReturnInfo AddUser([FromBody] ReturnUser LLL)
{
ReturnInfo returnInfo = new ReturnInfo();
try
{
// {
//"id": 0,
//"userName": "test6",
//"companyId": "",
//"companyName": "",
//"mobile": "",
//"weiXin": "",
//"email": "",
//"resetpsw": true,
//"permissions": [],
//"company": ""
//}
string username = LLL.UserName;
int companyId = LLL.CompanyId;
string mobile = LLL.Mobile;
string weiXin = LLL.WeiXin;
string email = LLL.Email;
TblUtsManageUser lll = new TblUtsManageUser();
lll.UserName = username;
lll.CompanyId = companyId;
lll.Mobile = mobile;
lll.WeiXin = weiXin;
lll.Email = email;
lll.IsValid = true;
lll.CreateTime = DateTime.Now;
lll.UpdateTime = DateTime.Now;
using (var q = new UtsManageContext())
{
var Q = q.TblUtsManageUsers.Where(A => A.UserName.Equals(username));
if (Q.Count() > 0)
{
returnInfo.isok = false;
returnInfo.message = "此用户名已经存在";
}
else
{
lll.PlaintextPwd = "123456";
lll.Password = "123456".ToMD5().ToMD5(); ;
q.TblUtsManageUsers.Add(lll);
returnInfo.isok = true;
}
q.SaveChanges();
}
}
catch (Exception ex)
{
returnInfo.isok = false;
returnInfo.message = ex.Message;
}
return returnInfo;
}
}
/// <summary>
/// 返回用户信息
/// </summary>
public class ReturnUser
{
public int Id { get; set; }
public string UserName { get; set; }
public int CompanyId { get; set; }
public string Mobile { get; set; }
public string WeiXin { get; set; }
public string Email { get; set; }
}
public class PWD_Reset
{
public int Id { get; set; }
public string PlaintextPwd { get; set; }
}
}

View File

@@ -0,0 +1,47 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using ViewModels;
using WebAPIServer.Common;
namespace WebAPIServer.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class ValuesController : ControllerBase
{
[HttpGet()]
public ReturnInfo GetAll_WebApiMethod(string VariableName)
{
ReturnInfo i = new ReturnInfo();
i.isok = true;
try
{
var result = StaticData.scope.GetVariable(VariableName);
i.response = result;
}
catch (Exception ex)
{
i.isok = false;
i.message = ex.Message;
}
return i;
}
[HttpPost()]
public ReturnInfo UpdateData()
{
ReturnInfo i = new ReturnInfo();
i.isok = true;
try
{
StaticData.GetWebAPIMethod();
i.response = "sucess";
}
catch (Exception ex)
{
i.isok = false;
i.message = ex.Message;
}
return i;
}
}
}

View File

@@ -0,0 +1,33 @@
using Microsoft.AspNetCore.Mvc;
namespace WebAPIServer.Controllers
{
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger)
{
_logger = logger;
}
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
}

View File

@@ -0,0 +1,85 @@
using System.Text;
using SkiaSharp;
using static IronPython.Modules._ast;
namespace WebAPIServer.Extensions
{
public class CaptchaHelperSkiaSharp
{
private static string GenerateRandomText(int length)
{
const string valid = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
StringBuilder res = new StringBuilder();
Random rnd = new Random();
while (0 < length--)
res.Append(valid[rnd.Next(valid.Length)]);
return res.ToString();
}
/// <summary>
/// 获取图像数字验证码
/// </summary>
/// <param name="text">验证码内容如4为数字</param>
/// <returns></returns>
public static byte[] GetVerifyCode(string text)
{
int width = 128;
int height = 45;
Random random = new();
//创建bitmap位图
using SKBitmap image = new(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
//创建画笔
using SKCanvas canvas = new(image);
//填充背景颜色为白色
canvas.DrawColor(SKColors.White);
//画图片的背景噪音线
for (int i = 0; i < (width * height * 0.015); i++)
{
using SKPaint drawStyle = new();
drawStyle.Color = new(Convert.ToUInt32(random.Next(Int32.MaxValue)));
canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width), random.Next(0, height), drawStyle);
}
//将文字写到画布上
using (SKPaint drawStyle = new())
{
drawStyle.Color = SKColors.Red;
drawStyle.TextSize = height;
drawStyle.StrokeWidth = 1;
float emHeight = height - (float)height * (float)0.14;
float emWidth = ((float)width / text.Length) - ((float)width * (float)0.13);
canvas.DrawText(text, emWidth, emHeight, drawStyle);
}
//画图片的前景噪音点
for (int i = 0; i < (width * height * 0.6); i++)
{
image.SetPixel(random.Next(0, width), random.Next(0, height), new SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue))));
}
using var img = SKImage.FromBitmap(image);
using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
return p.ToArray();
}
public static byte[] GenerateCaptchaImage(int width = 100, int height = 40)
{
var random = new Random();
string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
string captchaText = "";
for (int i = 0; i < 4; i++) // 生成6个字符的验证码
{
captchaText += chars[random.Next(chars.Length)];
}
return GetVerifyCode(captchaText);
}
}
}

View File

@@ -0,0 +1,346 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Drawing.Imaging;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace WebAPIServer.Extensions
{
/// <summary>
/// 字符串扩展函数工具类
/// </summary>
public static class StringExtensions
{
/// <summary>
/// 将\r\n替换成BR
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string ToSafeBR(this string str)
{
if (!string.IsNullOrEmpty(str))
{
return str.Replace("\r\n", "<br>").Replace("\r", "<br>").Replace("\n", "<br>");
}
return str;
}
/// <summary>
/// 得到父部门的ID
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string GetDepartmentFatherID(this string str)
{
if (!string.IsNullOrEmpty(str) && str.Length > 2)
{
str = str.Substring(0, str.Length - 3);
}
return str;
}
/// <summary>
/// 截取字符串,超过部分用...代替
/// </summary>
/// <param name="source"></param>
/// <param name="len"></param>
/// <returns></returns>
public static string Substr(this string source, int len)
{
return source.Substr(len, "...");
}
/// <summary>
/// 截取字符串,超过部分用自定义代替
/// </summary>
/// <param name="source"></param>
/// <param name="len"></param>
/// <param name="att"></param>
/// <returns></returns>
public static string Substr(this string source, int len, string att)
{
if (string.IsNullOrEmpty(source))
{
return string.Empty;
}
att = (att ?? string.Empty);
Regex regex = new Regex("[\\u4e00-\\u9fa5]");
Regex regex2 = new Regex("^[A-Za-z0-9]+$");
if (regex.IsMatch(source))
{
if (source.Length <= len)
{
return source;
}
return source.Substring(0, len) + att;
}
else if (regex2.IsMatch(source))
{
if (source.Length <= len * 2)
{
return source;
}
return source.Substring(0, len * 2) + att;
}
else
{
if (source.Length <= len)
{
return source;
}
return source.Substring(0, len) + att;
}
}
public static string InputStr(this string source)
{
if (!string.IsNullOrEmpty(source))
{
Regex regex = new Regex("[\\u4e00-\\u9fa5]");
Regex regex2 = new Regex("^[A-Za-z0-9]+$");
if (regex.IsMatch(source))
{
if (source.Length < 3)
{
return string.Format("{0}**", source[0]);
}
if (source.Length == 3)
{
return string.Format("{0}*{1}", source[0], source[source.Length - 1]);
}
if (source.Length > 3)
{
return string.Format("{0}**{1}", source[0], source[source.Length - 1]);
}
}
else
{
if (!regex2.IsMatch(source))
{
return string.Format("{0}**", source.Substring(0, 2));
}
if (source.Length < 6)
{
return string.Format("{0}**", source.Substring(0, 2));
}
return string.Format("{0}****{1}", source.Substring(0, 2), source.Substring(source.Length - 3, 2));
}
}
return string.Empty;
}
/// <summary>
/// 移除掉所有的Html代码
/// </summary>
/// <param name="strHtml"></param>
/// <returns></returns>
public static string RemoveHtml(this string strHtml)
{
Regex regex = new Regex("<.+?>", RegexOptions.IgnoreCase);
strHtml = regex.Replace(strHtml, "");
strHtml = strHtml.Replace("&nbsp;", "");
return strHtml;
}
/// <summary>
/// 生成0-9随机数
/// </summary>
/// <param name="VcodeNum">生成长度</param>
/// <returns></returns>
public static string RndNum(int VcodeNum)
{
StringBuilder stringBuilder = new StringBuilder(VcodeNum);
Random random = new Random();
for (int i = 1; i < VcodeNum + 1; i++)
{
int num = random.Next(9);
stringBuilder.AppendFormat("{0}", num);
}
return stringBuilder.ToString();
}
/// <summary>
/// 返回星号的加密
/// </summary>
/// <param name="items"></param>
/// <param name="mask"></param>
/// <returns></returns>
public static string MaskStar(Dictionary<string, string> items, bool mask)
{
StringBuilder stringBuilder = new StringBuilder();
if (mask)
{
foreach (KeyValuePair<string, string> keyValuePair in items)
{
stringBuilder.Append(string.Concat(new string[]
{
"$('#",
keyValuePair.Key,
"').attr('name', '",
keyValuePair.Key,
"mask');"
}));
}
stringBuilder.Append("$('.maskstar').attr('disabled', true);");
stringBuilder.Append("$('.maskstar').val('***');");
}
else
{
foreach (KeyValuePair<string, string> keyValuePair2 in items)
{
stringBuilder.Append(string.Concat(new string[]
{
"$('#",
keyValuePair2.Key,
"').attr('name', '",
keyValuePair2.Key,
"');"
}));
stringBuilder.Append(string.Concat(new string[]
{
"$('#",
keyValuePair2.Key,
"').val('",
keyValuePair2.Value,
"');"
}));
}
stringBuilder.Append("$('.maskstar').attr('disabled', false);");
}
return stringBuilder.ToString();
}
/// <summary>
/// 给自动填充使用
/// </summary>
/// <param name="str1"></param>
/// <param name="str2"></param>
/// <returns></returns>
public static string ToAutoComplate(this string str1, string str2)
{
if (!string.IsNullOrEmpty(str1) && !string.IsNullOrEmpty(str2))
{
return str1 + "," + str2;
}
return "";
}
/// <summary>
/// 返回红色字体
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string ToRedColor(this int value)
{
if (value != 0)
{
return "<font color='red'>" + value.ToString() + "</font>";
}
return value.ToString();
}
/// <summary>
/// 返回安全的字符串类型如果为NULL则返回空
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string ToSafeString(this object value)
{
if (value == null)
{
return "";
}
return value.ToString();
}
/// <summary>
/// 将中文转换成Unicode编码主要用在URL传递中文
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string GB2Unicode(this string str)
{
string text = "";
Encoding encoding = Encoding.GetEncoding("GB2312");
Encoding unicode = Encoding.Unicode;
byte[] bytes = encoding.GetBytes(str);
for (int i = 0; i < bytes.Length; i++)
{
string str2 = "%" + bytes[i].ToString("x");
text += str2;
}
return text;
}
/// <summary>
/// 将字符串转换成为大写的MD5
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string ToMD5(this string str)
{
MD5CryptoServiceProvider md5CryptoServiceProvider = new MD5CryptoServiceProvider();
byte[] array = md5CryptoServiceProvider.ComputeHash(Encoding.Default.GetBytes(str));
StringBuilder stringBuilder = new StringBuilder();
foreach (byte b in array)
{
stringBuilder.Append(b.ToString("x2"));
}
return stringBuilder.ToString().ToUpper();
}
/// <summary>
/// 字节码长度转可读字符串 00000000 bytes 0.0GB
/// </summary>
/// <param name="KSize"></param>
/// <returns></returns>
public static string ByteSizeToString(this long KSize)
{
if (KSize > 0L)
{
string[] array = new string[]
{
"B",
"KB",
"MB",
"GB",
"TB"
};
double num = 0.0;
int num2 = array.Length - 1;
while (num2 >= 0 && (num = Math.Round((double)KSize / Math.Pow(1024.0, (double)num2), 2)) < 1.0)
{
num2--;
}
return string.Format("{0}{1}", num, array[num2]);
}
return string.Empty;
}
/// <summary>
/// 将字符串转换成为大写的MD5
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
private static string GetMD5Code(this string str)
{
StringBuilder stringBuilder = new StringBuilder();
using (MD5CryptoServiceProvider md5CryptoServiceProvider = new MD5CryptoServiceProvider())
{
byte[] array = md5CryptoServiceProvider.ComputeHash(Encoding.Default.GetBytes(str));
foreach (byte b in array)
{
stringBuilder.Append(b.ToString("x2"));
}
}
return stringBuilder.ToString();
}
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebAPIServer.Extensions
{
public static class TimeExtensions
{
public static DateTime? ToDateTime(this string timeStamp)
{
long ticks = 0L;
if (long.TryParse(timeStamp, out ticks))
{
DateTime dateTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
TimeSpan value = new TimeSpan(ticks);
return new DateTime?(dateTime.Add(value));
}
DateTime now = DateTime.Now;
if (DateTime.TryParse(timeStamp, out now))
{
return new DateTime?(now);
}
return null;
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageApplist
{
/// <summary>
/// 索引,无作用
/// </summary>
public int Id { get; set; }
/// <summary>
/// 服务索引
/// </summary>
public int? ServiceId { get; set; }
/// <summary>
/// APP索引
/// </summary>
public int? AppId { get; set; }
/// <summary>
/// APP名称
/// </summary>
public string? AppName { get; set; }
/// <summary>
/// APP版本
/// </summary>
public string? AppVersion { get; set; }
/// <summary>
/// APP注册时间
/// </summary>
public DateTime? RegisterDateTime { get; set; }
/// <summary>
/// APP最后活动时间
/// </summary>
public DateTime? LastActiveDateTime { get; set; }
/// <summary>
/// App最新信息
/// </summary>
public string? LastInfomation { get; set; }
public string? Remark { get; set; }
}

View File

@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageApplog
{
/// <summary>
/// 索引,无作用
/// </summary>
public int Id { get; set; }
/// <summary>
/// 服务索引
/// </summary>
public int? ServiceId { get; set; }
/// <summary>
/// APP名字
/// </summary>
public string? AppName { get; set; }
/// <summary>
/// App版本
/// </summary>
public string? AppVersion { get; set; }
/// <summary>
/// 测试项目名
/// </summary>
public string? ProjectName { get; set; }
/// <summary>
/// 测试站名
/// </summary>
public string? StationName { get; set; }
/// <summary>
/// 测试流程名
/// </summary>
public string? TestPlan { get; set; }
/// <summary>
/// 产生日期
/// </summary>
public DateTime? DateTime { get; set; }
/// <summary>
/// 日志类型
/// </summary>
public string? LogType { get; set; }
/// <summary>
/// 日志内容
/// </summary>
public string? LogText { get; set; }
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageAuthlog
{
public int Id { get; set; }
public int? UserId { get; set; }
public int? AuthId { get; set; }
/// <summary>
/// 权限0禁止1只读2读写
/// </summary>
public int? Auth { get; set; }
/// <summary>
/// 存在
///
/// </summary>
public ulong Exist { get; set; }
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageAuthmanage
{
public int Id { get; set; }
/// <summary>
/// 部分权限
/// </summary>
public string? ModuleId { get; set; }
/// <summary>
/// 描述
/// </summary>
public string? Describe { get; set; }
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
/// <summary>
/// 客户列表
/// </summary>
public partial class TblUtsManageCompany
{
/// <summary>
/// ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 客户名称
/// </summary>
public string CustomerName { get; set; } = null!;
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreateTime { get; set; }
public DateTime UpdateTime { get; set; }
}

View File

@@ -0,0 +1,139 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageDataservicelist
{
/// <summary>
/// 服务索引唯一值
/// </summary>
public int Id { get; set; }
/// <summary>
/// 鉴权文件索引
/// </summary>
public int? LicenseId { get; set; }
/// <summary>
/// 鉴权文件有效日期
/// </summary>
public string? LicenseValidDateTime { get; set; }
/// <summary>
/// 公司名
/// </summary>
public string? CompanyName { get; set; }
/// <summary>
/// 服务操作系统
/// </summary>
public string? TerminalOs { get; set; }
/// <summary>
/// 服务终端类型
/// </summary>
public string? TerminalType { get; set; }
/// <summary>
/// 服务终端名称
/// </summary>
public string? TerminalName { get; set; }
/// <summary>
/// 服务自定义标识名
/// </summary>
public string? TerminalAlias { get; set; }
/// <summary>
/// 服务MAC地址
/// </summary>
public string? TerminalMac { get; set; }
/// <summary>
/// CUP序列号
/// </summary>
public string? ProcessorId { get; set; }
/// <summary>
/// 服务版本
/// </summary>
public string? ServiceVersion { get; set; }
/// <summary>
/// 服务注册日期
/// </summary>
public DateTime? ServiceRegisterDateTime { get; set; }
/// <summary>
/// 服务最后活动日期
/// </summary>
public DateTime? ServiceLastActiveDateTime { get; set; }
/// <summary>
/// 服务是否有效,注册默认有效
/// </summary>
public sbyte? ServiceValid { get; set; }
/// <summary>
/// 是否在线
/// </summary>
public bool IsOnline { get; set; }
/// <summary>
/// 服务上线时间
/// </summary>
public DateTime? ServiceOnlineDateTime { get; set; }
public DateTime? UpdateTime { get; set; }
/// <summary>
/// 故障信息
/// </summary>
public string? ErrMsg { get; set; }
/// <summary>
/// 更新服务版本
/// </summary>
public string? Usver { get; set; }
/// <summary>
/// 更新服务连接状态
/// </summary>
public bool? UsisOnline { get; set; }
/// <summary>
/// 更新服务的错误
/// </summary>
public string? UserrMsg { get; set; }
/// <summary>
/// 子网名称
/// </summary>
public string? BarnchNet { get; set; }
/// <summary>
/// 设备角色
/// </summary>
public int? Roles { get; set; }
/// <summary>
/// 内网连接状态
/// </summary>
public int? IsDbproxyConn { get; set; }
/// <summary>
/// 本机缓存数量
/// </summary>
public int? CacheCount { get; set; }
/// <summary>
/// 网上邻居
/// </summary>
public string? NetworkNeiborhood { get; set; }
/// <summary>
/// 服务当前状态,1有效,0无效
/// </summary>
public int? ManageStatus { get; set; }
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageDataservicelog
{
/// <summary>
/// 日志索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 数据服务索引
/// </summary>
public int? ServiceId { get; set; }
/// <summary>
/// 数据服务版本
/// </summary>
public string? ServiceVersion { get; set; }
/// <summary>
/// 更新服务版本
/// </summary>
public string? UpdateServiceVersion { get; set; }
/// <summary>
/// 厂商名称
/// </summary>
public string? VendorName { get; set; }
/// <summary>
/// 生成日期与时间
/// </summary>
public DateTime? DateTime { get; set; }
/// <summary>
/// 公网IP地址
/// </summary>
public string? PublicIp { get; set; }
/// <summary>
/// 内网IP地址
/// </summary>
public string? PrivateIp { get; set; }
/// <summary>
/// Mac地址
/// </summary>
public string? Mac { get; set; }
/// <summary>
/// 日志类型
/// </summary>
public string? LogType { get; set; }
/// <summary>
/// 日志内容
/// </summary>
public string? LogText { get; set; }
}

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageDblist
{
/// <summary>
/// 数据库ID
/// </summary>
public int Id { get; set; }
/// <summary>
/// 数据库关联公司的索引
/// </summary>
public int? CompanyId { get; set; }
/// <summary>
/// 数据库名
/// </summary>
public string? DatabaseName { get; set; }
/// <summary>
/// 数据库连接名
/// </summary>
public string? DatabaseUser { get; set; }
/// <summary>
/// 数据库连接密码
/// </summary>
public string? DatabasePassword { get; set; }
/// <summary>
/// 数据库详细说明
/// </summary>
public string? DatabaseDesc { get; set; }
public DateTime UpdateTime { get; set; }
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageDevlist
{
/// <summary>
/// 设备ID,唯一索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 设备名称
/// </summary>
public string? DevName { get; set; }
/// <summary>
/// 设备类型
/// </summary>
public string? DevType { get; set; }
/// <summary>
/// 设备MAC地址
/// </summary>
public string? Mac { get; set; }
/// <summary>
/// 第一次登陆时间
/// </summary>
public DateTime? FirstLoginDate { get; set; }
/// <summary>
/// 最后一次在线时间
/// </summary>
public DateTime? LastOnlineDate { get; set; }
/// <summary>
/// 在线状态
/// </summary>
public int? OnlineStatus { get; set; }
/// <summary>
/// 设备是有有效
/// </summary>
public int? Valid { get; set; }
public DateTime UpdateTime { get; set; }
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageDevlog
{
public int Id { get; set; }
public int? DevId { get; set; }
/// <summary>
/// 操作时间
/// </summary>
public DateTime? DateTime { get; set; }
/// <summary>
/// 设备公网IP
/// </summary>
public string? PublicIp { get; set; }
/// <summary>
/// 设备内网IP
/// </summary>
public string? PrivateIp { get; set; }
/// <summary>
/// Licence文件名
/// </summary>
public string? LicFileName { get; set; }
/// <summary>
/// 产生日志的App名
/// </summary>
public string? AppName { get; set; }
/// <summary>
/// APP版本号
/// </summary>
public string? AppVersion { get; set; }
/// <summary>
/// 测试配置名称
/// </summary>
public string? TestPlan { get; set; }
/// <summary>
/// 登陆用户账号索引
/// </summary>
public int? UserId { get; set; }
/// <summary>
/// 操作内容
/// </summary>
public string? Operation { get; set; }
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageErrcode
{
/// <summary>
/// 错误类型
/// </summary>
public string? ErrType { get; set; }
/// <summary>
/// 错误ID唯一值
/// </summary>
public string ErrCode { get; set; } = null!;
/// <summary>
/// 错误提示
/// </summary>
public string? ErrMsg { get; set; }
/// <summary>
/// 统计图表中对应的颜色
/// </summary>
public string ErrColor { get; set; } = null!;
public DateTime UpdateTime { get; set; }
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageLicenselist
{
/// <summary>
/// 鉴权文件索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 鉴权文件所属公司
/// </summary>
public string? CompanyName { get; set; }
/// <summary>
/// 发布日期
/// </summary>
public DateTime? ReleaseDate { get; set; }
/// <summary>
/// 有效日期
/// </summary>
public DateTime? ValidDateTime { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? Remark { get; set; }
public DateTime? UpdateTime { get; set; }
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
/// <summary>
/// 操作日志
/// </summary>
public partial class TblUtsManageLog
{
/// <summary>
/// 索引,无作用
/// </summary>
public int Id { get; set; }
/// <summary>
/// 用户索引
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 日志产生时间
/// </summary>
public DateTime DateTime { get; set; }
/// <summary>
/// 操作内容
/// </summary>
public string? Operation { get; set; }
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageModule
{
public int Id { get; set; }
/// <summary>
/// 功能描述
/// </summary>
public string? Operation { get; set; }
/// <summary>
/// 控制器
/// </summary>
public string? Controller { get; set; }
/// <summary>
/// 方法名
/// </summary>
public string? Method { get; set; }
/// <summary>
/// 1代表已录入
/// </summary>
public ulong? Exist { get; set; }
/// <summary>
/// 功能备注
/// </summary>
public string? Remark { get; set; }
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
/// <summary>
/// 操作权限列表
/// </summary>
public partial class TblUtsManageOperationlist
{
/// <summary>
/// 功能索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 功能模块名
/// </summary>
public string? OperationName { get; set; }
/// <summary>
/// 功能模块详细说明
/// </summary>
public string? OperationDesc { get; set; }
/// <summary>
/// 操作级别
/// </summary>
public int OperationLevel { get; set; }
public DateTime UpdateTime { get; set; }
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageOrderstatus
{
public int Id { get; set; }
public string StatusName { get; set; } = null!;
public string? Remark { get; set; }
public DateTime? UpdateTime { get; set; }
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageSearchkey
{
public int Id { get; set; }
/// <summary>
/// 数据库ID
/// </summary>
public int DataBaseId { get; set; }
/// <summary>
/// 查询条件
/// </summary>
public string SearchVarKey { get; set; } = null!;
}

View File

@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageServicelog
{
/// <summary>
/// 日志索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 公司名称
/// </summary>
public string? CompanyName { get; set; }
/// <summary>
/// 应用名称
/// </summary>
public string? AppName { get; set; }
/// <summary>
/// 应用版本
/// </summary>
public string? AppVersion { get; set; }
/// <summary>
/// 日志生成日期与时间
/// </summary>
public DateTime? DateTime { get; set; }
/// <summary>
/// 设备公网IP
/// </summary>
public string? DevPublicIp { get; set; }
/// <summary>
/// 设备内网IP地址
/// </summary>
public string? DevPrivateIp { get; set; }
/// <summary>
/// 设备MAC
/// </summary>
public string? DevMac { get; set; }
/// <summary>
/// 设备系统版本
/// </summary>
public string? DevOs { get; set; }
/// <summary>
/// 设备名称
/// </summary>
public string? DevName { get; set; }
/// <summary>
/// 设备用户名
/// </summary>
public string? DevUserName { get; set; }
/// <summary>
/// 设备网络状态
/// </summary>
public string? DevOnline { get; set; }
/// <summary>
/// 日志类型
/// </summary>
public string? LogType { get; set; }
/// <summary>
/// 日志内容
/// </summary>
public string? LogText { get; set; }
}

View File

@@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageSwreleaselog
{
/// <summary>
/// 软件发布索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 软件名称
/// </summary>
public string SoftwareName { get; set; } = null!;
/// <summary>
/// 发布日期与时间
/// </summary>
public DateTime ReleaseDate { get; set; }
/// <summary>
/// 发布版本号
/// </summary>
public string? ReleaseVersion { get; set; }
/// <summary>
/// 发布用户索引
/// </summary>
public int? UserId { get; set; }
/// <summary>
/// 发布说明
/// </summary>
public string? Remark { get; set; }
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageSwupdate
{
/// <summary>
/// 软件索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 软件名称
/// </summary>
public string? SoftwareName { get; set; }
/// <summary>
/// 最新版本号
/// </summary>
public string? LastVersion { get; set; }
/// <summary>
/// 发布日期
/// </summary>
public DateTime? ReleaseDate { get; set; }
/// <summary>
/// 升级的二进制文件
/// </summary>
public byte[]? BinPackage { get; set; }
/// <summary>
/// MD5校验码
/// </summary>
public string? BinPackageMd5 { get; set; }
/// <summary>
/// 软件包名
/// </summary>
public string? PackageName { get; set; }
public DateTime? UpdateTime { get; set; }
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageSynclist
{
public int Id { get; set; }
/// <summary>
/// 需要同步的表名
/// </summary>
public string TableName { get; set; } = null!;
/// <summary>
/// 表版本编号
/// </summary>
public int RevisionId { get; set; }
/// <summary>
/// 同步类型
/// </summary>
public string? SyncType { get; set; }
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageTestplantip
{
public int Id { get; set; }
/// <summary>
/// 列名
/// </summary>
public string? ColName { get; set; }
/// <summary>
/// 列类型
/// </summary>
public string? ColType { get; set; }
/// <summary>
/// 列描述
/// </summary>
public string? ColDesc { get; set; }
/// <summary>
/// 默认值
/// </summary>
public string? ColValue { get; set; }
public DateTime UpdateTime { get; set; }
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
/// <summary>
/// 用户列表
/// </summary>
public partial class TblUtsManageUser
{
/// <summary>
/// 用户索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 所属公司ID
/// </summary>
public int CompanyId { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// 登录密码
/// </summary>
public string? Password { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime? CreateTime { get; set; }
/// <summary>
/// 手机号码
/// </summary>
public string? Mobile { get; set; }
/// <summary>
/// 微信账号
/// </summary>
public string? WeiXin { get; set; }
/// <summary>
/// 电子邮箱
/// </summary>
public string? Email { get; set; }
/// <summary>
/// 是否有效
/// </summary>
public bool IsValid { get; set; }
/// <summary>
/// 是否为管理员 默认是0 管理员为1
/// </summary>
public bool IsAdmin { get; set; }
/// <summary>
/// 条码登陆
/// </summary>
public string? BarCode { get; set; }
/// <summary>
/// 设置条码权限
/// </summary>
public bool SetBarCode { get; set; }
public DateTime? UpdateTime { get; set; }
/// <summary>
/// 设置结单权限
/// </summary>
public bool AccountBill { get; set; }
/// <summary>
/// 登录密码明文
/// </summary>
public string? PlaintextPwd { get; set; }
}

View File

@@ -0,0 +1,82 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
/// <summary>
/// 用户列表
/// </summary>
public partial class TblUtsManageUser20230712
{
/// <summary>
/// 用户索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 所属公司ID
/// </summary>
public int CompanyId { get; set; }
/// <summary>
/// 用户名
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// 登录密码
/// </summary>
public string? Password { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime? CreateTime { get; set; }
/// <summary>
/// 手机号码
/// </summary>
public string? Mobile { get; set; }
/// <summary>
/// 微信账号
/// </summary>
public string? WeiXin { get; set; }
/// <summary>
/// 电子邮箱
/// </summary>
public string? Email { get; set; }
/// <summary>
/// 是否有效
/// </summary>
public bool IsValid { get; set; }
/// <summary>
/// 是否为管理员 默认是0 管理员为1
/// </summary>
public bool IsAdmin { get; set; }
/// <summary>
/// 条码登陆
/// </summary>
public string? BarCode { get; set; }
/// <summary>
/// 设置条码权限
/// </summary>
public bool SetBarCode { get; set; }
public DateTime? UpdateTime { get; set; }
/// <summary>
/// 设置结单权限
/// </summary>
public bool AccountBill { get; set; }
/// <summary>
/// 登录密码明文
/// </summary>
public string? PlaintextPwd { get; set; }
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
/// <summary>
/// 用户厂家权限
/// </summary>
public partial class TblUtsManageUserauthOperation
{
/// <summary>
/// 索引,无作用
/// </summary>
public int Id { get; set; }
/// <summary>
/// 用户索引
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 数据库索引
/// </summary>
public int DatabaseId { get; set; }
/// <summary>
/// 数据库名称
/// </summary>
public string? DatabaseName { get; set; }
/// <summary>
/// 拥有完整权限功能索引,用逗号分隔
/// </summary>
public string? FullAccess { get; set; }
/// <summary>
/// 拥有读写权限功能索引,用逗号分隔
/// </summary>
public string? ReadWriteAccess { get; set; }
/// <summary>
/// 拥有只读权限功能索引,用逗号分隔
/// </summary>
public string? ReadOnlyAccess { get; set; }
/// <summary>
/// 拥有机型权限索引,用逗号分隔
/// </summary>
public string? ReadProject { get; set; }
/// <summary>
/// 拥有管理权限索引,用逗号分隔
/// </summary>
public string? ManagerAccess { get; set; }
}

View File

@@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManageUtscmdlist
{
/// <summary>
/// 命令索引
/// </summary>
public int Id { get; set; }
/// <summary>
/// 命令类型
/// </summary>
public string? CmdType { get; set; }
/// <summary>
/// 命令名称
/// </summary>
public string? CmdName { get; set; }
/// <summary>
/// 命令说明
/// </summary>
public string? CmdDesc { get; set; }
/// <summary>
/// 命令参数总数
/// </summary>
public string? ParamCount { get; set; }
/// <summary>
/// 参数说明1
/// </summary>
public string? ParamDesc1 { get; set; }
/// <summary>
/// 参数说明2
/// </summary>
public string? ParamDesc2 { get; set; }
/// <summary>
/// 参数说明3
/// </summary>
public string? ParamDesc3 { get; set; }
/// <summary>
/// 参数说明4
/// </summary>
public string? ParamDesc4 { get; set; }
/// <summary>
/// 参数说明5
/// </summary>
public string? ParamDesc5 { get; set; }
/// <summary>
/// 参数说明6
/// </summary>
public string? ParamDesc6 { get; set; }
/// <summary>
/// 参数说明7
/// </summary>
public string? ParamDesc7 { get; set; }
/// <summary>
/// 参数说明8
/// </summary>
public string? ParamDesc8 { get; set; }
/// <summary>
/// 参数类型1
/// </summary>
public string? ParamType1 { get; set; }
/// <summary>
/// 参数类型2
/// </summary>
public string? ParamType2 { get; set; }
/// <summary>
/// 参数类型3
/// </summary>
public string? ParamType3 { get; set; }
/// <summary>
/// 参数类型4
/// </summary>
public string? ParamType4 { get; set; }
/// <summary>
/// 参数类型5
/// </summary>
public string? ParamType5 { get; set; }
/// <summary>
/// 参数类型6
/// </summary>
public string? ParamType6 { get; set; }
/// <summary>
/// 参数类型7
/// </summary>
public string? ParamType7 { get; set; }
/// <summary>
/// 参数类型8
/// </summary>
public string? ParamType8 { get; set; }
/// <summary>
/// 参数下限1
/// </summary>
public string? ParamLower1 { get; set; }
/// <summary>
/// 参数下限2
/// </summary>
public string? ParamLower2 { get; set; }
/// <summary>
/// 参数下限3
/// </summary>
public string? ParamLower3 { get; set; }
/// <summary>
/// 参数下限4
/// </summary>
public string? ParamLower4 { get; set; }
/// <summary>
/// 参数下限5
/// </summary>
public string? ParamLower5 { get; set; }
/// <summary>
/// 参数下限6
/// </summary>
public string? ParamLower6 { get; set; }
/// <summary>
/// 参数下限7
/// </summary>
public string? ParamLower7 { get; set; }
/// <summary>
/// 参数下限8
/// </summary>
public string? ParamLower8 { get; set; }
/// <summary>
/// 参数上限1
/// </summary>
public string? ParamUpper1 { get; set; }
/// <summary>
/// 参数上限2
/// </summary>
public string? ParamUpper2 { get; set; }
/// <summary>
/// 参数上限3
/// </summary>
public string? ParamUpper3 { get; set; }
/// <summary>
/// 参数上限4
/// </summary>
public string? ParamUpper4 { get; set; }
/// <summary>
/// 参数上限5
/// </summary>
public string? ParamUpper5 { get; set; }
/// <summary>
/// 参数上限6
/// </summary>
public string? ParamUpper6 { get; set; }
/// <summary>
/// 参数上限7
/// </summary>
public string? ParamUpper7 { get; set; }
/// <summary>
/// 参数上限8
/// </summary>
public string? ParamUpper8 { get; set; }
/// <summary>
/// 参数默认值1
/// </summary>
public string? ParamValue1 { get; set; }
/// <summary>
/// 参数默认值2
/// </summary>
public string? ParamValue2 { get; set; }
/// <summary>
/// 参数默认值3
/// </summary>
public string? ParamValue3 { get; set; }
/// <summary>
/// 参数默认值4
/// </summary>
public string? ParamValue4 { get; set; }
/// <summary>
/// 参数默认值5
/// </summary>
public string? ParamValue5 { get; set; }
/// <summary>
/// 参数默认值6
/// </summary>
public string? ParamValue6 { get; set; }
/// <summary>
/// 参数默认值7
/// </summary>
public string? ParamValue7 { get; set; }
/// <summary>
/// 参数默认值8
/// </summary>
public string? ParamValue8 { get; set; }
public DateTime? UpdateTime { get; set; }
}

View File

@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsManangeUseronlinelog
{
public int Id { get; set; }
/// <summary>
/// 用户名字
/// </summary>
public string? UserNames { get; set; }
/// <summary>
/// ip地址
/// </summary>
public string? Ip { get; set; }
/// <summary>
/// 1是在线 0不在线
/// </summary>
public int? State { get; set; }
public DateTime? CreationTime { get; set; }
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
namespace WebAPIServer.Models;
public partial class TblUtsUseroperation
{
public int Id { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime? CreationTime { get; set; }
/// <summary>
/// 用户名字
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// ip地址
/// </summary>
public string? Ip { get; set; }
/// <summary>
/// 浏览器版本
/// </summary>
public string? Browser { get; set; }
/// <summary>
/// 操作类型
/// </summary>
public string? Operation { get; set; }
/// <summary>
/// 选择的数据库
/// </summary>
public string? Database { get; set; }
/// <summary>
/// 设备型号
/// </summary>
public string? Device { get; set; }
/// <summary>
/// 地理位置
/// </summary>
public string? Location { get; set; }
}

File diff suppressed because it is too large Load Diff

89
WebAPIServer/Program.cs Normal file
View File

@@ -0,0 +1,89 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using WebAPIServer.Common;
namespace WebAPIServer
{
public class Program
{
public record STU(string nnn, string bbb);
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddMemoryCache();
builder.Services.AddControllers();
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "Vue3",
policy =>
{
//policy.WithOrigins("http://localhost:5180",
// "http://localhost:8809/",
// "http://www.contoso.com",
// "http://new.uts-data.com:6688/", "http://new.uts-data.com")
policy
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
builder.Services.AddAuthorization();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(option =>
{
var sec = Encoding.UTF8.GetBytes(builder.Configuration["JWT:SecretKey"]);
option.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["JwT:Issuer"],
ValidAudience = builder.Configuration["JwT:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(sec)
};
//option.Events = new JwtBearerEvents
//{
// OnMessageReceived = context =>
// {
// var token = context.Request.Headers["token"].FirstOrDefault();
// if (string.IsNullOrEmpty(token))
// {
// // <20><><EFBFBD><EFBFBD>û<EFBFBD><C3BB><EFBFBD>ҵ<EFBFBD> token ͷ<><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Authorization ͷ<><CDB7>
// token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
// }
// // <20><><EFBFBD><EFBFBD><EFBFBD>ҵ<EFBFBD><D2B5><EFBFBD> token<65><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD> HttpContext <20><>
// if (!string.IsNullOrEmpty(token))
// {
// context.Token = token;
// }
// return Task.CompletedTask;
// }
//};
});
var app = builder.Build();
// Configure the HTTP request pipeline.
app.UseCors("Vue3");
app.UseAuthentication(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֤<EFBFBD>м<EFBFBD><D0BC><EFBFBD>
app.UseAuthorization(); // ʹ<><CAB9><EFBFBD><EFBFBD>Ȩ<EFBFBD>м<EFBFBD><D0BC><EFBFBD>
app.MapControllers();
StaticData.GetWebAPIMethod();
app.Run();
}
}
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<DeleteExistingFiles>true</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Release\net8.0\publish\</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<_TargetId>Folder</_TargetId>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<ProjectGuid>a9d49d8f-14c1-413e-ab94-87cf21f0b3b8</ProjectGuid>
<SelfContained>true</SelfContained>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<_PublishTargetUrl>E:\Project\AUTS_New\WebAPIServer\bin\Release\net8.0\publish\</_PublishTargetUrl>
<History>True|2025-08-28T09:10:06.0215159Z||;True|2025-08-27T20:08:53.7448405+08:00||;True|2025-08-27T09:30:37.1012354+08:00||;True|2025-08-19T18:15:37.7913274+08:00||;True|2025-08-19T17:20:58.7412452+08:00||;True|2025-08-19T15:55:20.9527200+08:00||;True|2025-04-07T19:28:10.1279229+08:00||;True|2025-03-31T11:42:19.8860538+08:00||;True|2025-03-29T17:38:19.1679458+08:00||;True|2025-03-28T19:10:51.5374819+08:00||;True|2025-03-28T17:57:42.2820238+08:00||;True|2025-03-21T17:12:53.2430355+08:00||;False|2025-03-21T17:12:26.4177469+08:00||;True|2025-03-18T15:58:56.0927860+08:00||;True|2025-03-18T15:57:00.4917451+08:00||;True|2025-03-18T15:55:00.3530973+08:00||;</History>
<LastFailureDetails />
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,31 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:23553",
"sslPort": 0
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "weatherforecast",
"applicationUrl": "http://localhost:5135",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "weatherforecast",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,76 @@
## 查询公司名称
methodlists="SELECT * FROM `tbl_uts_manage_company` where ID=@ID;"
## 获取数据库表
getDbName="SHOW DATABASES;"
getCompany = "SELECT CustomerName FROM `tbl_uts_manage_company`;"
## 获取@TBName数据库表结构
getTable = '''
USE @DBName ;
SELECT
COLUMN_NAME AS 'name',
DATA_TYPE AS 'type',
COLUMN_COMMENT AS 'notes',
CHARACTER_MAXIMUM_LENGTH AS 'long'
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = '@DBName'
AND TABLE_NAME = '@TBName'
ORDER BY
TABLE_NAME,
ORDINAL_POSITION;
'''
## 添加@TBName数据库表字段
addTable = '''
USE @dbName;
ALTER TABLE @TBName
ADD COLUMN @name @type@long COMMENT '@notes';
'''
## 修改@TBName数据库表字段
updateTable = '''
USE @dbName;
ALTER TABLE @TBName
CHANGE COLUMN @oldName @name @type@long COMMENT '@notes';
'''
## 删除@TBName数据库表字段
deleteTable = '''
USE @dbName;
ALTER TABLE @TBName DROP COLUMN @name;
'''
## 查询tbl_uts_useroperation表数据
getLoginLogCount = "SELECT MAX(ID) AS LogCount FROM uts_manage.tbl_uts_useroperation;"
def getLoginLog(last_id = ""):
# 如果没有提供last_id则查询最新的25条记录
if last_id == "":
SQL1 = f"SELECT * FROM uts_manage.tbl_uts_useroperation ORDER BY ID DESC LIMIT 25;"
return SQL1
else:
# 如果提供了last_id则从该ID之后查询最新的25条记录
SQL2 = f"SELECT * FROM uts_manage.tbl_uts_useroperation WHERE ID < {last_id} ORDER BY ID DESC LIMIT 25;"
return SQL2
## 查询utsTestLog数据
## 查询机型列表
getModelList = '''
SELECT * FROM @dbName.tbl_project WHERE IsValid = TRUE;
'''
## 查询站位列表
getStationList = '''
SELECT * FROM @dbName.tbl_stationlist WHERE ProjectID = @ProjectID AND IsValid = TRUE ORDER BY ArtworkOrder;
'''
## 查询测试机台列表
getTestDeviceList = '''
SELECT * FROM uts_manage.tbl_uts_manage_dataservicelist AS ser
WHERE ID IN (SELECT log.ServiceID FROM @dbName.@tbName AS log GROUP BY log.ServiceID) AND ser.ServiceValid = TRUE;
'''
## 查询错误步骤列表
getFailStepsList = '''
SELECT FailSteps FROM @dbName.@tbName WHERE FailSteps IS NOT NULL AND FailSteps != '' GROUP BY FailSteps;
'''
##查询筛选字段列表
getColumnNameList = '''
SHOW COLUMNS FROM @dbName.@tbName
WHERE Field NOT IN ('ID', 'ServiceID', 'StartTime', 'DUT_SN', 'TestResult', 'Failsteps');
'''

View File

@@ -0,0 +1,13 @@
namespace WebAPIServer
{
public class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
}

View File

@@ -0,0 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ClosedXML" Version="0.105.0" />
<PackageReference Include="IronPython" Version="3.4.2" />
<PackageReference Include="IronPython.StdLib" Version="3.4.2" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.14" />
<PackageReference Include="Microsoft.AspNetCore.SignalR" Version="1.2.0" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.14">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.14" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.14">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
<PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.4.0" />
<PackageReference Include="NLog.Schema" Version="5.4.0" />
<PackageReference Include="NLog.Web.AspNetCore" Version="5.4.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.3" />
<PackageReference Include="RestSharp" Version="112.1.0" />
<PackageReference Include="SkiaSharp" Version="3.116.1" />
<PackageReference Include="UAParser.Core" Version="4.0.4" />
</ItemGroup>
<ItemGroup>
<Folder Include="Models\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ViewModels\ViewModels.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="ScriptConfig\webapi.py">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,6 @@
@WebAPIServer_HostAddress = http://localhost:5135
GET {{WebAPIServer_HostAddress}}/weatherforecast/
Accept: application/json
###

12
WebAPIServer/app.json Normal file
View File

@@ -0,0 +1,12 @@
{
//redis
"session_expire_minutes": "5",
"redis_server_session": "127.0.0.1:6379",
"redis_max_read_pool": "1000",
"redis_max_write_pool": "1000",
"MQTT_ServerIP": "120.24.73.62",
"MQTT_ServerPort": 1883,
"MQTT_User": "blw",
"MQTT_PWD": "blw@1234"
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,14 @@
{
"JwT": {
"SecretKey": "abcdefereworu3294378472386^&^$RT#GHJFGJEUIHGFJKDFGHKDJSFSDKg",
"Issuer": "AD>706,&L?$38oO#3N#E8@,742vyyd",
"Audience": "W*u93xxp*08DnW@%6}5Tjh6bE?;hW"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

35
WebAPIServer/nlog.config Normal file
View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- enable asp.net core layout renderers -->
<targets>
<!--项目日志保存文件路径说明fileName="${basedir}/保存目录,以年月日的格式创建/${shortdate}/${记录器名称}-${单级记录}-${shortdate}.txt"-->
<target name="info_file" xsi:type="File"
fileName="${basedir}/Logs/${shortdate}/info_${shortdate}.txt"
layout="${longdate}|${level:uppercase=true}|${logger}|${message}|${exception:format=ToString} ${newline} ${stacktrace} ${newline}"
archiveFileName="${basedir}/archives/info_${shortdate}-{#####}.txt"
archiveAboveSize="102400"
archiveNumbering="Sequence"
concurrentWrites="true"
keepFileOpen="false" />
<target name="error_file" xsi:type="File"
fileName="${basedir}/Logs/${shortdate}/error_${shortdate}.txt"
layout="${longdate}|${level:uppercase=true}|${logger}|${message}|${exception:format=ToString} ${newline} ${stacktrace} ${newline}"
archiveFileName="${basedir}/archives/error_${shortdate}-{#####}.txt"
archiveAboveSize="102400"
archiveNumbering="Sequence"
concurrentWrites="true"
keepFileOpen="false" />
</targets>
<!--规则配置,final - 最终规则匹配后不处理任何规则-->
<!--规则配置,final - 最终规则匹配后不处理任何规则-->
<!--定义使用哪个target输出-->
<rules>
<!-- 优先级从高到低依次为OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL -->
<!-- 将所有日志输出到文件 -->
<logger name="*" minlevel="FATAL" maxlevel="FATAL" writeTo="info_file" />
<logger name="*" minlevel="ERROR" maxlevel="ERROR" writeTo="error_file" />
</rules>
</nlog>

View File

@@ -0,0 +1,14 @@
root = true
[*]
indent_style = space
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[*.{ts,js,vue,css}]
indent_size = 2

5
auts_new.client/.env Normal file
View File

@@ -0,0 +1,5 @@
# 打包路径 根据项目不同按需配置
VITE_BASE_URL = /
VITE_IS_REQUEST_PROXY = true
VITE_API_URL = https://service-bv448zsw-1257786608.gz.apigw.tencentcs.com
VITE_API_URL_PREFIX = /api

View File

@@ -0,0 +1,5 @@
# 打包路径
VITE_BASE_URL = /
VITE_IS_REQUEST_PROXY = true
VITE_API_URL = https://service-exndqyuk-1257786608.gz.apigw.tencentcs.com
VITE_API_URL_PREFIX = /api

View File

@@ -0,0 +1,5 @@
# 打包路径 根据项目不同按需配置
VITE_BASE_URL = https://static.tdesign.tencent.com/starter/vue-next/
VITE_IS_REQUEST_PROXY = true
VITE_API_URL = https://service-bv448zsw-1257786608.gz.apigw.tencentcs.com
VITE_API_URL_PREFIX = /api

View File

@@ -0,0 +1,5 @@
# 打包路径 根据项目不同按需配置
VITE_BASE_URL = /
VITE_IS_REQUEST_PROXY = true
VITE_API_URL = https://service-exndqyuk-1257786608.gz.apigw.tencentcs.com
VITE_API_URL_PREFIX = /api

View File

@@ -0,0 +1,14 @@
snapshot*
dist
lib
es
esm
node_modules
src/_common
static
cypress
script/test/cypress
_site
temp*
static/
!.prettierrc.js

112
auts_new.client/.eslintrc Normal file
View File

@@ -0,0 +1,112 @@
{
"extends": [
"plugin:@typescript-eslint/recommended",
"eslint-config-airbnb-base",
"@vue/typescript/recommended",
"plugin:vue/vue3-recommended",
"plugin:vue-scoped-css/base",
"plugin:prettier/recommended"
],
"env": {
"browser": true,
"node": true,
"jest": true,
"es6": true
},
"globals": {
"defineProps": "readonly",
"defineEmits": "readonly"
},
"plugins": ["vue", "@typescript-eslint", "simple-import-sort"],
"parserOptions": {
"parser": "@typescript-eslint/parser",
"sourceType": "module",
"allowImportExportEverywhere": true,
"ecmaFeatures": {
"jsx": true
}
},
"settings": {
"import/extensions": [".js", ".jsx", ".ts", ".tsx"]
},
"rules": {
"no-console": "off",
"no-continue": "off",
"no-restricted-syntax": "off",
"no-plusplus": "off",
"no-param-reassign": "off",
"no-shadow": "off",
"guard-for-in": "off",
"import/extensions": "off",
"import/no-unresolved": "off",
"import/no-extraneous-dependencies": "off",
"import/prefer-default-export": "off",
"import/first": "off", // https://github.com/vuejs/vue-eslint-parser/issues/58
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"vue/first-attribute-linebreak": 0,
"@typescript-eslint/no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
"no-unused-vars": [
"error",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_"
}
],
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": "off",
"class-methods-use-this": "off", // 因为AxiosCancel必须实例化而能静态化所以加的规则如果有办法解决可以取消
"simple-import-sort/imports": "error",
"simple-import-sort/exports": "error"
},
"overrides": [
{
"files": ["*.vue"],
"rules": {
"vue/component-name-in-template-casing": [2, "kebab-case"],
"vue/require-default-prop": 0,
"vue/multi-word-component-names": 0,
"vue/no-reserved-props": 0,
"vue/no-v-html": 0,
"vue-scoped-css/enforce-style-type": ["error", { "allows": ["scoped"] }]
}
},
{
"files": ["*.ts", "*.tsx"], // https://github.com/typescript-eslint eslint-recommended
"rules": {
"constructor-super": "off", // ts(2335) & ts(2377)
"getter-return": "off", // ts(2378)
"no-const-assign": "off", // ts(2588)
"no-dupe-args": "off", // ts(2300)
"no-dupe-class-members": "off", // ts(2393) & ts(2300)
"no-dupe-keys": "off", // ts(1117)
"no-func-assign": "off", // ts(2539)
"no-import-assign": "off", // ts(2539) & ts(2540)
"no-new-symbol": "off", // ts(2588)
"no-obj-calls": "off", // ts(2349)
"no-redeclare": "off", // ts(2451)
"no-setter-return": "off", // ts(2408)
"no-this-before-super": "off", // ts(2376)
"no-undef": "off", // ts(2304)
"no-unreachable": "off", // ts(7027)
"no-unsafe-negation": "off", // ts(2365) & ts(2360) & ts(2358)
"no-var": "error", // ts transpiles let/const to var, so no need for vars any more
"prefer-const": "error", // ts provides better types with const
"prefer-rest-params": "error", // ts provides better types with rest args over arguments
"prefer-spread": "error", // ts transpiles spread to apply, so no need for manual apply
"valid-typeof": "off" // ts(2367)
}
}
]
}

6
auts_new.client/.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
*.ts text eol=lf
*.vue text eol=lf
*.tsx text eol=lf
*.jsx text eol=lf
*.html text eol=lf
*.json text eol=lf

37
auts_new.client/.gitignore vendored Normal file
View File

@@ -0,0 +1,37 @@
# OS specific files
.DS_Store
# dependencies manager
node_modules/
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
# build files
es/
lib/
dist/
typings/
_site
package
tmp*
temp*
coverage
test-report.html
.idea/
yarn-error.log
*.zip
.history
.stylelintcache
.env.local
.env.*.local
# lock文件 请根据自身项目或团队需求选择具体的包管理工具 并移除具体的ignore的lock文件
yarn.lock
pnpm-lock.yaml

View File

@@ -0,0 +1,8 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
if [[ "$OS" == "Windows_NT" ]]; then
npx.cmd --no-install commitlint -e $GIT_PARAMS
else
npx --no-install commitlint -e $GIT_PARAMS
fi

View File

@@ -0,0 +1,8 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
if [[ "$OS" == "Windows_NT" ]]; then
npx.cmd lint-staged
else
npx lint-staged
fi

View File

@@ -0,0 +1,10 @@
#!/bin/sh
[[ "$(uname -a)" = *"MINGW64"* ]] && exit 0
[ -n "$CI" ] && exit 0
. "$(dirname "$0")/_/husky.sh"
if [[ "$OS" == "Windows_NT" ]]; then
exec < /dev/tty && npx.cmd git-cz --hook || true
else
exec < /dev/tty && npx git-cz --hook || true
fi

3
auts_new.client/.npmrc Normal file
View File

@@ -0,0 +1,3 @@
shamefully-hoist = true
hoist = true
engine-strict =true

View File

@@ -0,0 +1,39 @@
export default {
// 一行最多 120 字符..
printWidth: 120,
// 使用 2 个空格缩进
tabWidth: 2,
// 不使用缩进符,而使用空格
useTabs: false,
// 行尾需要有分号
semi: true,
// 使用单引号
singleQuote: true,
// 对象的 key 仅在必要时用引号
quoteProps: 'as-needed',
// jsx 不使用单引号,而使用双引号
jsxSingleQuote: false,
// 末尾需要有逗号
trailingComma: 'all',
// 大括号内的首尾需要空格
bracketSpacing: true,
// jsx 标签的反尖括号需要换行
jsxBracketSameLine: false,
// 箭头函数,只有一个参数的时候,也需要括号
arrowParens: 'always',
// 每个文件格式化的范围是文件的全部内容
rangeStart: 0,
rangeEnd: Infinity,
// 不需要写文件开头的 @prettier
requirePragma: false,
// 不需要自动在文件开头插入 @prettier
insertPragma: false,
// 使用默认的折行标准
proseWrap: 'preserve',
// 根据显示样式决定 html 要不要折行
htmlWhitespaceSensitivity: 'css',
// vue 文件中的 script 和 style 内不用缩进
vueIndentScriptAndStyle: false,
// 换行符使用 lf
endOfLine: 'lf',
};

View File

@@ -0,0 +1,8 @@
# .stylelintignore
# 旧的不需打包的样式库
*.min.css
# 其他类型文件
*.js
*.jpg
*.woff

View File

@@ -0,0 +1,3 @@
{
"recommendations": ["dbaeumer.vscode-eslint"]
}

19
auts_new.client/.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,19 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "edge",
"request": "launch",
"name": "localhost (Edge)",
"url": "https://localhost:33891",
"webRoot": "${workspaceFolder}"
},
{
"type": "chrome",
"request": "launch",
"name": "localhost (Chrome)",
"url": "https://localhost:33891",
"webRoot": "${workspaceFolder}"
}
]
}

36
auts_new.client/.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,36 @@
{
"files.eol":"\n",
"editor.tabSize": 2,
"eslint.format.enable": true,
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "vue"],
"[vue]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescriptreact]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[javascriptreact]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[javascript]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"cSpell.words": [
"tdesign",
"tvision",
"echarts",
"nprogress",
"commitlint",
"stylelint",
"pinia",
"qrcode"
],
}

View File

@@ -0,0 +1 @@
nodeLinker: node-modules

View File

@@ -0,0 +1,361 @@
---
title: 更新日志
spline: explain
toc: false
docClass: timeline
---
## 🌈 0.12.0 `2025-01-06`
### 🐞 Bug Fixes
- `Vue`: 修复升级至 Vue 3.4 及 3.5 的生产模式下的问题 @uyarn ([#796](https://github.com/Tencent/tdesign-vue-next-starter/pull/796))
### 📈 Performance
- defineProps改为Vue3.5解构语法 @liect ([#799](https://github.com/Tencent/tdesign-vue-next-starter/pull/799))
## 🌈 0.11.0 `2024-11-06`
### 🚀 Features
- `feat`: 调整默认lock文件配置 @timi137137 ([#717](https://github.com/Tencent/tdesign-vue-next-starter/pull/717))
- `Router`: 路由跳转携带参数 @SuxueCode ([#720](https://github.com/Tencent/tdesign-vue-next-starter/pull/720))
- `feat`: 新增菜单自动折叠 @RSS1102 ([#744](https://github.com/Tencent/tdesign-vue-next-starter/pull/744))
### 🐞 Bug Fixes
- `breadcrumb`: 修复多层级路由指向错误 @lz6060788 ([#749](https://github.com/Tencent/tdesign-vue-next-starter/pull/749))
- `deps`: 修正因锁文件错误导致的编译失败 @timi137137 ([#777](https://github.com/Tencent/tdesign-vue-next-starter/pull/777))
### 🚧 Others
- `revert`: 回退Vue 3.3 @timi137137 ([#709](https://github.com/Tencent/tdesign-vue-next-starter/pull/709))
- build(deps-dev): bump @types/lodash from 4.14.202 to 4.17.6 @dependabot[bot] ([#732](https://github.com/Tencent/tdesign-vue-next-starter/pull/732))
- build(deps): bump tdesign-vue-next from 1.9.3 to 1.9.9 @dependabot[bot] ([#748](https://github.com/Tencent/tdesign-vue-next-starter/pull/748))
## 🌈 0.10.0 `2024-04-02`
### 🚀 Features
- 优化整体代码风格 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/638 https://github.com/Tencent/tdesign-vue-next-starter/pull/650 https://github.com/Tencent/tdesign-vue-next-starter/pull/680 https://github.com/Tencent/tdesign-vue-next-starter/pull/684)
- 新增侧边栏颜色切换 by @qingmang @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/681)
- 使用 `t-descriptions` 替换详情页代码 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/707)
### 🐞 Bug Fixes
- 修复国际化配置缺失 by @liweijie0812 @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/614 https://github.com/Tencent/tdesign-vue-next-starter/pull/632 https://github.com/Tencent/tdesign-vue-next-starter/pull/636)
- 修复 `ECharts` 图例缩放错误 by @lcosmos (https://github.com/Tencent/tdesign-vue-next-starter/pull/622)
- 修复 `ECharts` 图样文字重叠 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/682)
- 修复 `husky` 找不到npx命令 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/635)
- 修复路由切换时过渡动画异常 by @mokeyjay (https://github.com/Tencent/tdesign-vue-next-starter/pull/666)
- 修复mock环境下获取菜单异常 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/630)
## 🌈 0.9.0 `2023-10-04`
### 🚀 Features
- 新增内置国际化配置,支持中英切换 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/607)
- 新增 node 版本要求 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/605)
### 🐞 Bug Fixes
- 修复`t-link`在设置主题色时的样式异常 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/565)
- 移除无效的 `stylelint` 规则 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/584)
- 修复部分内置样式对 button 的影响 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/586)
- 修正部分模板页面卡片组件操作插槽用法 by @ngyyuusora (https://github.com/Tencent/tdesign-vue-next-starter/pull/587)
- 修改部分错别字 by @dufu1991 (https://github.com/Tencent/tdesign-vue-next-starter/pull/600)
- 优化”暂无通知“的样式问题 by @Summer-Shen (https://github.com/Tencent/tdesign-vue-next-starter/pull/604)
## 🌈 0.8.0 `2023-07-12`
### ❗️ BREAKING CHANGES
- 重构内置 axios 及请求相关逻辑,新增接口级防抖节流 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/556)
- 更新 stylelint 相关配置 移除 stylelint-less 依赖 by @timi137137 @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/553 https://github.com/Tencent/tdesign-vue-next-starter/pull/558)
### 🐞 Bug Fixes
- 修复路由跳转表头闪烁的问题 by @tanhh326 (https://github.com/Tencent/tdesign-vue-next-starter/pull/550)
- 修复筛选列表页搜索合同状态显示object的异常 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/559)
## 🌈 0.7.7 `2023-06-27`
### 🚀 Features
- Vite版本升级至4 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/533)
- 组件库版本升级至 1.3.8 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/548)
- Axios支持格式化Params by @ngyyuusora (https://github.com/Tencent/tdesign-vue-next-starter/pull/544)
### 🐞 Bug Fixes
- 修复登出后路由重置问题 by @ngyyuusora (https://github.com/Tencent/tdesign-vue-next-starter/pull/545)
- 修复请求时204无内容判断异常 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/539)
## 🌈 0.7.6 `2023-05-30`
### 🚀 Features
- 移除了将所有文件一并提交的代码 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/515)
- 组件库版本升级至 1.3.4 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/518)
- 禁止隐式Any类型声明 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/519)
### 🐞 Bug Fixes
- 修复多标签页中保活异常问题 by @ngyyuusora (https://github.com/Tencent/tdesign-vue-next-starter/pull/523)
- 修复store存储token读取异常问题 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/526)
## 🌈 0.7.5 `2023-05-18`
### 🚀 Features
- 站点引入主题生成器插件,支持在页面模板站点尝试及预览不同主题的效果 by @uyarn @timi137137
- 优化路由守卫获取菜单异常的处理,跳转登录页并弹窗提示 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/502)
- 规范不同系统中的结束符 by @SpringHgui @yunxifd (https://github.com/Tencent/tdesign-vue-next-starter/pull/505)
### 🐞 Bug Fixes
- 修复无法将通知设为未读的缺陷 by @izoyo (https://github.com/Tencent/tdesign-vue-next-starter/pull/511)
- 修复 store 中并未对 localStorage 的 TOKEN_NAME 键进行赋值的缺陷 by @SpringHgui (https://github.com/Tencent/tdesign-vue-next-starter/pull/504)
## 🌈 0.7.4 `2023-04-13`
### 🚀 Features
- Eslint 新增 `simple-import-sort` 插件规范引入 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/464)
- 菜单路由支持`keepAlive`参数控制页面是否开启缓存 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/470)
- 标签页可配置禁止拖拽 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/454)
### 🐞 Bug Fixes
- 修复拼音输入的问题 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/421)
- 修复同级路由路径存着相同启始字符时菜单高亮异常的问题 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/450)
- 修复部分`devDependencies`错误配置在`dependencies`的问题 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/456)
- 修复请求出错重试后触发两次回调的问题 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/458)
- 修复多级菜单高亮问题 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/459)
## 🌈 0.7.3 `2023-03-15`
### 🚀 Features
- 优化菜单生成 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/413)
- 优化修改主题色的逻辑 by @hzgotb (https://github.com/Tencent/tdesign-vue-next-starter/pull/428)
- 接口配置硬编码调整到环境变量 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/445)
### 🐞 Bug Fixes
- 修复修改.html文件stylelint检查出错的问题 by @hmingv (https://github.com/Tencent/tdesign-vue-next-starter/pull/436)
- 删除废弃的globEager by @hmingv (https://github.com/Tencent/tdesign-vue-next-starter/pull/439)
## 🌈 0.7.2 `2023-02-21`
### 🚀 Features
- 优化菜单生成逻辑 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/413)
- 多标签Tab栏支持拖拽排序 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/426)
### 🐞 Bug Fixes
- 修复列表页示例拼音输入的问题 by @liweijie0812 (https://github.com/Tencent/tdesign-vue-next-starter/pull/421)
- 优化登录页及个人中心页样式 by @Wen1kang (https://github.com/Tencent/tdesign-vue-next-starter/pull/415)
- 修复 tdesign-vue-next 1.0.8版本由于引入Teleport后drawer内样式穿透失效引起的样式错乱 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/425)
## 🌈 0.7.1 `2023-02-08`
### 🐞 Bug Fixes
- 修复环境变量的问题 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/399)
- 修复 stylelint 14的配置问题 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/404)
- 修复dashboard&layout相关样式Bug by @Wen1kang (https://github.com/Tencent/tdesign-vue-next-starter/pull/403)
- 修复菜单图标样式问题 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/402)
## 🌈 0.7.0 `2023-01-16`
### ❗️ BREAKING CHANGES
- 移除所有内置主题色相关代码,全部通过 `tvision-color` 计算获取,调整颜色相关方法的目录结构 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/392)
- 新增后端路由权限相关代码,默认菜单路由权限改为后端控制,具体使用可参考文档 [权限控制](https://tdesign.tencent.com/starter/docs/vue-next/permission-control) by @timi137137 @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/394)
### 🚀 Features
- 支持任意颜色作为初始化主题颜色 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/392)
- 升级 `tvision-color` 至1.5.0 使用新的`getColorGradations`方法,修正部分选择的过曝主题色 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/392)
- 升级相关依赖 `vite`需升级至`3.0`以上,支持图标后端配置等场景需求 by @timi137137 @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/394)
### 🐞 Bug Fixes
- 修复自定义颜色切换明亮暗黑模式时无法沿用的缺陷 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/392)
`Tips: 此次发布 较 0.6.x 版本 删除了此前大量内置项目的色彩生成逻辑,权限控制相关逻辑也发生巨大变动 若打开预览无法访问请清除 localStorage 等缓存再尝试 跟进升级请慎重`
## 🌈 0.6.1 `2022-12-19`
### 🚀 Features
- 优化登录跳转支持回跳带query参数的页面 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/374)
- 引入类型声明为type 方便CLI工具做JS版本转换处理 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/375)
- 新增打开外部页面(内嵌及外链)配置及示例 by @dianjie (https://github.com/Tencent/tdesign-vue-next-starter/pull/377)
- 支持编辑器使用`volar`提示组件名称及对应API by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/378)
### 🐞 Bug Fixes
- 修复DateRangePicker组件内分页样式显示异常 by @wandoupeas (https://github.com/Tencent/tdesign-vue-next-starter/pull/373)
- 修复组件升级引入的布局高度问题 by @dianjie (https://github.com/Tencent/tdesign-vue-next-starter/pull/367)
## 🌈 0.6.0 `2022-11-25`
### ❗️ BREAKING CHANGES
- 废弃大量内置`less variables`, 尺寸、色彩、字体、圆角及阴影统一使用组件库内置变量 具体变量可参考 [Design Token](https://tdesign.tencent.com/starter/docs/vue-next/design-token) by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/365)
- 升级默认主题色的配色方案 组件库升级至0.24.9及请参照改动 @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/365)
### 🐞 Bug Fixes
- 修复组件库升级至0.24.8及以上由于头部高度变化导致部分导航模式样式异常的问题 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/365)
- 避免 Content-Type 被改为 `text/plain` by @TonyLuo (https://github.com/Tencent/tdesign-vue-next-starter/pull/361)
## 🌈 0.5.6 `2022-11-18`
### 🐞 Bug Fixes
- 修正退出后 userStore.userInfo 存在残留的问题 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/357)
- 修复0.5.5 头部高度在多标签页的样式异常 by @uyarn @dodu2014 (https://github.com/Tencent/tdesign-vue-next-starter/pull/360)
## 🌈 0.5.5 `2022-11-16`
### 🚀 Features
- 升级axios至1.0版本 by @dependabot (https://github.com/Tencent/tdesign-vue-next-starter/pull/351)
- 升级tdesign-vue-next至0.24版本 支持尺寸类Design Token 部分样式需调整 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/355)
### 🐞 Bug Fixes
- 修复导航布局`side`模式下小屏显示问题 by @dianjie (https://github.com/Tencent/tdesign-vue-next-starter/pull/348)
## 🌈 0.5.4 `2022-10-26`
### 🚀 Features
- 升级`vue-router`至4.1+ by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/341)
- 升级`vue-tsc`至 1.0+ by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/341)
### 🐞 Bug Fixes
- 修复系统设置事件绑定位置的错误(#344) by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/345)
## 🌈 0.5.3 `2022-10-18`
### 🚀 Features
- 项目通用 less vars 设置为全局变量,不需要再手动引入 by @dianjie (https://github.com/Tencent/tdesign-vue-next-starter/pull/327)
- 升级组件库依赖至0.24.2 优化下拉菜单高度及多级结构 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/339)
## 🌈 0.5.2 `2022-09-27`
### 🚀 Features
- 升级组件库依赖至0.23 修复切换页面等场景下表格吸附效果未重新计算导致的样式异常 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/322)
- 增加urlPrefix判断 避免undefined拼接到url导致请求无效 @kerwin612 (https://github.com/Tencent/tdesign-vue-next-starter/pull/311)
### 🐞 Bug Fixes
- 修复`Sidenav`参数错误导致跟随系统样式异常的问题 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/315)
- 修复user持久化导致的问题 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/316)
- 修复路径重复拼接的问题 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/319)
## 🌈 0.5.1 `2022-09-14`
### 🚀 Features
- 多标签页的右键操作扩展支持非当前页进行操作 by @zhangpaopao0609 @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/297)
- 使用插件将store数据持久化 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/291)
- add README in English by @paiakarit @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/301 https://github.com/Tencent/tdesign-vue-next-starter/pull/305)
### 🐞 Bug Fixes
- 解决当打开多个标签后 退出会报错的问题 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/293)
- 修复底部版权信息及面包屑导航垂直居中问题 by @zengqiu (https://github.com/Tencent/tdesign-vue-next-starter/pull/299 https://github.com/Tencent/tdesign-vue-next-starter/pull/298)
- 修复浏览器不兼容页中浏览器推荐卡片遮挡页脚信息问题 by @zengqiu (https://github.com/Tencent/tdesign-vue-next-starter/pull/303)
## 🌈 0.5.0 `2022-09-06`
### ❗️ BREAKING CHANGES
- jsx代码全部改完sfc(.vue) 统一全部页面及组件用sfc编写 by @zhangpaopao0609 (https://github.com/Tencent/tdesign-vue-next-starter/pull/279)
### 🐞 Bug Fixes
- 修复混合模式下选择分割菜单再点击顶部登录页出现空白页的异常 by @setli (https://github.com/Tencent/tdesign-vue-next-starter/pull/287)
- 修复顶部布局头部缺失的问题 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/292)
- 修复侧边栏折叠时版本号前显示 false 问题 by @zengqiu (https://github.com/Tencent/tdesign-vue-next-starter/pull/294)
## 🌈 0.4.1 `2022-08-30`
### 🚀 Features
- 升级tdesign-vue-next至0.20.2版本 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/276)
- tabs-router 支持存储路由的参数 by @dodu2014 (https://github.com/Tencent/tdesign-vue-next-starter/pull/269)
### 🐞 Bug Fixes
- 修复更新vue-router版本后的遗留问题 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/261)
- 修正请求时formData类型的数据会被过滤的问题 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/272)
- 修正store内数据提前被清理导致报错的问题 by @PDieE (https://github.com/Tencent/tdesign-vue-next-starter/pull/274)
## 🌈 0.4.0 `2022-08-08`
### ❗️ BREAKING CHANGES
- 升级vue-router版本 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/257)
### 🚀 Features
- 处理代码中不符合规范的文件和写法 升级相关依赖 增加更多的规范 by @uyarn (https://github.com/Tencent/tdesign-vue-next-starter/pull/243)
- 新增支持子菜单是否默认展开的配置 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/245)
- 升级组件库依赖至0.19.0 组件圆角样式有变化 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/252)
### 🐞 Bug Fixes
- 修复变更颜色/模式时出现页面卡死的异常 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/254)
- 修复侧边栏开合时图表没有刷新的问题 by @timi137137 (https://github.com/Tencent/tdesign-vue-next-starter/pull/253)
- 填补登录页面缺失的手机号输入框及相关逻辑 by @hxywuya (https://github.com/Tencent/tdesign-vue-next-starter/pull/255)
## 🌈 0.3.6 `2022-07-18`
### 🚀 Features
- 升级tdesign-vue-next至0.18.0版本
- 增加apis目录 管理项目中使用到的api by @timi137137 ([#221](https://github.com/Tencent/tdesign-vue-next-starter/pull/221))
- router调整为自动导入 by @timi137137 ([#223](https://github.com/Tencent/tdesign-vue-next-starter/pull/223))
### 🐞 Bug Fixes
- 部分选择器未随自定义样式前缀更改 by @wandoupeas ([#229](https://github.com/Tencent/tdesign-vue-next-starter/pull/229))
## 🌈 0.3.5 `2022-06-27`
### 🚀 Features
- 调整类型相关问题的项目结构 by @timi137137 ([#184](https://github.com/Tencent/tdesign-vue-next-starter/pull/184))
- 改造请求封装相关代码 by @timi137137 ([#185](https://github.com/Tencent/tdesign-vue-next-starter/pull/185))
### 🐞 Bug Fixes
- 修复首页TAB关闭其他时的异常 by @SadWood ([#180](https://github.com/Tencent/tdesign-vue-next-starter/pull/180))
- 修复升级0.16版本后自定义设置中选项样式的异常 by @uyarn ([#193](https://github.com/Tencent/tdesign-vue-next-starter/pull/193))
## 🌈 0.3.4 `2022-06-17`
### 🚀 Features
- 升级组件库依赖至0.16.0`datepicker``dialog`组件的使用请参考改动 by @pengYYYYY ([#174](https://github.com/Tencent/tdesign-vue-next-starter/pull/174))
### 🐞 Bug Fixes
- 修复退出登录之后重新登陆新增了空Tab的缺陷 by @kerwin612 ([#168](https://github.com/Tencent/tdesign-vue-next-starter/pull/168))
- 修复切换多标签Tab页时的告警问题 by @kerwin612 ([#173](https://github.com/Tencent/tdesign-vue-next-starter/pull/173))
## 🌈 0.3.3 `2022-06-02`
### 🚀 Features
- 模板中使用颜色变量全部改造为CSS Token by @kerwin612 ([#157](https://github.com/Tencent/tdesign-vue-next-starter/pull/157))
### 🐞 Bug Fixes
- 升级组件库至0.15.4,修复菜单字重及顶部菜单箭头翻转方向、暗黑模式的颜色问题 by @uyarn @leejim ([#159](https://github.com/Tencent/tdesign-vue-next-starter/pull/159)) [tdesign-vue-next#916](https://github.com/Tencent/tdesign-vue-next/pull/916)
## 🌈 0.3.2 `2022-05-27`
### 🚀 Features
- 升级组件库依赖至0.15.1 by @pengYYYYY ([#154](https://github.com/Tencent/tdesign-vue-next-starter/pull/154))
- 增加多标签页增加支持指定路由不缓存的功能 by @uyarn ([#155](https://github.com/Tencent/tdesign-vue-next-starter/pull/155))
### 🐞 Bug Fixes
- 修复页面滚动条不重置的问题 by @kerwin612 ([#158](https://github.com/Tencent/tdesign-vue-next-starter/pull/158))
- 修复多标签页关闭逻辑缺陷 by @uyarn ([#156](https://github.com/Tencent/tdesign-vue-next-starter/pull/156))
## 🌈 0.3.1 `2022-05-13`
### 🚀 Features
- lint新增style scoped提示 by @kerwin612 ([#138](https://github.com/Tencent/tdesign-vue-next-starter/pull/138))
- 新增维护中页面 by @uyarn ([#146](https://github.com/Tencent/tdesign-vue-next-starter/pull/146))
- 升级组件库依赖至0.14+
### 🐞 Bug Fixes
- 修复多标签Tab页关闭左侧关闭其他可能导致主页标签被删除 by @kerwin612 ([#148](https://github.com/Tencent/tdesign-vue-next-starter/pull/148))
- 修复多个滚动列表之间切换时页面不刷新导致的样式缺陷 by @kerwin612 ([#152](https://github.com/Tencent/tdesign-vue-next-starter/pull/152))
## 🌈 0.3.0 `2022-04-28`
### 🚀 Features
- 优化菜单选中判断逻辑 by @kerwin612 ([#132](https://github.com/Tencent/tdesign-vue-next-starter/pull/132))
- 升级组件库依赖至0.13 + 版本 by @uyarn ([#133](https://github.com/Tencent/tdesign-vue-next-starter/pull/133))
- 替换全部Card为`t-card`卡片组件,减少重复代码实现
- 调整图表相关代码目录结构图表部分代码调整至所在Page内减少各页面模块的耦合
- 调整表格相关代码及展示增加吸顶功能展示、去除minWidth的使用等
### 🐞 Bug Fixes
- 修复分步表单页底部居中问题
- 修复顶部菜单栏下拉菜单与表单层级问题
## 🌈 0.2.3 `2022-04-26`
### 🚀 Features
- 补充mock示例 by @kerwin612 ([#127](https://github.com/Tencent/tdesign-vue-next-starter/pull/127))
### 🐞 Bug Fixes
- 修复顶部菜单栏未选中项样式问题 by @kerwin612 ([#131](https://github.com/Tencent/tdesign-vue-next-starter/pull/131))
- 修复搜索框样式异常问题 by @kerwin612 ([#130](https://github.com/Tencent/tdesign-vue-next-starter/pull/130))
- 修复顶部布局布局菜单样式问题 by @kerwin612 ([#129](https://github.com/Tencent/tdesign-vue-next-starter/pull/129))
## 🌈 0.2.2 `2022-04-06`
### 🚀 Features
- 支持多标签页支持持久化 by @uyarn ([#111](https://github.com/Tencent/tdesign-vue-next-starter/pull/111))
- 升级组件库依赖tdesign-vue-next至0.11版本 by @pengYYYYY
### 🐞 Bug Fixes
- 修复图表文字颜色异常 by @uyarn ([#112](https://github.com/Tencent/tdesign-vue-next-starter/pull/112))
- 修复mock roles模块错误 by @lscho ([#104](https://github.com/Tencent/tdesign-vue-next-starter/pull/104))
## 🌈 0.2.1 `2022-03-25`
### 🚀 Features
- 新增多标签Tab页功能 ([#98](https://github.com/Tencent/tdesign-vue-next-starter/pull/98))
## 🌈 0.2.0 `2022-03-04`
### 🚀 Features
- pinia替换vuex作为状态管理库 by @PengYYYYY
- 升级组件库依赖tdesign-vue-next至0.9版本
## 🌈 0.1.3 `2022-02-27`
### 🚀 Features
- 使用 `setup script` 重构了页面逻辑
### 🐞 Bug Fixes
- 修复菜单下拉与表格定位冲突
## 🌈 0.1.2 `2022-02-18`
### 🐞 Bug Fixes
- 修复面包屑点击跳转当前页错误的问题 by @ccccpj
## 🌈 0.1.1 `2022-01-27`
### 🐞 Bug Fixes
- 修复表单页检验提示未正常显示的问题
## 🌈 0.1.0 `2022-01-10`
### 🚀 Features
- 升级 `tdesign-vue-next` 版本到 `0.6.3`
### 🐞 Bug Fixes
- 修复一级菜单收起出现多余 `1` 的 bug
- 修复 `time-picker` 的文字覆盖
- 修复版本图表渲染问题

21
auts_new.client/LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 TDesign
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,10 @@
# 版本发布流程
## 发布流程
-`develop` 新建 `release/x.y.z` 分支,并修改 `package.json` 中的版本号,推送分支至远程仓库,并提交一个合入`develop`的 Pull Request 到仓库
- 仓库的 Github Action 会自动整理上个版本至今 commit 对应的 CHANGELOG并将 CHANGELOG 的 draft 作为一个评论推送到该 Pull Request 上
- 发布人检查 CHANGELOG并优化内容逻辑结构确认无误后删除对于评论首行提示Github Action 会将优化后的内容写入 CHANGELOG.md 内
- 确认无误后,合并分支入`develop`
合入 `develop` 后,仓库会触发 Github Action 合入 `main` 分支,并将版本号作为 `tag` 打在仓库上

View File

@@ -0,0 +1,117 @@
<p style="display:flex; justify-content: center">
</p>
<p align="center">
<a href="https://tdesign.tencent.com/starter/vue-next/#/dashboard/base" target="_blank">
<img alt="TDesign Logo" width="200" src="https://tdesign.gtimg.com/starter/brand-logo.svg">
</a>
</p>
<p align="center">
<a href="https://nodejs.org/en/about/releases/"><img src="https://img.shields.io/node/v/vite.svg" alt="node compatibility"></a>
<a href="https://github.com/Tencent/tdesign-vue-next/blob/develop/LICENSE">
<img src="https://img.shields.io/npm/l/tdesign-vue-next.svg?sanitize=true" alt="License">
</a>
</p>
简体中文 | [English](./README.md)
### 项目简介
TDesign Vue Next Starter 是一个基于 TDesign使用 `Vue3``Vite``Pinia``TypeScript` 开发,可进行个性化主题配置,旨在提供项目开箱即用的、配置式的中后台项目。
<p>
<a href="http://tdesign.tencent.com/starter/vue-next/">在线预览</a>
·
<a href="https://tdesign.tencent.com/starter/">使用文档</a>
</p>
<img src="docs/starter.png">
### 特性
- 内置多种常用的中后台页面
- 完善的目录结构
- 完善的代码规范配置
- 支持暗黑模式
- 自定义主题颜色
- 多种空间布局
- 内置 Mock 数据方案
### 使用
> 通过 `tdesign-starter-cli` 初始化项目仓库
```bash
## 1、安装 tdesign-starter-cli
npm i tdesign-starter-cli@latest -g
## 2、创建项目
td-starter init
```
### 开发
``` bash
## 安装依赖
npm install
## 启动项目
npm run dev
```
### 构建
```bash
## 构建正式环境
npm run build
## 构建测试环境
npm run build:test
```
### 其他
```bash
## 预览构建产物
npm run preview
## 代码格式检查
npm run lint
## 代码格式检查与自动修复
npm run lint:fix
## style格式检查
npm run stylelint
## style格式检查与自动修复
npm run stylelint:fix
```
### 如何贡献
非常欢迎您的贡献!提交您的 [Issue](https://github.com/tencent/tdesign-vue-next-starter/issues/new/choose) 或者提交 [Pull Request](https://github.com/Tencent/tdesign-vue-next-starter/pulls)。
#### 贡献提交规范
- [Angular Convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)
- [Vue Style Guide](https://v3.vuejs.org/style-guide/#rule-categories)
### 兼容性
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Edge >=84 | Firefox >=83 | Chrome >=84 | Safari >=14.1 |
### 社区版本
基于 TDesign Vue Next 的 starter-kit 有多种社区版本,访问 [社区链接](https://tdesign.tencent.com/starter/docs/vue-next/community-link) 可以访问更多版本。
如果您也开发了 TDesign Starter 的社区版本,可以提交 Issue 或者直接给我们提Pull Request 😊。
### 开源协议
TDesign 遵循 [MIT 协议](https://github.com/Tencent/tdesign-vue-next-starter/LICENSE)。

94
auts_new.client/README.md Normal file
View File

@@ -0,0 +1,94 @@
<p style="display:flex; justify-content: center">
</p>
<p align="center">
<a href="https://tdesign.tencent.com/starter/vue-next/#/dashboard/base" target="_blank">
<img alt="TDesign Logo" width="200" src="https://tdesign.gtimg.com/starter/brand-logo.svg">
</a>
</p>
<p align="center">
<a href="https://nodejs.org/en/about/releases/"><img src="https://img.shields.io/node/v/vite.svg" alt="node compatibility"></a>
<a href="https://github.com/Tencent/tdesign-vue-next/blob/develop/LICENSE">
<img src="https://img.shields.io/npm/l/tdesign-vue-next.svg?sanitize=true" alt="License">
</a>
</p>
English | [简体中文](./README-zh_CN.md)
### Introduction
TDesign Vue Next Starter is a TDesign-based developed with `Vue 3`, `Vite`, `Pinia`, `TypeScript`. It can be customized theme configuration, and aims to provide project out-of-the-box, configuration-style middle and background projects.
<p>
<a href="http://tdesign.tencent.com/starter/vue-next/">Live Preview</a>
·
<a href="https://tdesign.tencent.com/starter/">Documentation</a>
</p>
<img src="docs/starter.png">
### Features
- Various provided pages for develop
- Complete directory structure for develop
- Code specification configuration
- Support dark mode
- Custom theme colors
- Various space layouts
- Mock data scheme
### Usage
> Initialize project with our CLI tool `tdesign-starter-cli`
```bash
## install tdesign-starter-cli
npm i tdesign-starter-cli@latest -g
## create project
td-starter init
```
### Develop
```bash
## install dependencies
npm install
## set up
npm run dev
```
### Build
```bash
## build
npm run build
## build for test
npm run build:test
```
### Contributing Guide
We welcome contributions to our project. Create your [Issue](https://github.com/tencent/tdesign-vue-next-starter/issues/new/choose) or Submit your [Pull Request](https://github.com/Tencent/tdesign-vue-next-starter/pulls).
#### Commit Specification
- [Angular Convention](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)
- [Vue Style Guide](https://v3.vuejs.org/style-guide/#rule-categories)
### Browser Support
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br> IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Edge >=84 | Firefox >=83 | Chrome >=84 | Safari >=14.1 |
### Community Versions
There are kinds of community versions of starter-kit based on TDesign Vue Next, visit [community-link](https://tdesign.tencent.com/starter/docs/vue-next/community-link) for more detail. If you developed a community versions of tdesign starter, please create a issue or submit a pull request to let us know 😊.
### License
The MIT License. Please see [the license file](LICENSE) for more information.

View File

@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/1.0.1738743">
<PropertyGroup>
<StartupCommand>npm run dev</StartupCommand>
<JavaScriptTestRoot>.\</JavaScriptTestRoot>
<JavaScriptTestFramework>Jest</JavaScriptTestFramework>
<!-- Allows the build (or compile) script located on package.json to run on Build -->
<ShouldRunBuildScript>false</ShouldRunBuildScript>
<!-- Folder where production build objects will be placed -->
<BuildOutputFolder>$(MSBuildProjectDirectory)\dist</BuildOutputFolder>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,11 @@
// commit-lint config
export default {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [
2,
'always',
['build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'style', 'test', 'types'],
],
},
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

View File

@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>TDesign Vue Next Starter</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<script language="javascript">
if (window.location.host === 'tdesign.tencent.com') {
const aegis = new Aegis({
id: 'rDISNMyXgqWDFPyHMB', // 项目ID即上报key
reportAssetSpeed: true, // 静态资源测速
});
}
</script>
</body>
<script>
window.global = window;
</script>
</html>

View File

@@ -0,0 +1,23 @@
import Mock from 'mockjs';
import { MockMethod } from 'vite-plugin-mock';
export default [
{
url: '/api/detail-basic',
method: 'get',
response: () => ({
code: 0,
data: {
...Mock.mock({
name: 'td_20023747',
loginType: 'Web',
currentRole: 'Admin',
rightsList: '通用权限',
userStatus: '启用',
language: '简体中文',
timeZone: '(GMT+08:00)中国时区—北京Asia/Beijing',
}),
},
}),
},
] as MockMethod[];

10861
auts_new.client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
{
"name": "auts_new.client",
"version": "0.12.0",
"type": "module",
"scripts": {
"dev:mock": "vite --open --mode mock",
"dev": "vite --open --mode development",
"dev:linux": "vite --mode development",
"build:test": "vite build --mode test",
"build": "vue-tsc --noEmit && vite build --mode release",
"build:type": "vue-tsc --noEmit",
"build:site": "vue-tsc --noEmit && vite build --mode site",
"preview": "vite preview",
"lint": "eslint --ext .vue,.js,.jsx,.ts,.tsx ./ --max-warnings 0",
"lint:fix": "eslint --ext .vue,.js,jsx,.ts,.tsx ./ --max-warnings 0 --fix",
"stylelint": "stylelint src/**/*.{html,vue,sass,less}",
"stylelint:fix": "stylelint --fix src/**/*.{html,vue,css,sass,less}",
"prepare": "node -e \"if(require('fs').existsSync('.git')){process.exit(1)}\" || is-ci || husky install",
"site:preview": "npm run build && cp -r dist _site",
"test": "echo \"no test specified,work in process\"",
"test:coverage": "echo \"no test:coverage specified,work in process\""
},
"dependencies": {
"@vueuse/core": "^12.3.0",
"axios": "^1.7.9",
"dayjs": "^1.11.13",
"echarts": "5.4.3",
"lodash": "^4.17.21",
"nprogress": "^0.2.0",
"pinia": "2.1.7",
"pinia-plugin-persistedstate": "^3.2.0",
"qrcode.vue": "^3.4.1",
"qs": "^6.11.2",
"tdesign-icons-vue-next": "^0.3.3",
"tdesign-mobile-vue": "^1.8.2",
"tdesign-vue-next": "^1.11.2",
"tvision-color": "^1.6.0",
"vue": "^3.5.0",
"vue-i18n": "^9.9.1",
"vue-router": "~4.3.0"
},
"devDependencies": {
"@commitlint/cli": "^18.6.0",
"@commitlint/config-conventional": "^18.6.0",
"@types/echarts": "^4.9.21",
"@types/lodash": "^4.17.6",
"@types/mockjs": "^1.0.10",
"@types/nprogress": "^0.2.3",
"@types/qs": "^6.9.11",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@vitejs/plugin-vue": "^5.0.4",
"@vitejs/plugin-vue-jsx": "^3.0.2",
"@vue/compiler-sfc": "~3.3.8",
"@vue/eslint-config-typescript": "^12.0.0",
"commitizen": "^4.3.0",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.56.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-simple-import-sort": "^12.0.0",
"eslint-plugin-vue": "^9.21.1",
"eslint-plugin-vue-scoped-css": "^2.7.2",
"husky": "^9.1.7",
"less": "^4.2.0",
"lint-staged": "^15.2.2",
"mockjs": "^1.1.0",
"postcss-html": "^1.6.0",
"postcss-less": "^6.0.0",
"prettier": "^3.2.5",
"stylelint": "~16.2.1",
"stylelint-config-standard": "^36.0.0",
"stylelint-order": "~6.0.4",
"typescript": "~5.4.3",
"vite": "^5.1.0",
"vite-plugin-mock": "^3.0.1",
"vite-svg-loader": "^5.1.0",
"vue-tsc": "^1.8.27"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"lint-staged": {
"*.{js,jsx,vue,ts,tsx}": [
"prettier --write",
"npm run lint:fix"
],
"*.{html,vue,css,sass,less}": [
"npm run stylelint:fix"
]
},
"engines": {
"node": ">=18.0.0"
},
"description": "Base on tdesign-starter-cli"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,24 @@
<template>
<t-config-provider :global-config="getComponentsLocale">
<router-view :key="locale" :class="[mode]" />
</t-config-provider>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { useLocale } from '@/locales/useLocale';
import { useSettingStore } from '@/store';
const store = useSettingStore();
const mode = computed(() => {
return store.displayMode;
});
const { getComponentsLocale, locale } = useLocale();
</script>
<style lang="less" scoped>
#nprogress .bar {
background: var(--td-brand-color) !important;
}
</style>

View File

@@ -0,0 +1,19 @@
import type { ProjectListResult, PurchaseListResult } from '@/api/model/detailModel';
import { request } from '@/utils/request';
const Api = {
PurchaseList: '/get-purchase-list',
ProjectList: '/get-project-list',
};
export function getPurchaseList() {
return request.get<PurchaseListResult>({
url: Api.PurchaseList,
});
}
export function getProjectList() {
return request.get<ProjectListResult>({
url: Api.ProjectList,
});
}

View File

@@ -0,0 +1,19 @@
import type { CardListResult, ListResult } from '@/api/model/listModel';
import { request } from '@/utils/request';
const Api = {
BaseList: '/get-list',
CardList: '/get-card-list',
};
export function getList() {
return request.get<ListResult>({
url: Api.BaseList,
});
}
export function getCardList() {
return request.get<CardListResult>({
url: Api.CardList,
});
}

View File

@@ -0,0 +1,23 @@
export interface PurchaseListResult {
list: Array<PurchaseInfo>;
}
export interface PurchaseInfo {
adminName: string;
index: string;
pdName: string;
pdNum: string;
pdType: string;
purchaseNum: number;
updateTime: Date;
}
export interface ProjectListResult {
list: Array<ProjectInfo>;
}
export interface ProjectInfo {
adminName: string;
adminPhone: string;
index: number;
name: string;
updateTime: Date;
}

View File

@@ -0,0 +1,26 @@
export interface ListResult {
list: Array<ListModel>;
}
export interface ListModel {
adminName: string;
amount: string;
contractType: number;
index: number;
name: string;
no: string;
paymentType: number;
status: number;
updateTime: Date;
}
export interface CardListResult {
list: Array<CardList>;
}
export interface CardList {
banner: string;
description: string;
index: number;
isSetup: boolean;
name: string;
type: number;
}

Some files were not shown because too many files have changed in this diff Show More