From aa3f9191f936422ef2665cb21f783b98c88f05da Mon Sep 17 00:00:00 2001
From: lwh <2679599887@qq.com>
Date: Mon, 17 Jul 2023 02:08:00 +0800
Subject: [PATCH] =?UTF-8?q?feat=20=E6=B7=BB=E5=8A=A0=E5=95=86=E5=93=81?=
=?UTF-8?q?=E8=AF=84=E4=BB=B7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../GoodsComments/GoodsCommentDto.cs | 105 ++++++++++++
.../GoodsComments/GoodsComment.cs | 150 ++++++++++++++++++
.../GoodsComments/GoodsCommentVo.cs | 132 +++++++++++++++
.../GoodsComments/GoodsCommentRepository.cs | 20 +++
.../GoodsComments/GoodsCommentService.cs | 144 +++++++++++++++++
.../GoodsManager/Goodss/GoodsService.cs | 43 +++--
.../GoodsComments/IGoodsCommentService.cs | 45 ++++++
.../Api/Wechat/WeChatLoginController.cs | 4 +
.../GoodsComments/GoodsCommentController.cs | 120 ++++++++++++++
.../wwwroot/excel/商品导入模板模板 (5).xlsx | Bin 0 -> 11629 bytes
10 files changed, 748 insertions(+), 15 deletions(-)
create mode 100644 ARW.Model/Dto/Business/GoodsManager/GoodsComments/GoodsCommentDto.cs
create mode 100644 ARW.Model/Models/Business/GoodsManager/GoodsComments/GoodsComment.cs
create mode 100644 ARW.Model/Vo/Business/GoodsManager/GoodsComments/GoodsCommentVo.cs
create mode 100644 ARW.Repository/Business/GoodsManager/GoodsComments/GoodsCommentRepository.cs
create mode 100644 ARW.Service/Business/BusinessService/GoodsManager/GoodsComments/GoodsCommentService.cs
create mode 100644 ARW.Service/Business/IBusinessService/GoodsManager/GoodsComments/IGoodsCommentService.cs
create mode 100644 ARW.WebApi/Controllers/Business/GoodsManager/GoodsComments/GoodsCommentController.cs
create mode 100644 ARW.WebApi/wwwroot/excel/商品导入模板模板 (5).xlsx
diff --git a/ARW.Model/Dto/Business/GoodsManager/GoodsComments/GoodsCommentDto.cs b/ARW.Model/Dto/Business/GoodsManager/GoodsComments/GoodsCommentDto.cs
new file mode 100644
index 0000000..53ce348
--- /dev/null
+++ b/ARW.Model/Dto/Business/GoodsManager/GoodsComments/GoodsCommentDto.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using ARW.Model.Models.Business.GoodsManager.GoodsComments;
+
+namespace ARW.Model.Dto.Business.GoodsManager.GoodsComments
+{
+ ///
+ /// 商品评价输入对象
+ ///
+ /// @author admin
+ /// @date 2023-07-15
+ ///
+ public class GoodsCommentDto
+ {
+
+ public int GoodsCommentId { get; set; }
+
+ public long GoodsCommentGuid { get; set; }
+
+ [Required(ErrorMessage = "店铺guid不能为空")]
+ public long ShopGuid { get; set; }
+
+ [Required(ErrorMessage = "客户guid不能为空")]
+ public long CustomerGuid { get; set; }
+
+ [Required(ErrorMessage = "订单guid不能为空")]
+ public long OrderGuid { get; set; }
+
+ [Required(ErrorMessage = "商品guid不能为空")]
+ public long GoodsGuid { get; set; }
+
+ [Required(ErrorMessage = "订单商品guid不能为空")]
+ public long OrderGoodsGuid { get; set; }
+
+ [Required(ErrorMessage = "评分分数不能为空")]
+ public float GoodsCommentRating { get; set; }
+
+ [Required(ErrorMessage = "评分类型不能为空")]
+ public int GoodsCommentRatingType { get; set; }
+
+ [Required(ErrorMessage = "评价内容不能为空")]
+ public string GoodsCommentContent { get; set; }
+
+ public string GoodsCommentImages { get; set; }
+
+ [Required(ErrorMessage = "回复状态不能为空")]
+ public int GoodsCommentRecoverStatus { get; set; }
+
+ public string GoodsCommentRecoverContent { get; set; }
+
+ [Required(ErrorMessage = "显示状态不能为空")]
+ public int GoodsCommentStatus { get; set; }
+
+ [Required(ErrorMessage = "排序不能为空")]
+ public int GoodsCommentSort { get; set; }
+
+
+
+
+
+ }
+
+
+ ///
+ /// 商品评价查询对象
+ ///
+ /// @author admin
+ /// @date 2023-07-15
+ ///
+ public class GoodsCommentQueryDto : PagerInfo
+ {
+
+ public string ShopName { get; set; }
+
+ public string GoodsName { get; set; }
+
+ public long? ShopGuid { get; set; }
+ public int? GoodsCommentRatingType { get; set; }
+
+ public int? GoodsCommentStatus { get; set; }
+
+ public int? GoodsCommentRecoverStatus { get; set; }
+
+ public string ids { get; set; }
+ }
+
+
+ ///
+ ///
+ /// @author admin
+ /// @date 2023-07-17
+ /// 回复对象
+ ///
+ public class GoodsCommentRecoverDto
+ {
+ [Required(ErrorMessage = "id不能为空")]
+ public int GoodsCommentId { get; set; }
+
+ [Required(ErrorMessage = "回复内容不能为空")]
+ public string GoodsCommentRecoverContent { get; set; }
+ }
+
+
+}
diff --git a/ARW.Model/Models/Business/GoodsManager/GoodsComments/GoodsComment.cs b/ARW.Model/Models/Business/GoodsManager/GoodsComments/GoodsComment.cs
new file mode 100644
index 0000000..7d05c7f
--- /dev/null
+++ b/ARW.Model/Models/Business/GoodsManager/GoodsComments/GoodsComment.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections.Generic;
+using SqlSugar;
+using OfficeOpenXml.Attributes;
+using Newtonsoft.Json;
+
+namespace ARW.Model.Models.Business.GoodsManager.GoodsComments
+{
+ ///
+ /// 商品评价,数据实体对象
+ ///
+ /// @author admin
+ /// @date 2023-07-15
+ ///
+ [SugarTable("tb_goods_comment")]
+ public class GoodsComment : BusinessBase
+ {
+
+ ///
+ /// 描述 :
+ /// 空值 : false
+ ///
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnName = "goods_comment_id")]
+ public int GoodsCommentId { get; set; }
+
+
+ ///
+ /// 描述 :
+ /// 空值 : false
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ [SugarColumn(IsPrimaryKey = true, IsIdentity = false, ColumnName = "goods_comment_guid")]
+ public long GoodsCommentGuid { get; set; }
+
+
+ ///
+ /// 描述 :店铺guid
+ /// 空值 : false
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ [SugarColumn(ColumnName = "shop_guid")]
+ public long ShopGuid { get; set; }
+
+
+ ///
+ /// 描述 :客户guid
+ /// 空值 : false
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ [SugarColumn(ColumnName = "customer_guid")]
+ public long CustomerGuid { get; set; }
+
+
+ ///
+ /// 描述 :订单guid
+ /// 空值 : false
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ [SugarColumn(ColumnName = "order_guid")]
+ public long OrderGuid { get; set; }
+
+
+ ///
+ /// 描述 :商品guid
+ /// 空值 : false
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ [SugarColumn(ColumnName = "goods_guid")]
+ public long GoodsGuid { get; set; }
+
+
+ ///
+ /// 描述 :订单商品guid
+ /// 空值 : false
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ [SugarColumn(ColumnName = "order_goods_guid")]
+ public long OrderGoodsGuid { get; set; }
+
+
+ ///
+ /// 描述 :评分分数
+ /// 空值 : false
+ ///
+ [SugarColumn(ColumnName = "goods_comment_rating")]
+ public float GoodsCommentRating { get; set; }
+
+
+ ///
+ /// 描述 :评分类型
+ /// 空值 : false
+ ///
+ [SugarColumn(ColumnName = "goods_comment_rating_type")]
+ public int GoodsCommentRatingType { get; set; }
+
+
+ ///
+ /// 描述 :评价内容
+ /// 空值 : false
+ ///
+ [SugarColumn(ColumnName = "goods_comment_content")]
+ public string GoodsCommentContent { get; set; }
+
+
+ ///
+ /// 描述 :评价图片
+ /// 空值 : true
+ ///
+ [SugarColumn(ColumnName = "goods_comment_images")]
+ public string GoodsCommentImages { get; set; }
+
+
+ ///
+ /// 描述 :回复状态
+ /// 空值 : false
+ ///
+ [SugarColumn(ColumnName = "goods_comment_recover_status")]
+ public int GoodsCommentRecoverStatus { get; set; }
+
+
+ ///
+ /// 描述 :回复内容
+ /// 空值 : true
+ ///
+ [SugarColumn(ColumnName = "goods_comment_recover_content")]
+ public string GoodsCommentRecoverContent { get; set; }
+
+
+ ///
+ /// 描述 :显示状态
+ /// 空值 : false
+ ///
+ [SugarColumn(ColumnName = "goods_comment_status")]
+ public int GoodsCommentStatus { get; set; }
+
+
+ ///
+ /// 描述 :排序
+ /// 空值 : false
+ ///
+ [SugarColumn(ColumnName = "goods_comment_sort")]
+ public int GoodsCommentSort { get; set; }
+
+
+
+
+
+
+ }
+}
\ No newline at end of file
diff --git a/ARW.Model/Vo/Business/GoodsManager/GoodsComments/GoodsCommentVo.cs b/ARW.Model/Vo/Business/GoodsManager/GoodsComments/GoodsCommentVo.cs
new file mode 100644
index 0000000..8165547
--- /dev/null
+++ b/ARW.Model/Vo/Business/GoodsManager/GoodsComments/GoodsCommentVo.cs
@@ -0,0 +1,132 @@
+using Newtonsoft.Json;
+using OfficeOpenXml.Attributes;
+using SqlSugar;
+using System;
+
+namespace ARW.Model.Vo.Business.GoodsManager.GoodsComments
+{
+ ///
+ /// 商品评价展示对象
+ ///
+ /// @author admin
+ /// @date 2023-07-15
+ ///
+ public class GoodsCommentVo
+ {
+
+
+ ///
+ /// 描述 :
+ ///
+ public int GoodsCommentId { get; set; }
+
+
+ ///
+ /// 描述 :
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ public long GoodsCommentGuid { get; set; }
+
+
+ ///
+ /// 描述 :店铺guid
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ public long ShopGuid { get; set; }
+
+ ///
+ /// 描述 :店铺名称
+ ///
+ public string ShopName { get; set; }
+
+ ///
+ /// 描述 :客户guid
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ public long CustomerGuid { get; set; }
+
+ ///
+ /// 描述 :客户名称
+ ///
+ public string CustomerNickname { get; set; }
+
+
+ ///
+ /// 描述 :订单guid
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ public long OrderGuid { get; set; }
+
+
+ ///
+ /// 描述 :商品guid
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ public long GoodsGuid { get; set; }
+
+ ///
+ /// 描述 :商品名称
+ ///
+ public string GoodsName { get; set; }
+
+ ///
+ /// 描述 :商品图片
+ ///
+ public string GoodsPicture { get; set; }
+
+ ///
+ /// 描述 :订单商品guid
+ ///
+ [JsonConverter(typeof(ValueToStringConverter))]
+ public long OrderGoodsGuid { get; set; }
+
+
+ ///
+ /// 描述 :评分分数
+ ///
+ public float GoodsCommentRating { get; set; }
+
+
+ ///
+ /// 描述 :评分类型
+ ///
+ public int GoodsCommentRatingType { get; set; }
+
+
+ ///
+ /// 描述 :评价内容
+ ///
+ public string GoodsCommentContent { get; set; }
+
+
+ ///
+ /// 描述 :评价图片
+ ///
+ public string GoodsCommentImages { get; set; }
+
+
+ ///
+ /// 描述 :回复状态
+ ///
+ public int GoodsCommentRecoverStatus { get; set; }
+
+
+ ///
+ /// 描述 :回复内容
+ ///
+ public string GoodsCommentRecoverContent { get; set; }
+
+
+ ///
+ /// 描述 :显示状态
+ ///
+ public int GoodsCommentStatus { get; set; }
+
+
+ ///
+ /// 描述 :排序
+ ///
+ public int GoodsCommentSort { get; set; }
+
+ }
+}
diff --git a/ARW.Repository/Business/GoodsManager/GoodsComments/GoodsCommentRepository.cs b/ARW.Repository/Business/GoodsManager/GoodsComments/GoodsCommentRepository.cs
new file mode 100644
index 0000000..a8a8ed4
--- /dev/null
+++ b/ARW.Repository/Business/GoodsManager/GoodsComments/GoodsCommentRepository.cs
@@ -0,0 +1,20 @@
+using System;
+using Infrastructure.Attribute;
+using ARW.Repository.System;
+using ARW.Model.Models.Business.GoodsManager.GoodsComments;
+
+namespace ARW.Repository.Business.GoodsManager.GoodsComments
+{
+ ///
+ /// 商品评价仓储
+ ///
+ /// @author admin
+ /// @date 2023-07-15
+ ///
+ [AppService(ServiceLifetime = LifeTime.Transient)]
+ public class GoodsCommentRepository : BaseRepository
+ {
+ #region 业务逻辑代码
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/ARW.Service/Business/BusinessService/GoodsManager/GoodsComments/GoodsCommentService.cs b/ARW.Service/Business/BusinessService/GoodsManager/GoodsComments/GoodsCommentService.cs
new file mode 100644
index 0000000..3e45cf2
--- /dev/null
+++ b/ARW.Service/Business/BusinessService/GoodsManager/GoodsComments/GoodsCommentService.cs
@@ -0,0 +1,144 @@
+using Infrastructure.Attribute;
+using Microsoft.AspNetCore.Http;
+using SqlSugar;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Infrastructure;
+using ARW.Model;
+using ARW.Repository;
+using ARW.Repository.Business.GoodsManager.GoodsComments;
+using ARW.Service.Business.IBusinessService.GoodsManager.GoodsComments;
+using ARW.Model.Dto.Business.GoodsManager.GoodsComments;
+using ARW.Model.Models.Business.GoodsManager.GoodsComments;
+using ARW.Model.Vo.Business.GoodsManager.GoodsComments;
+using ARW.Model.Models.Business.ShopManager.Shops;
+using ARW.Model.Models.Business.GoodsManager.Goodss;
+using ARW.Model.Models.Business.Custom.Customers;
+
+namespace ARW.Service.Business.BusinessService.GoodsManager.GoodsComments
+{
+ ///
+ /// 商品评价接口实现类
+ ///
+ /// @author admin
+ /// @date 2023-07-15
+ ///
+ [AppService(ServiceType = typeof(IGoodsCommentService), ServiceLifetime = LifeTime.Transient)]
+ public class GoodsCommentServiceImpl : BaseService, IGoodsCommentService
+ {
+ private readonly GoodsCommentRepository _GoodsCommentRepository;
+
+ public GoodsCommentServiceImpl(GoodsCommentRepository GoodsCommentRepository)
+ {
+ this._GoodsCommentRepository = GoodsCommentRepository;
+ }
+
+ #region 业务逻辑代码
+
+
+ ///
+ /// 查询商品评价分页列表
+ ///
+ public async Task> GetGoodsCommentList(GoodsCommentQueryDto parm)
+ {
+ //开始拼装查询条件d
+ var predicate = Expressionable.Create();
+
+ predicate = predicate.AndIF(parm.ShopGuid != null, s => s.ShopGuid == parm.ShopGuid);
+ predicate = predicate.AndIF(parm.GoodsCommentRecoverStatus != null, s => s.GoodsCommentRecoverStatus == parm.GoodsCommentRecoverStatus);
+ predicate = predicate.AndIF(parm.GoodsCommentRatingType != null, s => s.GoodsCommentRatingType == parm.GoodsCommentRatingType);
+ predicate = predicate.AndIF(parm.GoodsCommentStatus != null, s => s.GoodsCommentStatus == parm.GoodsCommentStatus);
+ var query = _GoodsCommentRepository
+ .Queryable()
+ .LeftJoin((s, c) => s.ShopGuid == c.ShopGuid)
+ .LeftJoin((s, c, d) => s.GoodsGuid == d.GoodsGuid)
+ .LeftJoin((s, c, d, f) => s.CustomerGuid == f.CustomerGuid)
+ .WhereIF(!string.IsNullOrEmpty(parm.ShopName), (s, c, d, f) => c.ShopName.Contains(parm.ShopName))
+ .WhereIF(!string.IsNullOrEmpty(parm.GoodsName), (s, c, d, f) => d.GoodsName.Contains(parm.GoodsName))
+ .Where(predicate.ToExpression())
+ .OrderBy(s => s.GoodsCommentSort, OrderByType.Asc)
+ .Select((s, c, d, f) => new GoodsCommentVo
+ {
+ GoodsCommentId = s.GoodsCommentId,
+ GoodsCommentGuid = s.GoodsCommentGuid,
+ ShopGuid = s.ShopGuid,
+ ShopName = c.ShopName,
+ CustomerGuid = s.CustomerGuid,
+ CustomerNickname = f.CustomerNickname,
+ OrderGuid = s.OrderGuid,
+ GoodsGuid = s.GoodsGuid,
+ GoodsName = d.GoodsName,
+ GoodsPicture = d.GoodsPicture,
+ OrderGoodsGuid = s.OrderGoodsGuid,
+ GoodsCommentRating = s.GoodsCommentRating,
+ GoodsCommentRatingType = s.GoodsCommentRatingType,
+ GoodsCommentContent = s.GoodsCommentContent,
+ GoodsCommentImages = s.GoodsCommentImages,
+ GoodsCommentRecoverStatus = s.GoodsCommentRecoverStatus,
+ GoodsCommentRecoverContent = s.GoodsCommentRecoverContent,
+ GoodsCommentStatus = s.GoodsCommentStatus,
+ GoodsCommentSort = s.GoodsCommentSort,
+ });
+
+
+ return await query.ToPageAsync(parm);
+ }
+
+ ///
+ /// 添加或修改商品评价
+ ///
+ public async Task AddOrUpdateGoodsComment(GoodsComment model)
+ {
+ if (model.GoodsCommentRating < 3)
+ {
+ model.GoodsCommentRatingType = 3;
+ }
+ if (model.GoodsCommentRating < 3.5 && model.GoodsCommentRating >= 2.5)
+ {
+ model.GoodsCommentRatingType = 2;
+ }
+ if (model.GoodsCommentRating >= 3.5)
+ {
+ model.GoodsCommentRatingType = 1;
+ }
+
+ if (model.GoodsCommentId != 0)
+ {
+ var response = await _GoodsCommentRepository.UpdateAsync(model);
+ return "修改成功!";
+ }
+ else
+ {
+ model.GoodsCommentRecoverStatus = 1;
+ var response = await _GoodsCommentRepository.InsertReturnSnowflakeIdAsync(model);
+ return "添加成功!";
+ }
+ }
+
+ #region Excel处理
+
+
+ #endregion
+
+
+ ///
+ /// 回复
+ ///
+ public async Task Recover(GoodsCommentRecoverDto parm)
+ {
+ var response = await _GoodsCommentRepository.UpdateAsync(f => new GoodsComment
+ {
+ GoodsCommentRecoverContent = parm.GoodsCommentRecoverContent,
+ GoodsCommentRecoverStatus = 2
+ }, s => s.GoodsCommentId == parm.GoodsCommentId);
+ if (response) return "回复成功";
+ else return "回复失败";
+ }
+
+ #endregion
+
+ }
+}
diff --git a/ARW.Service/Business/BusinessService/GoodsManager/Goodss/GoodsService.cs b/ARW.Service/Business/BusinessService/GoodsManager/Goodss/GoodsService.cs
index 2fed5b7..3d7f92a 100644
--- a/ARW.Service/Business/BusinessService/GoodsManager/Goodss/GoodsService.cs
+++ b/ARW.Service/Business/BusinessService/GoodsManager/Goodss/GoodsService.cs
@@ -289,23 +289,36 @@ namespace ARW.Service.Business.BusinessService.GoodsManager.Goodss
// 商品类目
// 拆分上级类目和当前类目(手机/xxxx系列)
var nameArr = Goods.GoodsCategoryName.Split('/');
- if (nameArr.Length == 0 || nameArr.Length >= 3) throw new CustomException($"商品类目【{Goods.GoodsCategoryName}】格式不正确,参考(手机/xxxx系列)");
+ if (nameArr.Length == 0 || nameArr.Length >= 3) throw new CustomException($"商品类目【{Goods.GoodsCategoryName}】格式不正确,参考(手机/xxxx系列 或者 手机)");
- // 找出上级类目
- var parentGoodsCategory = await _ShopGoodsCategoryRepository.GetFirstAsync(
- s => s.ShopGoodsCategoryName == nameArr.First() &&
- s.ShopGuid == Goods.ShopGuid
- );
- if (parentGoodsCategory == null) throw new CustomException($"上级商品类目【{nameArr.First()}】不存在");
+ if (nameArr.Length != 1)
+ {
+ // 找出上级类目
+ var parentGoodsCategory = await _ShopGoodsCategoryRepository.GetFirstAsync(
+ s => s.ShopGoodsCategoryName == nameArr.First() &&
+ s.ShopGuid == Goods.ShopGuid
+ );
+ if (parentGoodsCategory == null) throw new CustomException($"上级商品类目【{nameArr.First()}】不存在");
- // 找出当前类目
- var currentGoodsCategory = await _ShopGoodsCategoryRepository.GetFirstAsync(
- s => s.ShopGoodsCategoryName == nameArr.Last() &&
- s.ShopGuid == Goods.ShopGuid &&
- s.ShopGoodsCategoryParentGuid == parentGoodsCategory.ShopGoodsCategoryGuid
- );
- if (currentGoodsCategory == null) throw new CustomException($"当前商品类目【{nameArr.First()}】不存在");
- Goods.ShopGoodsCategoryGuid = currentGoodsCategory.ShopGoodsCategoryGuid;
+ // 找出当前类目
+ var currentGoodsCategory = await _ShopGoodsCategoryRepository.GetFirstAsync(
+ s => s.ShopGoodsCategoryName == nameArr.Last() &&
+ s.ShopGuid == Goods.ShopGuid &&
+ s.ShopGoodsCategoryParentGuid == parentGoodsCategory.ShopGoodsCategoryGuid
+ );
+ if (currentGoodsCategory == null) throw new CustomException($"当前商品类目【{nameArr.First()}】不存在");
+ Goods.ShopGoodsCategoryGuid = currentGoodsCategory.ShopGoodsCategoryGuid;
+ }
+ else
+ {
+ // 找出当前类目
+ var currentGoodsCategory = await _ShopGoodsCategoryRepository.GetFirstAsync(
+ s => s.ShopGoodsCategoryName == Goods.GoodsCategoryName &&
+ s.ShopGuid == Goods.ShopGuid
+ );
+ if (currentGoodsCategory == null) throw new CustomException($"当前商品类目【{Goods.GoodsCategoryName}】不存在");
+ Goods.ShopGoodsCategoryGuid = currentGoodsCategory.ShopGoodsCategoryGuid;
+ }
// 配送模板
diff --git a/ARW.Service/Business/IBusinessService/GoodsManager/GoodsComments/IGoodsCommentService.cs b/ARW.Service/Business/IBusinessService/GoodsManager/GoodsComments/IGoodsCommentService.cs
new file mode 100644
index 0000000..0f80884
--- /dev/null
+++ b/ARW.Service/Business/IBusinessService/GoodsManager/GoodsComments/IGoodsCommentService.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using ARW.Model;
+using ARW.Model.Dto.Business.GoodsManager.GoodsComments;
+using ARW.Model.Models.Business.GoodsManager.GoodsComments;
+using ARW.Model.Vo.Business.GoodsManager.GoodsComments;
+
+namespace ARW.Service.Business.IBusinessService.GoodsManager.GoodsComments
+{
+ ///
+ /// 商品评价接口类
+ ///
+ /// @author admin
+ /// @date 2023-07-15
+ ///
+ public interface IGoodsCommentService : IBaseService
+ {
+ ///
+ /// 获取商品评价分页列表
+ ///
+ ///
+ ///
+ Task> GetGoodsCommentList(GoodsCommentQueryDto parm);
+
+
+ ///
+ /// 添加或修改商品评价
+ ///
+ ///
+ ///
+ Task AddOrUpdateGoodsComment(GoodsComment parm);
+
+
+
+
+ ///
+ /// 回复
+ ///
+ Task Recover(GoodsCommentRecoverDto parm);
+
+ }
+}
diff --git a/ARW.WebApi/Controllers/Api/Wechat/WeChatLoginController.cs b/ARW.WebApi/Controllers/Api/Wechat/WeChatLoginController.cs
index 5485195..fe14bed 100644
--- a/ARW.WebApi/Controllers/Api/Wechat/WeChatLoginController.cs
+++ b/ARW.WebApi/Controllers/Api/Wechat/WeChatLoginController.cs
@@ -71,6 +71,10 @@ namespace ARW.WebApi.Controllers.Api.Wechat
user = await _customerService.GetFirstAsync(s => s.CustomerGuid == response);
}
+ else
+ {
+ user.CustomerLastLoginTime = DateTime.Now;
+ }
LoginUser loginUser = new LoginUser
{
diff --git a/ARW.WebApi/Controllers/Business/GoodsManager/GoodsComments/GoodsCommentController.cs b/ARW.WebApi/Controllers/Business/GoodsManager/GoodsComments/GoodsCommentController.cs
new file mode 100644
index 0000000..2e229ef
--- /dev/null
+++ b/ARW.WebApi/Controllers/Business/GoodsManager/GoodsComments/GoodsCommentController.cs
@@ -0,0 +1,120 @@
+using Infrastructure;
+using Infrastructure.Attribute;
+using Infrastructure.Enums;
+using Infrastructure.Model;
+using Mapster;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using ARW.Admin.WebApi.Extensions;
+using ARW.Admin.WebApi.Filters;
+using ARW.Common;
+using ARW.Model.Dto.Business.GoodsManager.GoodsComments;
+using ARW.Service.Business.IBusinessService.GoodsManager.GoodsComments;
+using ARW.Admin.WebApi.Controllers;
+using ARW.Model.Models.Business.GoodsManager.GoodsComments;
+using ARW.Model.Vo.Business.GoodsManager.GoodsComments;
+using Microsoft.AspNetCore.Authorization;
+using ARW.Admin.WebApi.Framework;
+using ARW.Service.Business.IBusinessService.ShopManager.Shops;
+
+
+namespace ARW.WebApi.Controllers.Business.GoodsManager.GoodsComments
+{
+ ///
+ /// 商品评价控制器
+ ///
+ /// @author admin
+ /// @date 2023-07-15
+ ///
+ [Verify]
+ [Route("business/[controller]")]
+ public class GoodsCommentController : BaseController
+ {
+ private readonly IGoodsCommentService _GoodsCommentService;
+ private readonly IShopService _ShopService;
+
+ ///
+ /// 依赖注入
+ ///
+ /// 商品评价服务
+ public GoodsCommentController(IGoodsCommentService GoodsCommentService, IShopService shopService)
+ {
+ _GoodsCommentService = GoodsCommentService;
+ _ShopService = shopService;
+ }
+
+
+ ///
+ /// 获取商品评价列表
+ ///
+ /// 查询参数
+ ///
+ [HttpGet("getGoodsCommentList")]
+ [ActionPermissionFilter(Permission = "business:goodscomment:list")]
+ public async Task GetGoodsCommentList([FromQuery] GoodsCommentQueryDto parm)
+ {
+ var user = JwtUtil.GetLoginUser(App.HttpContext);
+ if (user.UserId != 1)
+ {
+ var shop = await _ShopService.GetFirstAsync(s => s.ShopUserId == user.UserId);
+ if (shop == null) throw new Exception("当前用户没有店铺");
+ parm.ShopGuid = shop.ShopGuid;
+ }
+
+ var res = await _GoodsCommentService.GetGoodsCommentList(parm);
+ return SUCCESS(res);
+ }
+
+ ///
+ /// 添加或修改商品评价
+ ///
+ ///
+ ///
+ [HttpPost("addOrUpdateGoodsComment")]
+ [ActionPermissionFilter(Permission = "business:goodscomment:addOrUpdate")]
+ [Log(Title = "添加或修改商品评价", BusinessType = BusinessType.ADDORUPDATE)]
+ public async Task AddOrUpdateGoodsComment([FromBody] GoodsCommentDto parm)
+ {
+ if (parm == null) { throw new CustomException("请求参数错误"); }
+
+ var modal = new GoodsComment();
+ if (parm.GoodsCommentId != 0) modal = parm.Adapt().ToUpdate(HttpContext);
+ else modal = parm.Adapt().ToCreate(HttpContext);
+
+ var res = await _GoodsCommentService.AddOrUpdateGoodsComment(modal);
+ return SUCCESS(res);
+ }
+
+ ///
+ /// 删除商品评价
+ ///
+ ///
+ [HttpDelete("{ids}")]
+ [ActionPermissionFilter(Permission = "business:goodscomment:delete")]
+ [Log(Title = "商品评价删除", BusinessType = BusinessType.DELETE)]
+ public IActionResult Delete(string ids)
+ {
+ long[] idsArr = Tools.SpitLongArrary(ids);
+ if (idsArr.Length <= 0) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); }
+ var response = _GoodsCommentService.Delete(idsArr);
+ return SUCCESS("删除成功!");
+ }
+
+
+
+ ///
+ /// 回复商品评价
+ ///
+ ///
+ [HttpPut("recover")]
+ [ActionPermissionFilter(Permission = "business:goodscomment:recover")]
+ public async Task RecoverGoodsComment([FromBody] GoodsCommentRecoverDto param)
+ {
+ var res = await _GoodsCommentService.Recover(param);
+ return SUCCESS(res);
+ }
+
+
+
+ }
+}
diff --git a/ARW.WebApi/wwwroot/excel/商品导入模板模板 (5).xlsx b/ARW.WebApi/wwwroot/excel/商品导入模板模板 (5).xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..6eec5aecf90b0a44530391d69805b579569bf55c
GIT binary patch
literal 11629
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