From eede0d8477e7117e652b870cb29ef78a95b7f38a Mon Sep 17 00:00:00 2001
From: hwh <332078369@qq.com>
Date: 星期三, 19 六月 2024 14:08:41 +0800
Subject: [PATCH] 全局异常处理和规范返回

---
 HTML/js/public.js                                       |   51 +
 Wms/Utility/Entity/ApiResponse.cs                       |   20 
 Wms/Utility/Extension/RequestAuditLogFilter.cs          |   26 
 Wms/Utility/Enum/ErrorCodeEnum.cs                       |  592 ++++++++++++++++++
 Wms/Wms/Wms.csproj                                      |   16 
 Wms/Utility/Filter/CustomerExceptionMiddleware.cs       |   64 ++
 Wms/Utility/Extension/LogExtends.cs                     |   75 ++
 Wms/Utility/Exception/ErrorCodeTypeAttribute.cs         |   14 
 Wms/Utility/Exception/AppFriendlyException.cs           |   80 ++
 Wms/Utility/Exception/Oops.cs                           |  209 ++++++
 Wms/Utility/UnitOfWork/UnitOfWorkAttribute.cs           |  290 +++++++++
 Wms/Wms/Controllers/BllTaskController.cs                |    3 
 Wms/Wms/Startup.cs                                      |   19 
 Wms/Wms/Program.cs                                      |   17 
 Wms/Utility/Extension/ApplicationBuilderExtensions.cs   |   85 ++
 Wms/Utility/Extension/ApiResponseActionFilter.cs        |   37 +
 Wms/Utility/Extension/ApiResponseMiddleware.cs          |   97 +++
 Wms/Utility/Utility.csproj                              |   14 
 Wms/Utility/Enum/ResponseEnum.cs                        |   15 
 Wms/Utility/Extension/ServiceCollectionExtensions.cs    |   79 ++
 Wms/Utility/UnitOfWork/IUnitOfWork.cs                   |   38 +
 Wms/Utility/Exception/ErrorCodeItemMetadataAttribute.cs |   40 +
 22 files changed, 1,874 insertions(+), 7 deletions(-)

diff --git a/HTML/js/public.js b/HTML/js/public.js
index a15a788..27b625e 100644
--- a/HTML/js/public.js
+++ b/HTML/js/public.js
@@ -282,4 +282,55 @@
       });
     });
   }  
+}
+//娣辨嫹璐�
+function deepClone(source) {
+  if (typeof source !== 'object' || source == null) {
+    return source;
+  }
+  const target = Array.isArray(source) ? [] : {};
+  for (const key in source) {
+    if (Object.prototype.hasOwnProperty.call(source, key)) {
+      if (typeof source[key] === 'object' && source[key] !== null) {
+        target[key] = deepClone(source[key]);
+      } else {
+        target[key] = source[key];
+      }
+    }
+  }
+  return target;
+} 
+/**
+ * 灏嗚〃鍗曡祴鍊间负鎸囧畾鐨勫璞�
+ * @param {Object} data - 鍖呭惈琛ㄥ崟鏁版嵁鐨勫璞�
+ * @param {String} formSelector - 琛ㄥ崟鐨勯�夋嫨鍣紝渚嬪 '#myForm' 鎴� '.myForm'
+ */
+function setFormData(data, formSelector) {
+  var $form = $(formSelector);
+
+  $.each(data, function(key, value) {
+      var $field = $form.find('[name=' + key + ']');
+
+      if ($field.length > 0) {
+          var fieldType = $field.attr('type');
+
+          switch (fieldType) {
+              case 'checkbox':
+                  if (Array.isArray(value)) {
+                      $field.each(function() {
+                          $(this).prop('checked', value.includes($(this).val()));
+                      });
+                  } else {
+                      $field.prop('checked', value);
+                  }
+                  break;
+              case 'radio':
+                  $field.filter('[value=' + value + ']').prop('checked', true);
+                  break;
+              default:
+                  $field.val(value);
+                  break;
+          }
+      }
+  });
 }
