diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveDto.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveDto.java new file mode 100644 index 000000000..ab7c006da --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveDto.java @@ -0,0 +1,34 @@ +package com.bsd.pjcloud.canteen.dto.canteenonline; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import com.bsd.pjcloud.common.core.util.TenantTable; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 在线点餐spu + * + * @author zjf + * @date 2024-12-16 23:42:19 + */ +@Data +@Schema(description = "在线点餐批量关联新增每日菜谱") +public class CanteenOnlineSpuSaveDto { + + + /** + * 商户编号 + */ + @Schema(description="商户编号") + private Long merchantId; + + private List items; + + + +} \ No newline at end of file diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveItemDto.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveItemDto.java new file mode 100644 index 000000000..4df5dcebd --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveItemDto.java @@ -0,0 +1,57 @@ +package com.bsd.pjcloud.canteen.dto.canteenonline; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Data +public class CanteenOnlineSpuSaveItemDto { + + + /** + * 商品名称 + */ + @Schema(description="商品名称") + private String name; + + + @Schema(description="关联每日菜谱id") + private Long linkSpuId; + + /** + * 商品分类编号 + */ + @Schema(description="商品分类编号") + private Long categoryId; + + /** + * 商品封面图 + */ + @Schema(description="商品封面图") + private String picUrl; + + + /** + * 排序字段 + */ + @Schema(description="排序字段") + private Integer sort; + + /** + * 商品状态: 1 上架(开启) 0 下架(禁用) -1 回收 + */ + @Schema(description="商品状态: 1 上架(开启) 0 下架(禁用) -1 回收") + private Integer status; + + /** + * 商品价格,单位使用:分 + */ + @Schema(description="商品价格,单位使用:分") + private Integer price; + + + /** + * 库存 + */ + @Schema(description="库存") + private Integer stock; +} diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineCategoryEntity.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineCategoryEntity.java index 94c951e59..35b12c287 100644 --- a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineCategoryEntity.java +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenOnlineCategoryEntity.java @@ -112,4 +112,7 @@ public class CanteenOnlineCategoryEntity extends Model { */ @Schema(description="租户编号") private Long tenantId; + + @Schema(description="关联每日菜谱id") + private Long linkSpuId; } \ No newline at end of file diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuController.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuController.java index 684e79835..8019f5f1c 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuController.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenOnlineSpuController.java @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.bsd.pjcloud.canteen.dto.CanteenOnlineSpuUpdateStockReqDTO; +import com.bsd.pjcloud.canteen.dto.canteenonline.CanteenOnlineSpuSaveDto; import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO; import com.bsd.pjcloud.canteen.vo.app.CanteenOnlineSpuAppVO; import com.bsd.pjcloud.common.core.util.BeanUtils; @@ -58,7 +59,7 @@ public class CanteenOnlineSpuController { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); wrapper.like(StrUtil.isNotBlank(canteenOnlineSpu.getName()), CanteenOnlineSpuEntity::getName, canteenOnlineSpu.getName()); wrapper.eq(Objects.nonNull(canteenOnlineSpu.getCategoryId()), CanteenOnlineSpuEntity::getCategoryId, canteenOnlineSpu.getCategoryId()); - return R.ok(canteenOnlineSpuService.page(page, wrapper)); + return R.ok(canteenOnlineSpuService.pageScope(page, wrapper)); } @@ -90,6 +91,14 @@ public class CanteenOnlineSpuController { return R.ok(canteenOnlineSpuService.save(canteenOnlineSpu)); } + @Operation(summary = "批量新增关联每日菜谱", description = "批量新增关联每日菜谱") + @SysLog("批量导入新增点餐spu") + @PostMapping("/saveCanteenSpuBatch") + @PreAuthorize("@pms.hasPermission('canteen_canteenOnlineSpu_add')") + public R saveCanteenSpuBatch(@RequestBody CanteenOnlineSpuSaveDto canteenOnlineSpuSaveDto) { + return R.ok(canteenOnlineSpuService.saveCanteenSpuBatch(canteenOnlineSpuSaveDto)); + } + /** * 修改在线点餐spu * @@ -146,8 +155,9 @@ public class CanteenOnlineSpuController { @GetMapping("/app/getCanteenSpuList") @Operation(summary = "获取在线点餐的菜品列表", description = "1.通过分类id,可以不填,默认查全部,2.商户id,必传") public R> getCanteenSpuList(@RequestParam(value = "categoryId", required = false) String categoryId, - @RequestParam(value = "merchantId") String merchantId) { - return canteenOnlineSpuService.getCanteenOnlineSpuList(categoryId, merchantId); + @RequestParam(value = "merchantId") String merchantId, + @RequestParam(value = "time")String time) { + return canteenOnlineSpuService.getCanteenOnlineSpuList(categoryId, merchantId,time); } diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuService.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuService.java index 96df20ae2..f97770add 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuService.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenOnlineSpuService.java @@ -1,7 +1,10 @@ package com.bsd.pjcloud.canteen.service; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; import com.bsd.pjcloud.canteen.dto.CanteenOnlineSpuUpdateStockReqDTO; +import com.bsd.pjcloud.canteen.dto.canteenonline.CanteenOnlineSpuSaveDto; import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity; import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO; import com.bsd.pjcloud.common.core.util.R; @@ -18,7 +21,7 @@ public interface CanteenOnlineSpuService extends IService> getCanteenOnlineSpuList(String categoryId, String merchantId); + R> getCanteenOnlineSpuList(String categoryId, String merchantId,String time); /** @@ -27,4 +30,20 @@ public interface CanteenOnlineSpuService extends IService wrapper); } \ No newline at end of file diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuServiceImpl.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuServiceImpl.java index dc576cd08..c78827025 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuServiceImpl.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenOnlineSpuServiceImpl.java @@ -1,18 +1,33 @@ package com.bsd.pjcloud.canteen.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.bsd.pjcloud.canteen.dto.CanteenOnlineSpuUpdateStockReqDTO; +import com.bsd.pjcloud.canteen.dto.canteenonline.CanteenOnlineSpuSaveDto; +import com.bsd.pjcloud.canteen.dto.canteenonline.CanteenOnlineSpuSaveItemDto; +import com.bsd.pjcloud.canteen.entity.CanteenCategoryEntity; +import com.bsd.pjcloud.canteen.entity.CanteenDailyMenuEntity; +import com.bsd.pjcloud.canteen.entity.CanteenOnlineCategoryEntity; import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity; +import com.bsd.pjcloud.canteen.mapper.CanteenCategoryMapper; +import com.bsd.pjcloud.canteen.mapper.CanteenDailyMenuMapper; +import com.bsd.pjcloud.canteen.mapper.CanteenOnlineCategoryMapper; import com.bsd.pjcloud.canteen.mapper.CanteenOnlineSpuMapper; import com.bsd.pjcloud.canteen.service.CanteenOnlineSpuService; import com.bsd.pjcloud.canteen.vo.APPOnlineSpuVO; import com.bsd.pjcloud.common.core.util.BeanUtils; import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.data.datascope.DataScope; +import com.bsd.pjcloud.common.security.util.SecurityUtils; +import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; /** * 在线点餐spu @@ -21,14 +36,33 @@ import java.util.List; * @date 2024-12-16 23:42:19 */ @Service +@AllArgsConstructor public class CanteenOnlineSpuServiceImpl extends ServiceImpl implements CanteenOnlineSpuService { + + private final CanteenCategoryMapper categoryMapper; + + private final CanteenOnlineCategoryMapper canteenOnlineCategoryMapper; + + private final CanteenDailyMenuMapper canteenDailyMenuMapper; @Override - public R> getCanteenOnlineSpuList(String categoryId, String merchantId) { + public R> getCanteenOnlineSpuList(String categoryId, String merchantId,String time) { LambdaQueryWrapper canteenOnlineSpuEntityLambdaQueryWrapper = new LambdaQueryWrapper<>(); canteenOnlineSpuEntityLambdaQueryWrapper.eq(StringUtils.isNotEmpty(categoryId), CanteenOnlineSpuEntity::getCategoryId, categoryId); canteenOnlineSpuEntityLambdaQueryWrapper.eq(CanteenOnlineSpuEntity::getMerchantId, merchantId); List canteenSpuEntities = baseMapper.selectList(canteenOnlineSpuEntityLambdaQueryWrapper); - List bean = BeanUtils.toBean(canteenSpuEntities, APPOnlineSpuVO.class); + + //根据商户查询当前日期的每日菜谱,查询每日菜谱上架的菜的id,然后在从在线订餐的列表筛选出今天有上新的数据 + LambdaQueryWrapper dailyMenuEntityLambdaQueryWrapper = new LambdaQueryWrapper<>(); + dailyMenuEntityLambdaQueryWrapper.eq(CanteenDailyMenuEntity::getMerchantId, merchantId); + dailyMenuEntityLambdaQueryWrapper.eq(CanteenDailyMenuEntity::getStartTime,time); + List dailyMenuEntities = canteenDailyMenuMapper.selectList(dailyMenuEntityLambdaQueryWrapper); + List linkSpuIds = dailyMenuEntities.stream().map(d -> d.getSpuId()).collect(Collectors.toList()); + //从canteenSpuEntities中筛选出今天有上新的数据 + List finallyCanteenSpuEntities = + canteenSpuEntities.stream().filter(c -> { + return c.getLinkSpuId() == null || linkSpuIds.contains(c.getLinkSpuId()); + }).collect(Collectors.toList()); + List bean = BeanUtils.toBean(finallyCanteenSpuEntities, APPOnlineSpuVO.class); return R.ok(bean); } @@ -50,4 +84,39 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl items = canteenOnlineSpuSaveDto.getItems(); + List canteenSpuEntities = BeanUtils.toBean(items, CanteenOnlineSpuEntity.class); + //每日菜谱的分类,查询在线分类里面是否有 + Set categoryIds = canteenSpuEntities.stream().map(c -> c.getCategoryId()).collect(Collectors.toSet()); + List canteenCategoryEntities = categoryMapper.selectList(new LambdaQueryWrapper().select(CanteenCategoryEntity::getId).in(CanteenCategoryEntity::getId, categoryIds)); + //把canteenCategoryEntities转为key map + Map canteenCategoryEntityMap = canteenCategoryEntities.stream().collect(Collectors.toMap(CanteenCategoryEntity::getId, c -> c)); + + Long deptId = SecurityUtils.getUser().getDeptId(); + canteenSpuEntities.forEach(c -> { + CanteenCategoryEntity canteenCategoryEntity = canteenCategoryEntityMap.get(c.getCategoryId()); + String name = canteenCategoryEntity.getName(); + //查询分类里面是否有 + CanteenOnlineCategoryEntity canteenOnlineCategoryEntity = canteenOnlineCategoryMapper.selectOne(new LambdaQueryWrapper().eq(CanteenOnlineCategoryEntity::getName, name)); + if (canteenOnlineCategoryEntity == null){ + CanteenOnlineCategoryEntity bean = BeanUtils.toBean(canteenCategoryEntity, CanteenOnlineCategoryEntity.class); + canteenOnlineCategoryMapper.insert(bean); + c.setCategoryId(bean.getId()); + }else { + c.setCategoryId(canteenOnlineCategoryEntity.getId()); + } + c.setMerchantId(merchantId); + c.setDeptId(deptId); + }); + return baseMapper.insert(canteenSpuEntities); + } + + @Override + public Object pageScope(Page page, LambdaQueryWrapper wrapper) { + return baseMapper.selectPageByScope(page, wrapper, DataScope.of()); + } } \ No newline at end of file diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineCategoryMapper.xml b/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineCategoryMapper.xml index b2f58437c..34c92e696 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineCategoryMapper.xml +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineCategoryMapper.xml @@ -17,5 +17,7 @@ + + \ No newline at end of file diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineSpuMapper.xml b/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineSpuMapper.xml index f2299a8a9..d3d1fce62 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineSpuMapper.xml +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenOnlineSpuMapper.xml @@ -28,5 +28,6 @@ + \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/notice/NoticeScreenVo.java b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/notice/NoticeScreenVo.java index 6a97f07fa..7fea95da2 100644 --- a/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/notice/NoticeScreenVo.java +++ b/pjcloud-integrated/pjcloud-integrated-api/src/main/java/com/bsd/pjcloud/integrated/vo/notice/NoticeScreenVo.java @@ -6,6 +6,8 @@ import java.time.LocalDateTime; @Data public class NoticeScreenVo { + + private Long id; @Schema(description = "标题") private String title; diff --git a/pjcloud-integrated/pjcloud-integrated-biz/API-INTEGRATION-GUIDE.md b/pjcloud-integrated/pjcloud-integrated-biz/API-INTEGRATION-GUIDE.md new file mode 100644 index 000000000..002fb9072 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/API-INTEGRATION-GUIDE.md @@ -0,0 +1,387 @@ +# 外部系统滚动通知接口集成指南 + +## 📋 概述 + +本文档介绍如何集成使用 PJCloud 系统的滚动通知接口,该接口提供安全的 API 访问,供外部系统获取滚动通知信息。 + +## 🔐 认证方式 + +接口采用 **AppId + AppSecret** 的认证方式,通过 HTTP 请求头进行身份验证。 + +### 认证参数 + +| 参数名 | 位置 | 必填 | 说明 | +|--------|------|------|------| +| X-App-Id | 请求头 | 是 | 应用ID,由系统管理员分配 | +| X-App-Secret | 请求头 | 是 | 应用密钥,由系统管理员分配 | + +## 🌐 接口信息 + +### 滚动通知接口 + +- **接口地址**: `GET /notice/external/scroll` +- **请求方式**: GET +- **认证方式**: 请求头认证 +- **数据格式**: JSON + +### 请求参数 + +#### 查询参数 +| 参数名 | 必填 | 默认值 | 说明 | +|--------|------|--------|------| +| limit | 否 | 20 | 返回条数,最大50条 | + +#### 请求头示例 +```http +X-App-Id: 202501270001 +X-App-Secret: 550e8400-e29b-41d4-a716-446655440001 +``` + +## 📡 响应格式 + +### 成功响应 +```json +{ + "code": 0, + "msg": "操作成功", + "data": [ + { + "title": "系统维护通知", + "createTime": "2025-01-27 10:00:00", + "description": "系统将于今晚进行维护升级" + }, + { + "title": "新功能上线", + "createTime": "2025-01-26 15:30:00", + "description": "新增用户管理功能模块" + } + ] +} +``` + +### 错误响应 +```json +{ + "code": 500, + "msg": "无效的应用ID或密钥", + "data": null +} +``` + +## 💻 集成示例 + +### JavaScript 调用示例 + +#### 基础调用 +```javascript +// 获取滚动通知 +async function getScrollNotices(limit = 20) { + try { + const response = await fetch('/notice/external/scroll?limit=' + limit, { + method: 'GET', + headers: { + 'X-App-Id': '202501270001', + 'X-App-Secret': '550e8400-e29b-41d4-a716-446655440001', + 'Content-Type': 'application/json' + } + }); + + const result = await response.json(); + + if (result.code === 0) { + return result.data; + } else { + throw new Error(result.msg); + } + } catch (error) { + console.error('获取通知失败:', error); + throw error; + } +} + +// 使用示例 +getScrollNotices(15) + .then(notices => { + console.log('获取到通知:', notices); + // 处理通知数据 + displayNotices(notices); + }) + .catch(error => { + console.error('错误:', error.message); + }); +``` + +#### 滚动展示组件 +```javascript +// 滚动通知展示组件 +class ScrollNoticeDisplay { + constructor(containerId, appId, appSecret) { + this.container = document.getElementById(containerId); + this.appId = appId; + this.appSecret = appSecret; + this.notices = []; + this.currentIndex = 0; + this.interval = null; + } + + // 获取通知数据 + async fetchNotices() { + try { + const response = await fetch('/notice/external/scroll?limit=10', { + headers: { + 'X-App-Id': this.appId, + 'X-App-Secret': this.appSecret + } + }); + + const result = await response.json(); + if (result.code === 0) { + this.notices = result.data; + this.startScroll(); + } + } catch (error) { + console.error('获取通知失败:', error); + } + } + + // 开始滚动 + startScroll() { + if (this.notices.length === 0) return; + + this.interval = setInterval(() => { + this.showNextNotice(); + }, 3000); // 每3秒切换一次 + + this.showNextNotice(); // 立即显示第一条 + } + + // 显示下一条通知 + showNextNotice() { + if (this.notices.length === 0) return; + + const notice = this.notices[this.currentIndex]; + this.container.innerHTML = ` +
+ ${notice.title} + ${notice.createTime} +
+ `; + + this.currentIndex = (this.currentIndex + 1) % this.notices.length; + } + + // 停止滚动 + stopScroll() { + if (this.interval) { + clearInterval(this.interval); + this.interval = null; + } + } +} + +// 使用示例 +const noticeDisplay = new ScrollNoticeDisplay( + 'notice-container', + '202501270001', + '550e8400-e29b-41d4-a716-446655440001' +); + +noticeDisplay.fetchNotices(); +``` + +### cURL 调用示例 + +#### 基础调用 +```bash +curl -X GET "http://your-domain/notice/external/scroll?limit=15" \ + -H "X-App-Id: 202501270001" \ + -H "X-App-Secret: 550e8400-e29b-41d4-a716-446655440001" +``` + +#### 获取最大条数 +```bash +curl -X GET "http://your-domain/notice/external/scroll?limit=50" \ + -H "X-App-Id: 202501270001" \ + -H "X-App-Secret: 550e8400-e29b-41d4-a716-446655440001" +``` + +### Java 调用示例 + +```java +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +public class NoticeApiClient { + + private final String baseUrl; + private final String appId; + private final String appSecret; + private final RestTemplate restTemplate; + + public NoticeApiClient(String baseUrl, String appId, String appSecret) { + this.baseUrl = baseUrl; + this.appId = appId; + this.appSecret = appSecret; + this.restTemplate = new RestTemplate(); + } + + public List getScrollNotices(int limit) { + HttpHeaders headers = new HttpHeaders(); + headers.set("X-App-Id", appId); + headers.set("X-App-Secret", appSecret); + + HttpEntity entity = new HttpEntity<>(headers); + + String url = baseUrl + "/notice/external/scroll?limit=" + limit; + + ResponseEntity response = restTemplate.exchange( + url, + HttpMethod.GET, + entity, + ApiResponse.class + ); + + if (response.getBody() != null && response.getBody().getCode() == 0) { + return response.getBody().getData(); + } + + throw new RuntimeException("获取通知失败"); + } +} + +// 使用示例 +NoticeApiClient client = new NoticeApiClient( + "http://your-domain", + "202501270001", + "550e8400-e29b-41d4-a716-446655440001" +); + +List notices = client.getScrollNotices(20); +``` + +## 🎨 CSS 样式示例 + +```css +/* 滚动通知容器 */ +.notice-container { + width: 100%; + height: 40px; + background: linear-gradient(90deg, #f8f9fa, #e9ecef); + border: 1px solid #dee2e6; + border-radius: 4px; + overflow: hidden; + position: relative; +} + +/* 通知项 */ +.notice-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 16px; + height: 100%; + animation: slideIn 0.5s ease-in-out; +} + +/* 通知标题 */ +.notice-title { + font-weight: 500; + color: #495057; + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +/* 通知时间 */ +.notice-time { + font-size: 12px; + color: #6c757d; + margin-left: 16px; +} + +/* 滑动动画 */ +@keyframes slideIn { + from { + transform: translateX(100%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +/* 响应式设计 */ +@media (max-width: 768px) { + .notice-container { + height: 50px; + } + + .notice-item { + padding: 12px 16px; + } + + .notice-time { + display: none; /* 移动端隐藏时间 */ + } +} +``` + +## ⚠️ 注意事项 + +### 安全要求 +1. **密钥保护**: 请妥善保管 AppSecret,不要泄露给第三方 +2. **HTTPS 传输**: 建议使用 HTTPS 协议进行数据传输 +3. **访问频率**: 建议控制调用频率,避免频繁请求 + +### 技术限制 +1. **返回条数**: 单次请求最多返回 50 条通知 +2. **数据时效**: 只返回已发布的公告信息 +3. **排序规则**: 按置顶状态和创建时间倒序排列 + +### 错误处理 +1. **认证失败**: 检查 AppId 和 AppSecret 是否正确 +2. **网络异常**: 实现重试机制和超时处理 +3. **数据异常**: 对返回数据进行有效性验证 + +## 🔧 故障排除 + +### 常见问题 + +#### 1. 认证失败 +**错误信息**: "无效的应用ID或密钥" +**解决方案**: +- 检查 AppId 和 AppSecret 是否正确 +- 确认应用是否已启用 +- 联系系统管理员验证配置 + +#### 2. 网络超时 +**错误信息**: 请求超时或无响应 +**解决方案**: +- 检查网络连接 +- 确认服务器地址是否正确 +- 实现请求超时和重试机制 + +#### 3. 数据为空 +**可能原因**: +- 当前没有已发布的公告 +- 查询参数设置不当 +- 系统维护中 + +## 📞 技术支持 + +如果在集成过程中遇到问题,请联系技术支持: + +- **技术文档**: 本文档 +- **API 地址**: `/notice/external/scroll` +- **认证方式**: AppId + AppSecret +- **数据格式**: JSON + +--- + +*最后更新时间: 2025-01-27* +*版本: v1.0* \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/README-EXTERNAL-API.md b/pjcloud-integrated/pjcloud-integrated-biz/README-EXTERNAL-API.md new file mode 100644 index 000000000..039105fe3 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/README-EXTERNAL-API.md @@ -0,0 +1,98 @@ +# 外部系统滚动通知接口使用说明 + +## 接口概述 + +提供安全的API访问,供其他系统获取滚动通知信息。 + +## 接口信息 + +- **接口地址**: `GET /notice/external/scroll` +- **请求方式**: GET +- **认证方式**: 请求头认证 + +## 请求参数 + +### 请求头 +| 参数名 | 必填 | 说明 | +|--------|------|------| +| X-App-Id | 是 | 应用ID,在配置文件中配置 | +| X-App-Secret | 是 | 应用密钥,在配置文件中配置 | + +### 查询参数 +| 参数名 | 必填 | 默认值 | 说明 | +|--------|------|--------|------| +| limit | 否 | 20 | 返回条数,最大50条 | + +## 响应格式 + +```json +{ + "code": 0, + "msg": "操作成功", + "data": [ + { + "title": "通知标题", + "createTime": "2025-01-27 10:00:00", + "description": "通知描述" + } + ] +} +``` + +## 使用示例 + +### JavaScript 调用示例 +```javascript +fetch('/notice/external/scroll?limit=15', { + method: 'GET', + headers: { + 'X-App-Id': 'external_app_001', + 'X-App-Secret': 'secret_2024_001' + } +}) +.then(response => response.json()) +.then(data => { + if (data.code === 0) { + // 处理通知数据 + console.log(data.data); + } +}) +.catch(error => { + console.error('获取通知失败:', error); +}); +``` + +### cURL 调用示例 +```bash +curl -X GET "http://your-domain/notice/external/scroll?limit=10" \ + -H "X-App-Id: external_app_001" \ + -H "X-App-Secret: secret_2024_001" +``` + +## 配置说明 + +在 `application.yml` 中添加以下配置: + +```yaml +pjcloud: + external-app: + apps: + - appId: "your_app_id" + appSecret: "your_app_secret" + appName: "你的应用名称" + enabled: true +``` + +## 安全特性 + +1. **应用认证**: 通过 appId 和 appSecret 验证调用方身份 +2. **访问控制**: 只返回已发布的公告 +3. **数据限制**: 限制最大返回条数,防止恶意调用 +4. **信息脱敏**: 只返回必要的滚动信息 + +## 注意事项 + +1. 请妥善保管应用密钥,不要泄露给第三方 +2. 建议使用HTTPS协议进行传输 +3. 可以根据需要调整返回条数限制 +4. 支持动态启用/禁用应用访问权限 \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/config/ExternalAppConfig.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/config/ExternalAppConfig.java new file mode 100644 index 000000000..3016692ff --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/config/ExternalAppConfig.java @@ -0,0 +1,51 @@ +package com.bsd.pjcloud.integrated.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 外部应用配置 + * 用于管理外部系统的应用ID和密钥 + * + * @author zjf + * @date 2025-01-27 + */ +@Data +@Component +@ConfigurationProperties(prefix = "pjcloud.external-app") +public class ExternalAppConfig { + + /** + * 外部应用列表 + */ + private List apps; + + /** + * 应用凭证 + */ + @Data + public static class AppCredential { + /** + * 应用ID + */ + private String appId; + + /** + * 应用密钥 + */ + private String appSecret; + + /** + * 应用名称 + */ + private String appName; + + /** + * 是否启用 + */ + private Boolean enabled = true; + } +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/CleanUserController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/CleanUserController.java new file mode 100644 index 000000000..55a264282 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/CleanUserController.java @@ -0,0 +1,139 @@ +package com.bsd.pjcloud.integrated.controller; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.log.annotation.SysLog; +import com.bsd.pjcloud.common.security.util.SecurityUtils; +import com.bsd.pjcloud.integrated.entity.CleanUserEntity; +import com.bsd.pjcloud.integrated.service.CleanUserService; +import org.springframework.security.access.prepost.PreAuthorize; +import com.bsd.pjcloud.common.excel.annotation.ResponseExcel; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.http.HttpHeaders; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Objects; + +/** + * 保洁信息 + * + * @author zjf + * @date 2025-08-11 11:07:52 + */ +@RestController +@RequiredArgsConstructor +@RequestMapping("/cleanUser" ) +@Tag(description = "cleanUser" , name = "保洁信息管理" ) +@SecurityRequirement(name = HttpHeaders.AUTHORIZATION) +public class CleanUserController { + + private final CleanUserService cleanUserService; + + /** + * 分页查询 + * @param page 分页对象 + * @param cleanUser 保洁信息 + * @return + */ + @Operation(summary = "分页查询" , description = "分页查询" ) + @GetMapping("/page" ) + @PreAuthorize("@pms.hasPermission('integrated_cleanUser_view')" ) + public R getCleanUserPage(@ParameterObject Page page, @ParameterObject CleanUserEntity cleanUser) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(StrUtil.isNotBlank(cleanUser.getName()),CleanUserEntity::getName,cleanUser.getName()); + wrapper.eq(StrUtil.isNotBlank(cleanUser.getPhone()),CleanUserEntity::getPhone,cleanUser.getPhone()); + return R.ok(cleanUserService.page(page, wrapper)); + } + + + /** + * 通过id查询保洁信息 + * @param id id + * @return R + */ + @Operation(summary = "通过id查询" , description = "通过id查询" ) + @GetMapping("/{id}" ) + @PreAuthorize("@pms.hasPermission('integrated_cleanUser_view')" ) + public R getById(@PathVariable("id" ) Long id) { + return R.ok(cleanUserService.getById(id)); + } + + /** + * 新增保洁信息 + * @param cleanUser 保洁信息 + * @return R + */ + @Operation(summary = "新增保洁信息" , description = "新增保洁信息" ) + @SysLog("新增保洁信息" ) + @PostMapping + @PreAuthorize("@pms.hasPermission('integrated_cleanUser_add')" ) + public R save(@RequestBody CleanUserEntity cleanUser) { + cleanUser.setDeptId(SecurityUtils.getUser().getDeptId()); + return R.ok(cleanUserService.save(cleanUser)); + } + + /** + * 修改保洁信息 + * @param cleanUser 保洁信息 + * @return R + */ + @Operation(summary = "修改保洁信息" , description = "修改保洁信息" ) + @SysLog("修改保洁信息" ) + @PutMapping + @PreAuthorize("@pms.hasPermission('integrated_cleanUser_edit')" ) + public R updateById(@RequestBody CleanUserEntity cleanUser) { + return R.ok(cleanUserService.updateById(cleanUser)); + } + + /** + * 通过id删除保洁信息 + * @param ids id列表 + * @return R + */ + @Operation(summary = "通过id删除保洁信息" , description = "通过id删除保洁信息" ) + @SysLog("通过id删除保洁信息" ) + @DeleteMapping + @PreAuthorize("@pms.hasPermission('integrated_cleanUser_del')" ) + public R removeById(@RequestBody Long[] ids) { + return R.ok(cleanUserService.removeBatchByIds(CollUtil.toList(ids))); + } + + + /** + * 导出excel 表格 + * @param cleanUser 查询条件 + * @param ids 导出指定ID + * @return excel 文件流 + */ + @ResponseExcel + @GetMapping("/export") + @PreAuthorize("@pms.hasPermission('integrated_cleanUser_export')" ) + public List export(CleanUserEntity cleanUser,Long[] ids) { + return cleanUserService.list(Wrappers.lambdaQuery(cleanUser).in(ArrayUtil.isNotEmpty(ids), CleanUserEntity::getId, ids)); + } + + /** + * 获取保洁用户下拉列表 + * @return R + */ + @Operation(summary = "获取保洁用户下拉列表", description = "获取保洁用户下拉列表") + @GetMapping("/dropdown") +// @PreAuthorize("@pms.hasPermission('integrated_cleanUser_view')") + public R getCleanUserDropdown() { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.select(CleanUserEntity::getId, CleanUserEntity::getName, CleanUserEntity::getPhone); + wrapper.orderByAsc(CleanUserEntity::getName); + List list = cleanUserService.list(wrapper); + return R.ok(list); + } +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/NoticeController.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/NoticeController.java index 1a12702f3..8c5ed997a 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/NoticeController.java +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/NoticeController.java @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.bsd.pjcloud.common.core.util.R; import com.bsd.pjcloud.common.log.annotation.SysLog; +import com.bsd.pjcloud.common.security.annotation.Inner; import com.bsd.pjcloud.common.security.util.SecurityUtils; import com.bsd.pjcloud.integrated.entity.NoticeEntity; import com.bsd.pjcloud.integrated.service.NoticeService; @@ -22,6 +23,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import com.bsd.pjcloud.integrated.vo.notice.NoticeScreenVo; import java.util.stream.Collectors; +import com.bsd.pjcloud.integrated.config.ExternalAppConfig; import java.util.List; import java.util.Objects; @@ -40,6 +42,7 @@ import java.util.Objects; public class NoticeController { private final NoticeService noticeService; + private final ExternalAppConfig externalAppConfig; /** * 分页查询 @@ -192,4 +195,72 @@ public class NoticeController { }).collect(Collectors.toList()); return R.ok(voList); } + + /** + * 外部系统滚动通知接口 + * 提供安全的API访问,用于其他系统展示滚动通知 + * @param appId 应用ID + * @param appSecret 应用密钥 + * @param limit 返回条数限制,默认20条 + * @return R + */ + @Operation(summary = "外部系统滚动通知接口", description = "提供安全的API访问,用于其他系统展示滚动通知") + @GetMapping("/external/scroll") + @Inner(value = false) + public R getExternalScrollNotices( + @RequestHeader("X-App-Id") String appId, + @RequestHeader("X-App-Secret") String appSecret, + @RequestParam(defaultValue = "20") Integer limit) { + + // 验证应用ID和密钥 + if (!isValidAppCredentials(appId, appSecret)) { + return R.failed("无效的应用ID或密钥"); + } + + // 限制最大返回条数,防止恶意调用 + if (limit > 50) { + limit = 50; + } + + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(NoticeEntity::getStatus, "0"); // 只查询已发布的公告 + wrapper.orderByDesc(NoticeEntity::getIsTop, NoticeEntity::getCreateTime); // 置顶优先,时间倒序 + wrapper.last("limit " + limit); + + List list = noticeService.list(wrapper); + + // 转换为简化的VO对象,只返回必要信息 + List voList = list.stream().map(e -> { + NoticeScreenVo vo = new NoticeScreenVo(); + vo.setId(e.getId()); + vo.setTitle(e.getTitle()); + vo.setCreateTime(e.getCreateTime()); + vo.setDescription(e.getDescription()); + return vo; + }).collect(Collectors.toList()); + + return R.ok(voList); + } + + /** + * 验证应用ID和密钥 + * @param appId 应用ID + * @param appSecret 应用密钥 + * @return 是否有效 + */ + private boolean isValidAppCredentials(String appId, String appSecret) { + // 从配置中读取有效的应用ID和密钥 + if (StrUtil.isBlank(appId) || StrUtil.isBlank(appSecret)) { + return false; + } + + // 从配置中验证应用凭证 + if (externalAppConfig.getApps() != null) { + return externalAppConfig.getApps().stream() + .filter(ExternalAppConfig.AppCredential::getEnabled) + .anyMatch(app -> appId.equals(app.getAppId()) && appSecret.equals(app.getAppSecret())); + } + + return false; + } } \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/CleanUserEntity.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/CleanUserEntity.java new file mode 100644 index 000000000..6cc5b95db --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/CleanUserEntity.java @@ -0,0 +1,97 @@ +package com.bsd.pjcloud.integrated.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import com.bsd.pjcloud.common.core.util.TenantTable; +import java.time.LocalDateTime; + +/** + * 保洁信息 + * + * @author zjf + * @date 2025-08-11 11:07:52 + */ +@Data +@TenantTable +@TableName("clean_user") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "保洁信息") +public class CleanUserEntity extends Model { + + + /** + * id + */ + @TableId(type = IdType.ASSIGN_ID) + @Schema(description="id") + private Long id; + + /** + * 姓名 + */ + @Schema(description="姓名") + private String name; + + /** + * 手机号 + */ + @Schema(description="手机号") + private String phone; + + /** + * 部门id + */ + @Schema(description="部门id") + private Long deptId; + + /** + * 照片 + */ + @Schema(description="照片") + private String picUrl; + + /** + * 创建者 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description="创建者") + private String createBy; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + @Schema(description="创建时间") + private LocalDateTime createTime; + + /** + * 更新者 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description="更新者") + private String updateBy; + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + @Schema(description="更新时间") + private LocalDateTime updateTime; + + /** + * 是否删除 + */ + @TableLogic + @TableField(fill = FieldFill.INSERT) + @Schema(description="是否删除") + private String delFlag; + + /** + * 租户编号 + */ + @Schema(description="租户编号") + private Long tenantId; +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/mapper/CleanUserMapper.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/mapper/CleanUserMapper.java new file mode 100644 index 000000000..30e9c0db8 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/mapper/CleanUserMapper.java @@ -0,0 +1,11 @@ +package com.bsd.pjcloud.integrated.mapper; + +import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper; +import com.bsd.pjcloud.integrated.entity.CleanUserEntity; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface CleanUserMapper extends PjcloudBaseMapper { + + +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/CleanUserService.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/CleanUserService.java new file mode 100644 index 000000000..1c91dacbf --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/CleanUserService.java @@ -0,0 +1,8 @@ +package com.bsd.pjcloud.integrated.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.integrated.entity.CleanUserEntity; + +public interface CleanUserService extends IService { + +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/CleanUserServiceImpl.java b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/CleanUserServiceImpl.java new file mode 100644 index 000000000..ce687bf0e --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/CleanUserServiceImpl.java @@ -0,0 +1,16 @@ +package com.bsd.pjcloud.integrated.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.bsd.pjcloud.integrated.entity.CleanUserEntity; +import com.bsd.pjcloud.integrated.mapper.CleanUserMapper; +import com.bsd.pjcloud.integrated.service.CleanUserService; +import org.springframework.stereotype.Service; +/** + * 保洁信息 + * + * @author zjf + * @date 2025-08-11 11:07:52 + */ +@Service +public class CleanUserServiceImpl extends ServiceImpl implements CleanUserService { +} \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/application-external-app.yml b/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/application-external-app.yml new file mode 100644 index 000000000..c01fb32a5 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/application-external-app.yml @@ -0,0 +1,29 @@ +# 外部应用配置示例 +# 将此配置添加到你的 application.yml 或 application-{profile}.yml 文件中 + +pjcloud: + external-app: + apps: + # 外部系统1 + - appId: "202501270001" + appSecret: "550e8400-e29b-41d4-a716-446655440001" + appName: "外部系统A" + enabled: true + + # 外部系统2 + - appId: "202501270002" + appSecret: "550e8400-e29b-41d4-a716-446655440002" + appName: "外部系统B" + enabled: true + + # 外部系统3 + - appId: "202501270003" + appSecret: "550e8400-e29b-41d4-a716-446655440003" + appName: "外部系统C" + enabled: true + + # 外部系统4(已禁用) + - appId: "202501270004" + appSecret: "550e8400-e29b-41d4-a716-446655440004" + appName: "外部系统D" + enabled: false \ No newline at end of file diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/application.yml b/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/application.yml index c091aaecc..1fc8795d3 100644 --- a/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/application.yml +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/application.yml @@ -26,3 +26,11 @@ spring: visitor: jwt-secret: "u8Jk2n3Lk4pQ5r6T7s8V9w0X1y2Z3a4B" qr-secret: "Qw8eR2t9Yp3sV6bN1mZ4xT7cL0vB5nH2" # 新增二维码secret,随机生成 + +pjcloud: + external-app: + apps: + - appId: "202501270001" + appSecret: "550e8400-e29b-41d4-a716-446655440001" + appName: "通知公告" + enabled: true diff --git a/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/mapper/CleanUserMapper.xml b/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/mapper/CleanUserMapper.xml new file mode 100644 index 000000000..f02641609 --- /dev/null +++ b/pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/mapper/CleanUserMapper.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpInventoryRecordsServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpInventoryRecordsServiceImpl.java index 5699750ab..1a0a2f1ac 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpInventoryRecordsServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmErpInventoryRecordsServiceImpl.java @@ -107,6 +107,10 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl cgPlanItemEntities = BeanUtils.toBean(items, SmErpInventoryRecordsItemEntity.class); List updateStockDTOS = new ArrayList<>(); + Set units = cgPlanItemEntities.stream().map(s -> s.getUnitId()).collect(Collectors.toSet()); + List smErpUnitEntities = smErpUnitMapper.selectList(new LambdaQueryWrapper().in(SmErpUnitEntity::getId, units)); + Map unitMap = smErpUnitEntities.stream().collect(Collectors.toMap(SmErpUnitEntity::getId, unit -> unit)); + for (SmErpInventoryRecordsItemEntity cgPlanItemEntity : cgPlanItemEntities) { cgPlanItemEntity.setInventoryId(smErpCgDdEntity.getId()); cgPlanItemEntity.setDeptId(deptId); @@ -115,10 +119,11 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl items = inventoryRecordEditDTO.getItems(); List updateStockDTOS = new ArrayList<>(); List smErpInventoryRecordsItemEntityList = new ArrayList<>(); + Set units = items.stream().map(s -> s.getUnitId()).collect(Collectors.toSet()); + List smErpUnitEntities = smErpUnitMapper.selectList(new LambdaQueryWrapper().in(SmErpUnitEntity::getId, units)); + Map unitMap = smErpUnitEntities.stream().collect(Collectors.toMap(SmErpUnitEntity::getId, unit -> unit)); for (InventoryRecordEditItemDTO item : items){ SmErpInventoryRecordsItemEntity smErpInventoryRecordsItemEntity = new SmErpInventoryRecordsItemEntity(); @@ -470,10 +478,11 @@ public class SmErpInventoryRecordsServiceImpl extends ServiceImpl dataBaseSmErpInventoryRecordsItemEntityList = smErpInventoryRecordsItemMapper .selectList(new LambdaQueryWrapper().eq(SmErpInventoryRecordsItemEntity::getInventoryId, inventoryRecordEditDTO.getId())); + + Set unitsRemoved = dataBaseSmErpInventoryRecordsItemEntityList.stream().map(s -> s.getUnitId()).collect(Collectors.toSet()); + List smErpUnitEntitiesRemoved = smErpUnitMapper.selectList(new LambdaQueryWrapper().in(SmErpUnitEntity::getId, unitsRemoved)); + Map unitMapRemoved = smErpUnitEntitiesRemoved.stream().collect(Collectors.toMap(SmErpUnitEntity::getId, unit -> unit)); + //这部分是数据库原本添加的库存数据,需要全部减掉,重新添加更新的库存数据进去 dataBaseSmErpInventoryRecordsItemEntityList.forEach(item -> { + Integer packageNum = unitMapRemoved.get(item.getUnitId()).getPackageNum(); UpdateStockDTO updateStockDTO = new UpdateStockDTO(); updateStockDTO.setId(item.getErpSpuId()); - updateStockDTO.setIncrCount(-item.getQuantity()); + if (item.getOrderType().equals(OrderTypeEnum.RK.getType())){ + updateStockDTO.setIncrCount(-packageNum *item.getQuantity()); + } + if (item.getOrderType().equals(OrderTypeEnum.CK.getType())){ + updateStockDTO.setIncrCount(packageNum *item.getQuantity()); + } updateStockDTOS.add(updateStockDTO); });