Browse Source

权限分配、兽医登录

master
maotiantian 2 months ago
parent
commit
c5b7decd65
  1. 1
      chenhai-admin/src/main/java/com/chenhai/web/controller/auth/MultiAuthController.java
  2. 15
      chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/CarouselAdsController.java
  3. 18
      chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java
  4. 69
      chenhai-framework/src/main/java/com/chenhai/framework/web/service/SysLoginService.java
  5. 15
      chenhai-system/src/main/java/com/chenhai/muhu/domain/CarouselAds.java
  6. 11
      chenhai-system/src/main/java/com/chenhai/muhu/domain/DisasterWarning.java
  7. 13
      chenhai-system/src/main/java/com/chenhai/muhu/domain/MuhuConsultationForms.java
  8. 9
      chenhai-system/src/main/java/com/chenhai/muhu/mapper/CarouselAdsMapper.java
  9. 8
      chenhai-system/src/main/java/com/chenhai/muhu/service/ICarouselAdsService.java
  10. 14
      chenhai-system/src/main/java/com/chenhai/muhu/service/impl/CarouselAdsServiceImpl.java
  11. 22
      chenhai-system/src/main/java/com/chenhai/system/domain/SysMedicineRecommendation.java
  12. 11
      chenhai-system/src/main/java/com/chenhai/system/mapper/SysUserMapper.java
  13. 10
      chenhai-system/src/main/java/com/chenhai/system/service/ISysUserService.java
  14. 16
      chenhai-system/src/main/java/com/chenhai/system/service/impl/SysUserServiceImpl.java
  15. 11
      chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java
  16. 2
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java
  17. 24
      chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java
  18. 14
      chenhai-system/src/main/resources/mapper/muhu/CarouselAdsMapper.xml
  19. 13
      chenhai-system/src/main/resources/mapper/muhu/DisasterWarningMapper.xml
  20. 39
      chenhai-system/src/main/resources/mapper/muhu/MuhuConsultationFormsMapper.xml
  21. 30
      chenhai-system/src/main/resources/mapper/system/SysUserMapper.xml
  22. 22
      chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml
  23. 38
      chenhai-ui/src/api/vet/merchant.js
  24. 39
      chenhai-ui/src/api/vet/product.js
  25. 42
      chenhai-ui/src/views/vet/knowledge/index.vue
  26. 576
      chenhai-ui/src/views/vet/merchant/index.vue
  27. 826
      chenhai-ui/src/views/vet/product/index.vue

1
chenhai-admin/src/main/java/com/chenhai/web/controller/auth/MultiAuthController.java

@ -26,6 +26,7 @@ public class MultiAuthController {
/**
* 微信小程序登录 - 保持原逻辑
*/
@PostMapping("/wechat/login")
public AjaxResult wechatLogin(@Valid @RequestBody WechatLoginBody loginBody) {
Map<String, Object> result = loginService.wechatLogin(

15
chenhai-admin/src/main/java/com/chenhai/web/controller/muhu/CarouselAdsController.java

@ -32,7 +32,7 @@ public class CarouselAdsController extends BaseController
* 查询轮播广告列表
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:list')")
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger') or @ss.hasRole('vet')")
@GetMapping("/list")
public TableDataInfo list(CarouselAds carouselAds)
{
@ -45,7 +45,7 @@ public class CarouselAdsController extends BaseController
* 导出轮播广告列表
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:export')")
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "轮播广告", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, CarouselAds carouselAds)
@ -59,10 +59,13 @@ public class CarouselAdsController extends BaseController
* 获取轮播广告详细信息
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:query')")
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger') or @ss.hasRole('vet')")
@GetMapping(value = "/{carouselId}")
public AjaxResult getInfo(@PathVariable("carouselId") Long carouselId)
{
// 先增加浏览量
carouselAdsService.incrementViewCount(carouselId);
// 再查询详情
return success(carouselAdsService.selectCarouselAdsByCarouselId(carouselId));
}
@ -70,7 +73,7 @@ public class CarouselAdsController extends BaseController
* 新增轮播广告
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:add')")
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasRole('muhu') or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "轮播广告", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody CarouselAds carouselAds)
@ -82,7 +85,7 @@ public class CarouselAdsController extends BaseController
* 修改轮播广告
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:edit')")
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "轮播广告", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody CarouselAds carouselAds)
@ -94,7 +97,7 @@ public class CarouselAdsController extends BaseController
* 删除轮播广告
*/
// @PreAuthorize("@ss.hasPermi('muhu:ads:remove')")
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasRole('muhu')or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "轮播广告", businessType = BusinessType.DELETE)
@DeleteMapping("/{carouselIds}")
public AjaxResult remove(@PathVariable Long[] carouselIds)

18
chenhai-admin/src/main/java/com/chenhai/web/controller/vet/VetKnowledgeController.java