\ No newline at end of file
diff --git a/Wms/Utility/Entity/ApiResponse.cs b/Wms/Utility/Entity/ApiResponse.cs
new file mode 100644
index 0000000..c88a3a1
--- /dev/null
+++ b/Wms/Utility/Entity/ApiResponse.cs
@@ -0,0 +1,20 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Utility.Entity
+{
+    public class ApiResponse<T>
+    {
+        public int code { get; set; }
+        public string msg { get; set; }
+        public T data { get; set; }
+
+        public ApiResponse(int code, string message, T data)
+        {
+            this.code = code;
+            this.msg = message;
+            this.data = data;
+        }
+    }
+}
diff --git a/Wms/Utility/Enum/ErrorCodeEnum.cs b/Wms/Utility/Enum/ErrorCodeEnum.cs
new file mode 100644
index 0000000..eda5615
--- /dev/null
+++ b/Wms/Utility/Enum/ErrorCodeEnum.cs
@@ -0,0 +1,592 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Text;
+
+
+namespace Utility
+{
+    /// <summary>
+    /// 绯荤粺閿欒鐮�
+    /// </summary>
+    [ErrorCodeType]
+    [Description("绯荤粺閿欒鐮�")]
+    public enum ErrorCodeEnum
+    {
+        /// <summary>
+        /// 楠岃瘉鐮侀敊璇�
+        /// </summary>
+        [ErrorCodeItemMetadata("楠岃瘉鐮侀敊璇�")]
+        D0008,
+
+        /// <summary>
+        /// 璐﹀彿涓嶅瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("璐﹀彿涓嶅瓨鍦�")]
+        D0009,
+
+        /// <summary>
+        /// 瀵嗙爜涓嶆纭�
+        /// </summary>
+        [ErrorCodeItemMetadata("瀵嗙爜涓嶆纭�")]
+        D1000,
+
+        /// <summary>
+        /// 闈炴硶鎿嶄綔锛佺姝㈠垹闄よ嚜宸�
+        /// </summary>
+        [ErrorCodeItemMetadata("闈炴硶鎿嶄綔锛岀姝㈠垹闄よ嚜宸�")]
+        D1001,
+
+        /// <summary>
+        /// 璁板綍涓嶅瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("璁板綍涓嶅瓨鍦�")]
+        D1002,
+
+        /// <summary>
+        /// 璐﹀彿宸插瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("璐﹀彿宸插瓨鍦�")]
+        D1003,
+
+        /// <summary>
+        /// 鏃у瘑鐮佷笉鍖归厤
+        /// </summary>
+        [ErrorCodeItemMetadata("鏃у瘑鐮佽緭鍏ラ敊璇�")]
+        D1004,
+
+        /// <summary>
+        /// 娴嬭瘯鏁版嵁绂佹鏇存敼admin瀵嗙爜
+        /// </summary>
+        [ErrorCodeItemMetadata("娴嬭瘯鏁版嵁绂佹鏇存敼鐢ㄦ埛銆恆dmin銆戝瘑鐮�")]
+        D1005,
+
+        /// <summary>
+        /// 鏁版嵁宸插瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("鏁版嵁宸插瓨鍦�")]
+        D1006,
+
+        /// <summary>
+        /// 鏁版嵁涓嶅瓨鍦ㄦ垨鍚湁鍏宠仈寮曠敤锛岀姝㈠垹闄�
+        /// </summary>
+        [ErrorCodeItemMetadata("鏁版嵁涓嶅瓨鍦ㄦ垨鍚湁鍏宠仈寮曠敤锛岀姝㈠垹闄�")]
+        D1007,
+
+        /// <summary>
+        /// 绂佹涓虹鐞嗗憳鍒嗛厤瑙掕壊
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹涓虹鐞嗗憳鍒嗛厤瑙掕壊")]
+        D1008,
+
+        /// <summary>
+        /// 閲嶅鏁版嵁鎴栬褰曞惈鏈変笉瀛樺湪鏁版嵁
+        /// </summary>
+        [ErrorCodeItemMetadata("閲嶅鏁版嵁鎴栬褰曞惈鏈変笉瀛樺湪鏁版嵁")]
+        D1009,
+
+        /// <summary>
+        /// 绂佹涓鸿秴绾х鐞嗗憳瑙掕壊鍒嗛厤鏉冮檺
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹涓鸿秴绾х鐞嗗憳瑙掕壊鍒嗛厤鏉冮檺")]
+        D1010,
+
+        /// <summary>
+        /// 闈炴硶鎿嶄綔锛屾湭鐧诲綍
+        /// </summary>
+        [ErrorCodeItemMetadata("闈炴硶鎿嶄綔锛屾湭鐧诲綍")]
+        D1011,
+
+        /// <summary>
+        /// Id涓嶈兘涓虹┖
+        /// </summary>
+        [ErrorCodeItemMetadata("Id涓嶈兘涓虹┖")]
+        D1012,
+
+        /// <summary>
+        /// 鎵�灞炴満鏋勪笉鍦ㄨ嚜宸辩殑鏁版嵁鑼冨洿鍐�
+        /// </summary>
+        [ErrorCodeItemMetadata("娌℃湁鏉冮檺鎿嶄綔璇ユ暟鎹�")]
+        D1013,
+
+        /// <summary>
+        /// 绂佹鍒犻櫎瓒呯骇绠$悊鍛�
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹鍒犻櫎瓒呯骇绠$悊鍛�")]
+        D1014,
+
+        /// <summary>
+        /// 绂佹淇敼瓒呯骇绠$悊鍛樼姸鎬�
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹淇敼瓒呯骇绠$悊鍛樼姸鎬�")]
+        D1015,
+
+        /// <summary>
+        /// 娌℃湁鏉冮檺
+        /// </summary>
+        [ErrorCodeItemMetadata("娌℃湁鏉冮檺")]
+        D1016,
+
+        /// <summary>
+        /// 璐﹀彿宸插喕缁�
+        /// </summary>
+        [ErrorCodeItemMetadata("璐﹀彿宸插喕缁�")]
+        D1017,
+
+        /// <summary>
+        /// 绂佹鍒犻櫎绠$悊鍛�
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹鍒犻櫎绠$悊鍛�")]
+        D1018,
+
+        /// <summary>
+        /// 绂佹鍒犻櫎绯荤粺绠$悊鍛樿鑹�
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹鍒犻櫎绯荤粺绠$悊鍛樿鑹�")]
+        D1019,
+
+        /// <summary>
+        /// 绂佹淇敼绯荤粺绠$悊鍛樿鑹�
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹淇敼绯荤粺绠$悊鍛樿鑹�")]
+        D1020,
+
+        /// <summary>
+        /// 绂佹涓虹郴缁熺鐞嗗憳瑙掕壊鍒嗛厤鏉冮檺
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹涓虹郴缁熺鐞嗗憳瑙掕壊鍒嗛厤鏉冮檺")]
+        D1021,
+
+        /// <summary>
+        /// 绂佹涓鸿秴绾х鐞嗗憳鍒嗛厤瑙掕壊
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹涓鸿秴绾х鐞嗗憳鍒嗛厤瑙掕壊")]
+        D1022,
+
+        /// <summary>
+        /// 绂佹鍒犻櫎榛樿绉熸埛
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹鍒犻櫎榛樿绉熸埛")]
+        D1023,
+
+        /// <summary>
+        /// 宸插皢鍏朵粬鍦版柟鐧诲綍璐﹀彿涓嬬嚎
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插皢鍏朵粬鍦版柟鐧诲綍璐﹀彿涓嬬嚎")]
+        D1024,
+
+        /// <summary>
+        /// 鐖舵満鏋勪笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("鐖舵満鏋勪笉瀛樺湪")]
+        D2000,
+
+        /// <summary>
+        /// 褰撳墠鏈烘瀯Id涓嶈兘涓庣埗鏈烘瀯Id鐩稿悓
+        /// </summary>
+        [ErrorCodeItemMetadata("褰撳墠鏈烘瀯Id涓嶈兘涓庣埗鏈烘瀯Id鐩稿悓")]
+        D2001,
+
+        /// <summary>
+        /// 宸叉湁鐩稿悓缁勭粐鏈烘瀯,缂栫爜鎴栧悕绉扮浉鍚�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸叉湁鐩稿悓缁勭粐鏈烘瀯,缂栫爜鎴栧悕绉扮浉鍚�")]
+        D2002,
+
+        /// <summary>
+        /// 娌℃湁鏉冮檺鎿嶄綔鏈烘瀯
+        /// </summary>
+        [ErrorCodeItemMetadata("娌℃湁鏉冮檺鎿嶄綔鏈烘瀯")]
+        D2003,
+
+        /// <summary>
+        /// 璇ユ満鏋勪笅鏈夌敤鎴风姝㈠垹闄�
+        /// </summary>
+        [ErrorCodeItemMetadata("璇ユ満鏋勪笅鏈夌敤鎴风姝㈠垹闄�")]
+        D2004,
+
+        /// <summary>
+        /// 闄勫睘鏈烘瀯涓嬫湁鐢ㄦ埛绂佹鍒犻櫎
+        /// </summary>
+        [ErrorCodeItemMetadata("闄勫睘鏈烘瀯涓嬫湁鐢ㄦ埛绂佹鍒犻櫎")]
+        D2005,
+
+        /// <summary>
+        /// 鍙兘澧炲姞涓嬬骇鏈烘瀯
+        /// </summary>
+        [ErrorCodeItemMetadata("鍙兘澧炲姞涓嬬骇鏈烘瀯")]
+        D2006,
+
+        /// <summary>
+        /// 涓嬬骇鏈烘瀯涓嬫湁鐢ㄦ埛绂佹鍒犻櫎
+        /// </summary>
+        [ErrorCodeItemMetadata("涓嬬骇鏈烘瀯涓嬫湁鐢ㄦ埛绂佹鍒犻櫎")]
+        D2007,
+
+        /// <summary>
+        /// 绉熸埛榛樿鏈烘瀯绂佹鍒犻櫎
+        /// </summary>
+        [ErrorCodeItemMetadata("绉熸埛榛樿鏈烘瀯绂佹鍒犻櫎")]
+        D2008,
+
+        /// <summary>
+        /// 瀛楀吀绫诲瀷涓嶅瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("瀛楀吀绫诲瀷涓嶅瓨鍦�")]
+        D3000,
+
+        /// <summary>
+        /// 瀛楀吀绫诲瀷宸插瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("瀛楀吀绫诲瀷宸插瓨鍦�,鍚嶇О鎴栫紪鐮侀噸澶�")]
+        D3001,
+
+        /// <summary>
+        /// 瀛楀吀绫诲瀷涓嬮潰鏈夊瓧鍏稿�肩姝㈠垹闄�
+        /// </summary>
+        [ErrorCodeItemMetadata("瀛楀吀绫诲瀷涓嬮潰鏈夊瓧鍏稿�肩姝㈠垹闄�")]
+        D3002,
+
+        /// <summary>
+        /// 瀛楀吀鍊煎凡瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("瀛楀吀鍊煎凡瀛樺湪,鍚嶇О鎴栫紪鐮侀噸澶�")]
+        D3003,
+
+        /// <summary>
+        /// 瀛楀吀鍊间笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("瀛楀吀鍊间笉瀛樺湪")]
+        D3004,
+
+        /// <summary>
+        /// 瀛楀吀鐘舵�侀敊璇�
+        /// </summary>
+        [ErrorCodeItemMetadata("瀛楀吀鐘舵�侀敊璇�")]
+        D3005,
+
+        /// <summary>
+        /// 鑿滃崟宸插瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("鑿滃崟宸插瓨鍦�")]
+        D4000,
+
+        /// <summary>
+        /// 璺敱鍦板潃涓虹┖
+        /// </summary>
+        [ErrorCodeItemMetadata("璺敱鍦板潃涓虹┖")]
+        D4001,
+
+        /// <summary>
+        /// 鎵撳紑鏂瑰紡涓虹┖
+        /// </summary>
+        [ErrorCodeItemMetadata("鎵撳紑鏂瑰紡涓虹┖")]
+        D4002,
+
+        /// <summary>
+        /// 鏉冮檺鏍囪瘑鏍煎紡涓虹┖
+        /// </summary>
+        [ErrorCodeItemMetadata("鏉冮檺鏍囪瘑鏍煎紡涓虹┖")]
+        D4003,
+
+        /// <summary>
+        /// 鏉冮檺鏍囪瘑鏍煎紡閿欒
+        /// </summary>
+        [ErrorCodeItemMetadata("鏉冮檺鏍囪瘑鏍煎紡閿欒 濡倄xx:xxx")]
+        D4004,
+
+        /// <summary>
+        /// 鏉冮檺涓嶅瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("鏉冮檺涓嶅瓨鍦�")]
+        D4005,
+
+        /// <summary>
+        /// 鐖剁骇鑿滃崟涓嶈兘涓哄綋鍓嶈妭鐐癸紝璇烽噸鏂伴�夋嫨鐖剁骇鑿滃崟
+        /// </summary>
+        [ErrorCodeItemMetadata("鐖剁骇鑿滃崟涓嶈兘涓哄綋鍓嶈妭鐐癸紝璇烽噸鏂伴�夋嫨鐖剁骇鑿滃崟")]
+        D4006,
+
+        /// <summary>
+        /// 涓嶈兘绉诲姩鏍硅妭鐐�
+        /// </summary>
+        [ErrorCodeItemMetadata("涓嶈兘绉诲姩鏍硅妭鐐�")]
+        D4007,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮佸簲鐢�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮佸簲鐢�")]
+        D5000,
+
+        /// <summary>
+        /// 榛樿婵�娲荤郴缁熷彧鑳芥湁涓�涓�
+        /// </summary>
+        [ErrorCodeItemMetadata("榛樿婵�娲荤郴缁熷彧鑳芥湁涓�涓�")]
+        D5001,
+
+        /// <summary>
+        /// 璇ュ簲鐢ㄤ笅鏈夎彍鍗曠姝㈠垹闄�
+        /// </summary>
+        [ErrorCodeItemMetadata("璇ュ簲鐢ㄤ笅鏈夎彍鍗曠姝㈠垹闄�")]
+        D5002,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮佸簲鐢�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮佸簲鐢�")]
+        D5003,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮佽亴浣�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮佽亴浣�")]
+        D6000,
+
+        /// <summary>
+        /// 璇ヨ亴浣嶄笅鏈夌敤鎴风姝㈠垹闄�
+        /// </summary>
+        [ErrorCodeItemMetadata("璇ヨ亴浣嶄笅鏈夌敤鎴风姝㈠垹闄�")]
+        D6001,
+
+        /// <summary>
+        /// 閫氱煡鍏憡鐘舵�侀敊璇�
+        /// </summary>
+        [ErrorCodeItemMetadata("閫氱煡鍏憡鐘舵�侀敊璇�")]
+        D7000,
+
+        /// <summary>
+        /// 閫氱煡鍏憡鍒犻櫎澶辫触
+        /// </summary>
+        [ErrorCodeItemMetadata("閫氱煡鍏憡鍒犻櫎澶辫触")]
+        D7001,
+
+        /// <summary>
+        /// 閫氱煡鍏憡缂栬緫澶辫触
+        /// </summary>
+        [ErrorCodeItemMetadata("閫氱煡鍏憡缂栬緫澶辫触锛岀被鍨嬪繀椤讳负鑽夌")]
+        D7002,
+
+        /// <summary>
+        /// 閫氱煡鍏憡鎿嶄綔澶辫触锛岄潪鍙戝竷鑰呬笉鑳借繘琛屾搷浣�
+        /// </summary>
+        [ErrorCodeItemMetadata("閫氱煡鍏憡鎿嶄綔澶辫触锛岄潪鍙戝竷鑰呬笉鑳借繘琛屾搷浣�")]
+        D7003,
+
+        /// <summary>
+        /// 鏂囦欢涓嶅瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("鏂囦欢涓嶅瓨鍦�")]
+        D8000,
+
+        /// <summary>
+        /// 涓嶅厑璁哥殑鏂囦欢绫诲瀷
+        /// </summary>
+        [ErrorCodeItemMetadata("涓嶅厑璁哥殑鏂囦欢绫诲瀷")]
+        D8001,
+
+        /// <summary>
+        /// 鏂囦欢瓒呰繃鍏佽澶у皬
+        /// </summary>
+        [ErrorCodeItemMetadata("鏂囦欢瓒呰繃鍏佽澶у皬")]
+        D8002,
+
+        /// <summary>
+        /// 鏂囦欢鍚庣紑閿欒
+        /// </summary>
+        [ErrorCodeItemMetadata("鏂囦欢鍚庣紑閿欒")]
+        D8003,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮佸弬鏁伴厤缃�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮佸弬鏁伴厤缃�")]
+        D9000,
+
+        /// <summary>
+        /// 绂佹鍒犻櫎绯荤粺鍙傛暟
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹鍒犻櫎绯荤粺鍙傛暟")]
+        D9001,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄥ悓鍚嶄换鍔¤皟搴�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄥ悓鍚嶄换鍔¤皟搴�")]
+        D1100,
+
+        /// <summary>
+        /// 浠诲姟璋冨害涓嶅瓨鍦�
+        /// </summary>
+        [ErrorCodeItemMetadata("浠诲姟璋冨害涓嶅瓨鍦�")]
+        D1101,
+
+        /// <summary>
+        /// 婕旂ず鐜绂佹淇敼鏁版嵁
+        /// </summary>
+        [ErrorCodeItemMetadata("婕旂ず鐜绂佹淇敼鏁版嵁")]
+        D1200,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄥ悓鍚嶇殑绉熸埛
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄥ悓鍚嶇殑绉熸埛")]
+        D1300,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄥ悓鍚嶇殑绉熸埛绠$悊鍛�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄥ悓鍚嶇殑绉熸埛绠$悊鍛�")]
+        D1301,
+
+        /// <summary>
+        /// 璇ヨ〃浠g爜妯℃澘宸茬粡鐢熸垚杩�
+        /// </summary>
+        [ErrorCodeItemMetadata("璇ヨ〃浠g爜妯℃澘宸茬粡鐢熸垚杩�")]
+        D1400,
+
+        /// <summary>
+        /// 璇ョ被鍨嬩笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("璇ョ被鍨嬩笉瀛樺湪")]
+        D1501,
+
+        /// <summary>
+        /// 璇ュ瓧娈典笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("璇ュ瓧娈典笉瀛樺湪")]
+        D1502,
+
+        /// <summary>
+        /// 璇ョ被鍨嬩笉鏄灇涓剧被鍨�
+        /// </summary>
+        [ErrorCodeItemMetadata("璇ョ被鍨嬩笉鏄灇涓剧被鍨�")]
+        D1503,
+
+        /// <summary>
+        /// 璇ュ疄浣撲笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("璇ュ疄浣撲笉瀛樺湪")]
+        D1504,
+
+        /// <summary>
+        /// 鐖惰彍鍗曚笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("鐖惰彍鍗曚笉瀛樺湪")]
+        D1505,
+
+        /// <summary>
+        /// 鐖惰祫婧愪笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("鐖惰祫婧愪笉瀛樺湪")]
+        D1600,
+
+        /// <summary>
+        /// 褰撳墠璧勬簮Id涓嶈兘涓庣埗璧勬簮Id鐩稿悓
+        /// </summary>
+        [ErrorCodeItemMetadata("褰撳墠璧勬簮Id涓嶈兘涓庣埗璧勬簮Id鐩稿悓")]
+        D1601,
+
+        /// <summary>
+        /// 宸叉湁鐩稿悓缂栫爜鎴栧悕绉�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸叉湁鐩稿悓缂栫爜鎴栧悕绉�")]
+        D1602,
+
+        /// <summary>
+        /// 鑴氭湰浠g爜涓嶈兘涓虹┖
+        /// </summary>
+        [ErrorCodeItemMetadata("鑴氭湰浠g爜涓嶈兘涓虹┖")]
+        D1701,
+
+        /// <summary>
+        /// 鑴氭湰浠g爜涓殑浣滀笟绫伙紝闇�瑕佸畾涔� [JobDetail] 鐗规��
+        /// </summary>
+        [ErrorCodeItemMetadata("鑴氭湰浠g爜涓殑浣滀笟绫伙紝闇�瑕佸畾涔� [JobDetail] 鐗规��")]
+        D1702,
+
+        /// <summary>
+        /// 浣滀笟缂栧彿闇�瑕佷笌鑴氭湰浠g爜涓殑浣滀笟绫� [JobDetail('jobId')] 涓�鑷�
+        /// </summary>
+        [ErrorCodeItemMetadata("浣滀笟缂栧彿闇�瑕佷笌鑴氭湰浠g爜涓殑浣滀笟绫� [JobDetail('jobId')] 涓�鑷�")]
+        D1703,
+
+        /// <summary>
+        /// 绂佹淇敼浣滀笟缂栧彿
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹淇敼浣滀笟缂栧彿")]
+        D1704,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮侀」鐩�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄥ悓鍚嶆垨鍚岀紪鐮侀」鐩�")]
+        xg1000,
+
+        /// <summary>
+        /// 宸插瓨鍦ㄧ浉鍚岃瘉浠跺彿鐮佷汉鍛�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸插瓨鍦ㄧ浉鍚岃瘉浠跺彿鐮佷汉鍛�")]
+        xg1001,
+
+        /// <summary>
+        /// 妫�娴嬫暟鎹笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("妫�娴嬫暟鎹笉瀛樺湪")]
+        xg1002,
+
+        /// <summary>
+        /// 璇锋坊鍔犳暟鎹垪
+        /// </summary>
+        [ErrorCodeItemMetadata("璇锋坊鍔犳暟鎹垪")]
+        db1000,
+
+        /// <summary>
+        /// 鏁版嵁琛ㄤ笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("鏁版嵁琛ㄤ笉瀛樺湪")]
+        db1001,
+
+        /// <summary>
+        /// 鏁版嵁琛ㄤ笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("涓嶅厑璁告坊鍔犵浉鍚屽瓧娈靛悕")]
+        db1002,
+
+        /// <summary>
+        /// 鐖惰妭鐐逛笉瀛樺湪
+        /// </summary>
+        [ErrorCodeItemMetadata("鐖惰妭鐐逛笉瀛樺湪")]
+        R2000,
+
+        /// <summary>
+        /// 褰撳墠鑺傜偣Id涓嶈兘涓庣埗鑺傜偣Id鐩稿悓
+        /// </summary>
+        [ErrorCodeItemMetadata("褰撳墠鑺傜偣Id涓嶈兘涓庣埗鑺傜偣Id鐩稿悓")]
+        R2001,
+
+        /// <summary>
+        /// 宸叉湁鐩稿悓缂栫爜鎴栧悕绉�
+        /// </summary>
+        [ErrorCodeItemMetadata("宸叉湁鐩稿悓缂栫爜鎴栧悕绉�")]
+        R2002,
+
+        /// <summary>
+        /// 榛樿绉熸埛鐘舵�佺姝慨鏀�
+        /// </summary>
+        [ErrorCodeItemMetadata("榛樿绉熸埛鐘舵�佺姝慨鏀�")]
+        Z1001,
+
+        /// <summary>
+        /// 绂佹鍒涘缓姝ょ被鍨嬬殑鏁版嵁搴�
+        /// </summary>
+        [ErrorCodeItemMetadata("绂佹鍒涘缓姝ょ被鍨嬬殑鏁版嵁搴�")]
+        Z1002,
+
+        /// <summary>
+        /// 绉熸埛宸茬鐢�
+        /// </summary>
+        [ErrorCodeItemMetadata("绉熸埛宸茬鐢�")]
+        Z1003,
+    }
+}
\ No newline at end of file
diff --git a/Wms/Utility/Enum/ResponseEnum.cs b/Wms/Utility/Enum/ResponseEnum.cs
new file mode 100644
index 0000000..43852d0
--- /dev/null
+++ b/Wms/Utility/Enum/ResponseEnum.cs
@@ -0,0 +1,15 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Utility
+{
+    public enum ResponseEnum
+    {
+        Sucess = 0,
+
+        Fail = 1,
+
+        Error = 2,
+    }
+}
diff --git a/Wms/Utility/Exception/AppFriendlyException.cs b/Wms/Utility/Exception/AppFriendlyException.cs
new file mode 100644
index 0000000..c45772d
--- /dev/null
+++ b/Wms/Utility/Exception/AppFriendlyException.cs
@@ -0,0 +1,80 @@
+锘縰sing Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Utility
+{
+    public class AppFriendlyException : Exception
+    {
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        public AppFriendlyException() : base()
+        {
+        }
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="message"></param>
+        /// <param name="errorCode"></param>
+        public AppFriendlyException(string message, object errorCode) : base(message)
+        {
+            ErrorMessage = message;
+            ErrorCode = OriginErrorCode = errorCode;
+        }
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="message"></param>
+        /// <param name="errorCode"></param>
+        /// <param name="innerException"></param>
+        public AppFriendlyException(string message, object errorCode, Exception innerException) : base(message, innerException)
+        {
+            ErrorMessage = message;
+            ErrorCode = OriginErrorCode = errorCode;
+        }
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="info"></param>
+        /// <param name="context"></param>
+        public AppFriendlyException(SerializationInfo info, StreamingContext context) : base(info, context)
+        {
+        }
+
+        /// <summary>
+        /// 閿欒鐮�
+        /// </summary>
+        public object ErrorCode { get; set; }
+
+        /// <summary>
+        /// 閿欒鐮侊紙娌¤澶嶅啓杩囩殑 ErrorCode 锛�
+        /// </summary>
+        public object OriginErrorCode { get; set; }
+
+        /// <summary>
+        /// 閿欒娑堟伅锛堟敮鎸� Object 瀵硅薄锛�
+        /// </summary>
+        public object ErrorMessage { get; set; }
+
+        /// <summary>
+        /// 鐘舵�佺爜
+        /// </summary>
+        public int StatusCode { get; set; } = StatusCodes.Status500InternalServerError;
+
+        /// <summary>
+        /// 鏄惁鏄暟鎹獙璇佸紓甯�
+        /// </summary>
+        public bool ValidationException { get; set; } = false;
+
+        /// <summary>
+        /// 棰濆鏁版嵁
+        /// </summary>
+        public new object Data { get; set; }
+    }
+}
diff --git a/Wms/Utility/Exception/ErrorCodeItemMetadataAttribute.cs b/Wms/Utility/Exception/ErrorCodeItemMetadataAttribute.cs
new file mode 100644
index 0000000..0f2faed
--- /dev/null
+++ b/Wms/Utility/Exception/ErrorCodeItemMetadataAttribute.cs
@@ -0,0 +1,40 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Utility
+{
+
+    /// <summary>
+    /// 寮傚父鍏冩暟鎹壒鎬�
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field)]
+    public sealed class ErrorCodeItemMetadataAttribute : Attribute
+    {
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="errorMessage">閿欒娑堟伅</param>
+        /// <param name="args">鏍煎紡鍖栧弬鏁�</param>
+        public ErrorCodeItemMetadataAttribute(string errorMessage, params object[] args)
+        {
+            ErrorMessage = errorMessage;
+            Args = args;
+        }
+
+        /// <summary>
+        /// 閿欒娑堟伅
+        /// </summary>
+        public string ErrorMessage { get; set; }
+
+        /// <summary>
+        /// 閿欒鐮�
+        /// </summary>
+        public object ErrorCode { get; set; }
+
+        /// <summary>
+        /// 鏍煎紡鍖栧弬鏁�
+        /// </summary>
+        public object[] Args { get; set; }
+    }
+}
diff --git a/Wms/Utility/Exception/ErrorCodeTypeAttribute.cs b/Wms/Utility/Exception/ErrorCodeTypeAttribute.cs
new file mode 100644
index 0000000..aa37e27
--- /dev/null
+++ b/Wms/Utility/Exception/ErrorCodeTypeAttribute.cs
@@ -0,0 +1,14 @@
+锘縰sing System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Utility
+{
+    /// <summary>
+    /// 閿欒浠g爜绫诲瀷鐗规��
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Enum)]
+    public sealed class ErrorCodeTypeAttribute : Attribute
+    {
+    }
+}
diff --git a/Wms/Utility/Exception/Oops.cs b/Wms/Utility/Exception/Oops.cs
new file mode 100644
index 0000000..09b43d7
--- /dev/null
+++ b/Wms/Utility/Exception/Oops.cs
@@ -0,0 +1,209 @@
+锘縰sing Microsoft.AspNetCore.DataProtection.KeyManagement;
+using Microsoft.AspNetCore.Http;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace Utility
+{
+    /// <summary>
+    /// 鎶涘紓甯搁潤鎬佺被
+    /// </summary>
+    public static class Oops
+    {
+
+        /// <summary>
+        /// 閿欒浠g爜绫诲瀷
+        /// </summary>
+        private static readonly IEnumerable<Type> ErrorCodeTypes;
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        static Oops()
+        {
+            ErrorCodeTypes = GetErrorCodeTypes();
+
+        }
+
+        /// <summary>
+        /// 鎶涘嚭涓氬姟寮傚父淇℃伅
+        /// </summary>
+        /// <param name="errorMessage">寮傚父娑堟伅</param>
+        /// <param name="args">String.Format 鍙傛暟</param>
+        /// <returns>寮傚父瀹炰緥</returns>
+        public static AppFriendlyException Bah(string errorMessage, params object[] args)
+        {
+            var friendlyException = Oh(errorMessage, typeof(ValidationException), args);
+            friendlyException.StatusCode = StatusCodes.Status400BadRequest;
+            friendlyException.ValidationException = true;
+            return friendlyException;
+        }
+
+        /// <summary>
+        /// 鎶涘嚭涓氬姟寮傚父淇℃伅
+        /// </summary>
+        /// <param name="errorCode">閿欒鐮�</param>
+        /// <param name="args">String.Format 鍙傛暟</param>
+        /// <returns>寮傚父瀹炰緥</returns>
+        public static AppFriendlyException Bah(object errorCode, params object[] args)
+        {
+            var friendlyException = Oh(errorCode, typeof(ValidationException), args);
+            friendlyException.StatusCode = StatusCodes.Status400BadRequest;
+            friendlyException.ValidationException = true;
+            return friendlyException;
+        }
+
+        /// <summary>
+        /// 鎶涘嚭瀛楃涓插紓甯�
+        /// </summary>
+        /// <param name="errorMessage">寮傚父娑堟伅</param>
+        /// <param name="args">String.Format 鍙傛暟</param>
+        /// <returns>寮傚父瀹炰緥</returns>
+        public static AppFriendlyException Oh(string errorMessage, params object[] args)
+        {
+            var friendlyException = new AppFriendlyException(errorMessage, default);
+
+            friendlyException.StatusCode = StatusCodes.Status400BadRequest;
+            friendlyException.ValidationException = true;
+            return friendlyException;
+        }
+
+        /// <summary>
+        /// 鎶涘嚭瀛楃涓插紓甯�
+        /// </summary>
+        /// <param name="errorMessage">寮傚父娑堟伅</param>
+        /// <param name="exceptionType">鍏蜂綋寮傚父绫诲瀷</param>
+        /// <param name="args">String.Format 鍙傛暟</param>
+        /// <returns>寮傚父瀹炰緥</returns>
+        public static AppFriendlyException Oh(string errorMessage, Type exceptionType, params object[] args)
+        {
+            var exceptionMessage = string.Format(errorMessage, args);
+            return new AppFriendlyException(exceptionMessage, default,
+                Activator.CreateInstance(exceptionType, new object[] { exceptionMessage }) as Exception);
+        }
+
+        /// <summary>
+        /// 鎶涘嚭瀛楃涓插紓甯�
+        /// </summary>
+        /// <typeparam name="TException">鍏蜂綋寮傚父绫诲瀷</typeparam>
+        /// <param name="errorMessage">寮傚父娑堟伅</param>
+        /// <param name="args">String.Format 鍙傛暟</param>
+        /// <returns>寮傚父瀹炰緥</returns>
+        public static AppFriendlyException Oh<TException>(string errorMessage, params object[] args)
+            where TException : class
+        {
+            return Oh(errorMessage, typeof(TException), args);
+        }
+
+        /// <summary>
+        /// 鎶涘嚭閿欒鐮佸紓甯�
+        /// </summary>
+        /// <param name="errorCode">閿欒鐮�</param>
+        /// <param name="args">String.Format 鍙傛暟</param>
+        /// <returns>寮傚父瀹炰緥</returns>
+        public static AppFriendlyException Oh(object errorCode, params object[] args)
+        {
+            var (ErrorCode, Message) = GetErrorCodeMessage(errorCode, args);
+            var friendlyException = new AppFriendlyException(Message, errorCode) { ErrorCode = ErrorCode };
+
+            friendlyException.StatusCode = StatusCodes.Status400BadRequest;
+            friendlyException.ValidationException = true;
+            return friendlyException;
+        }
+
+        /// <summary>
+        /// 鎶涘嚭閿欒鐮佸紓甯�
+        /// </summary>
+        /// <param name="errorCode">閿欒鐮�</param>
+        /// <param name="exceptionType">鍏蜂綋寮傚父绫诲瀷</param>
+        /// <param name="args">String.Format 鍙傛暟</param>
+        /// <returns>寮傚父瀹炰緥</returns>
+        public static AppFriendlyException Oh(object errorCode, Type exceptionType, params object[] args)
+        {
+            var (ErrorCode, Message) = GetErrorCodeMessage(errorCode, args);
+            return new AppFriendlyException(Message, errorCode,
+                Activator.CreateInstance(exceptionType, new object[] { Message }) as Exception)
+            { ErrorCode = ErrorCode };
+        }
+
+        /// <summary>
+        /// 鎶涘嚭閿欒鐮佸紓甯�
+        /// </summary>
+        /// <typeparam name="TException">鍏蜂綋寮傚父绫诲瀷</typeparam>
+        /// <param name="errorCode">閿欒鐮�</param>
+        /// <param name="args">String.Format 鍙傛暟</param>
+        /// <returns>寮傚父瀹炰緥</returns>
+        public static AppFriendlyException Oh<TException>(object errorCode, params object[] args)
+            where TException : class
+        {
+            return Oh(errorCode, typeof(TException), args);
+        }
+        /// <summary>
+        /// 鑾峰彇閿欒鐮佹秷鎭�
+        /// </summary>
+        /// <param name="errorCode"></param>
+        /// <param name="args"></param>
+        /// <returns></returns>
+        private static (object ErrorCode, string Message) GetErrorCodeMessage(object errorCode, params object[] args)
+        {
+            string errorMessage = "";
+            (errorCode, errorMessage) = HandleEnumErrorCode(errorCode);
+            return (errorCode, errorMessage);
+        }
+        /// <summary>
+        /// 澶勭悊鏋氫妇绫诲瀷閿欒鐮�
+        /// </summary>
+        /// <param name="errorCode">閿欒鐮�</param>
+        /// <returns></returns>
+        private static (object ErrorCode, string Message) HandleEnumErrorCode(object errorCode)
+        {
+            string errorMessage = "";
+            // 鑾峰彇绫诲瀷
+            var errorType = errorCode.GetType();
+
+            // 鍒ゆ柇鏄惁鏄唴缃灇涓剧被鍨嬶紝濡傛灉鏄В鏋愮壒鎬�
+            if (ErrorCodeTypes.Any(u => u == errorType))
+            {
+                var fieldinfo = errorType.GetField(Enum.GetName(errorType, errorCode));
+                if (fieldinfo.IsDefined(typeof(ErrorCodeItemMetadataAttribute), true))
+                {
+                    var info = GetErrorCodeItemInformation(fieldinfo);
+                    errorCode = info.Key;
+                    errorMessage = info.Value;
+                }
+            }
+
+            return (errorCode, errorMessage);
+        }
+        /// <summary>
+        /// 鑾峰彇閿欒浠g爜淇℃伅
+        /// </summary>
+        /// <param name="fieldInfo">瀛楁瀵硅薄</param>
+        /// <returns>(object key, object value)</returns>
+        private static (object Key, string Value) GetErrorCodeItemInformation(FieldInfo fieldInfo)
+        {
+            var errorCodeItemMetadata = fieldInfo.GetCustomAttribute<ErrorCodeItemMetadataAttribute>();
+            return (errorCodeItemMetadata.ErrorCode ?? fieldInfo.Name, string.Format(errorCodeItemMetadata.ErrorMessage, errorCodeItemMetadata.Args));
+        }
+        /// <summary>
+        /// 鑾峰彇閿欒浠g爜绫诲瀷
+        /// </summary>
+        /// <returns></returns>
+        private static IEnumerable<Type> GetErrorCodeTypes()
+        {
+            var typesWithErrorCodeTypeAttribute = AppDomain.CurrentDomain
+            .GetAssemblies()
+            .SelectMany(assembly => assembly.GetTypes())
+            .Where(type => type.IsEnum && type.GetCustomAttribute<ErrorCodeTypeAttribute>() != null)
+            .ToList();
+            return typesWithErrorCodeTypeAttribute;
+
+        }
+
+    }
+}
diff --git a/Wms/Utility/Extension/ApiResponseActionFilter.cs b/Wms/Utility/Extension/ApiResponseActionFilter.cs
new file mode 100644
index 0000000..186f008
--- /dev/null
+++ b/Wms/Utility/Extension/ApiResponseActionFilter.cs
@@ -0,0 +1,37 @@
+锘縰sing Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Utility.Entity;
+
+namespace Utility
+{
+    public class ApiResponseActionFilter: IAsyncActionFilter
+    {
+        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+        {
+            // 鍦ㄦ墽琛屽姩浣滀箣鍓嶇殑閫昏緫
+            var resultContext = await next(); // 鎵ц鍔ㄤ綔鏂规硶骞惰幏鍙栨墽琛岀粨鏋�
+
+            // 鍦ㄦ墽琛屽姩浣滀箣鍚庣殑閫昏緫
+            if (resultContext.Result is ObjectResult objectResult)
+            {
+                var apiResponse = new ApiResponse<object>(
+                    context.HttpContext.Response.StatusCode,
+                    context.HttpContext.Response.StatusCode == 200 ? "璇锋眰鎴愬姛" : "閿欒",
+                    objectResult.Value
+                );
+
+                var json = JsonConvert.SerializeObject(apiResponse);
+                context.HttpContext.Response.ContentType = "application/json";
+                context.HttpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(json);
+
+                await context.HttpContext.Response.WriteAsync(json);
+            }
+        }
+    }
+}
diff --git a/Wms/Utility/Extension/ApiResponseMiddleware.cs b/Wms/Utility/Extension/ApiResponseMiddleware.cs
new file mode 100644
index 0000000..745862c
--- /dev/null
+++ b/Wms/Utility/Extension/ApiResponseMiddleware.cs
@@ -0,0 +1,97 @@
+锘縰sing Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Utility.Entity;
+
+namespace Utility.Extension
+{
+    public class ApiResponseMiddleware : IMiddleware
+    {
+        public ApiResponseMiddleware()
+        {
+
+        }
+
+        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
+        {
+            if (ShouldApplyApiResponseMiddleware(context))
+            {
+                // 鎹曡幏鍝嶅簲
+                var originalBodyStream = context.Response.Body;
+
+                using (var responseBody = new MemoryStream())
+                {
+                    context.Response.Body = responseBody;
+
+                    await next(context);
+                    // 璇诲彇鍝嶅簲鍐呭
+                    context.Response.Body.Seek(0, SeekOrigin.Begin);
+                    var body = await new StreamReader(context.Response.Body).ReadToEndAsync();
+                    context.Response.Body.Seek(0, SeekOrigin.Begin);
+
+                    // 鍙嶅簭鍒楀寲鍝嶅簲鍐呭
+                    object data = null;
+                    if (!string.IsNullOrEmpty(body))
+                    {
+                        try
+                        {
+                            data = JsonConvert.DeserializeObject<object>(body);
+                        }
+                        catch (JsonException)
+                        {
+                            // 濡傛灉鍝嶅簲涓嶆槸鏈夋晥鐨凧SON鏍煎紡锛岀洿鎺ュ皢鍏朵綔涓哄瓧绗︿覆鏁版嵁澶勭悊
+                            data = body;
+                        }
+                    }
+
+                    var apiResponse = new ApiResponse<object>(
+                        code: context.Response.StatusCode == StatusCodes.Status200OK ? (int)ResponseEnum.Sucess : (int)ResponseEnum.Fail,
+                        message: context.Response.StatusCode == StatusCodes.Status200OK ? "璇锋眰鎴愬姛" : "",
+                        data: data
+                    );
+
+                    var json = JsonConvert.SerializeObject(apiResponse);
+                    context.Response.ContentType = "application/json";
+                    context.Response.ContentLength = Encoding.UTF8.GetByteCount(json);
+
+                    context.Response.Body = originalBodyStream;
+                    await context.Response.WriteAsync(json);
+                }
+            }
+            else
+            {
+                await next(context);
+            }
+        }
+        private bool ShouldApplyApiResponseMiddleware(HttpContext context)
+        {
+            // 鑾峰彇褰撳墠澶勭悊璇锋眰鐨勬帶鍒跺櫒淇℃伅
+            var controllerActionDescriptor = context.GetEndpoint()?.Metadata.GetMetadata<ControllerActionDescriptor>();
+            if (controllerActionDescriptor != null)
+            {
+                // 鍒ゆ柇鎺у埗鍣ㄦ槸鍚﹀甫鏈� ResponseAttribute 鐗规��
+                return controllerActionDescriptor.ControllerTypeInfo.IsDefined(typeof(UnifyResponseAttribute), inherit: true);
+            }
+            return false;
+        }
+    }
+    public static class ApiResponse
+    {
+        public static void UseApiResponse(this IApplicationBuilder app)
+        {
+            app.UseMiddleware<ApiResponseMiddleware>();
+        }
+    }
+
+    public class UnifyResponseAttribute : Attribute
+    {
+
+    }
+}
diff --git a/Wms/Utility/Extension/ApplicationBuilderExtensions.cs b/Wms/Utility/Extension/ApplicationBuilderExtensions.cs
new file mode 100644
index 0000000..5c72390
--- /dev/null
+++ b/Wms/Utility/Extension/ApplicationBuilderExtensions.cs
@@ -0,0 +1,85 @@
+锘縰sing Microsoft.AspNetCore.Builder;
+using System;
+using Serilog;
+using Serilog.Events;
+using System.IO;
+using System.Net;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Http.Headers;
+using System.Runtime.CompilerServices;
+using Utility.Tools;
+using System.Security.Claims;
+using System.IdentityModel.Tokens.Jwt;
+using System.Linq;
+
+namespace Utility
+{
+    public static class ApplicationBuilderExtensions
+    {
+        /// <summary>
+        ///  娣诲姞浣跨敤Serilog璇锋眰鏃ュ織
+        /// </summary>
+        /// <param name="app"></param>
+        /// <returns></returns>
+        public static IApplicationBuilder UseSerilogRequestLogging(this IApplicationBuilder app)
+        {
+            //鍏佽body閲嶇敤
+            app.Use(next => context =>
+            {
+                context.Request.EnableBuffering();
+                return next(context);
+            });
+
+            // 娣诲姞浣跨敤Serilog璁板綍璇锋眰鏃ュ織
+            app.UseSerilogRequestLogging(options =>
+            {
+                // 璇锋眰鏃ュ織杈撳嚭妯℃澘
+                options.MessageTemplate = "\n {RequestMethod}={_RequestPath} | 鐘舵��={StatusCode} | 鏃堕棿={Elapsed}ms | 鎿嶄綔浜�={_UserName} \n 璇锋眰鍐呭={_RequestBody} \n 杩斿洖缁撴灉={_ResponseBody}";
+
+                // 鍙戝嚭璋冭瘯绾у埆浜嬩欢鑰屼笉鏄粯璁や簨浠讹紝灏嗚姹傛棩蹇楄褰曞埌:Debug鏃ュ織
+                options.GetLevel = (httpContext, elapsed, ex) =>
+                {
+                    var method = httpContext.Request.Method.ToLower();
+                    if (method == "options")
+                        return LogEventLevel.Debug;
+                    return LogEventLevel.Information;
+                };
+
+                // 灏嗗叾浠栧睘鎬ч檮鍔犲埌璇锋眰瀹屾垚浜嬩欢锛屽皢璇锋眰灞炴�ч檮鍔犲彲浠ュ湪妯℃澘涓娇鐢�
+                options.EnrichDiagnosticContext = (diagnosticContext, httpContext) =>
+                {
+                    diagnosticContext.Set("_RequestPath", WebUtility.UrlDecode(httpContext.Request.Path + httpContext.Request.QueryString));
+                    var token = httpContext.Request.Headers["Token"].ToString();
+                    if (!string.IsNullOrEmpty(token))
+                    {
+                        var handler = new JwtSecurityTokenHandler();
+                        var jwtToken = handler.ReadJwtToken(token);
+                        var claim = jwtToken.Payload.Claims.FirstOrDefault(s => s.Type == "LoginName");
+                        //foreach (var claim in jwtToken.Payload.Claims)
+                        //{
+                        //    Console.WriteLine($"{claim.Type}: {claim.Value}");
+                        //}
+                        if (claim != null)
+                            diagnosticContext.Set("_UserName", claim.Value);
+                        else
+                            diagnosticContext.Set("_UserName", "");
+                    }
+                    //璇锋眰body
+                    var requestContent = "{}";
+                    var method = httpContext.Request.Method.ToLower();
+                    if (method == "post" || method == "put")
+                    {
+                        httpContext.Request.Body.Position = 0;
+                        var requestReader = new StreamReader(httpContext.Request.Body);
+                        if (requestReader.BaseStream.Length != 0)
+                            requestContent = requestReader.ReadToEnd();
+                    }
+                    diagnosticContext.Set("_RequestBody", requestContent);
+                    diagnosticContext.Set("_Service", AppDomain.CurrentDomain.FriendlyName);
+                };
+            });
+
+            return app;
+        }
+    }
+}
diff --git a/Wms/Utility/Extension/LogExtends.cs b/Wms/Utility/Extension/LogExtends.cs
new file mode 100644
index 0000000..de01c02
--- /dev/null
+++ b/Wms/Utility/Extension/LogExtends.cs
@@ -0,0 +1,75 @@
+锘縰sing Serilog.Events;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+
+namespace Wms
+{
+    public static class LogExtends
+    {
+        //const string infoPath = "Logs/Information.log";
+        //const string warnPath = "Logs/Warning.log";
+        //const string errorPath = "Logs/Error.log";
+        //const string fatalPath = "Logs/Fatal.log";
+        //const string template = "鏃堕棿: {Timestamp:yyyy-MM-dd HH:mm:ss}{NewLine}鏉ユ簮: {SourceContext}{NewLine}鍐呭: [{Level:u3}] {Message}{NewLine}{Exception}{NewLine}";
+
+        //// 鍙互灏嗘棩蹇楄緭鍑哄埌鎺у埗鍙般�佹枃浠躲�佹暟鎹簱銆丒S绛�
+        //public static void AddSerilog(this IServiceCollection c)
+        //{
+        //    Log.Logger = new LoggerConfiguration()
+        //        .MinimumLevel.Information()
+        //        .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) // 鎺掗櫎Dotnet鑷甫鐨勬棩蹇�
+        //        .Enrich.FromLogContext()
+        //        .WriteTo.Console(outputTemplate: template)
+        //        .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Information).WriteTo.Async(congfig => congfig.File(
+        //                infoPath,
+        //                rollingInterval: RollingInterval.Day,
+        //                fileSizeLimitBytes: 1024 * 1024 * 10,    //榛樿1GB
+        //                retainedFileCountLimit: 100,                   //淇濈暀鏈�杩戝灏戜釜鏂囦欢,榛樿31涓�
+        //                rollOnFileSizeLimit: true,                       //瓒呰繃鏂囦欢澶у皬鏃�,鑷姩鍒涘缓鏂版枃浠�  
+        //                shared: true,
+        //                outputTemplate: template)
+        //            ))
+
+        //        .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Warning).WriteTo.Async(congfig => congfig.File(
+        //                warnPath,
+        //                rollingInterval: RollingInterval.Day,
+        //                fileSizeLimitBytes: 1024 * 1024 * 10,
+        //                retainedFileCountLimit: 100,
+        //                rollOnFileSizeLimit: true,
+        //                shared: true,
+        //                outputTemplate: template)
+        //        ))
+
+        //        .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Error).WriteTo.Async(congfig => congfig.File(
+        //                errorPath,
+        //                rollingInterval: RollingInterval.Day,
+        //                fileSizeLimitBytes: 1024 * 1024 * 10,
+        //                retainedFileCountLimit: 100,
+        //                rollOnFileSizeLimit: true,
+        //                shared: true,
+        //                outputTemplate: template)
+        //        ))
+
+        //        .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(lev => lev.Level == LogEventLevel.Fatal).WriteTo.Async(congfig => congfig.File(
+        //                fatalPath,
+        //                rollingInterval: RollingInterval.Day,
+        //                fileSizeLimitBytes: 1024 * 1024 * 10,
+        //                retainedFileCountLimit: 100,
+        //                rollOnFileSizeLimit: true,
+        //                shared: true,
+        //                outputTemplate: template)
+        //        )).CreateLogger();
+
+        //    // 娉ㄥ叆鍒板鍣�
+        //    c.AddLogging(opt =>
+        //    {
+        //        opt.ClearProviders();
+        //        opt.AddSerilog(dispose: true);
+        //    });
+        //}
+    }
+}
diff --git a/Wms/Utility/Extension/RequestAuditLogFilter.cs b/Wms/Utility/Extension/RequestAuditLogFilter.cs
new file mode 100644
index 0000000..26ddd49
--- /dev/null
+++ b/Wms/Utility/Extension/RequestAuditLogFilter.cs
@@ -0,0 +1,26 @@
+锘縰sing Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Newtonsoft.Json;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Utility
+{
+    public class RequestAuditLogFilter : IResultFilter
+    {
+        private readonly IDiagnosticContext _diagnosticContext;
+
+        public RequestAuditLogFilter(IDiagnosticContext diagnosticContext) { _diagnosticContext = diagnosticContext; }
+
+        public void OnResultExecuted(ResultExecutedContext context)
+        {
+            var result = context.Result as ObjectResult;
+            var resultJson = JsonConvert.SerializeObject(result?.Value);
+            _diagnosticContext.Set("_ResponseBody", resultJson);
+        }
+
+        public void OnResultExecuting(ResultExecutingContext context) { }
+    }
+}
diff --git a/Wms/Utility/Extension/ServiceCollectionExtensions.cs b/Wms/Utility/Extension/ServiceCollectionExtensions.cs
new file mode 100644
index 0000000..c15adad
--- /dev/null
+++ b/Wms/Utility/Extension/ServiceCollectionExtensions.cs
@@ -0,0 +1,79 @@
+锘縰sing Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Serilog.Events;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Serilog.Sinks.SystemConsole.Themes;
+using Serilog.Filters;
+
+namespace Utility
+{
+    public static class ServiceCollectionExtensions
+    {
+        const string template = "鏃堕棿: {Timestamp:yyyy-MM-dd HH:mm:ss}{NewLine}鏉ユ簮: {SourceContext}{NewLine}鍐呭: [{Level:u3}] {Message}{NewLine}{Exception}{NewLine}";
+        /// <summary>
+        /// 娣诲姞閰嶇疆Serilog
+        /// </summary>
+        /// <param name="services"></param>
+        /// <param name="configuration"></param>
+        /// <returns></returns>
+        public static IServiceCollection AddConfigSerilog(this IServiceCollection services)
+        {
+            // 鍒涘缓Serilog璁板綍鏃ュ織
+            Log.Logger = new LoggerConfiguration()
+                .MinimumLevel.Information()
+                .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) // 鎺掗櫎Dotnet鑷甫鐨勬棩蹇�
+                //.MinimumLevel.Verbose()
+                //.MinimumLevel.Override("System", LogEventLevel.Debug)
+                //.MinimumLevel.Override("Microsoft", LogEventLevel.Debug)
+                //.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Error)
+                //.MinimumLevel.Override("Microsoft.AspNetCore.Cors.Infrastructure.CorsService", LogEventLevel.Error)
+                //.MinimumLevel.Override("Microsoft.AspNetCore.Mvc", LogEventLevel.Error)
+                //.MinimumLevel.Override("Microsoft.AspNetCore.Hosting", LogEventLevel.Error)
+                // 鍏ㄩ儴鏃ュ織鍐欏叆鍒癈onsole
+                .WriteTo.Console()
+                .WriteTo.Async(c => c.Console(
+                   theme: AnsiConsoleTheme.Literate,
+                    outputTemplate: template))
+                // Information鏃ュ織鍐欏叆鍒版枃浠�
+                .WriteTo.Async(c => c.File(
+                    path: "Logs/Information_.txt",
+                    rollingInterval: RollingInterval.Day,
+                    fileSizeLimitBytes: 1024 * 1024 * 10,
+                    retainedFileCountLimit: 100,
+                    outputTemplate: template,
+                    restrictedToMinimumLevel: LogEventLevel.Information))
+                // Debug鏃ュ織鍐欏叆鍒版枃浠�
+                //.WriteTo.Async(c => c.File(
+                //    path: "Logs/Debug.txt",
+                //    rollingInterval: RollingInterval.Day,
+                //    fileSizeLimitBytes: 1024 * 1024 * 10,
+                //    retainedFileCountLimit: 100,
+                //    outputTemplate: template,
+                //    restrictedToMinimumLevel: LogEventLevel.Debug))
+                // Warning鏃ュ織鍐欏叆鍒版枃浠�
+                .WriteTo.Async(c => c.File(
+                    path: "Logs/Warning_.txt",
+                    rollingInterval: RollingInterval.Day,
+                    fileSizeLimitBytes: 1024 * 1024 * 10,
+                    retainedFileCountLimit: 100,
+                    outputTemplate: template,
+                    restrictedToMinimumLevel: LogEventLevel.Warning))
+                // Error鏃ュ織鍐欏叆鍒版枃浠�
+                .WriteTo.Async(c => c.File(
+                    path: "Logs/Error_.txt",
+                    rollingInterval: RollingInterval.Day,
+                    fileSizeLimitBytes: 1024 * 1024 * 10,
+                    retainedFileCountLimit: 1000,
+                    outputTemplate: template,
+                    restrictedToMinimumLevel: LogEventLevel.Error))
+                .CreateLogger();
+
+            services.AddSerilog();
+
+            return services;
+        }
+    }
+}
diff --git a/Wms/Utility/Filter/CustomerExceptionMiddleware.cs b/Wms/Utility/Filter/CustomerExceptionMiddleware.cs
new file mode 100644
index 0000000..f07c390
--- /dev/null
+++ b/Wms/Utility/Filter/CustomerExceptionMiddleware.cs
@@ -0,0 +1,64 @@
+锘縰sing Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using System.Threading.Tasks;
+using System;
+using System.Text.Json;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.Extensions.Logging;
+using Utility.Entity;
+using Newtonsoft.Json;
+
+namespace Utility
+{
+    public class CustomerExceptionMiddleware
+    {
+        private readonly RequestDelegate _next;
+        private readonly ILogger<CustomerExceptionMiddleware> _logger;
+
+        public CustomerExceptionMiddleware(RequestDelegate next, ILogger<CustomerExceptionMiddleware> logger)
+        {
+            _next = next;
+            _logger = logger;
+        }
+
+        public async Task Invoke(HttpContext context)
+        {
+            try
+            {
+                await _next(context);
+            }
+            catch (Exception ex)
+            {
+                _logger.LogError(ex, ex.Message);
+                context.Response.ContentType = "application/json";
+                context.Response.StatusCode = StatusCodes.Status500InternalServerError;
+                var result = "绯荤粺寮傚父锛岃鑱旂郴绠$悊鍛�";
+                if (ex is AppFriendlyException)
+                    result = ex.Message;
+                var apiResponse = new ApiResponse<object>(
+                        code: (int)ResponseEnum.Error,
+                        message: result,
+                        data: result
+                    );
+
+                await context.Response.WriteAsync(JsonConvert.SerializeObject(apiResponse));
+            }
+        }
+    }
+
+    /// <summary>
+    /// 闈欐�佺被
+    /// </summary>
+    public static class ExceptionMiddlewareExtension
+    {
+        /// <summary>
+        /// 闈欐�佹柟娉�
+        /// </summary>
+        /// <param name="app">瑕佽繘琛屾墿灞曠殑绫诲瀷</param>
+        public static void UseExceptionMiddleware(this IApplicationBuilder app)
+        {
+            app.UseMiddleware(typeof(CustomerExceptionMiddleware));
+        }
+    }
+}
+
diff --git a/Wms/Utility/UnitOfWork/IUnitOfWork.cs b/Wms/Utility/UnitOfWork/IUnitOfWork.cs
new file mode 100644
index 0000000..5a7abbd
--- /dev/null
+++ b/Wms/Utility/UnitOfWork/IUnitOfWork.cs
@@ -0,0 +1,38 @@
+锘縰sing Microsoft.AspNetCore.Mvc.Filters;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Utility
+{
+    public interface IUnitOfWork
+    {
+        /// <summary>
+        /// 寮�鍚伐浣滃崟鍏冨鐞�
+        /// </summary>
+        /// <param name="context"></param>
+        /// <param name="unitOfWork"></param>
+        void BeginTransaction(FilterContext context, UnitOfWorkAttribute unitOfWork);
+
+        /// <summary>
+        /// 鎻愪氦宸ヤ綔鍗曞厓澶勭悊
+        /// </summary>
+        /// <param name="resultContext"></param>
+        /// <param name="unitOfWork"></param>
+        void CommitTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);
+
+        /// <summary>
+        /// 鍥炴粴宸ヤ綔鍗曞厓澶勭悊
+        /// </summary>
+        /// <param name="resultContext"></param>
+        /// <param name="unitOfWork"></param>
+        void RollbackTransaction(FilterContext resultContext, UnitOfWorkAttribute unitOfWork);
+
+        /// <summary>
+        /// 鎵ц瀹屾瘯锛堟棤璁烘垚鍔熷け璐ワ級
+        /// </summary>
+        /// <param name="context"></param>
+        /// <param name="resultContext"></param>
+        void OnCompleted(FilterContext context, FilterContext resultContext);
+    }
+}
diff --git a/Wms/Utility/UnitOfWork/UnitOfWorkAttribute.cs b/Wms/Utility/UnitOfWork/UnitOfWorkAttribute.cs
new file mode 100644
index 0000000..aefa7fb
--- /dev/null
+++ b/Wms/Utility/UnitOfWork/UnitOfWorkAttribute.cs
@@ -0,0 +1,290 @@
+锘縰sing Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Reflection;
+using System.Threading.Tasks;
+using System.Transactions;
+
+namespace Utility
+{
+    /// <summary>
+    /// 宸ヤ綔鍗曞厓閰嶇疆鐗规��
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Method)]
+    public sealed class UnitOfWorkAttribute : Attribute, IAsyncActionFilter, IAsyncPageFilter, IOrderedFilter
+    {
+        /// <summary>
+        /// 纭繚浜嬪姟鍙敤
+        /// <para>姝ゆ柟娉曚负浜嗚В鍐抽潤鎬佺被鏂瑰紡鎿嶄綔鏁版嵁搴撶殑闂</para>
+        /// </summary>
+        public bool EnsureTransaction { get; set; } = false;
+
+        /// <summary>
+        /// 鏄惁浣跨敤鍒嗗竷寮忕幆澧冧簨鍔�
+        /// </summary>
+        public bool UseAmbientTransaction { get; set; } = false;
+
+        /// <summary>
+        /// 鍒嗗竷寮忕幆澧冧簨鍔¤寖鍥�
+        /// </summary>
+        /// <remarks><see cref="UseAmbientTransaction"/> 涓� true 鏈夋晥</remarks>
+        public TransactionScopeOption TransactionScope { get; set; } = TransactionScopeOption.Required;
+
+        /// <summary>
+        /// 鍒嗗竷寮忕幆澧冧簨鍔¢殧绂荤骇鍒�
+        /// </summary>
+        /// <remarks><see cref="UseAmbientTransaction"/> 涓� true 鏈夋晥</remarks>
+        public IsolationLevel TransactionIsolationLevel { get; set; } = IsolationLevel.ReadCommitted;
+
+        /// <summary>
+        /// 鍒嗗竷寮忕幆澧冧簨鍔¤秴鏃舵椂闂�
+        /// </summary>
+        /// <remarks>鍗曚綅绉�</remarks>
+        public int TransactionTimeout { get; set; } = 0;
+
+        /// <summary>
+        /// 鏀寔鍒嗗竷寮忕幆澧冧簨鍔″紓姝ユ祦
+        /// </summary>
+        /// <remarks><see cref="UseAmbientTransaction"/> 涓� true 鏈夋晥</remarks>
+        public TransactionScopeAsyncFlowOption TransactionScopeAsyncFlow { get; set; } = TransactionScopeAsyncFlowOption.Enabled;
+
+        /// <summary>
+        ///  MiniProfiler 鍒嗙被鍚�
+        /// </summary>
+        private const string MiniProfilerCategory = "unitOfWork";
+
+        /// <summary>
+        /// 杩囨护鍣ㄦ帓搴�
+        /// </summary>
+        private const int FilterOrder = 9999;
+
+        /// <summary>
+        /// 鎺掑簭灞炴��
+        /// </summary>
+        public int Order => FilterOrder;
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        public UnitOfWorkAttribute()
+        {
+        }
+
+        /// <summary>
+        /// 鏋勯�犲嚱鏁�
+        /// </summary>
+        /// <param name="ensureTransaction"></param>
+        public UnitOfWorkAttribute(bool ensureTransaction)
+        {
+            EnsureTransaction = ensureTransaction;
+        }
+
+        /// <summary>
+        /// 鎷︽埅璇锋眰
+        /// </summary>
+        /// <param name="context">鍔ㄤ綔鏂规硶涓婁笅鏂�</param>
+        /// <param name="next">涓棿浠跺鎵�</param>
+        /// <returns></returns>
+        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+        {
+            // 鑾峰彇鍔ㄤ綔鏂规硶鎻忚堪鍣�
+            var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
+            var method = actionDescriptor.MethodInfo;
+
+            // 鍒涘缓鍒嗗竷寮忕幆澧冧簨鍔�
+            (var transactionScope, var logger) = CreateTransactionScope(context);
+
+            try
+            {
+                // 鎵撳嵃宸ヤ綔鍗曞厓寮�濮嬫秷鎭�
+                Console.WriteLine("Beginning (Ambient)");
+                // 寮�濮嬩簨鍔�
+                BeginTransaction(context, method, out var _unitOfWork, out var unitOfWorkAttribute);
+
+                // 鑾峰彇鎵ц Action 缁撴灉
+                var resultContext = await next();
+
+                // 鎻愪氦浜嬪姟
+                CommitTransaction(context, _unitOfWork, unitOfWorkAttribute, resultContext);
+
+                // 鎻愪氦鍒嗗竷寮忕幆澧冧簨鍔�
+                if (resultContext.Exception == null)
+                {
+                    transactionScope?.Complete();
+
+                    // 鎵撳嵃浜嬪姟鎻愪氦娑堟伅
+                    if (UseAmbientTransaction) Console.WriteLine("Completed (Ambient)");
+                }
+                else
+                {
+                    // 鎵撳嵃浜嬪姟鍥炴粴娑堟伅
+                    if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)");
+
+                    logger.LogError(resultContext.Exception, "Transaction Failed.");
+                }
+            }
+            catch (Exception ex)
+            {
+                logger.LogError(ex, "Transaction Failed.");
+
+                // 鎵撳嵃浜嬪姟鍥炴粴娑堟伅
+                if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)");
+
+                throw;
+            }
+            finally
+            {
+                transactionScope?.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// 妯″瀷缁戝畾鎷︽埅
+        /// </summary>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        public Task OnPageHandlerSelectionAsync(PageHandlerSelectedContext context)
+        {
+            return Task.CompletedTask;
+        }
+
+        /// <summary>
+        /// 鎷︽埅璇锋眰
+        /// </summary>
+        /// <param name="context"></param>
+        /// <param name="next"></param>
+        /// <returns></returns>
+        public async Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next)
+        {
+            // 鑾峰彇鍔ㄤ綔鏂规硶鎻忚堪鍣�
+            var method = context.HandlerMethod?.MethodInfo;
+            // 澶勭悊 Blazor Server
+            if (method == null)
+            {
+                _ = await next.Invoke();
+                return;
+            }
+
+            // 鍒涘缓鍒嗗竷寮忕幆澧冧簨鍔�
+            (var transactionScope, var logger) = CreateTransactionScope(context);
+
+            try
+            {
+                // 鎵撳嵃宸ヤ綔鍗曞厓寮�濮嬫秷鎭�
+                if (UseAmbientTransaction) Console.WriteLine("Beginning (Ambient)");
+
+                // 寮�濮嬩簨鍔�
+                BeginTransaction(context, method, out var _unitOfWork, out var unitOfWorkAttribute);
+
+                // 鑾峰彇鎵ц Action 缁撴灉
+                var resultContext = await next.Invoke();
+
+                // 鎻愪氦浜嬪姟
+                CommitTransaction(context, _unitOfWork, unitOfWorkAttribute, resultContext);
+
+                // 鎻愪氦鍒嗗竷寮忕幆澧冧簨鍔�
+                if (resultContext.Exception == null)
+                {
+                    transactionScope?.Complete();
+
+                    // 鎵撳嵃浜嬪姟鎻愪氦娑堟伅
+                    if (UseAmbientTransaction) Console.WriteLine("Completed (Ambient)");
+                }
+                else
+                {
+                    // 鎵撳嵃浜嬪姟鍥炴粴娑堟伅
+                    if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)");
+
+                    logger.LogError(resultContext.Exception, "Transaction Failed.");
+                }
+            }
+            catch (Exception ex)
+            {
+                logger.LogError(ex, "Transaction Failed.");
+
+                // 鎵撳嵃浜嬪姟鍥炴粴娑堟伅
+                if (UseAmbientTransaction) Console.WriteLine("Rollback (Ambient)");
+
+                throw;
+            }
+            finally
+            {
+                transactionScope?.Dispose();
+            }
+        }
+
+        /// <summary>
+        /// 鍒涘缓鍒嗗竷寮忕幆澧冧簨鍔�
+        /// </summary>
+        /// <param name="context"></param>
+        /// <returns></returns>
+        private (TransactionScope, ILogger) CreateTransactionScope(FilterContext context)
+        {
+            // 鏄惁鍚敤鍒嗗竷寮忕幆澧冧簨鍔�
+            var transactionScope = UseAmbientTransaction
+                 ? new TransactionScope(TransactionScope,
+                new TransactionOptions { IsolationLevel = TransactionIsolationLevel, Timeout = TransactionTimeout > 0 ? TimeSpan.FromSeconds(TransactionTimeout) : default }
+                , TransactionScopeAsyncFlow)
+                 : default;
+
+            // 鍒涘缓鏃ュ織璁板綍鍣�
+            var logger = context.HttpContext.RequestServices.GetRequiredService<ILogger<UnitOfWorkAttribute>>();
+
+            return (transactionScope, logger);
+        }
+
+        /// <summary>
+        /// 寮�濮嬩簨鍔�
+        /// </summary>
+        /// <param name="context"></param>
+        /// <param name="method"></param>
+        /// <param name="_unitOfWork"></param>
+        /// <param name="unitOfWorkAttribute"></param>
+        private static void BeginTransaction(FilterContext context, MethodInfo method, out IUnitOfWork _unitOfWork, out UnitOfWorkAttribute unitOfWorkAttribute)
+        {
+            // 瑙f瀽宸ヤ綔鍗曞厓鏈嶅姟
+            _unitOfWork = context.HttpContext.RequestServices.GetRequiredService<IUnitOfWork>();
+
+            // 鑾峰彇宸ヤ綔鍗曞厓鐗规��
+            unitOfWorkAttribute = method.GetCustomAttribute<UnitOfWorkAttribute>();
+
+            // 璋冪敤寮�鍚簨鍔℃柟娉�
+            _unitOfWork.BeginTransaction(context, unitOfWorkAttribute);
+
+            // 鎵撳嵃宸ヤ綔鍗曞厓寮�濮嬫秷鎭�
+            if (!unitOfWorkAttribute.UseAmbientTransaction) Console.WriteLine("Beginning");
+        }
+
+        /// <summary>
+        /// 鎻愪氦浜嬪姟
+        /// </summary>
+        /// <param name="context"></param>
+        /// <param name="_unitOfWork"></param>
+        /// <param name="unitOfWorkAttribute"></param>
+        /// <param name="resultContext"></param>
+        private static void CommitTransaction(FilterContext context, IUnitOfWork _unitOfWork, UnitOfWorkAttribute unitOfWorkAttribute, FilterContext resultContext)
+        {
+            // 鑾峰彇鍔ㄦ�佺粨鏋滀笂涓嬫枃
+            dynamic dynamicResultContext = resultContext;
+
+            if (dynamicResultContext.Exception == null)
+            {
+                // 璋冪敤鎻愪氦浜嬪姟鏂规硶
+                _unitOfWork.CommitTransaction(resultContext, unitOfWorkAttribute);
+            }
+            else
+            {
+                // 璋冪敤鍥炴粴浜嬪姟鏂规硶
+                _unitOfWork.RollbackTransaction(resultContext, unitOfWorkAttribute);
+            }
+
+            // 璋冪敤鎵ц瀹屾瘯鏂规硶
+            _unitOfWork.OnCompleted(context, resultContext);
+
+            // 鎵撳嵃宸ヤ綔鍗曞厓缁撴潫娑堟伅
+            if (!unitOfWorkAttribute.UseAmbientTransaction) Console.WriteLine("Ending");
+        }
+    }
+}
diff --git a/Wms/Utility/Utility.csproj b/Wms/Utility/Utility.csproj
index d2026ba..49a3a6a 100644
--- a/Wms/Utility/Utility.csproj
+++ b/Wms/Utility/Utility.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+锘�<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <TargetFramework>netcoreapp3.1</TargetFramework>
@@ -13,8 +13,18 @@
   </ItemGroup>
 
   <ItemGroup>
