yanjinhui
2025-04-03 2623a84ddaeb38f5c8c6234a24980302b1ec550b
添加人脸识别
已修改7个文件
已添加7个文件
1067 ■■■■■ 文件已修改
项目代码/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v17/HierarchyCache.v1.txt 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/BaiDuFaceHelper.cs 369 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/WIDESEAWCS_Common.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_DTO/System/AddUserDTO.cs 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_ISystemServices/ISys_UserService.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITelescopicService/IFaceRecognitionServer .cs 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/LoginInfo.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/System/Sys_User.cs 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/Telescopic/Dt_FaceRecognition.cs 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/System/Sys_UserController.cs 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Telescopic/FaceRecognitionController .cs 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/wwwroot/image/logo1.png 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_SystemServices/Sys_UserService.cs 437 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
项目代码/WCS/WIDESEAWCS_Server/WIDESEAWCS_TelescopicService/FaceRecognitionServer.cs 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/.vs/WIDESEAWCS_Server/v17/HierarchyCache.v1.txt
Binary files differ
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/BaiDuFaceHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,369 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace WIDESEAWCS_Common
{
    public class BaiDuFaceHelper
    {
        /// <summary>
        /// èŽ·å–AccessToken
        /// </summary>
        /// <returns></returns>
        public static string GetAccessToken()
        {
            //string url = string.Format("https://aip.baidubce.com/oauth/2.0/token?client_id={0}&client_secret={1}&grant_type={2}", "TqFQHXSNt6Z7cPQ4vDBfBNjq", "0cli6I6s8JFz3qM1Czi5ciRpDqrJuVvm", "client_credentials");
            //string returnStr = BDWebRequest(url, "", "POST");
            //NLog.LogManager.GetCurrentClassLogger().Trace("百度人脸识别返回:" + returnStr);
            //BDToken token = JsonConvert.DeserializeObject<BDToken>(returnStr);
            //token.getdate = DateTime.Now.ToString();
            //return token.access_token;
            var str = "24.83aee44079e5a27530bc72d5ec7049a3.2592000.1746152354.282335-118294290";
            return str;
        }
        public static string BDWebRequest(string url, string data, string method)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = string.IsNullOrEmpty(method) ? "POST" : method.ToUpper();
                request.UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22";
                request.ServicePoint.Expect100Continue = false;
                request.Timeout = 1000 * 60;
                request.ContentType = "application/x-www-form-urlencoded";
                if (!string.IsNullOrEmpty(method) && method.ToUpper() == "POST" && !string.IsNullOrEmpty(data))
                {
                    byte[] byteArray = Encoding.UTF8.GetBytes(data);
                    request.ContentLength = byteArray.Length;
                    using (Stream myRequestStream = request.GetRequestStream())
                    {
                        myRequestStream.Write(byteArray, 0, byteArray.Length);
                    }
                }
                HttpWebResponse myHttpWebResponse = (HttpWebResponse)request.GetResponse();
                using (Stream response = myHttpWebResponse.GetResponseStream())
                {
                    using (StreamReader reader = new StreamReader(response, Encoding.UTF8))
                    {
                        return reader.ReadToEnd();
                    }
                }
            }
            catch { return ""; }
        }
        /// <summary>
        /// äººè„¸æ£€æµ‹ä¸Žå±žæ€§åˆ†æž
        /// </summary>
        /// <returns></returns>
        public static string FaceDetect(string path)
        {
            string token = GetAccessToken();
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=" + token;
            var imgbase64 = GetFileContentAsBase64(path);
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "POST";
            request.KeepAlive = true;
            String str = "{\"image\":\""+ imgbase64 + "\",\"image_type\":\"BASE64\"}";
            byte[] buffer = encoding.GetBytes(str);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string result = reader.ReadToEnd();
            NLog.LogManager.GetCurrentClassLogger().Trace("人脸检测与属性分析:" + result);
            return result;
        }
        /// <summary>
        /// åˆ›å»ºç”¨æˆ·äººè„¸è¯†åˆ«ç»„
        /// </summary>
        /// <returns></returns>
        public static string GroupAdd(string group)
        {
            string token = GetAccessToken();
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/add?access_token=" + token;
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "post";
            request.KeepAlive = true;
            String str = "{\"group_id\":\""+ group + "\"}";
            byte[] buffer = encoding.GetBytes(str);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string result = reader.ReadToEnd();
            NLog.LogManager.GetCurrentClassLogger().Trace("创建用户组:" + result);
            return result;
        }
        /// <summary>
        /// èŽ·å–æ–‡ä»¶base64编码
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns>base64编码信息,不带文件头</returns>
        //public static string GetFileContentAsBase64(string path)
        //{
        //    using (FileStream filestream = new FileStream(path, FileMode.Open))
        //    {
        //        byte[] arr = new byte[filestream.Length];
        //        filestream.Read(arr, 0, (int)filestream.Length);
        //        string base64 = Convert.ToBase64String(arr);
        //        return base64;
        //    }
        //}
        public static string GetFileContentAsBase64(string filePath)
        {
            // åªä¿ç•™æ–‡ä»¶åï¼Œé¿å…è·¯å¾„错误
            string fileName = Path.GetFileName(filePath);
            // èŽ·å–æ–‡ä»¶çš„å®Œæ•´è·¯å¾„
            string fullPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "image", fileName);
            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("文件不存在:" + fullPath);
            }
            using (FileStream filestream = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
            {
                byte[] arr = new byte[filestream.Length];
                filestream.Read(arr, 0, arr.Length);
                return Convert.ToBase64String(arr);
            }
        }
        /// <summary>
        /// äººè„¸æ³¨å†Œ
        /// </summary>
        /// <returns></returns>
        public static CreateUserResult AddUser(BDUserInfo info)
        {
            string token = GetAccessToken();
            var imgbase64 = GetFileContentAsBase64(info.ImgPath);
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/add?access_token=" + token;
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "POST";
            request.KeepAlive = true;
            String str = "{\"image\":\"" + imgbase64 + "\",\"image_type\":\"BASE64\",\"group_id\":\"" + info.group_id + "\",\"user_id\":\"" + info.user_id + "\",\"quality_control\":\"LOW\",\"liveness_control\":\"NORMAL\"}";
            byte[] buffer = encoding.GetBytes(str);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string result = reader.ReadToEnd();
            NLog.LogManager.GetCurrentClassLogger().Trace("人脸注册:" + result);
            CreateUserResult res= JsonConvert.DeserializeObject<CreateUserResult>(result);//需要将log_id和face_token保存到用户表中,在人脸删除中需要用到
            return res;
        }
        /// <summary>
        /// äººè„¸åˆ é™¤ï¼ˆåˆ é™¤ç”¨æˆ·çš„æŸä¸€å¼ äººè„¸ï¼Œå¦‚果该用户只有一张人脸图片,则同时删除用户。)
        /// </summary>
        /// <returns></returns>
        public static string DeleteUserImg(DeleteUserImg info)
        {
            string token = GetAccessToken();
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/delete?access_token=" + token;
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "POST";
            request.KeepAlive = true;
            String str = "{\"face_token\":\"" + info.face_token + "\",\"log_id\":\"" + info.log_id + "\",\"group_id\":\"" + info.group_id + "\",\"user_id\":\"" + info.user_id + "\"}";
            byte[] buffer = encoding.GetBytes(str);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string result = reader.ReadToEnd();
            NLog.LogManager.GetCurrentClassLogger().Trace("人脸删除:" + result);
            return result;
        }
        /// <summary>
        /// ç”¨æˆ·åˆ é™¤
        /// </summary>
        /// <returns></returns>
        public static string DeleteUser(DeleteUserImg info)
        {
            string token = GetAccessToken();
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/faceset/user/delete?access_token=" + token;
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "POST";
            request.KeepAlive = true;
            String str = "{\"group_id\":\"" + info.group_id + "\",\"user_id\":\"" + info.user_id + "\"}";
            byte[] buffer = encoding.GetBytes(str);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string result = reader.ReadToEnd();
            NLog.LogManager.GetCurrentClassLogger().Trace("用户删除:" + result);
            return result;
        }
        /// <summary>
        /// äººè„¸æœç´¢
        /// </summary>
        /// <returns></returns>
        public static SearchResult FaceSearch(string path,string group_id_list)
        {
            string token = GetAccessToken();
            var imgbase64 = GetFileContentAsBase64(path);
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/search?access_token=" + token;
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "POST";
            request.KeepAlive = true;
            String str = "{\"image\":\"" + imgbase64 + "\",\"image_type\":\"BASE64\",\"group_id_list\":\""+ group_id_list + "\",\"quality_control\":\"LOW\",\"liveness_control\":\"NORMAL\"}";
            byte[] buffer = encoding.GetBytes(str);
            request.ContentLength = buffer.Length;
            request.GetRequestStream().Write(buffer, 0, buffer.Length);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
            string result = reader.ReadToEnd();
            NLog.LogManager.GetCurrentClassLogger().Trace("人脸搜索:" + result);
            SearchResult searchResult = JsonConvert.DeserializeObject<SearchResult>(result);
            return searchResult;
        }
    }
    /// <summary>
    /// token获取信息
    /// </summary>
    public class BDToken
    {
        /// <summary>
        /// è®¤è¯token
        /// </summary>
        public string access_token { get; set; }
        /// <summary>
        /// Access Token的有效期(秒为单位,有效期30天)
        /// </summary>
        public int expires_in { get; set; }
        /// <summary>
        /// èŽ·å–æ—¶é—´
        /// </summary>
        public string getdate { get; set; }
    }
    /// <summary>
    /// äººè„¸æ³¨å†Œä¿¡æ¯
    /// </summary>
    public class BDUserInfo
    {
        /// <summary>
        /// å›¾ç‰‡è·¯å¾„(总数据大小应小于10M,分辨率应小于1920*1080)
        /// </summary>
        public string ImgPath { get; set; }
        /// <summary>
        /// ç”¨æˆ·ç»„id,标识一组用户(由数字、字母、下划线组成),长度限制48B
        /// </summary>
        public string group_id { get; set; }
        /// <summary>
        /// ç”¨æˆ·id(由数字、字母、下划线组成),对应系统账号
        /// </summary>
        public string user_id { get; set; }
    }
    /// <summary>
    /// äººè„¸æ³¨å†Œæ—¶è¿”回对象
    /// </summary>
    public class CreateUserResult
    {
        /// <summary>
        /// æ£€ç´¢æˆåŠŸè¿”å›ž0
        /// </summary>
        public int error_code { get; set; }
        public string error_msg { get; set; }
        /// <summary>
        /// è¯·æ±‚标识码,随机数,唯一
        /// </summary>
        public string log_id {  get; set; }
        public CreateUser result { get; set; }
    }
    public class CreateUser
    {
        /// <summary>
        /// äººè„¸å›¾ç‰‡çš„唯一标识
        /// </summary>
        public string face_token {  get; set; }
    }
    /// <summary>
    /// äººè„¸æœç´¢æ—¶è¿”回的对象
    /// </summary>
    public class SearchResult
    {
        /// <summary>
        /// æ£€ç´¢æˆåŠŸè¿”å›ž0
        /// </summary>
        public int error_code { get; set; }
        public string error_msg { get; set;}
        public UserResult result { get; set;}
    }
    public class UserResult
    {
        public string face_token {  get; set; }
        public List<User_List> user_list { get; set;}
    }
    public class User_List
    {
        public string user_id { get; set; }
        /// <summary>
        /// ç”¨æˆ·çš„匹配得分,80分以上可以判断为同一人
        /// </summary>
        public string score { get; set;}
    }
    /// <summary>
    /// äººè„¸åˆ é™¤çš„入参对象(只删除某一张图片,如果该用户只有一张图片,那该用户整体删除
    /// </summary>
    public class DeleteUserImg
    {
        /// <summary>
        /// è¯·æ±‚标识码,随机数,唯一
        /// </summary>
        public int log_id { get; set;}
        /// <summary>
        /// ç”¨æˆ·id(由数字、字母、下划线组成),长度限制48B
        /// </summary>
        //public string user_id { get; set;}
        public string user_id { get; set;}
        /// <summary>
        /// ç”¨æˆ·ç»„id(由数字、字母、下划线组成) é•¿åº¦é™åˆ¶48B,删除指定group_id中的user_id信息
        /// </summary>
        public string group_id { get; set;}
        /// <summary>
        /// éœ€è¦åˆ é™¤çš„人脸图片token,(由数字、字母、下划线组成)长度限制64B
        /// </summary>
        public string face_token { get; set;}
    }
}
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Common/WIDESEAWCS_Common.csproj
@@ -8,6 +8,7 @@
  <ItemGroup>
    <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
    <PackageReference Include="NLog" Version="5.4.0" />
  </ItemGroup>