@ -56,7 +56,7 @@ public class VetKnowledgeController extends BaseController
* 导出兽医文章列表
*/
@PreAuthorize("@ss.hasPermi('vet:knowledge:export') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:export') or @ss.hasRole('muhu')or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "兽医文章", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, VetKnowledge vetKnowledge)
@ -69,7 +69,7 @@ public class VetKnowledgeController extends BaseController
/**
* 获取兽医文章详细信息
*/
@PreAuthorize("@ss.hasPermi('vet:knowledge:query') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:query') or @ss.hasRole('muhu')or @ss.hasRole('manger') or @ss.hasRole('vet')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
@ -80,20 +80,20 @@ public class VetKnowledgeController extends BaseController
* 新增兽医文章
*/
@SensitiveCheck
@PreAuthorize("@ss.hasPermi('vet:knowledge:add') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:add') or @ss.hasRole('muhu')or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "兽医文章", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody VetKnowledge vetKnowledge)
{
vetKnowledge.setArticleStatus("0"); // 草稿
vetKnowledge.setAuditStatus("0"); // 待审核
vetKnowledge.setAuditStatus("1"); // 待审核
return toAjax(vetKnowledgeService.insertVetKnowledge(vetKnowledge));
}
/**
* 修改兽医文章
*/
@PreAuthorize("@ss.hasPermi('vet:knowledge:edit') or @ss.hasRole('muhu')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:edit') or @ss.hasRole('muhu') or @ss.hasRole('vet')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody VetKnowledge vetKnowledge)
@ -104,7 +104,7 @@ public class VetKnowledgeController extends BaseController
/**
* 删除兽医文章
*/
@PreAuthorize("@ss.hasPermi('vet:knowledge:remove')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:remove') or @ss.hasRole('vet')")
@Log(title = "兽医文章", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
@ -141,7 +141,7 @@ public class VetKnowledgeController extends BaseController
/**
* 发布文章
*/
@PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping("/publish/{id}")
public AjaxResult publish(@PathVariable Long id) {
@ -151,7 +151,7 @@ public class VetKnowledgeController extends BaseController
/**
* 上架文章
*/
@PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping("/online/{id}")
public AjaxResult online(@PathVariable Long id) {
@ -161,7 +161,7 @@ public class VetKnowledgeController extends BaseController
/**
* 下架文章
*/
@PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger')")
@PreAuthorize("@ss.hasPermi('vet:knowledge:publish') or @ss.hasRole('muhu')or @ss.hasRole('manger') or @ss.hasRole('vet')")
@Log(title = "兽医文章", businessType = BusinessType.UPDATE)
@PutMapping("/offline/{id}")
public AjaxResult offline(@PathVariable Long id, @RequestParam(required = false) String auditComment) {

69
chenhai-framework/src/main/java/com/chenhai/framework/web/service/SysLoginService.java

@ -1,5 +1,6 @@
package com.chenhai.framework.web.service;
import com.chenhai.common.core.domain.entity.SysUserAuth;
import com.chenhai.common.utils.*;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
@ -278,25 +279,17 @@ public class SysLoginService
throw new ServiceException("获取手机号失败");
}
// 4. 查询手机号是否已注册
SysUser existingUser = userService.selectUserByPhone(phone);
// 4. 转换用户类型代码
String targetUserTypeCode = "herdsman".equals(userType) ? "02" : "01";
// 5. 用户不存在创建新用户
if (existingUser == null) {
String userTypeCode = "herdsman".equals(userType) ? "02" : "01";
existingUser = createUserForWechat(phone, userTypeCode, nickName, avatarUrl, clientType);
} else {
// 6. 用户已存在检查用户类型是否匹配
String existingUserType = existingUser.getUserType();
String expectedUserType = "herdsman".equals(userType) ? "02" : "01";
// 5. 查询该手机号指定类型的用户
SysUser existingUser = userService.selectUserByPhoneAndType(phone, targetUserTypeCode);
if (!existingUserType.equals(expectedUserType)) {
String existingTypeName = "01".equals(existingUserType) ? "兽医" : "牧户";
String expectedTypeName = "01".equals(expectedUserType) ? "兽医" : "牧户";
throw new ServiceException("该手机号已注册为" + existingTypeName + ",请使用" + expectedTypeName + "小程序");
}
if (existingUser != null) {
// 6. 该类型用户已存在更新信息
log.info("该手机号已注册为{}用户,更新信息: phone={}, userId={}",
"02".equals(targetUserTypeCode) ? "牧户" : "兽医", phone, existingUser.getUserId());
// 7. 用户类型匹配更新用户信息
if (nickName != null) {
existingUser.setNickName(nickName);
}
@ -304,12 +297,31 @@ public class SysLoginService
existingUser.setAvatar(avatarUrl);
}
userService.updateUser(existingUser);
} else {
// 7. 该类型用户不存在创建新用户
log.info("手机号{}未注册为{}用户,创建新用户",
phone, "02".equals(targetUserTypeCode) ? "牧户" : "兽医");
existingUser = createUserForWechat(phone, targetUserTypeCode, nickName, avatarUrl, clientType);
}
// 8. 绑定微信openid
// 8. 检查微信是否已绑定 - 使用 findUserByAuth 替代
SysUser boundUser = userAuthService.findUserByAuth(authType, openid);
if (boundUser != null) {
if (!boundUser.getUserId().equals(existingUser.getUserId())) {
// 微信已绑定其他账号
throw new ServiceException("该微信已绑定其他账号");
}
// 已绑定当前用户无需重复绑定
log.info("微信已绑定当前用户: userId={}, openid={}", existingUser.getUserId(), openid);
} else {
// 9. 绑定微信openid
userAuthService.bindAuth(existingUser.getUserId(), authType, openid, sessionKey);
log.info("微信绑定成功: userId={}, openid={}", existingUser.getUserId(), openid);
}
// 9. 创建登录用户
// 10. 创建登录用户
LoginUser loginUser = new LoginUser(
existingUser.getUserId(),
existingUser.getDeptId(),
@ -320,23 +332,23 @@ public class SysLoginService
recordLoginInfo(loginUser.getUserId());
// 10. 生成token
// 11. 生成token
String token = tokenService.createToken(loginUser);
// 11. 清理Redis临时数据
// 12. 清理Redis临时数据
redisCache.deleteObject("wechat:session:" + tempCode);
Map<String, Object> result = new HashMap<>();
result.put("token", token);
result.put("message", "绑定成功");
result.put("userType", "02".equals(targetUserTypeCode) ? "herdsman" : "vet");
return result;
} catch (Exception e) {
// 保持原异常处理方式返回 AjaxResult.error 的字符串
log.error("微信绑定失败: {}", e.getMessage(), e);
throw new ServiceException("绑定失败: " + e.getMessage());
}
}
/**
* 手机号+密码登录 - 多端登录新增
*/
@ -434,10 +446,13 @@ public class SysLoginService
// 2. 验证密码强度
validatePassword(password);
// 3. 检查手机号是否已注册
checkPhoneRegistered(phone);
// 3. 检查该手机号是否已注册为兽医
SysUser existingVet = userService.selectUserByPhoneAndType(phone, "01"); // 兽医类型
if (existingVet != null) {
throw new ServiceException("该手机号已注册为兽医账号");
}
// 4. 创建牧户用户
// 4. 创建兽医用户允许手机号已注册为牧户
SysUser user = createVetUser(phone, password, clientType);
// 5. 创建登录用户
@ -504,6 +519,10 @@ public class SysLoginService
if (authUser != null) {
throw new ServiceException("该手机号已注册");
}
SysUser existingVet = userService.selectUserByPhoneAndType(phone, "01");
if (existingVet != null) {
throw new ServiceException("该手机号已注册为兽医账号");
}
}
/**

15
chenhai-system/src/main/java/com/chenhai/muhu/domain/CarouselAds.java

@ -149,6 +149,10 @@ public class CarouselAds extends BaseEntity
@Excel(name = "更新时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date updatedAt;
/** 浏览量 */
@Excel(name = "浏览量")
private Long viewCount;
public void setAdsType(String adsType)
{
this.adsType = adsType;
@ -469,6 +473,16 @@ public class CarouselAds extends BaseEntity
return updatedAt;
}
public void setViewCount(Long viewCount)
{
this.viewCount = viewCount;
}
public Long getViewCount()
{
return viewCount;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@ -504,6 +518,7 @@ public class CarouselAds extends BaseEntity
.append("createdAt", getCreatedAt())
.append("updatedAt", getUpdatedAt())
.append("adsType",getAdsType())
.append("viewCount", getViewCount())
.toString();
}
}

11
chenhai-system/src/main/java/com/chenhai/muhu/domain/DisasterWarning.java

@ -62,6 +62,9 @@ public class DisasterWarning extends BaseEntity
@Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd")
private Date createdTime;
/** 关键词搜索(非数据库字段) */
private String keyword;
public void setId(Long id)
{
this.id = id;
@ -172,6 +175,14 @@ public class DisasterWarning extends BaseEntity
return createdTime;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

13
chenhai-system/src/main/java/com/chenhai/muhu/domain/MuhuConsultationForms.java

@ -83,8 +83,8 @@ public class MuhuConsultationForms extends BaseEntity
@Excel(name = "头像")
private String avatar;
/** 今日回复总数(非数据库字段,用于统计) */
private Long todayReplyCount;
/** 今日回复总数(所有问诊单的今日回复总和) */
private Long totalTodayReplyCount;
public void setFormId(Long formId)
{
@ -246,12 +246,12 @@ public class MuhuConsultationForms extends BaseEntity
return avatar;
}
public Long getTodayReplyCount() {
return todayReplyCount;
public Long getTotalTodayReplyCount() {
return totalTodayReplyCount;
}
public void setTodayReplyCount(Long todayReplyCount) {
this.todayReplyCount = todayReplyCount;
public void setTotalTodayReplyCount(Long totalTodayReplyCount) {
this.totalTodayReplyCount = totalTodayReplyCount;
}
@ -274,7 +274,6 @@ public class MuhuConsultationForms extends BaseEntity
.append("replyCount", getReplyCount())
.append("createdTime", getCreatedTime())
.append("avatar", getAvatar())
.append("todayReplyCount", getTodayReplyCount())
.toString();
}
}

9
chenhai-system/src/main/java/com/chenhai/muhu/mapper/CarouselAdsMapper.java

@ -1,6 +1,7 @@
package com.chenhai.muhu.mapper;
import com.chenhai.muhu.domain.CarouselAds;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -59,4 +60,12 @@ public interface CarouselAdsMapper
* @return 结果
*/
public int deleteCarouselAdsByCarouselIds(Long[] carouselIds);
/**
* 增加浏览量
*
* @param carouselId 轮播广告主键
* @return 结果
*/
public int incrementViewCount(@Param("carouselId") Long carouselId);
}

8
chenhai-system/src/main/java/com/chenhai/muhu/service/ICarouselAdsService.java

@ -59,4 +59,12 @@ public interface ICarouselAdsService
* @return 结果
*/
public int deleteCarouselAdsByCarouselId(Long carouselId);
/**
* 增加浏览量
*
* @param carouselId 轮播广告主键
* @return 结果
*/
public int incrementViewCount(Long carouselId);
}

14
chenhai-system/src/main/java/com/chenhai/muhu/service/impl/CarouselAdsServiceImpl.java

@ -6,6 +6,7 @@ import com.chenhai.muhu.mapper.CarouselAdsMapper;
import com.chenhai.muhu.service.ICarouselAdsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@ -92,4 +93,17 @@ public class CarouselAdsServiceImpl implements ICarouselAdsService
{
return carouselAdsMapper.deleteCarouselAdsByCarouselId(carouselId);
}
/**
* 增加浏览量
*
* @param carouselId 轮播广告主键
* @return 结果
*/
@Override
@Transactional
public int incrementViewCount(Long carouselId)
{
return carouselAdsMapper.incrementViewCount(carouselId);
}
}

22
chenhai-system/src/main/java/com/chenhai/system/domain/SysMedicineRecommendation.java

@ -146,6 +146,12 @@ public class SysMedicineRecommendation extends BaseEntity
@Excel(name = "纬度")
private BigDecimal latitude;
/** 排序字段 */
private String orderByColumn;
/** 排序方向 */
private String orderDirection;
public void setId(Long id)
{
this.id = id;
@ -494,6 +500,22 @@ public class SysMedicineRecommendation extends BaseEntity
return searchKeywords;
}
public String getOrderByColumn() {
return orderByColumn;
}
public void setOrderByColumn(String orderByColumn) {
this.orderByColumn = orderByColumn;
}
public String getOrderDirection() {
return orderDirection;
}
public void setOrderDirection(String orderDirection) {
this.orderDirection = orderDirection;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)

11
chenhai-system/src/main/java/com/chenhai/system/mapper/SysUserMapper.java

@ -156,4 +156,15 @@ public interface SysUserMapper
public SysUser checkEmailUnique(String email);
public int updateUserAreaCode(@Param("userId") Long userId, @Param("areaCode") String areaCode);
/**
* 根据手机号和用户类型查询用户
*/
SysUser selectUserByPhoneAndType(@Param("phonenumber") String phone,
@Param("userType") String userType);
/**
* 查询手机号已注册的类型列表
*/
List<String> selectUserTypesByPhone(@Param("phonenumber") String phone);
}

10
chenhai-system/src/main/java/com/chenhai/system/service/ISysUserService.java

@ -232,4 +232,14 @@ public interface ISysUserService
public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
public int updateUserAreaCode(Long userId, String areaCode);
/**
* 根据手机号和用户类型查询用户
*/
SysUser selectUserByPhoneAndType(String phone, String userType);
/**
* 查询手机号已注册的所有类型
*/
List<String> selectUserTypesByPhone(String phone);
}