+    <PackageReference Include="Autofac" Version="8.0.0" />
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.32" />
+    <PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
     <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
-    <PackageReference Include="System.Drawing.Common" Version="5.0.3" />
+    <PackageReference Include="Serilog" Version="4.0.0" />
+    <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
+    <PackageReference Include="Serilog.Sinks.Async" Version="2.0.0" />
+    <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
+    <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
+    <PackageReference Include="System.Drawing.Common" Version="6.0.0" />
     <PackageReference Include="ZXing.Net" Version="0.16.7" />
   </ItemGroup>
 
diff --git a/Wms/Wms/Controllers/BllTaskController.cs b/Wms/Wms/Controllers/BllTaskController.cs
index 3fd9e3b..9688f2d 100644
--- a/Wms/Wms/Controllers/BllTaskController.cs
+++ b/Wms/Wms/Controllers/BllTaskController.cs
@@ -7,6 +7,8 @@
 using System.Linq;
 using System.Security.Claims;
 using System.Threading.Tasks;
+using Utility;
+using Utility.Extension;
 using Wms.Tools;
 using WMS.IBLL.IBllTaskServer;
 
@@ -36,6 +38,7 @@
         /// <param name="model"></param>
         /// <returns></returns>
         [HttpPost]
+        [AllowAnonymous]
         public IActionResult GetTaskSyncList(TaskSyncVm model)
         {
             try
diff --git a/Wms/Wms/Program.cs b/Wms/Wms/Program.cs
index ebbbefe..0c08ea0 100644
--- a/Wms/Wms/Program.cs
+++ b/Wms/Wms/Program.cs
@@ -3,6 +3,7 @@
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Logging;
+using Serilog;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -14,7 +15,18 @@
     {
         public static void Main(string[] args)
         {
-            CreateHostBuilder(args).Build().Run();
+            try
+            {
+                CreateHostBuilder(args).Build().Run();
+            }
+            catch (Exception ex)
+            {
+                Log.Fatal(ex, "*** Program Stop ***");
+            }
+            finally
+            {
+                Log.CloseAndFlush();
+            }
         }
 
         public static IHostBuilder CreateHostBuilder(string[] args) =>
@@ -22,6 +34,7 @@
                 .ConfigureWebHostDefaults(webBuilder =>
                 {
                     webBuilder.UseStartup<Startup>();
-                }).UseServiceProviderFactory(new AutofacServiceProviderFactory());
+                }).UseServiceProviderFactory(new AutofacServiceProviderFactory())
+                .UseSerilog();
     }
 }
