diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/dto/CreateTaskRequest.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/dto/CreateTaskRequest.java new file mode 100644 index 0000000..5e81b27 --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/dto/CreateTaskRequest.java @@ -0,0 +1,19 @@ +package org.nl.extInterface.wms.service.dto; + +import com.alibaba.fastjson.JSONObject; +import lombok.Data; + +@Data +public class CreateTaskRequest { + private String houseCode; + private String systemCode; + private JSONObject parameters; + private String taskCode; + private String taskType; + private String taskCreateDateTime; + private String containerCode; + private String containerType; + private String locationFrom; + private String locationTo; + private Integer priority; +} diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/controller/notice/VersionController.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/controller/notice/VersionController.java new file mode 100644 index 0000000..dd7ca5a --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/controller/notice/VersionController.java @@ -0,0 +1,89 @@ +package org.nl.system.controller.notice; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaIgnore; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; +import org.nl.common.domain.query.PageQuery; +import org.nl.system.service.notice.IVersionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +/** + * 版本更新通知控制器 + * + * @author miguannan + * @date 2026-05-06 + */ +@Slf4j +@RestController +@RequestMapping("/api/version") +public class VersionController { + + @Autowired + private IVersionService versionService; + + /** + * 发布版本更新通知 + * + * @param json 版本信息 + * @return ResponseEntity + */ + @PostMapping("/release") + @SaCheckPermission("version:release") + public ResponseEntity release(@RequestBody JSONObject json) { + versionService.releaseVersion(json); + return new ResponseEntity<>(HttpStatus.OK); + } + + /** + * 获取当前版本信息(供前端轮询) + * + * @return 版本信息 + */ + @GetMapping("/current") + @SaIgnore + public ResponseEntity current() { + return new ResponseEntity<>(versionService.getCurrentVersion(), HttpStatus.OK); + } + + /** + * 查询版本通知列表 + * + * @param pageQuery 分页参数 + * @return 版本通知分页数据 + */ + @GetMapping("/list") + @SaCheckPermission("version:list") + public ResponseEntity list(PageQuery pageQuery) { + return new ResponseEntity<>(versionService.listVersions(pageQuery), HttpStatus.OK); + } + + /** + * 修改版本通知 + * + * @param json 通知信息(id, title, content) + * @return ResponseEntity + */ + @PutMapping("/update") + @SaCheckPermission("version:edit") + public ResponseEntity update(@RequestBody JSONObject json) { + versionService.updateVersion(json); + return new ResponseEntity<>(HttpStatus.OK); + } + + /** + * 删除版本通知 + * + * @param id 通知ID + * @return ResponseEntity + */ + @DeleteMapping("/delete/{id}") + @SaCheckPermission("version:del") + public ResponseEntity delete(@PathVariable String id) { + versionService.deleteVersion(id); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/notice/IVersionService.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/notice/IVersionService.java new file mode 100644 index 0000000..89c9e06 --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/notice/IVersionService.java @@ -0,0 +1,53 @@ +package org.nl.system.service.notice; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.metadata.IPage; +import org.nl.common.domain.query.PageQuery; +import org.nl.system.service.notice.dao.SysNotice; + +import java.util.Map; + +/** + * 版本更新通知服务接口 + * + * @author miguannan + * @date 2026-05-06 + */ +public interface IVersionService { + + /** + * 发布版本更新通知 + * + * @param json 版本信息(version, title, content) + */ + void releaseVersion(JSONObject json); + + /** + * 获取当前版本信息 + * + * @return 包含 version、enabled、pollInterval、releaseTime 的 Map + */ + Map getCurrentVersion(); + + /** + * 查询版本通知列表 + * + * @param pageQuery 分页参数 + * @return 版本通知分页数据 + */ + IPage listVersions(PageQuery pageQuery); + + /** + * 修改版本通知 + * + * @param json 通知信息(id, title, content) + */ + void updateVersion(JSONObject json); + + /** + * 删除版本通知 + * + * @param id 通知ID + */ + void deleteVersion(String id); +} diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/notice/impl/VersionServiceImpl.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/notice/impl/VersionServiceImpl.java new file mode 100644 index 0000000..0419626 --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/system/service/notice/impl/VersionServiceImpl.java @@ -0,0 +1,187 @@ +package org.nl.system.service.notice.impl; + + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.nl.common.domain.query.PageQuery; +import lombok.extern.slf4j.Slf4j; +import org.nl.common.enums.NoticeEnum; +import org.nl.common.exception.BadRequestException; +import org.nl.common.mnt.websocket.MsgType; +import org.nl.common.mnt.websocket.SocketMsg; +import org.nl.common.mnt.websocket.WebSocketServer; +import org.nl.system.service.notice.ISysNoticeService; +import org.nl.system.service.notice.IVersionService; +import org.nl.system.service.notice.dao.SysNotice; +import org.nl.system.service.notice.dao.mapper.SysNoticeMapper; +import org.nl.system.service.param.ISysParamService; +import org.nl.system.service.param.dao.Param; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * 版本更新通知服务实现 + * + * @author miguannan + * @date 2026-05-06 + */ +@Slf4j +@Service +public class VersionServiceImpl implements IVersionService { + + @Autowired + private ISysNoticeService noticeService; + + @Autowired + private ISysParamService paramService; + + @Autowired + private SysNoticeMapper noticeMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public void releaseVersion(JSONObject json) { + String version = json.getString("version"); + String title = json.getString("title"); + String content = json.getString("content"); + + if (StrUtil.isBlank(version)) { + throw new BadRequestException("版本号不能为空"); + } + if (StrUtil.isBlank(title)) { + throw new BadRequestException("标题不能为空"); + } + + // 检查是否已有相同版本的未读通知,避免重复发布 + long count = noticeMapper.selectCount(new LambdaQueryWrapper() + .eq(SysNotice::getNotice_type, "version_update") + .likeRight(SysNotice::getNotice_title, version + " ")); + if (count > 0) { + throw new BadRequestException("已存在相同版本发布信息,请先处理后再发布"); + } + + // 1. 创建通知记录 + noticeService.createNotice(content, version + " " + title, "version_update"); + + // 2. 更新系统版本号 + Param appVersionParam = paramService.findByCode("app_version"); + if (appVersionParam == null) { + throw new BadRequestException("系统参数 app_version 不存在,请先执行初始化脚本"); + } + appVersionParam.setValue(version); + paramService.update(appVersionParam); + + // 3. WebSocket 广播给所有在线用户 + JSONObject msgData = new JSONObject(); + msgData.put("data", "version_update"); + msgData.put("version", version); + msgData.put("title", title); + SocketMsg socketMsg = new SocketMsg(msgData, MsgType.INFO); + try { + WebSocketServer.sendInfo(socketMsg, null); + } catch (IOException e) { + log.error("版本更新WebSocket广播失败", e); + } + } + + @Override + public Map getCurrentVersion() { + Map result = new HashMap<>(); + + // 当前版本号 + Param appVersionParam = paramService.findByCode("app_version"); + String version = (appVersionParam != null) ? appVersionParam.getValue() : "1.0.0"; + + // 功能开关 + Param enabledParam = paramService.findByCode("version_notify_enabled"); + boolean enabled = (enabledParam == null) || "true".equals(enabledParam.getValue()); + + // 轮询间隔 + Param intervalParam = paramService.findByCode("version_notify_poll_interval"); + int pollInterval = 30; + if (intervalParam != null && StrUtil.isNotBlank(intervalParam.getValue())) { + try { + pollInterval = Integer.parseInt(intervalParam.getValue()); + } catch (NumberFormatException e) { + log.warn("version_notify_poll_interval 值非法: {}", intervalParam.getValue()); + } + } + + result.put("version", version); + result.put("enabled", enabled); + result.put("pollInterval", pollInterval); + + // 最新版本通知的发布时间 + SysNotice latest = noticeMapper.selectOne(new QueryWrapper() + .eq("notice_type", "version_update") + .orderByDesc("create_time") + .last("LIMIT 1")); + if (latest != null) { + result.put("releaseTime", latest.getCreate_time()); + // notice_title 存储格式为 "version title",分离出版本号和标题 + String noticeTitle = latest.getNotice_title(); + if (StrUtil.isNotBlank(noticeTitle) && noticeTitle.startsWith(version + " ")) { + result.put("title", noticeTitle.substring(version.length() + 1)); + } else { + result.put("title", noticeTitle); + } + result.put("content", latest.getNotice_content()); + } + + return result; + } + + @Override + public IPage listVersions(PageQuery pageQuery) { + LambdaQueryWrapper lam = new LambdaQueryWrapper<>(); + lam.eq(SysNotice::getNotice_type, "version_update") + .orderByDesc(SysNotice::getCreate_time); + IPage pages = new Page<>(pageQuery.getPage() + 1, pageQuery.getSize()); + noticeMapper.selectPage(pages, lam); + return pages; + } + + @Override + public void updateVersion(JSONObject json) { + String id = json.getString("id"); + String title = json.getString("title"); + String content = json.getString("content"); + + if (StrUtil.isBlank(id)) { + throw new BadRequestException("ID不能为空"); + } + if (StrUtil.isBlank(title)) { + throw new BadRequestException("标题不能为空"); + } + + SysNotice notice = noticeMapper.selectById(id); + if (notice == null || !"version_update".equals(notice.getNotice_type())) { + throw new BadRequestException("版本通知不存在"); + } + + notice.setNotice_title(title); + notice.setNotice_content(content); + noticeMapper.updateById(notice); + } + + @Override + public void deleteVersion(String id) { + if (StrUtil.isBlank(id)) { + throw new BadRequestException("ID不能为空"); + } + SysNotice notice = noticeMapper.selectById(id); + if (notice == null || !"version_update".equals(notice.getNotice_type())) { + throw new BadRequestException("版本通知不存在"); + } + noticeMapper.deleteById(id); + } +} diff --git a/acs2/nladmin-ui/src/App.vue b/acs2/nladmin-ui/src/App.vue index e34417a..5a4fd3d 100644 --- a/acs2/nladmin-ui/src/App.vue +++ b/acs2/nladmin-ui/src/App.vue @@ -22,15 +22,27 @@ export default { } }, mounted() { - this.$bus.on('version_update', (msg) => { + this.$bus.on('version_update', msg => { this.checkVersion(msg.version) }) + this.$bus.on('version_check', () => { + this.doVersionCheck() + }) + if (this.$route.path === '/login') { + return + } this.startPolling() - this.checkVersionOnLogin() + if (localStorage.getItem('needVersionCheck') === '1') { + localStorage.removeItem('needVersionCheck') + this.doVersionCheck() + } else { + this.doVersionCheck() + } }, beforeDestroy() { clearInterval(this.pollTimer) this.$bus.off('version_update') + this.$bus.off('version_check') }, methods: { moveEvent: function() { @@ -58,9 +70,10 @@ export default { } this.$refs.versionDialog.show(serverVersion) }, - checkVersionOnLogin() { - const token = localStorage.getItem('token') || sessionStorage.getItem('token') - if (!token) return + /** + * 执行版本检查(登录后或手动触发) + */ + doVersionCheck() { getCurrentVersion().then(res => { if (!res.enabled) return this.checkVersion(res.version) diff --git a/acs2/nladmin-ui/src/api/system/version.js b/acs2/nladmin-ui/src/api/system/version.js index b65fa6b..92d02cd 100644 --- a/acs2/nladmin-ui/src/api/system/version.js +++ b/acs2/nladmin-ui/src/api/system/version.js @@ -24,4 +24,41 @@ export function releaseVersion(data) { }) } -export default { getCurrentVersion, releaseVersion } +/** + * 查询版本通知列表 + * @returns {AxiosPromise} + */ +export function listVersions(params) { + return request({ + url: '/api/version/list', + method: 'get', + params + }) +} + +/** + * 修改版本通知 + * @param {Object} data - { id, title, content } + * @returns {AxiosPromise} + */ +export function updateVersion(data) { + return request({ + url: '/api/version/update', + method: 'put', + data + }) +} + +/** + * 删除版本通知 + * @param {string} id + * @returns {AxiosPromise} + */ +export function deleteVersion(id) { + return request({ + url: '/api/version/delete/' + id, + method: 'delete' + }) +} + +export default { getCurrentVersion, releaseVersion, listVersions, updateVersion, deleteVersion } diff --git a/acs2/nladmin-ui/src/components/VersionNotification/VersionNotification.vue b/acs2/nladmin-ui/src/components/VersionNotification/VersionNotification.vue index b4c2c5e..b20ca54 100644 --- a/acs2/nladmin-ui/src/components/VersionNotification/VersionNotification.vue +++ b/acs2/nladmin-ui/src/components/VersionNotification/VersionNotification.vue @@ -12,6 +12,10 @@ {{ $t('auto.version.versionNo') }}: v{{ versionInfo.version }} +
+ {{ $t('auto.version.noticeTitle') }}: + {{ versionInfo.title }} +
{{ $t('auto.version.releaseTime') }}: {{ versionInfo.releaseTime }} @@ -37,6 +41,7 @@ export default { dialogVisible: false, versionInfo: { version: '', + title: '', releaseTime: '', content: '' } @@ -65,19 +70,17 @@ export default { getCurrentVersion().then(res => { if (!res.enabled) return this.versionInfo.version = res.version || serverVersion + this.versionInfo.title = res.title || '' this.versionInfo.releaseTime = res.releaseTime || '' - this.fetchVersionContent() + this.versionInfo.content = res.content || '' this.dialogVisible = true }) }, - fetchVersionContent() { - // 从站内信获取最新的版本通知内容 - // 内容通过后端 /api/version/current 返回的 releaseTime 已含, - // 如果需要额外展示详细内容,可调用通知接口查询 - }, handleConfirm() { localStorage.setItem('lastSeenVersion', this.versionInfo.version) this.dialogVisible = false + // 点击后跳转到版本信息页面 + this.$router.push('/system/version') } } } diff --git a/acs2/nladmin-ui/src/views/login.vue b/acs2/nladmin-ui/src/views/login.vue index c1e48e6..7b5f440 100644 --- a/acs2/nladmin-ui/src/views/login.vue +++ b/acs2/nladmin-ui/src/views/login.vue @@ -3,22 +3,21 @@ - + :particle-opacity="0.7" + :particles-number="80" + shape-type="circle" + :particle-size="4" + lines-color="#dedede" + :lines-width="1" + :line-linked="true" + :line-opacity="0.4" + :lines-distance="150" + :move-speed="3" + :hover-effect="true" + hover-mode="grab" + :click-effect="true" + click-mode="push" + />