16
chenhai-system/src/main/java/com/chenhai/system/service/impl/SysUserServiceImpl.java

@ -579,4 +579,20 @@ public class SysUserServiceImpl implements ISysUserService
public int updateUserAreaCode(Long userId, String areaCode) {
return userMapper.updateUserAreaCode(userId, areaCode);
}
@Override
public SysUser selectUserByPhoneAndType(String phone, String userType) {
if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(userType)) {
return null;
}
return userMapper.selectUserByPhoneAndType(phone, userType);
}
@Override
public List<String> selectUserTypesByPhone(String phone) {
if (StringUtils.isEmpty(phone)) {
return new ArrayList<>();
}
return userMapper.selectUserTypesByPhone(phone);
}
}

11
chenhai-system/src/main/java/com/chenhai/vet/domain/MerchantInfo.java

@ -85,7 +85,9 @@ public class MerchantInfo extends BaseEntity
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date offlineTime;
/** 产品数量 */
@Excel(name = "产品数量")
private Long productCount;
public void setShopId(Long shopId)
{
@ -238,7 +240,13 @@ public class MerchantInfo extends BaseEntity
this.businessLicenseImage = businessLicenseImage;
}
public Long getProductCount() {
return productCount;
}
public void setProductCount(Long productCount) {
this.productCount = productCount;
}
@Override
public String toString() {
@ -260,6 +268,7 @@ public class MerchantInfo extends BaseEntity
.append("offlineTime", getOfflineTime())
.append("shopLogo", getShopLogo())
.append("businessLicenseImage", getBusinessLicenseImage())
.append("productCount", getProductCount())
.toString();
}
}

2
chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetKnowledgeServiceImpl.java

@ -55,7 +55,7 @@ public class VetKnowledgeServiceImpl implements IVetKnowledgeService
vetKnowledge.setArticleStatus("0"); // 草稿
}
if (vetKnowledge.getAuditStatus() == null) {
vetKnowledge.setAuditStatus("0"); // 待审核
vetKnowledge.setAuditStatus("1"); // 待审核
}
return vetKnowledgeMapper.insertVetKnowledge(vetKnowledge);
}

24
chenhai-system/src/main/java/com/chenhai/vet/service/impl/VetProductServiceImpl.java

