From 7c7c55d90e61d86f1c20f12719b5d3f11372f7c4 Mon Sep 17 00:00:00 2001
From: zjf <1799650030@qq.com>
Date: Mon, 11 Aug 2025 17:14:22 +0800
Subject: [PATCH 1/5] =?UTF-8?q?=E9=80=9A=E7=9F=A5=E5=85=AC=E5=91=8A?=
=?UTF-8?q?=EF=BC=8C=E4=BC=9A=E8=AE=AE=E4=BF=9D=E6=B4=81=E6=B7=BB=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../API-INTEGRATION-GUIDE.md | 387 ++++++++++++++++++
.../README-EXTERNAL-API.md | 98 +++++
.../integrated/config/ExternalAppConfig.java | 51 +++
.../controller/CleanUserController.java | 139 +++++++
.../controller/NoticeController.java | 70 ++++
.../integrated/entity/CleanUserEntity.java | 97 +++++
.../integrated/mapper/CleanUserMapper.java | 11 +
.../integrated/service/CleanUserService.java | 8 +
.../service/impl/CleanUserServiceImpl.java | 16 +
.../resources/application-external-app.yml | 29 ++
.../src/main/resources/application.yml | 8 +
.../main/resources/mapper/CleanUserMapper.xml | 19 +
12 files changed, 933 insertions(+)
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/API-INTEGRATION-GUIDE.md
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/README-EXTERNAL-API.md
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/config/ExternalAppConfig.java
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/controller/CleanUserController.java
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/entity/CleanUserEntity.java
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/mapper/CleanUserMapper.java
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/CleanUserService.java
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/src/main/java/com/bsd/pjcloud/integrated/service/impl/CleanUserServiceImpl.java
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/application-external-app.yml
create mode 100644 pjcloud-integrated/pjcloud-integrated-biz/src/main/resources/mapper/CleanUserMapper.xml
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..4c47aae07 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,71 @@ 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.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
From f105a19caf32b6ec53e3d984a04de4370d1888cc Mon Sep 17 00:00:00 2001
From: zjf <1799650030@qq.com>
Date: Tue, 12 Aug 2025 00:22:29 +0800
Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=9B=B4=E6=96=B0?=
=?UTF-8?q?=E5=BA=93=E5=AD=98*=E5=86=85=E8=A3=85=E6=95=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../SmErpInventoryRecordsServiceImpl.java | 30 +++++++++++++++----
1 file changed, 25 insertions(+), 5 deletions(-)
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);
});
From d40694c61e03d243baf2afa99349593d4b8fc9c4 Mon Sep 17 00:00:00 2001
From: zjf <1799650030@qq.com>
Date: Tue, 12 Aug 2025 10:08:34 +0800
Subject: [PATCH 3/5] =?UTF-8?q?=E9=80=9A=E7=9F=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../com/bsd/pjcloud/integrated/vo/notice/NoticeScreenVo.java | 2 ++
.../com/bsd/pjcloud/integrated/controller/NoticeController.java | 1 +
2 files changed, 3 insertions(+)
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/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 4c47aae07..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
@@ -232,6 +232,7 @@ public class NoticeController {
// 转换为简化的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());
From b432b803248fb2f5e158eaac669e85db554d81a4 Mon Sep 17 00:00:00 2001
From: zjf <1799650030@qq.com>
Date: Tue, 12 Aug 2025 14:35:53 +0800
Subject: [PATCH 4/5] =?UTF-8?q?=E9=A3=9F=E5=A0=82=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../CanteenOnlineSpuSaveDto.java | 34 +++++++++++
.../CanteenOnlineSpuSaveItemDto.java | 57 +++++++++++++++++++
.../entity/CanteenOnlineCategoryEntity.java | 3 +
.../entity/CanteenOnlineSpuEntity.java | 3 +
.../CanteenOnlineSpuController.java | 11 +++-
.../service/CanteenOnlineSpuService.java | 19 +++++++
.../impl/CanteenOnlineSpuServiceImpl.java | 53 +++++++++++++++++
.../mapper/CanteenOnlineCategoryMapper.xml | 2 +
.../mapper/CanteenOnlineSpuMapper.xml | 1 +
9 files changed, 182 insertions(+), 1 deletion(-)
create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveDto.java
create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/canteenonline/CanteenOnlineSpuSaveItemDto.java
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..b152d679d 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
*
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..f202a84af 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;
@@ -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..51fb152ba 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,31 @@
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.CanteenOnlineCategoryEntity;
import com.bsd.pjcloud.canteen.entity.CanteenOnlineSpuEntity;
+import com.bsd.pjcloud.canteen.mapper.CanteenCategoryMapper;
+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,7 +34,12 @@ 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;
@Override
public R> getCanteenOnlineSpuList(String categoryId, String merchantId) {
LambdaQueryWrapper canteenOnlineSpuEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
@@ -50,4 +68,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
From 94e6a9428d0ab1d82ba04655d292c44fc66a6b4c Mon Sep 17 00:00:00 2001
From: zjf <1799650030@qq.com>
Date: Tue, 12 Aug 2025 15:11:00 +0800
Subject: [PATCH 5/5] =?UTF-8?q?=E9=A3=9F=E5=A0=82=E9=A2=84=E5=AE=9A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../CanteenOnlineSpuController.java | 5 +++--
.../service/CanteenOnlineSpuService.java | 2 +-
.../impl/CanteenOnlineSpuServiceImpl.java | 20 +++++++++++++++++--
3 files changed, 22 insertions(+), 5 deletions(-)
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 b152d679d..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
@@ -155,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 f202a84af..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
@@ -21,7 +21,7 @@ public interface CanteenOnlineSpuService extends IService> getCanteenOnlineSpuList(String categoryId, String merchantId);
+ R> getCanteenOnlineSpuList(String categoryId, String merchantId,String time);
/**
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 51fb152ba..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
@@ -7,9 +7,11 @@ 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;
@@ -40,13 +42,27 @@ public class CanteenOnlineSpuServiceImpl extends ServiceImpl> 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);
}