diff --git a/Wms/Wms/Startup.cs b/Wms/Wms/Startup.cs
index 93f1405..9414fe7 100644
--- a/Wms/Wms/Startup.cs
+++ b/Wms/Wms/Startup.cs
@@ -14,6 +14,12 @@
 using Wms.Tools;
 using WMS.Entity.Context;
 using WMS.IBLL.IDataServer;
+using Serilog;
+using Autofac.Core;
+using Utility;
+using Utility.Extension;
+using Microsoft.Extensions.Options;
+using Microsoft.AspNetCore.Http;
 
 namespace Wms
 {
@@ -37,7 +43,9 @@
             services.AddHostedService<DailyTaskService>(provider =>
             new DailyTaskService(url,url2));
 
-            services.AddControllers()
+            services.AddControllers(options => {
+                options.Filters.Add<RequestAuditLogFilter>();
+            })
                 .AddJsonOptions(options =>
                     {
                         //不使用驼峰样式的key
@@ -110,6 +118,9 @@
             services.AddAutoMapper(typeof(AutoMapperProfile)); // automapper依赖
             #endregion
 
+            //注册serilog
+            services.AddConfigSerilog();
+            services.AddScoped<ApiResponseActionFilter>();
         }
         public void ConfigureContainer(ContainerBuilder builder)
         {
@@ -133,7 +144,12 @@
                     c.RoutePrefix = string.Empty;
                 });
             }