@ -378,8 +378,6 @@ public class VetProductServiceImpl implements IVetProductService
@Transactional
public int insertVetProduct(VetProduct vetProduct)
{
// 如果已经传入了shopId就不需要查询
if (vetProduct.getShopId() == null) {
// 设置默认值
vetProduct.setStatus("0");
vetProduct.setAuditStatus("0");
@ -387,18 +385,33 @@ public class VetProductServiceImpl implements IVetProductService
vetProduct.setCreatedAt(new Date());
vetProduct.setUpdatedAt(new Date());
// 设置当前用户ID并查询店铺ID
// 设置当前用户ID
try {
Long userId = SecurityUtils.getUserId();
vetProduct.setUserId(userId);
} catch (Exception e) {
throw new RuntimeException("获取用户信息失败");
}
// 关键修改如果前端已经传入了shopId直接使用不再查询
if (vetProduct.getShopId() != null) {
// 验证该店铺是否属于当前用户可选
// 这里可以添加验证逻辑确保用户只能给自己店铺添加产品
} else {
// 如果前端没有传入shopId则查询用户的默认店铺
try {
// 查询用户的店铺
MerchantInfo merchantQuery = new MerchantInfo();
merchantQuery.setUserId(userId); // 这里直接调用setter方法
merchantQuery.setUserId(vetProduct.getUserId());
List<MerchantInfo> merchantList = merchantInfoMapper.selectMerchantInfoList(merchantQuery);
if (merchantList != null && !merchantList.isEmpty()) {
vetProduct.setShopId(merchantList.get(0).getShopId());
// 如果有多个店铺默认使用第一个
Long shopId = merchantList.get(0).getShopId();
vetProduct.setShopId(shopId);
} else {
throw new RuntimeException("用户未关联任何店铺,无法创建产品");
}
@ -410,7 +423,6 @@ public class VetProductServiceImpl implements IVetProductService
return vetProductMapper.insertVetProduct(vetProduct);
}
/**
* 管理员查询所有兽医产品信息列表用于审核
*/

14
chenhai-system/src/main/resources/mapper/muhu/CarouselAdsMapper.xml

@ -37,10 +37,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="createdAt" column="created_at" />
<result property="updatedAt" column="updated_at" />
<result property="adsType" column="ads_type"/>
<result property="viewCount" column="view_count" />
</resultMap>
<sql id="selectCarouselAdsVo">
select carousel_id, title, subtitle, image_url, alt_text, image_size, bg_color, text_color, button_text, button_class, link_type, link_url, link_params, sort_order, display_type, is_active, start_time, end_time, is_always_valid, caption_position, caption_style, button_style, display_count, click_count, status, review_notes, reviewed_by, reviewed_at, created_by, created_at, updated_at, ads_type from muhu_carousel_ads
select carousel_id, title, subtitle, image_url, alt_text, image_size, bg_color, text_color, button_text, button_class, link_type, link_url, link_params, sort_order, display_type, is_active, start_time, end_time, is_always_valid, caption_position, caption_style, button_style, display_count, click_count, status, review_notes, reviewed_by, reviewed_at, created_by, created_at, updated_at, ads_type, view_count from muhu_carousel_ads
</sql>
<select id="selectCarouselAdsList" parameterType="CarouselAds" resultMap="CarouselAdsResult">
@ -77,6 +78,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null "> and created_at = #{createdAt}</if>
<if test="updatedAt != null "> and updated_at = #{updatedAt}</if>
<if test="adsType != null"> and ads_type = #{adsType}</if>
<if test="viewCount != null "> and view_count = #{viewCount}</if>
</where>
</select>
@ -119,6 +121,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null">created_at,</if>
<if test="updatedAt != null">updated_at,</if>
<if test="adsType != null">ads_type,</if>
<if test="viewCount != null">view_count,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="title != null and title != ''">#{title},</if>
@ -152,6 +155,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null">#{createdAt},</if>
<if test="updatedAt != null">#{updatedAt},</if>
<if test="adsType != null">#{adsType},</if>
<if test="viewCount != null">#{viewCount},</if>
</trim>
</insert>
@ -189,6 +193,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="createdAt != null">created_at = #{createdAt},</if>
<if test="updatedAt != null">updated_at = #{updatedAt},</if>
<if test="adsType != null">ads_type = #{adsType}</if>
<if test="viewCount != null">view_count = #{viewCount},</if>
</trim>
where carousel_id = #{carouselId}
</update>
@ -203,4 +208,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{carouselId}
</foreach>
</delete>
<!-- 增加浏览量 -->
<update id="incrementViewCount">
update muhu_carousel_ads
set view_count = ifnull(view_count, 0) + 1
where carousel_id = #{carouselId}
</update>
</mapper>

13
chenhai-system/src/main/resources/mapper/muhu/DisasterWarningMapper.xml

@ -35,6 +35,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="affectedRegions != null and affectedRegions != ''"> and affected_regions = #{affectedRegions}</if>
<if test="lastUpdated != null "> and last_updated = #{lastUpdated}</if>
<if test="createdTime != null "> and created_time = #{createdTime}</if>
<!-- 添加搜索字段:支持标题、内容、措施、编码、区域等多字段模糊搜索 -->
<if test="keyword != null and keyword != ''">
AND (
title LIKE CONCAT('%', #{keyword}, '%')
OR brief_content LIKE CONCAT('%', #{keyword}, '%')
OR detail_content LIKE CONCAT('%', #{keyword}, '%')
OR response_measures LIKE CONCAT('%', #{keyword}, '%')
OR warning_code LIKE CONCAT('%', #{keyword}, '%')
OR affected_regions LIKE CONCAT('%', #{keyword}, '%')
OR warning_type LIKE CONCAT('%', #{keyword}, '%')
OR warning_level LIKE CONCAT('%', #{keyword}, '%')
)
</if>
</where>
</select>

39
chenhai-system/src/main/resources/mapper/muhu/MuhuConsultationFormsMapper.xml

@ -21,8 +21,8 @@
<result property="createdTime" column="created_time" />
<result property="avatar" column="avatar" />
<result property="images" column="images" />
<!-- 今日回复总数字段 -->
<result property="todayReplyCount" column="today_reply_count" />
<!-- 添加今日回复总数字段映射 -->
<result property="totalTodayReplyCount" column="total_today_reply_count" />
</resultMap>
<sql id="selectMuhuConsultationFormsVo">
@ -68,19 +68,46 @@
<!-- 查询今日问诊单列表,并统计今日回复总数 -->
<select id="selectTodayConsultationFormsList" parameterType="MuhuConsultationForms" resultMap="MuhuConsultationFormsResult">
SELECT
cf.*,
cf.form_id,
cf.farmer_name,
cf.user_id,
cf.title,
cf.description,
cf.animal_type,
cf.animal_age,
cf.animal_gender,
cf.images,
cf.status,
cf.is_sensitive,
cf.sensitive_words,
cf.view_count,
cf.created_time,
cf.avatar,
(SELECT COUNT(*) FROM vet_comments vc WHERE vc.consultation_id = cf.form_id) as reply_count,
COALESCE((
SELECT COUNT(*)
FROM vet_comments vc
WHERE vc.consultation_id = cf.form_id
AND DATE(vc.create_time) = CURDATE()
), 0) as today_reply_count
AND DATE(vc.created_at) = CURDATE()
), 0) as today_reply_count,
-- 添加 total_today_reply_count 字段
COALESCE((
SELECT COUNT(*)
FROM vet_comments vc2
WHERE DATE(vc2.created_at) = CURDATE()
AND vc2.consultation_id IN (
SELECT form_id
FROM muhu_consultation_forms cf2
WHERE DATE(cf2.created_time) = CURDATE()
<if test="userId != null">
AND cf2.user_id = #{userId}
</if>
)
), 0) as total_today_reply_count
FROM muhu_consultation_forms cf
<where>
<!-- 只查询今天的数据 -->
AND DATE(cf.created_time) = CURDATE()
<if test="farmerName != null "> and cf.farmer_name = #{farmerName}</if>
<if test="userId != null "> and cf.user_id = #{userId}</if>
<if test="title != null and title != ''">

30
chenhai-system/src/main/resources/mapper/system/SysUserMapper.xml

@ -294,4 +294,34 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
update sys_user set area_code = #{areaCode} where user_id = #{userId}
</update>
<!-- 根据手机号和用户类型查询用户 -->
<select id="selectUserByPhoneAndType" resultMap="SysUserResult">
select u.user_id, u.dept_id, u.user_name, u.nick_name, u.user_type,
u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status,
u.del_flag, u.login_ip, u.login_date, u.pwd_update_date,
u.area_code, u.create_by, u.create_time, u.remark,
d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num,
d.leader, d.status as dept_status,
r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope,
r.status as role_status,
a.id as sys_area_id, a.name as sys_area_name, a.code as sys_area_code,
a.parent_code, a.type, a.sort, a.status, a.name_path, a.code_path, a.deleted
from sys_user u
left join sys_dept d on u.dept_id = d.dept_id
left join sys_user_role ur on u.user_id = ur.user_id
left join sys_role r on r.role_id = ur.role_id
left join sys_area a on u.area_code = a.code
where u.phonenumber = #{phonenumber}
and u.user_type = #{userType}
and u.del_flag = '0'
</select>
<!-- 查询手机号已注册的类型列表 -->
<select id="selectUserTypesByPhone" resultType="string">
select distinct user_type
from sys_user
where phonenumber = #{phonenumber}
and del_flag = '0'
</select>
</mapper>

22
chenhai-system/src/main/resources/mapper/vet/MerchantInfoMapper.xml

@ -22,10 +22,30 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="shopStatus" column="shop_status" />
<result property="publishTime" column="publish_time" />
<result property="offlineTime" column="offline_time" />
<result property="productCount" column="product_count" />
</resultMap>
<sql id="selectMerchantInfoVo">
select shop_id, shop_name, shop_address, phone, user_id, created_at, updated_at, is_active ,shop_logo, business_license_image, audit_status, audit_opinion, audit_user_id, audit_time, shop_status, publish_time, offline_time from merchant_info
select
m.shop_id,
m.shop_name,
m.shop_address,
m.phone,
m.user_id,
m.created_at,
m.updated_at,
m.is_active,
m.shop_logo,
m.business_license_image,
m.audit_status,
m.audit_opinion,
m.audit_user_id,
m.audit_time,
m.shop_status,
m.publish_time,
m.offline_time,
(select count(*) from vet_product p where p.shop_id = m.shop_id and p.is_deleted = 0) as product_count
from merchant_info m
</sql>
<select id="selectMerchantInfoList" parameterType="MerchantInfo" resultMap="MerchantInfoResult">

38
chenhai-ui/src/api/vet/merchant.js

@ -43,15 +43,17 @@ export function delMerchant(shopId) {
})
}
// Post /vet/merchant/audit 审核
export function audit(shopId) {
// 审核商家(单个审核)
export function auditMerchant(data) {
// data 应该包含 { shopId, auditStatus, auditOpinion }
return request({
url: '/vet/merchant/audit/' + shopId,
method: 'post'
url: '/vet/merchant/audit',
method: 'post',
data: data
})
}
///vet/merchant/submitAudit/{shopId}提交审核
// 提交审核
export function submitAudit(shopId) {
return request({
url: '/vet/merchant/submitAudit/' + shopId,
@ -59,7 +61,7 @@ export function submitAudit(shopId) {
})
}
// /vet/merchant/publish/{shopId}上架
// 上架
export function publish(shopId) {
return request({
url: '/vet/merchant/publish/' + shopId,
@ -67,7 +69,7 @@ export function publish(shopId) {
})
}
// /vet/merchant/offline/{shopId}下架
// 下架
export function offline(shopId) {
return request({
url: '/vet/merchant/offline/' + shopId,
@ -75,15 +77,7 @@ export function offline(shopId) {
})
}
// Get /vet/product/shop/{shopId} 详情
export function getShop(shopId) {
return request({
url: '/vet/product/shop/' + shopId,
method: 'get'
})
}
// /vet/merchant/resubmitAudit/{shopId}商家重新提交审核
// 重新提交审核
export function resubmitAudit(shopId) {
return request({
url: '/vet/merchant/resubmitAudit/' + shopId,
@ -91,10 +85,20 @@ export function resubmitAudit(shopId) {
})
}
// /vet/merchant/cancelAudit/{shopId}取消审核
// 取消审核
export function cancelAudit(shopId) {
return request({
url: '/vet/merchant/cancelAudit/' + shopId,
method: 'post'
})
}
// 批量审核接口
export function batchAuditMerchant(data) {
// data 应该包含 { shopIds, auditStatus, auditOpinion }
return request({
url: '/vet/merchant/batch-audit',
method: 'post',
data: data
})
}

39
chenhai-ui/src/api/vet/product.js

@ -43,9 +43,7 @@ export function delProduct(id) {
})
}
// auditStatus审核状态 auditOpinion审核意见 shopStatus店铺状态
// /vet/product/submitAudit/{id}提交审核
// 提交审核
export function submitAuditProduct(id) {
return request({
url: '/vet/product/submitAudit/' + id,
@ -53,28 +51,31 @@ export function submitAuditProduct(id) {
})
}
// /vet/product/publish/{id}上架
// 上架
export function publishProduct(id) {
return request({
url: '/vet/product/publish/' + id,
method: 'post'
})
}
// /vet/product/offline/{id}下架
// 下架
export function offlineProduct(id) {
return request({
url: '/vet/product/offline/' + id,
method: 'post'
})
}
// /vet/product/cancelAudit/{id}取消审核
// 取消审核
export function cancelAuditProduct(id) {
return request({
url: '/vet/product/cancelAudit/' + id,
method: 'post'
})
}
// /vet/product/audit/list 管理员查询所有产品信息列表
// 管理员查询所有产品信息列表
export function listAuditProduct(query) {
return request({
url: '/vet/product/audit/list',
@ -82,7 +83,8 @@ export function listAuditProduct(query) {
params: query
})
}
// /vet/product/batchSubmitAudit/{shopId}批量提交产品审核(按商家)
// 批量提交产品审核(按商家)
export function batchSubmitAuditProduct(shopId) {
return request({
url: '/vet/product/batchSubmitAudit/' + shopId,
@ -90,7 +92,7 @@ export function batchSubmitAuditProduct(shopId) {
})
}
// /vet/product/resubmitAudit/{id}产品重新提交审核
// 产品重新提交审核
export function resubmitAuditProduct(id) {
return request({
url: '/vet/product/resubmitAudit/' + id,
@ -98,3 +100,22 @@ export function resubmitAuditProduct(id) {
})
}
// 审核产品(单个审核)
export function auditProduct(data) {
// data 应该包含 { id, auditStatus, auditOpinion }
return request({
url: '/vet/product/audit',
method: 'post',
data: data
})
}
// 批量审核产品
export function batchAuditProduct(data) {
// data 应该包含 { ids, auditStatus, auditOpinion }
return request({
url: '/vet/product/batch-audit',
method: 'post',
data: data
})
}

42
chenhai-ui/src/views/vet/knowledge/index.vue

@ -81,17 +81,17 @@
v-hasPermi="['vet:knowledge:add']"
>发布文章</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-s-promotion"
size="mini"
:disabled="single"
@click="handleSubmitAudit"
v-hasPermi="['vet:knowledge:submit']"
>提交审核</el-button>
</el-col>
<!-- <el-col :span="1.5">-->
<!-- <el-button-->
<!-- type="info"-->
<!-- plain-->
<!-- icon="el-icon-s-promotion"-->
<!-- size="mini"-->
<!-- :disabled="single"-->
<!-- @click="handleSubmitAudit"-->
<!-- v-hasPermi="['vet:knowledge:submit']"-->
<!-- >提交审核</el-button>-->
<!-- </el-col>-->
<el-col :span="1.5">
<el-button
type="primary"
@ -216,16 +216,16 @@
v-if="scope.row.articleStatus === '0' && scope.row.auditStatus === '0'"
class="info-btn alter-btn"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-s-promotion"
style="color: #dab708"
@click="handleSubmitAudit(scope.row.id)"
v-hasPermi="['vet:knowledge:submit']"
v-if="scope.row.articleStatus === '0' && scope.row.auditStatus === '0'"
class="info-btn submit-btn"
>提交审核</el-button>
<!-- <el-button-->
<!-- size="mini"-->
<!-- type="text"-->
<!-- icon="el-icon-s-promotion"-->
<!-- style="color: #dab708"-->
<!-- @click="handleSubmitAudit(scope.row.id)"-->
<!-- v-hasPermi="['vet:knowledge:submit']"-->
<!-- v-if="scope.row.articleStatus === '0' && scope.row.auditStatus === '0'"-->
<!-- class="info-btn submit-btn"-->
<!-- >提交审核</el-button>-->
<el-button
size="mini"
type="text"

576
chenhai-ui/src/views/vet/merchant/index.vue

@ -25,38 +25,6 @@
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- <el-form-item label="关联用户ID" prop="userId">-->
<!-- <el-input-->
<!-- v-model="queryParams.userId"-->
<!-- placeholder="请输入关联用户ID"-->
<!-- clearable-->
<!-- @keyup.enter.native="handleQuery"-->
<!-- />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="创建时间" prop="createdAt">-->
<!-- <el-date-picker clearable-->
<!-- v-model="queryParams.createdAt"-->
<!-- type="date"-->
<!-- value-format="yyyy-MM-dd"-->
<!-- placeholder="请选择创建时间">-->
<!-- </el-date-picker>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="更新时间" prop="updatedAt">-->
<!-- <el-date-picker clearable-->
<!-- v-model="queryParams.updatedAt"-->
<!-- type="date"-->
<!-- value-format="yyyy-MM-dd"-->
<!-- placeholder="请选择更新时间">-->
<!-- </el-date-picker>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="是否启用" prop="isActive">-->
<!-- <el-input-->
<!-- v-model="queryParams.isActive"-->
<!-- placeholder="请输入是否启用"-->
<!-- clearable-->
<!-- @keyup.enter.native="handleQuery"-->
<!-- />-->
<!-- </el-form-item>-->
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
@ -74,6 +42,18 @@
v-hasPermi="['vet:merchant:add']"
>店铺资质</el-button>
</el-col>
<!-- 审核按钮 -->
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-finished"
size="mini"
:disabled="single"
@click="handleAuditDialog"
v-hasPermi="['vet:merchant:audit']"
>审核</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
@ -111,50 +91,47 @@
<el-table v-loading="loading" :data="merchantList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="店铺ID,主键" align="center" prop="shopId" />-->
<el-table-column label="店铺logo" align="center" prop="shopLogo" width="100">
<template slot-scope="scope">
<image-preview :src="scope.row.shopLogo" :width="50" :height="50"/>
</template>
</el-table-column>
<el-table-column label="店铺名称" align="center" prop="shopName"/>
<el-table-column label="店铺名称" align="center" prop="shopName" min-width="120" show-overflow-tooltip/>
<el-table-column label="店铺地址" align="center" prop="shopAddress" width="150" :show-overflow-tooltip="true"/>
<el-table-column label="联系电话" align="center" prop="phone" width="200"/>
<el-table-column label="联系电话" align="center" prop="phone" width="120"/>
<el-table-column label="营业执照" align="center" prop="businessLicenseImage" width="100">
<template slot-scope="scope">
<image-preview :src="scope.row.businessLicenseImage" :width="50" :height="50"/>
</template>
</el-table-column>
<el-table-column label="审核状态" prop="auditStatus" width="120" align="center">
<!-- 产品数量列 -->
<el-table-column label="产品数量" align="center" width="100">
<template slot-scope="scope">
<el-tag size="small" :type="scope.row.productCount > 0 ? 'success' : 'info'">
{{ scope.row.productCount || 0 }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="审核状态" prop="auditStatus" width="100" align="center">
<template slot-scope="scope">
<el-tag :type="getAuditStatusTagType(scope.row.auditStatus)" size="small">
{{ getAuditStatusText(scope.row.auditStatus) }}
</el-tag>
</template>
</el-table-column>
<!-- <el-table-column label="关联用户ID" align="center" prop="userId" />-->
<!-- <el-table-column label="创建时间" align="center" prop="createdAt" width="180">-->
<!-- <template slot-scope="scope">-->
<!-- <span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="更新时间" align="center" prop="updatedAt" width="180">-->
<!-- <template slot-scope="scope">-->
<!-- <span>{{ parseTime(scope.row.updatedAt, '{y}-{m}-{d}') }}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="是否启用" align="center" prop="isActive"/>-->
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="300">
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" fixed="right" width="350">
<template slot-scope="scope">
<!-- 查看产品按钮 - 审核通过后才显示 -->
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handleView(scope.row)"
@click="handleViewProducts(scope.row)"
class="info-btn view-btn"
v-if="scope.row.auditStatus === '2'"
>详情</el-button>
>查看产品</el-button>
<!-- 修改按钮 -->
<el-button
size="mini"
type="text"
@ -165,6 +142,7 @@
v-if="scope.row.auditStatus === '0' || scope.row.auditStatus === '3'"
class="info-btn alter-btn"
>修改</el-button>
<!-- 删除按钮 -->
<el-button
size="mini"
type="text"
@ -174,6 +152,18 @@
v-hasPermi="['vet:merchant:remove']"
class="info-btn delete-btn"
>删除</el-button>
<!-- 审核按钮管理员可见审核中状态 -->
<el-button
size="mini"
type="text"
icon="el-icon-finished"
style="color: #072eed"
@click="handleSingleAudit(scope.row)"
v-hasPermi="['vet:merchant:audit']"
v-if="scope.row.auditStatus === '1' && isAdmin"
class="info-btn audit-btn"
>审核</el-button>
<!-- 提交审核按钮待审核状态 -->
<el-button
size="mini"
type="text"
@ -183,9 +173,8 @@
v-hasPermi="['vet:product:submit']"
v-if="scope.row.auditStatus === '0'"
class="info-btn submit-btn"
>
提交审核
</el-button>
>提交审核</el-button>
<!-- 取消审核按钮审核中状态非管理员可见 -->
<el-button
size="mini"
type="text"
@ -193,11 +182,10 @@
style="color: #5607b3"
@click="handleCancelAudit(scope.row)"
v-hasPermi="['vet:product:edit']"
v-if="scope.row.auditStatus === '1'"
v-if="scope.row.auditStatus === '1' && !isAdmin"
class="info-btn cancel-btn"
>
取消审核
</el-button>
>取消审核</el-button>
<!-- 重新提交按钮审核拒绝状态 -->
<el-button
size="mini"
type="text"
@ -207,9 +195,7 @@
v-hasPermi="['vet:product:submit']"
v-if="scope.row.auditStatus === '3'"
class="info-btn resubmit-btn"
>
重新提交
</el-button>
>重新提交</el-button>
</template>
</el-table-column>
</el-table>
@ -240,28 +226,6 @@
<el-form-item label="营业执照" prop="businessLicenseImage">
<image-upload :limit=1 v-model="form.businessLicenseImage"/>
</el-form-item>
<!-- <el-form-item label="关联用户ID" prop="userId">-->
<!-- <el-input v-model="form.userId" placeholder="请输入关联用户ID" />-->
<!-- </el-form-item>-->
<!-- <el-form-item label="创建时间" prop="createdAt">-->
<!-- <el-date-picker clearable-->
<!-- v-model="form.createdAt"-->
<!-- type="date"-->
<!-- value-format="yyyy-MM-dd"-->
<!-- placeholder="请选择创建时间">-->
<!-- </el-date-picker>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="更新时间" prop="updatedAt">-->
<!-- <el-date-picker clearable-->
<!-- v-model="form.updatedAt"-->
<!-- type="date"-->
<!-- value-format="yyyy-MM-dd"-->
<!-- placeholder="请选择更新时间">-->
<!-- </el-date-picker>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="是否启用" prop="isActive">-->
<!-- <el-input v-model="form.isActive" placeholder="请输入是否启用" />-->
<!-- </el-form-item>-->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
@ -269,26 +233,129 @@
</div>
</el-dialog>
<!-- 详情弹窗 -->
<!-- 店铺产品列表弹窗 -->
<el-dialog
title="产品信息"
:visible.sync="replyOpen"
width="80%"
:title="'【' + currentShopName + '】的产品列表'"
:visible.sync="productDialogVisible"
width="95%"
append-to-body
:close-on-click-modal="false"
@closed="handleProductDialogClose"
destroy-on-close
>
<!-- 传递 shopId 给产品组件 -->
<product-list
:shop-id="shopId"
v-if="replyOpen"
v-if="productDialogVisible"
:shop-id="currentShopId"
:shop-name="currentShopName"
:key="'product_' + currentShopId + '_' + new Date().getTime()"
/>
</el-dialog>
<!-- 单个审核对话框 -->
<el-dialog
title="商家审核"
:visible.sync="auditDialogVisible"
width="500px"
append-to-body
:close-on-click-modal="false"
@closed="resetAuditForm"
>
<el-form ref="auditFormRef" :model="auditForm" :rules="auditRules" label-width="80px">
<el-form-item label="审核结果" prop="auditStatus">
<el-radio-group v-model="auditForm.auditStatus">
<el-radio
v-for="item in auditStatusOptions"
:key="item.value"
:label="item.value"
>
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="审核意见" prop="auditOpinion">
<el-input
v-model="auditForm.auditOpinion"
type="textarea"
:rows="4"
placeholder="请输入审核意见(审核拒绝时必须填写)"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitAudit" :loading="auditLoading"> </el-button>
<el-button @click="cancelAudit"> </el-button>
</div>
</el-dialog>
<!-- 批量审核对话框 -->
<el-dialog
title="批量审核商家"
:visible.sync="batchAuditDialogVisible"
width="500px"
append-to-body
:close-on-click-modal="false"
@closed="resetBatchAuditForm"
>
<el-form ref="batchAuditFormRef" :model="batchAuditForm" :rules="batchAuditRules" label-width="80px">
<el-form-item label="审核结果" prop="auditStatus">
<el-radio-group v-model="batchAuditForm.auditStatus">
<el-radio
v-for="item in auditStatusOptions"
:key="item.value"
:label="item.value"
>
{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="审核意见" prop="auditOpinion">
<el-input
v-model="batchAuditForm.auditOpinion"
type="textarea"
:rows="4"
placeholder="请输入审核意见(审核拒绝时必须填写)"
maxlength="500"
show-word-limit
/>
</el-form-item>
<el-alert
v-if="batchAuditForm.shopIds.length > 0"
type="info"
:closable="false"
style="margin-top: 10px;"
>
已选择 {{ batchAuditForm.shopIds.length }} 个商家进行批量审核
</el-alert>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitBatchAudit" :loading="batchAuditLoading"> </el-button>
<el-button @click="cancelBatchAudit"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listMerchant, getMerchant, delMerchant, addMerchant, updateMerchant, submitAudit, resubmitAudit, cancelAudit } from "@/api/vet/merchant"
import {
listMerchant,
getMerchant,
delMerchant,
addMerchant,
updateMerchant,
submitAudit,
resubmitAudit,
cancelAudit,
auditMerchant,
batchAuditMerchant
} from "@/api/vet/merchant"
import ProductList from '@/views/vet/product/index.vue'
export default {
@ -300,7 +367,9 @@ export default {
return {
//
loading: true,
shopId:null,
//
currentShopId: null,
currentShopName: '',
//
ids: [],
//
@ -317,8 +386,11 @@ export default {
title: "",
//
open: false,
//
replyOpen: false,
//
productDialogVisible: false,
//
isAdmin: false,
//
queryParams: {
pageNum: 1,
@ -331,8 +403,10 @@ export default {
updatedAt: null,
isActive: null
},
//
form: {},
//
rules: {
shopName: [
@ -340,23 +414,73 @@ export default {
],
shopAddress: [
{ required: true, message: "店铺地址不能为空", trigger: "blur" }
]
},
//
auditDialogVisible: false,
auditForm: {
shopId: null,
auditStatus: '2',
auditOpinion: ''
},
auditStatusOptions: [
{ value: '2', label: '审核通过', type: 'success' },
{ value: '3', label: '审核拒绝', type: 'danger' }
],
userId: [
{ required: true, message: "关联用户ID不能为空", trigger: "blur" }
],
createdAt: [
{ required: true, message: "创建时间不能为空", trigger: "blur" }
],
updatedAt: [
{ required: true, message: "更新时间不能为空", trigger: "blur" }
],
auditRules: {
auditOpinion: [
{
validator: (rule, value, callback) => {
if (this.auditForm.auditStatus === '3' && (!value || value.trim() === '')) {
callback(new Error('审核拒绝时必须填写审核意见'))
} else {
callback()
}
},
trigger: 'blur'
}
]
},
auditLoading: false,
//
batchAuditDialogVisible: false,
batchAuditForm: {
shopIds: [],
auditStatus: '2',
auditOpinion: ''
},
batchAuditRules: {
auditOpinion: [
{
validator: (rule, value, callback) => {
if (this.batchAuditForm.auditStatus === '3' && (!value || value.trim() === '')) {
callback(new Error('审核拒绝时必须填写审核意见'))
} else {
callback()
}
},
trigger: 'blur'
}
]
},
batchAuditLoading: false
}
},
created() {
this.getList()
this.checkAdminRole()
},
methods: {
/** 检查是否是管理员 */
checkAdminRole() {
const userInfo = this.$store.getters.userInfo || {}
this.isAdmin = userInfo.roles && userInfo.roles.includes('admin')
},
/** 查询商家信息列表 */
getList() {
this.loading = true
@ -366,11 +490,13 @@ export default {
this.loading = false
})
},
//
cancel() {
this.open = false
this.reset()
},
//
reset() {
this.form = {
@ -385,16 +511,19 @@ export default {
}
this.resetForm("form")
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm")
this.handleQuery()
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.shopId)
@ -402,13 +531,22 @@ export default {
this.multiple = !selection.length
},
//
handleView(row) {
console.log('查看的店铺信息:', row)
console.log('shopId:', row.shopId)
this.shopRow = row
this.shopId = row.shopId
this.replyOpen = true
/** 查看店铺产品 */
handleViewProducts(row) {
// shopId
this.currentShopId = Number(row.shopId);
this.currentShopName = row.shopName;
this.productDialogVisible = true;
},
/** 关闭产品对话框 */
handleProductDialogClose() {
console.log('关闭产品对话框');
this.productDialogVisible = false;
this.currentShopId = null;
this.currentShopName = '';
},
/** 新增按钮操作 */
@ -417,6 +555,7 @@ export default {
this.open = true
this.title = "添加商家信息"
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset()
@ -427,6 +566,7 @@ export default {
this.title = "修改商家信息"
})
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
@ -447,16 +587,18 @@ export default {
}
})
},
/** 删除按钮操作 */
handleDelete(row) {
const shopIds = row.shopId || this.ids
this.$modal.confirm('是否确认删除商家信息编号为"' + shopIds + '"的数据项?').then(function() {
this.$modal.confirm('是否确认删除商家信息编号为"' + shopIds + '"的数据项?').then(() => {
return delMerchant(shopIds)
}).then(() => {
this.getList()
this.$modal.msgSuccess("删除成功")
}).catch(() => {})
},
/** 导出按钮操作 */
handleExport() {
this.download('vet/merchant/export', {
@ -488,26 +630,226 @@ export default {
//
handleSubmitAudit(row) {
submitAudit(row.shopId).then(response => {
this.$confirm('是否确认提交审核?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
return submitAudit(row.shopId)
}).then(response => {
this.$modal.msgSuccess("提交成功")
this.getList()
})
}).catch(() => {})
},
//
handleCancelAudit(row) {
cancelAudit(row.shopId).then(response => {
this.$confirm('确定要取消审核吗?取消后可以重新提交审核', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
return cancelAudit(row.shopId)
}).then(response => {
this.$modal.msgSuccess("取消成功")
this.getList()
})
}).catch(() => {})
},
//
handleResubmitAudit(row) {
resubmitAudit(row.shopId).then(response => {
this.$confirm('是否确认重新提交审核?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
return resubmitAudit(row.shopId)
}).then(response => {
this.$modal.msgSuccess("重新提交成功")
this.getList()
}).catch(() => {})
},
/** 打开审核对话框(顶部按钮点击) */
handleAuditDialog() {
if (this.ids.length === 0) {
this.$message.warning('请至少选择一个需要审核的商家')
return
}
if (this.ids.length === 1) {
//
const shopId = this.ids[0]
const shop = this.merchantList.find(item => item.shopId === shopId)
if (shop && shop.auditStatus !== '1') {
this.$message.warning('只有审核中的商家才能进行审核操作')
return
}
this.handleSingleAudit({ shopId })
} else {
//
this.handleBatchAudit()
}
},
/** 单个审核 */
handleSingleAudit(row) {
const shopId = row.shopId || row
//
if (row.auditStatus && row.auditStatus !== '1') {
this.$message.warning('只有审核中的商家才能进行审核操作')
return
}
this.auditForm = {
shopId: shopId,
auditStatus: '2',
auditOpinion: ''
}
this.auditDialogVisible = true
},
/** 批量审核 */
handleBatchAudit() {
//
const auditShops = this.merchantList.filter(item =>
this.ids.includes(item.shopId) && item.auditStatus === '1'
)
if (auditShops.length === 0) {
this.$message.warning('选中的商家中没有审核中的商家')
return
}
if (auditShops.length < this.ids.length) {
this.$message.warning('部分选中的商家不是审核中状态,将只对审核中的商家进行审核')
}
this.batchAuditForm = {
shopIds: auditShops.map(item => item.shopId),
auditStatus: '2',
auditOpinion: ''
}
this.batchAuditDialogVisible = true
},
/** 提交单个审核 */
async submitAudit() {
try {
await this.$refs.auditFormRef.validate()
const message = this.auditForm.auditStatus === '2'
? '是否确认审核通过该商家?'
: '是否确认审核拒绝该商家?'
await this.$confirm(message, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
this.auditLoading = true
const response = await auditMerchant({
shopId: this.auditForm.shopId,
auditStatus: this.auditForm.auditStatus,
auditOpinion: this.auditForm.auditOpinion || ''
})
if (response.code === 200) {
this.$message.success('审核成功')
this.auditDialogVisible = false
this.getList()
} else {
this.$message.error(response.msg || '审核失败')
}
} catch (error) {
if (error === 'cancel') return
console.error('审核错误:', error)
this.$message.error('审核失败:' + (error.message || '未知错误'))
} finally {
this.auditLoading = false
}
},
/** 提交批量审核 */
async submitBatchAudit() {
try {
await this.$refs.batchAuditFormRef.validate()
const message = this.batchAuditForm.auditStatus === '2'
? `是否确认审核通过选中的 ${this.batchAuditForm.shopIds.length} 个商家?`
: `是否确认审核拒绝选中的 ${this.batchAuditForm.shopIds.length} 个商家?`
await this.$confirm(message, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
this.batchAuditLoading = true
const response = await batchAuditMerchant({
shopIds: this.batchAuditForm.shopIds,
auditStatus: this.batchAuditForm.auditStatus,
auditOpinion: this.batchAuditForm.auditOpinion || ''
})
if (response.code === 200) {
this.$message.success(`批量审核成功,${response.msg || ''}`)
this.batchAuditDialogVisible = false
this.getList()
} else {
this.$message.error(response.msg || '批量审核失败')
}
} catch (error) {
if (error === 'cancel') return
console.error('批量审核错误:', error)
this.$message.error('批量审核失败:' + (error.message || '未知错误'))
} finally {
this.batchAuditLoading = false
}
},
/** 关闭审核对话框 */
cancelAudit() {
this.auditDialogVisible = false
this.resetAuditForm()
},
/** 关闭批量审核对话框 */
cancelBatchAudit() {
this.batchAuditDialogVisible = false
this.resetBatchAuditForm()
},
/** 重置审核表单 */
resetAuditForm() {
this.auditForm = {
shopId: null,
auditStatus: '2',
auditOpinion: ''
}
if (this.$refs.auditFormRef) {
this.$nextTick(() => {
this.$refs.auditFormRef.clearValidate()
})
}
},
/** 重置批量审核表单 */
resetBatchAuditForm() {
this.batchAuditForm = {
shopIds: [],
auditStatus: '2',
auditOpinion: ''
}
if (this.$refs.batchAuditFormRef) {
this.$nextTick(() => {
this.$refs.batchAuditFormRef.clearValidate()
})
}
}
}
}

826
chenhai-ui/src/views/vet/product/index.vue
File diff suppressed because it is too large
View File

Loading…
Cancel
Save