</Project>
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_DTO/System/AddUserDTO.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WIDESEAWCS_DTO.SerialPort
{
    public class AddUserDTO
    {
        /// <summary>
        /// ç”¨æˆ·id用来修改
        /// </summary>
        public int id { get; set; }
        public string  username { get; set; }
        public string usertruename { get; set; }
        /// <summary>
        /// ç™¾åº¦äº‘分组
        /// </summary>
      //  public int log_id { get; set; }
        public string  phoneno { get; set; }
        /// <summary>
        /// ç»„别
        /// </summary>
        public int roleid { get; set; }
        /// <summary>
        /// ç”¨æˆ·ç±»åˆ«
        /// </summary>
        public string rolename { get; set; }
        /// <summary>
        /// æ˜¯å¦å¯ç”¨
        /// </summary>
        public  byte    enable { get; set; }
        /// <summary>
        /// ä¸Šä¼ å›¾ç‰‡å
        /// </summary>
        public string?path { get; set; }
        /// <summary>
        /// å›¾ç‰‡token
        /// </summary>
        //public string ?face_token { get; set; }
    }
}
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_ISystemServices/ISys_UserService.cs
@@ -45,5 +45,31 @@
        /// <param name="files"></param>
        /// <returns></returns>
        WebResponseContent SaveFiles(IFormCollection files);
        /// <summary>
        /// æ·»åŠ ç”¨æˆ·
        /// </summary>
        /// <param name="addUserDTO"></param>
        /// <returns></returns>
        WebResponseContent AdduserData(AddUserDTO addUserDTO);
        WebResponseContent UpuserData(AddUserDTO addUserDTO);
        WebResponseContent DeleteUserData(string userAccount);
        /// <summary>
        /// æ¸…理数据库中没有使用的图片
        /// </summary>
        /// <returns></returns>
        WebResponseContent CleanUnusedImages();
        /// <summary>
        /// ä¿å­˜äººè„¸ç™»å…¥æ—¶çš„图片
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        WebResponseContent SaveFaceFiles(IFormCollection files);
    }
}
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_ITelescopicService/IFaceRecognitionServer .cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_DTO.Telescopic;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_ITaskInfoService
{
    public interface IFaceRecognitionServer : IService<Dt_FaceRecognition>
    {
        IRepository<Dt_FaceRecognition> Repository { get; }
    }
}
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/LoginInfo.cs
@@ -11,5 +11,16 @@
        public string UserName { get; set; }
        public string Password { get; set; }
        /// <summary>
        /// äººè„¸è¯†åˆ«
        /// </summary>
        public string? path { get; set; }
        /// <summary>
        /// ç™¾åº¦äº‘分组face表中的Groupid
        /// </summary>
        //public string? groupid { get; set; }
    }
}
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/System/Sys_User.cs
@@ -29,6 +29,17 @@
        public string UserName { get; set; }
        /// <summary>
        /// äººè„¸è¯†åˆ«ç»„
        /// </summary>
        [SugarColumn(IsNullable = true, ColumnDescription = "人脸识别组")]
        public string Log_id { get; set; }
        /// <summary>
        /// äººè„¸è¯†åˆ«token
        /// </summary>
        [SugarColumn(Length = 100, IsNullable = true, ColumnDescription = "人脸识别token")]
        public string Face_token { get; set; }
        /// <summary>
        ///卡号
        /// </summary>
        [SugarColumn( IsNullable = true, ColumnDescription = "卡号")]
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Model/Models/Telescopic/Dt_FaceRecognition.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SqlSugar;
using WIDESEAWCS_Core.DB.Models;
using WIDESEAWCS_Core.Tenants;
namespace WIDESEAWCS_Model.Models
{
    [SugarTable("Dt_FaceRecognition", "人脸识别表"), MultiTenant]
    public class Dt_FaceRecognition:BaseEntity
    {
        /// <summary>
        /// id
        /// </summary>
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "主键")]
        public int ID { get; set; }
        /// <summary>
        /// äººè„¸è¯†åˆ«ç»„
        /// </summary>
        [SugarColumn(IsNullable = true, Length = 50, ColumnDescription = "人脸识别组")]
        public string GroupID { get; set; }
    }
}
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/System/Sys_UserController.cs
@@ -65,6 +65,8 @@
            return new { result = false };
        }
        [HttpPost, Route("login"), AllowAnonymous]
        public IActionResult Login([FromBody] LoginInfo loginInfo)
        {
@@ -169,6 +171,61 @@
        }
        /// <summary>
        /// æ·»åŠ ç”¨æˆ·
        /// </summary>
        /// <param name="addUserDTO"></param>
        /// <returns></returns>
        [HttpPost, Route("AdduserData"), AllowAnonymous]
        public WebResponseContent AdduserData([FromBody] AddUserDTO addUserDTO)
        {
            return Service.AdduserData(addUserDTO);
        }
        /// <summary>
        /// æ›´æ–°ç”¨æˆ·
        /// </summary>
        /// <param name="addUserDTO"></param>
        /// <returns></returns>
        [HttpPost, Route("UpuserData"), AllowAnonymous]
        public WebResponseContent UpuserData([FromBody] AddUserDTO addUserDTO)
        {
            return Service.UpuserData(addUserDTO);
        }
        /// <summary>
        /// åˆ é™¤ç”¨æˆ·
        /// </summary>
        /// <param name="deleteUserDTO"></param>
        /// <returns></returns>
        [HttpPost, Route("DeleteUserData"), AllowAnonymous]
        public WebResponseContent DeleteUserData(string userAccount)
        {
            return Service.DeleteUserData(userAccount);
        }
        /// <summary>
        /// ç™»å…¥åŽæ¸…除这次全部调用SaveFaceFiles方法的图片
        /// </summary>
        /// <returns></returns>
        [HttpGet, Route("CleanUnusedImages"), AllowAnonymous]
        public WebResponseContent CleanUnusedImages()
        {
            return Service.CleanUnusedImages();
        }
        /// <summary>
        ///人脸登入时调用该方法上传图片
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        [HttpPost, Route("SaveFaceFiles"), AllowAnonymous]
        public WebResponseContent SaveFaceFiles(IFormCollection files)
        {
            return Service.SaveFaceFiles(files);
        }
    }
    public class SwaggerLoginRequest
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/Controllers/Telescopic/FaceRecognitionController .cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseController;
using WIDESEAWCS_DTO.TaskInfo;
using WIDESEAWCS_DTO.Telescopic;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_TaskInfoService;
namespace WIDESEAWCS_Server.Controllers.SerialPort
{
    [Route("api/[controller]")]
    [ApiController]
    public class FaceRecognitionController : ApiBaseController<IFaceRecognitionServer, Dt_FaceRecognition>
    {
        public FaceRecognitionController(IFaceRecognitionServer service) : base(service)
        {
        }
    }
}
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_Server/wwwroot/image/logo1.png
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_SystemServices/Sys_UserService.cs
@@ -12,6 +12,8 @@
using WIDESEAWCS_Core.Caches;
using WIDESEAWCS_DTO.SerialPort;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using WIDESEAWCS_Common;
namespace WIDESEAWCS_SystemServices
{
@@ -20,21 +22,91 @@
        private readonly IUnitOfWorkManage _unitOfWorkManage;
        private readonly ICacheService _cacheService;
        private readonly ISys_MenuService _menuService;
        public Sys_UserService(IRepository<Sys_User> repository, IUnitOfWorkManage unitOfWorkManage, ICacheService cacheService, ISys_MenuService menuService) : base(repository)
        private readonly IRepository<Dt_FaceRecognition> _faceServer;
        private readonly IRepository<Dt_Loginhsy> _LoginhsyServer;
        public Sys_UserService(IRepository<Dt_Loginhsy> LoginhsyServer,IRepository<Dt_FaceRecognition> faceServer, IRepository<Sys_User> repository, IUnitOfWorkManage unitOfWorkManage, ICacheService cacheService, ISys_MenuService menuService) : base(repository)
        {
            _faceServer = faceServer;
            _LoginhsyServer = LoginhsyServer;
            _unitOfWorkManage = unitOfWorkManage;
            _cacheService = cacheService;
            _menuService = menuService;
        }
        #region
        //public WebResponseContent Login(LoginInfo loginInfo)
        //{
        //    WebResponseContent content = new WebResponseContent();
        //    try
        //    {
        //        //BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName);
        //        string msg = string.Empty;
        //        #region ä¸´æ—¶ä½¿ç”¨
        //        try
        //        {
        //            loginInfo.Password = loginInfo.Password.EncryptDES(AppSecret.User);
        //        }
        //        catch
        //        {
        //        }
        //        #endregion
        //        UserInfo user = BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName && x.UserPwd == loginInfo.Password, x => new UserInfo { HeadImageUrl = x.HeadImageUrl, RoleId = x.Role_Id, TenantId = x.TenantId, UserId = x.User_Id, UserName = x.UserName, UserTrueName = x.UserTrueName });
        //        if (user != null)
        //        {
        //            object obj = _menuService.GetMenuActionList(user.RoleId);
        //            if (obj is not IEnumerable<object> list)
        //            {
        //                return WebResponseContent.Instance.Error("无登录权限");
        //            }
        //            if (!list.Any())
        //            {
        //                return WebResponseContent.Instance.Error("无登录权限");
        //            }
        //            string token = JwtHelper.IssueJwt(new TokenModelJwt()
        //            {
        //                UserId = user.UserId,
        //                RoleId = user.RoleId,
        //                UserName = user.UserName,
        //                TenantId = user.TenantId,
        //            });
                 // _cacheService.AddOrUpdate(user.UserId.ToString(), token);
        //            content = WebResponseContent.Instance.OK(data: new { token, userName = user.UserTrueName, img = user.HeadImageUrl,ID=user.UserId });
        //        }
        //        else
        //        {
        //            content = WebResponseContent.Instance.Error("账号或密码错误");
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        content = WebResponseContent.Instance.Error(ex.Message);
        //    }
        //    return content;
        //}
        #endregion
        /// <summary>
        /// äººè„¸è¯†åˆ«ç™»å…¥æŽ¥å£
        /// </summary>
        /// <param name="loginInfo"></param>
        /// <returns></returns>
        public WebResponseContent Login(LoginInfo loginInfo)
        {
            WebResponseContent content = new WebResponseContent();
            try
            {
                //BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName);
                string msg = string.Empty;
                //string msg = string.Empty;
                #region ä¸´æ—¶ä½¿ç”¨
                try
@@ -43,23 +115,74 @@
                }
                catch
                {
                }
                #endregion
                // å…ˆèŽ·å–ç”¨æˆ·ä¿¡æ¯
                UserInfo user = null;
                if (!string.IsNullOrEmpty(loginInfo.path))
                {
                    // äººè„¸è¯†åˆ«ç™»å½•
                    var groupId = _faceServer.QueryData().Select(x => x.GroupID).FirstOrDefault();
                    if (groupId == null)
                    {
                        return WebResponseContent.Instance.Error("没找到该人脸识别分组");
                    }
                UserInfo user = BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName && x.UserPwd == loginInfo.Password, x => new UserInfo { HeadImageUrl = x.HeadImageUrl, RoleId = x.Role_Id, TenantId = x.TenantId, UserId = x.User_Id, UserName = x.UserName, UserTrueName = x.UserTrueName });
                    var faceResult = BaiDuFaceHelper.FaceSearch(loginInfo.path, groupId);
                    if (faceResult != null && faceResult.error_code == 0)
                    {
                        var bestMatch = faceResult.result.user_list.OrderByDescending(u => u.score).FirstOrDefault();
                        string usercount = bestMatch.user_id;
                        if (bestMatch != null && double.TryParse(bestMatch.score, out double score) && score > 80)
                        {
                            //用识别到的 user_id æ¥èŽ·å–ç”¨æˆ·ä¿¡æ¯
                            var faceuser = BaseDal.QueryData(x => x.UserName == usercount).FirstOrDefault(); // èŽ·å–åŒ¹é…çš„ç¬¬ä¸€ä¸ªç”¨æˆ·
                            if (faceuser != null)
                            {
                                // æ‰‹åЍ将 Sys_User æ˜ å°„到 UserInfo
                                user = new UserInfo
                                {
                                    UserId = faceuser.User_Id,
                                    UserName = faceuser.UserName,
                                    UserTrueName = faceuser.UserTrueName,
                                    HeadImageUrl = faceuser.HeadImageUrl,
                                    RoleId = faceuser.Role_Id,
                                    TenantId = faceuser.TenantId,
                                };
                            }
                        }
                        if (user == null)
                        {
                            return WebResponseContent.Instance.Error("人脸识别失败,请重试");
                        }
                        loginInfo.UserName = user.UserName;
                    }
                }
                else
                {
                    // å¯†ç ç™»å½•
                    user = GetUserInfo(loginInfo.UserName, loginInfo.Password);
                }
                // å¦‚果找到用户
                if (user != null)
                {
                    object obj = _menuService.GetMenuActionList(user.RoleId);
                    if (obj is not IEnumerable<object> list)
                    var disbled = BaseDal.QueryFirst(x => x.UserName == loginInfo.UserName);
                    if (disbled.Enable != 1)
                    {
                        return WebResponseContent.Instance.Error("无登录权限");
                        return WebResponseContent.Instance.Error("你的账号已被禁用,请联系管理员");
                    }
                    if (!list.Any())
                    // èŽ·å–è§’è‰²æƒé™
                    object obj = _menuService.GetMenuActionList(user.RoleId);
                    if (obj is not IEnumerable<object> list || !list.Any())
                    {
                        return WebResponseContent.Instance.Error("无登录权限");
                    }
                    // ç”Ÿæˆ JWT Token
                    string token = JwtHelper.IssueJwt(new TokenModelJwt()
                    {
                        UserId = user.UserId,
@@ -68,9 +191,27 @@
                        TenantId = user.TenantId,
                    });
                    _cacheService.AddOrUpdate(user.UserId.ToString(), token);
                    // è®°å½•登录历史
                    var loghis = new Dt_Loginhsy
                    {
                        UserName = user.UserName,
                        LoginTiem =DateTime.Now,
                        CreateDate = DateTime.Now
                    };
                    content = WebResponseContent.Instance.OK(data: new { token, userName = user.UserTrueName, img = user.HeadImageUrl,ID=user.UserId });
                    // ä¿å­˜ç”¨æˆ·ç™»å½•信息
                    _cacheService.AddOrUpdate(user.UserId.ToString(), token);
                    _LoginhsyServer.AddData(loghis);
                    // è¿”回响应
                    content = WebResponseContent.Instance.OK(data: new
                    {
                        token,
                        userName = user.UserTrueName,
                        img = user.HeadImageUrl,
                        ID = user.UserId,
                        RoleId = user.RoleId
                    });
                }
                else
                {
@@ -303,5 +444,277 @@
                return new WebResponseContent { Status = false, Message = "上传文件失败:" + ex.Message };
            }
        }
        /// <summary>
        /// æ·»åŠ ç”¨æˆ·
        /// </summary>
        /// <param name="addUserDTO"></param>
        /// <returns></returns>
        public WebResponseContent AdduserData(AddUserDTO addUserDTO)
        {
            try
            {
                if (addUserDTO == null)
                {
                    return new WebResponseContent { Status = false, Message = "请求数据为空,可能是 JSON è§£æžå¤±è´¥" };
                }
                var list = BaseDal.QueryData(a => a.UserName == addUserDTO.username).FirstOrDefault();
                if (list != null)
                {
                    return new WebResponseContent { Status = false, Message = "账号重复,请重新录入" };
                }
                var face = _faceServer.QueryData().Select(x => x.GroupID).FirstOrDefault(); ;
                var baiduResult = BaiDuFaceHelper.AddUser(new BDUserInfo
                {
                    ImgPath = addUserDTO.path,
                    user_id = addUserDTO.username,
                    group_id = face // è¿™é‡Œåº”该填百度人脸库分组
                                    // group_id = baiduResult.result.log_id
                });
                // åˆ¤æ–­ç™¾åº¦è¿”回是否成功
                if (baiduResult == null || baiduResult.error_code != 0)
                {
                    return new WebResponseContent { Status = false, Data = "人脸注册失败:" + baiduResult.error_msg };
                }
                // åˆ›å»ºç”¨æˆ·æ•°æ®
                var sys = new Sys_User
                {
                    UserName = addUserDTO.username,
                    UserTrueName = addUserDTO.usertruename,
                    HeadImageUrl = addUserDTO.path,
                    Log_id = baiduResult.log_id,
                    Face_token = baiduResult.result.face_token,
                    PhoneNo = addUserDTO.phoneno,
                    Role_Id = addUserDTO.roleid,
                    RoleName = addUserDTO.rolename,
                    Enable = addUserDTO.enable,
                    UserPwd = "j79rYYvCz4vdhcboB1Ausg==",
                    CreateDate = DateTime.Now
                };
                BaseDal.AddData(sys);
                return new WebResponseContent { Status = true, Data = sys };
            }
            catch (Exception ex)
            {
                return new WebResponseContent { Status = false, Message = "失败" + ex };
            }
        }
        /// <summary>
        /// æ›´æ–°ç”¨æˆ·
        /// </summary>
        /// <param name="addUserDTO"></param>
        /// <returns></returns>
        public WebResponseContent UpuserData(AddUserDTO addUserDTO)
        {
            try
            {
                // 1. æŸ¥è¯¢ç”¨æˆ·
                var sys = BaseDal.QueryData(x => x.User_Id == addUserDTO.id).FirstOrDefault();
                if (sys == null)
                {
                    return new WebResponseContent { Status = false, Message = "没找到该用户" };
                }
                // 2. æŸ¥è¯¢äººè„¸åº“分组 ID
                var faceGroupID = _faceServer.QueryData().Select(x => x.GroupID).FirstOrDefault();
                // 3. åˆ¤æ–­æ˜¯å¦éœ€è¦æ›´æ–°äººè„¸ä¿¡æ¯
                string faceToken = null;
                if (!string.IsNullOrEmpty(addUserDTO.path)) // åªæœ‰ä¼ äº†æ–°å›¾ç‰‡ï¼Œæ‰æ›´æ–°äººè„¸ä¿¡æ¯
                {
                    var baiduResult = BaiDuFaceHelper.AddUser(new BDUserInfo
                    {
                        ImgPath = addUserDTO.path,
                        user_id = addUserDTO.username,
                        group_id = faceGroupID // è¿™é‡Œåº”该填百度人脸库分组
                    });
                    // 4. åˆ¤æ–­ç™¾åº¦ API æ˜¯å¦æˆåŠŸ
                    if (baiduResult == null || baiduResult.error_code != 0)
                    {
                        return new WebResponseContent { Status = false, Message = "该图片也存在,不要重复上传:" + baiduResult.error_msg };
                    }
                    // 5. åªæœ‰å½“上传了新图片并成功时,才更新这些字段
                    faceToken = baiduResult.result.face_token;
                    sys.Log_id = baiduResult.log_id;
                    sys.HeadImageUrl = addUserDTO.path;
                }
                // 6. æ›´æ–°ç”¨æˆ·å…¶ä»–信息
                sys.UserName = addUserDTO.username;
                sys.UserTrueName = addUserDTO.usertruename;
                sys.Face_token = faceToken ?? sys.Face_token; // åªæœ‰å½“ faceToken æœ‰å€¼æ—¶æ‰æ›´æ–°ï¼Œå¦åˆ™ä¿æŒåŽŸå€¼
                sys.PhoneNo = addUserDTO.phoneno;
                sys.Role_Id = addUserDTO.roleid;
                sys.RoleName = addUserDTO.rolename;
                sys.Enable = addUserDTO.enable;
                // 7. æ›´æ–°æ•°æ®åº“
                BaseDal.UpdateData(sys);
                return new WebResponseContent { Status = true, Data = sys };
            }
            catch (Exception ex)
            {
                return new WebResponseContent { Status = false, Message = "失败:" + ex.Message };
            }
        }
        /// <summary>
        /// åˆ é™¤
        /// </summary>
        /// <param name="deleteUserDTO"></param>
        /// <returns></returns>
        public WebResponseContent DeleteUserData(string account)
        {
            try
            {
                // 2. æŸ¥è¯¢äººè„¸åº“分组 ID
                var faceGroupID = _faceServer.QueryData().Select(x => x.GroupID).FirstOrDefault();
                WIDESEAWCS_Common.DeleteUserImg deleteUserImg = new WIDESEAWCS_Common.DeleteUserImg();
                deleteUserImg.group_id = faceGroupID;
                deleteUserImg.user_id = account;
                string apiResult = BaiDuFaceHelper.DeleteUser(deleteUserImg);//只要给token和log_id
                // 2. è§£æžè¿”回结果,判断删除是否成功
                dynamic resultObj = JsonConvert.DeserializeObject(apiResult);
                if (resultObj.error_code == 0)
                {
                    // ç™¾åº¦åˆ é™¤æˆåŠŸåŽï¼Œåˆ é™¤æ•°æ®åº“ä¸­çš„ç”¨æˆ·
                    var user = BaseDal.QueryData(x => x.UserName == account);
                    if (user != null)
                    {
                        BaseDal.DeleteData(user);
                    }
                    return WebResponseContent.Instance.OK("用户删除成功");
                }
                else
                {
                    return WebResponseContent.Instance.Error("百度 API åˆ é™¤å¤±è´¥ï¼š" + resultObj.error_msg);
                }
            }
            catch (Exception ex)
            {
                return WebResponseContent.Instance.Error("删除用户失败:" + ex.Message);
            }
        }
        public WebResponseContent SaveFaceFiles(IFormCollection files)
        {
            if (files == null || files.Files.Count == 0)
                return new WebResponseContent { Status = false, Message = "请上传文件" };
            // 1. ç¡®ä¿å­˜å‚¨ç›®å½•存在
            string baseDirectory = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "UploadfaceImage");
            if (!Directory.Exists(baseDirectory))
                Directory.CreateDirectory(baseDirectory);
            try
            {
                var file = files.Files[0]; // åªå¤„理第一个文件
                string fileName = file.FileName; // ç›´æŽ¥ä½¿ç”¨å‰ç«¯çš„æ–‡ä»¶å
                string fullFilePath = Path.Combine(baseDirectory, fileName);
                // 2. ä¿å­˜æ–‡ä»¶ï¼ˆå¦‚果存在,则覆盖)
                using (var stream = new FileStream(fullFilePath, FileMode.Create))
                {
                    file.CopyTo(stream);
                }
                // 3. è¿”回文件名
                return new WebResponseContent { Status = true, Message = "文件上传成功", Data = fileName };
            }
            catch (Exception ex)
            {
                return new WebResponseContent { Status = false, Message = "上传文件失败:" + ex.Message };
            }
        }
        /// <summary>
        /// åˆ é™¤æ•°æ®åº“中没有使用的图片
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public WebResponseContent CleanUnusedImages()
        {
            try
            {
                // èŽ·å–æ–‡ä»¶çš„å®Œæ•´è·¯å¾„
                string pathimage = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "image");
                // å¦‚果文件夹不存在,返回错误信息
                if (!Directory.Exists(pathimage))
                {
                    return new WebResponseContent { Status = false, Message = "图片文件夹不存在" };
                }
                // **使用 HashSet æé«˜æŸ¥æ‰¾æ•ˆçއ**
                var userImageSet = BaseDal.QueryData(x => !string.IsNullOrEmpty(x.HeadImageUrl))
                                          .Select(x => x.HeadImageUrl)
                                          .ToHashSet(); // **提升查询速度**
                // èŽ·å–æ–‡ä»¶å¤¹ä¸­çš„æ‰€æœ‰å›¾ç‰‡æ–‡ä»¶ï¼ˆæ–‡ä»¶åï¼‰
                var imageFiles = Directory.GetFiles(pathimage)
                                          .Select(Path.GetFileName)
                                          .ToList();
                int deletedCount = 0;
                foreach (var file in imageFiles)
                {
                    // **HashSet æŸ¥è¯¢ O(1)**
                    if (!userImageSet.Contains(file))
                    {
                        string filePath = Path.Combine(pathimage, file);
                        try
                        {
                            File.Delete(filePath);
                            deletedCount++;
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine($"无法删除文件 {file}: {ex.Message}");
                        }
                    }
                }
                return new WebResponseContent { Status = true, Message = $"清理完成,删除了 {deletedCount} å¼ æœªä½¿ç”¨çš„图片" };
            }
            catch (Exception ex)
            {
                return new WebResponseContent { Status = false, Message = $"清理失败: {ex.Message}" };
            }
    }
        /// <summary>
        /// GetUserInfo登入方法
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public UserInfo GetUserInfo(string userName, string password)
        {
            return BaseDal.QueryFirst(x => x.UserName == userName && x.UserPwd == password, x => new UserInfo { HeadImageUrl = x.HeadImageUrl, RoleId = x.Role_Id, TenantId = x.TenantId, UserId = x.User_Id, UserName = x.UserName, UserTrueName = x.UserTrueName });
        }
    }
}
ÏîÄ¿´úÂë/WCS/WIDESEAWCS_Server/WIDESEAWCS_TelescopicService/FaceRecognitionServer.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WIDESEAWCS_Core;
using WIDESEAWCS_Core.BaseRepository;
using WIDESEAWCS_Core.BaseServices;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
namespace WIDESEAWCS_TelescopicService
{
    public class FaceRecognitionServer : ServiceBase<Dt_FaceRecognition, IRepository<Dt_FaceRecognition>>, IFaceRecognitionServer
    {
        public IRepository<Dt_FaceRecognition> Repository => BaseDal;
        public FaceRecognitionServer(IRepository<Dt_FaceRecognition> BaseDal) : base(BaseDal)
        {
        }
    }
}