+            //全局返回规范
+            //app.UseApiResponse();//弃用 改用Filter [ServiceFilter(typeof(ApiResponseActionFilter))]
+            app.UseExceptionMiddleware();
 
+            //使用Serilog记录请求日志
+            app.UseSerilogRequestLogging();
             //app.UseHttpsRedirection();
 
             app.UseRouting();
@@ -141,7 +157,6 @@
             app.UseAuthentication();
             app.UseAuthorization();
             app.UseCors("MyCors");//跨域
-
 
             app.UseEndpoints(endpoints =>
             {
diff --git a/Wms/Wms/Wms.csproj b/Wms/Wms/Wms.csproj
index 6ea9517..63bb75b 100644
--- a/Wms/Wms/Wms.csproj
+++ b/Wms/Wms/Wms.csproj
@@ -11,18 +11,28 @@
   </PropertyGroup>
 
   <ItemGroup>
+    <Compile Remove="Logs\**" />
     <Compile Remove="ModelVm\**" />
+    <Content Remove="Logs\**" />
     <Content Remove="ModelVm\**" />
+    <EmbeddedResource Remove="Logs\**" />
     <EmbeddedResource Remove="ModelVm\**" />
+    <None Remove="Logs\**" />
     <None Remove="ModelVm\**" />
   </ItemGroup>
 	
   <ItemGroup>
-    <PackageReference Include="Autofac" Version="6.5.0" />
+    <PackageReference Include="Autofac" Version="8.0.0" />
     <PackageReference Include="Autofac.Extensions.DependencyInjection" Version="8.0.0" />
     <PackageReference Include="AutoMapper" Version="12.0.1" />
     <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.0" />
     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.32" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
+    <PackageReference Include="Serilog" Version="4.0.0" />
+    <PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
+    <PackageReference Include="Serilog.Sinks.Async" Version="2.0.0" />
+    <PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
+    <PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
     <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.6" />
   </ItemGroup>
@@ -31,6 +41,10 @@
     <ProjectReference Include="..\WMS.BLL\WMS.BLL.csproj" />
   </ItemGroup>
 	
+  <ItemGroup>
+    <Folder Include="Configuration\" />
+  </ItemGroup>
+	
   <ProjectExtensions><VisualStudio><UserProperties appsettings_1json__JsonSchema="" /></VisualStudio></ProjectExtensions>
 
 

--
Gitblit v1.8.0