diff --git a/.codex/skills/query-shz-highgo/scripts/write.sh b/.codex/skills/query-shz-highgo/scripts/write.sh new file mode 100644 index 0000000..16d91a2 --- /dev/null +++ b/.codex/skills/query-shz-highgo/scripts/write.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +set -euo pipefail + +skill_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +password_file="${HIGHGO_PASSWORD_FILE:-$skill_dir/.password}" + +ssh_host="root@124.243.245.42" +psql_path="/opt/HighGo4.5.7-see/bin/psql" +db_host="39.98.44.136" +db_port="6023" +db_name="highgo" +db_user="sysdba" + +if [[ ! -r "$password_file" ]]; then + echo "HighGo password file is missing or unreadable: $password_file" >&2 + exit 2 +fi + +if [[ $# -eq 0 ]]; then + echo "Usage: $0 'SQL_STATEMENT'" >&2 + exit 2 +fi + +sql="$*" +sql_without_final_semicolon="${sql%;}" +if [[ "$sql_without_final_semicolon" == *';'* ]]; then + echo "Rejected: multiple SQL statements are not allowed. Run them one at a time." >&2 + exit 3 +fi + +password="$(<"$password_file")" +sql_base64="$(printf '%s' "$sql" | base64 | tr -d '\n')" + +{ + printf '%s\n' "$password" + printf '%s\n' "$sql_base64" +} | ssh -o BatchMode=yes -o ConnectTimeout=10 "$ssh_host" \ + "read -r PGPASSWORD; read -r SQL_BASE64; export PGPASSWORD; export PGOPTIONS='-c search_path=shz,public -c statement_timeout=30000'; SQL=\$(printf '%s' \"\$SQL_BASE64\" | base64 -d); exec '$psql_path' -X --no-psqlrc -h '$db_host' -p '$db_port' -U '$db_user' -d '$db_name' -v ON_ERROR_STOP=1 -P pager=off -c \"\$SQL\"" diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/CmsFileController.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/CmsFileController.java new file mode 100644 index 0000000..bb6cfb4 --- /dev/null +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/controller/cms/CmsFileController.java @@ -0,0 +1,66 @@ +package com.ruoyi.cms.controller.cms; + +import java.util.List; +import java.util.Map; + +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.File; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.cms.service.IFileService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +/** + * 后台:风采文件审核管理 + * + * @author admin + * @date 2026-07-07 + */ +@RestController +@RequestMapping("/cms/file") +@Api(tags = "后台:风采审核管理") +public class CmsFileController extends BaseController { + + @Autowired + private IFileService fileService; + + @ApiOperation("风采审核列表") + @PreAuthorize("@ss.hasPermi('cms:showcase:review:list')") + @GetMapping("/review/list") + public TableDataInfo reviewList(File file) { + startPage(); + List list = fileService.selectFileListForReview(file); + return getDataTable(list); + } + + @ApiOperation("风采审核(通过/驳回)") + @PreAuthorize("@ss.hasPermi('cms:showcase:review')") + @PutMapping("/review/{id}") + public AjaxResult review(@PathVariable Long id, @RequestBody Map body) { + String reviewStatus = body.get("reviewStatus"); + validateReviewStatus(reviewStatus); + + String reviewRemark = body.get("reviewRemark"); + validateRejectRemark(reviewStatus, reviewRemark); + + String reviewBy = getUsername(); + return toAjax(fileService.reviewFile(id, reviewStatus, reviewRemark, reviewBy)); + } + + private void validateReviewStatus(String reviewStatus) { + if (!"1".equals(reviewStatus) && !"2".equals(reviewStatus)) { + throw new ServiceException("审核状态不正确,只能为 1(通过) 或 2(驳回)"); + } + } + + private void validateRejectRemark(String reviewStatus, String reviewRemark) { + if ("2".equals(reviewStatus) && (reviewRemark == null || reviewRemark.trim().isEmpty())) { + throw new ServiceException("驳回时请填写原因"); + } + } +} diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/FileMapper.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/FileMapper.java index b4bdf13..e888fda 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/FileMapper.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/mapper/FileMapper.java @@ -26,4 +26,9 @@ public interface FileMapper extends BaseMapper public List selectFileListByBussinessIds(@Param("longs") List longs); public int updateIds(@Param("longs") List longs,@Param("newBussinessid") Long bussinessid); + + /** + * 查询风采审核列表(后台管理用) + */ + public List selectFileListForReview(File file); } diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IFileService.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IFileService.java index 4e1b0aa..6e945ca 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IFileService.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/IFileService.java @@ -58,4 +58,20 @@ public interface IFileService AjaxResult upload(MultipartFile file, Long bussinessid); AjaxResult uploadFile(MultipartFile file, Long bussinessid, HttpServletRequest request); + + /** + * 查询风采审核列表(后台管理用) + */ + public List selectFileListForReview(File file); + + /** + * 审核风采文件 + * + * @param id 文件ID + * @param reviewStatus 审核状态 1=通过 2=驳回 + * @param reviewRemark 审核备注(驳回时必填) + * @param reviewBy 审核人 + * @return 结果 + */ + public int reviewFile(Long id, String reviewStatus, String reviewRemark, String reviewBy); } diff --git a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/FileServiceImpl.java b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/FileServiceImpl.java index 40b4a2a..29aa7d8 100644 --- a/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/FileServiceImpl.java +++ b/ruoyi-bussiness/src/main/java/com/ruoyi/cms/service/impl/FileServiceImpl.java @@ -12,6 +12,7 @@ import com.ruoyi.common.core.domain.entity.File; import com.ruoyi.cms.mapper.FileMapper; import com.ruoyi.cms.service.IFileService; import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.uuid.UUID; import org.springframework.beans.factory.annotation.Autowired; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -171,4 +172,25 @@ public class FileServiceImpl extends ServiceImpl implements IF this.save(file); return file; } + + @Override + public List selectFileListForReview(File file) { + return fileMapper.selectFileListForReview(file); + } + + @Override + public int reviewFile(Long id, String reviewStatus, String reviewRemark, String reviewBy) { + File existing = fileMapper.selectById(id); + if (existing == null) { + throw new ServiceException("文件不存在"); + } + if (existing.getReviewStatus() != null && !"0".equals(existing.getReviewStatus())) { + throw new ServiceException("该记录已审核,请勿重复操作"); + } + existing.setReviewStatus(reviewStatus); + existing.setReviewRemark(reviewRemark); + existing.setReviewBy(reviewBy); + existing.setReviewTime(new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date())); + return fileMapper.updateById(existing); + } } diff --git a/ruoyi-bussiness/src/main/resources/mapper/app/FileMapper.xml b/ruoyi-bussiness/src/main/resources/mapper/app/FileMapper.xml index 29c3320..5da9d44 100644 --- a/ruoyi-bussiness/src/main/resources/mapper/app/FileMapper.xml +++ b/ruoyi-bussiness/src/main/resources/mapper/app/FileMapper.xml @@ -13,10 +13,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + - select id, file_url, bussinessid, del_flag, create_by, create_time, update_by, update_time from file + select id, file_url, bussinessid, del_flag, create_by, create_time, update_by, update_time, review_status, review_remark, review_by, review_time from file + + update file diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/File.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/File.java index e67f28a..62a1c42 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/File.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/File.java @@ -34,4 +34,16 @@ public class File extends BaseEntity @ApiModelProperty("业务id") private Long bussinessid; + @ApiModelProperty("审核状态 0待审核 1审核通过 2审核未通过") + private String reviewStatus; + + @ApiModelProperty("审核备注") + private String reviewRemark; + + @ApiModelProperty("审核人") + private String reviewBy; + + @ApiModelProperty("审核时间") + private String reviewTime; + } diff --git a/sql/migration_showcase_review.sql b/sql/migration_showcase_review.sql new file mode 100644 index 0000000..60c4f48 --- /dev/null +++ b/sql/migration_showcase_review.sql @@ -0,0 +1,51 @@ +-- ============================================= +-- 风采审核功能 — 数据库迁移 +-- 在 file 表新增审核相关字段 +-- 执行方式: 逐条执行以下 ALTER TABLE 语句 +-- 注意: 当前库 file 表在 shz schema 下(由 currentSchema 决定),无需加 schema 前缀 +-- ============================================= + +ALTER TABLE "shz"."file" ADD COLUMN "review_status" char(1) DEFAULT '0'; +COMMENT ON COLUMN "shz"."file"."review_status" IS '审核状态:0-待审核,1-审核通过,2-审核未通过'; + +ALTER TABLE "shz"."file" ADD COLUMN "review_remark" text; +COMMENT ON COLUMN "shz"."file"."review_remark" IS '审核备注(驳回原因)'; + +ALTER TABLE "shz"."file" ADD COLUMN "review_by" varchar(64); +COMMENT ON COLUMN "shz"."file"."review_by" IS '审核人'; + +ALTER TABLE "shz"."file" ADD COLUMN "review_time" timestamp(0); +COMMENT ON COLUMN "shz"."file"."review_time" IS '审核时间'; + +-- 可选:将已有数据批量设为审核通过 +-- UPDATE "shz"."file" SET "review_status" = '1' WHERE "review_status" IS NULL OR "review_status" = '0'; + +-- ============================================= +-- 菜单和权限配置(通过后台菜单管理页面配置,或执行以下 SQL) +-- 注意: parent_id 和 order_num 请根据实际菜单结构调整 +-- ============================================= + +-- 1. 新增菜单: 风采审核(请替换 parent_id 为实际的 management 菜单 ID) +-- INSERT INTO "shz"."sys_menu" ( +-- "menu_name", "parent_id", "order_num", "path", "component", +-- "visible", "status", "perms", "icon", "menu_type" +-- ) VALUES ( +-- '风采审核', , 10, +-- 'management/showcase-review', 'Management/ShowcaseReview', +-- '0', '0', 'cms:showcase:review:list', 'audit', 'C' +-- ); + +-- 2. 给管理员角色授权(请替换 role_id 为实际的管理员角色 ID) +-- INSERT INTO "shz"."sys_role_menu" ("role_id", "menu_id") +-- SELECT , "menu_id" FROM "shz"."sys_menu" +-- WHERE "perms" = 'cms:showcase:review:list'; + +-- 3. 如果用角色-权限直接关联方式,可执行: +-- 先在 sys_menu 中创建按钮级权限: +-- INSERT INTO "shz"."sys_menu" ( +-- "menu_name", "parent_id", "order_num", "path", "component", +-- "visible", "status", "perms", "menu_type" +-- ) VALUES +-- ('风采审核列表', <风采审核_menu_id>, 1, '', '', '0', '0', 'cms:showcase:review:list', 'F'), +-- ('风采审核操作', <风采审核_menu_id>, 2, '', '', '0', '0', 'cms:showcase:review', 'F'); +-- 然后将这些权限分配给需要的角色