From b41cf77cac8785595d403ca270d0702e9660a5ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=83=AD=E5=BA=86=E6=B3=B0?= <12369755+htcloud1@user.noreply.gitee.com> Date: Mon, 17 Aug 2026 01:15:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(publicity):=20=E5=85=AC=E7=A4=BA=E9=A1=B5?= =?UTF-8?q?=E6=94=AF=E6=8C=81/=E6=89=A7=E8=A1=8C=E6=84=8F=E5=90=91=20(?= =?UTF-8?q?=E5=8C=BF=E5=90=8D=E6=8F=90=E4=BA=A4=20+=20=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=AE=A1=E6=A0=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 biz_publicity_support_intent / biz_publicity_execution_intent 两张独立表 (与已登录视角的 biz_support_intent / biz_execution_intent 解耦, 避免匿名数据污染强绑表) - 后端 BizPublicityIntentController: 公开提交 + 公开查重 (按 project_id+phone+source) + 管理 CRUD 已登录直接取 user_id, 未登录但 phone 命中 sys_user 仍自动关联 user_id (不回强制登录) - /business/publicity/** 加 Spring Security permitAll - 前端 PublicityDetail.vue: 右侧 2 个意向按钮 (已登录/匿名都弹 dialog 填 5 字段), 已提交状态用 hasPublicityIntent 按 phonenumber 持久化查回 - 重写 manager/SupportIntent.vue + manager/ExecIntent.vue: 列表/筛选/CSV导出/状态变更/批量删除 --- .../BizPublicityIntentController.java | 208 ++++++++++++++++++ .../domain/BizPublicityExecutionIntent.java | 86 ++++++++ .../domain/BizPublicitySupportIntent.java | 86 ++++++++ .../BizPublicityExecutionIntentMapper.java | 18 ++ .../BizPublicitySupportIntentMapper.java | 18 ++ .../IBizPublicityExecutionIntentService.java | 15 ++ .../IBizPublicitySupportIntentService.java | 15 ++ ...izPublicityExecutionIntentServiceImpl.java | 26 +++ .../BizPublicitySupportIntentServiceImpl.java | 26 +++ .../BizPublicityExecutionIntentMapper.xml | 114 ++++++++++ .../BizPublicitySupportIntentMapper.xml | 114 ++++++++++ .../framework/config/SecurityConfig.java | 2 +- ry-vue3/src/api/public.js | 37 ++++ ry-vue3/src/views/manager/ExecIntent.vue | 141 ++++++++++-- ry-vue3/src/views/manager/SupportIntent.vue | 146 ++++++++++-- ry-vue3/src/views/portal/PublicityDetail.vue | 158 ++++++++++++- 16 files changed, 1168 insertions(+), 42 deletions(-) create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/controller/BizPublicityIntentController.java create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizPublicityExecutionIntent.java create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizPublicitySupportIntent.java create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BizPublicityExecutionIntentMapper.java create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BizPublicitySupportIntentMapper.java create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/IBizPublicityExecutionIntentService.java create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/IBizPublicitySupportIntentService.java create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizPublicityExecutionIntentServiceImpl.java create mode 100644 ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizPublicitySupportIntentServiceImpl.java create mode 100644 ry-api/ruoyi-business/src/main/resources/mapper/business/BizPublicityExecutionIntentMapper.xml create mode 100644 ry-api/ruoyi-business/src/main/resources/mapper/business/BizPublicitySupportIntentMapper.xml diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/controller/BizPublicityIntentController.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/controller/BizPublicityIntentController.java new file mode 100644 index 0000000..cc80537 --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/controller/BizPublicityIntentController.java @@ -0,0 +1,208 @@ +package com.ruoyi.business.controller; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.business.domain.BizProject; +import com.ruoyi.business.domain.BizPublicityExecutionIntent; +import com.ruoyi.business.domain.BizPublicitySupportIntent; +import com.ruoyi.business.service.IBizProjectService; +import com.ruoyi.business.service.IBizPublicityExecutionIntentService; +import com.ruoyi.business.service.IBizPublicitySupportIntentService; +import com.ruoyi.system.mapper.SysUserMapper; + +/** + * 公示页意向 Controller (匿名 + 管理后台共用) + * + * 公开端点 (公开门户 + 匿名访客可调): + * - POST /business/publicity/supportIntent 提交支持意向 + * - POST /business/publicity/executionIntent 提交执行意向 + * - GET /business/publicity/hasIntent 查"是否已提交" (按 projectId + phone + type) + * + * 管理端点 (manager / admin 后台列表, 复用通用 /list /{id} / POST / PUT / DELETE): + * - /business/publicitySupportIntent/... + * - /business/publicityExecutionIntent/... + */ +@RestController +public class BizPublicityIntentController extends BaseController { + + @Autowired private IBizProjectService bizProjectService; + @Autowired private IBizPublicitySupportIntentService supportIntentService; + @Autowired private IBizPublicityExecutionIntentService executionIntentService; + @Autowired private SysUserMapper sysUserMapper; + + private static final String SOURCE_PUBLICITY = "publicity"; + + // ============== 公开端点: 提交 ============== + + /** + * 提交支持意向 (公开) + * POST /business/publicity/supportIntent + * body: { projectId, name, phone, workUnit, department?, position? } + * 已登录自动回填 user_id + */ + @Log(title = "公示页-支持意向", businessType = BusinessType.INSERT) + @PostMapping("/business/publicity/supportIntent") + public AjaxResult submitSupportIntent(@RequestBody BizPublicitySupportIntent intent) { + return doSubmit(intent, supportIntentService); + } + + /** + * 提交执行意向 (公开) + */ + @Log(title = "公示页-执行意向", businessType = BusinessType.INSERT) + @PostMapping("/business/publicity/executionIntent") + public AjaxResult submitExecutionIntent(@RequestBody BizPublicityExecutionIntent intent) { + return doSubmit(intent, executionIntentService); + } + + /** 通用提交逻辑 (支持 + 执行 同构) */ + private AjaxResult doSubmit(T rawIntent, Object service) { + // 取通用字段 + Long projectId = null; + String name = null, phone = null, workUnit = null, department = null, position = null; + if (rawIntent instanceof BizPublicitySupportIntent) { + BizPublicitySupportIntent i = (BizPublicitySupportIntent) rawIntent; + projectId = i.getProjectId(); name = i.getName(); phone = i.getPhone(); + workUnit = i.getWorkUnit(); department = i.getDepartment(); position = i.getPosition(); + } else if (rawIntent instanceof BizPublicityExecutionIntent) { + BizPublicityExecutionIntent i = (BizPublicityExecutionIntent) rawIntent; + projectId = i.getProjectId(); name = i.getName(); phone = i.getPhone(); + workUnit = i.getWorkUnit(); department = i.getDepartment(); position = i.getPosition(); + } + if (projectId == null) return error("projectId 不能为空"); + if (name == null || name.trim().isEmpty()) return error("姓名不能为空"); + if (phone == null || phone.trim().isEmpty()) return error("手机号不能为空"); + if (workUnit == null || workUnit.trim().isEmpty()) return error("工作单位不能为空"); + // 反查项目 no/name 写冗余 + BizProject proj = bizProjectService.getById(String.valueOf(projectId)); + if (proj == null) return error("项目不存在"); + // 查重 (按 project_id + phone + source) + Object dup; + if (service instanceof IBizPublicitySupportIntentService) { + dup = ((IBizPublicitySupportIntentService) service).findDuplicate(projectId, phone, SOURCE_PUBLICITY); + } else { + dup = ((IBizPublicityExecutionIntentService) service).findDuplicate(projectId, phone, SOURCE_PUBLICITY); + } + if (dup != null) return error("您已提交过该意向"); + // 回填 user_id + createBy: + // 1) 已登录直接取当前用户 + // 2) 未登录但 phone 能匹配到 sys_user → 仍回填 userId (账号自动关联, 不需要登录) + // 3) 完全匿名 → 两者都为空 + String createBy = null; + Long userId = null; + try { + if (SecurityUtils.getUsername() != null && !"anonymous".equals(SecurityUtils.getUsername())) { + createBy = SecurityUtils.getUsername(); + userId = SecurityUtils.getUserId(); + } + } catch (Exception ignore) { /* 匿名 */ } + if (userId == null && phone != null && !phone.isEmpty()) { + try { + com.ruoyi.common.core.domain.entity.SysUser u = sysUserMapper.checkPhoneUnique(phone); + if (u != null && u.getUserId() != null) { + userId = u.getUserId(); + // 匿名场景下也补一下 createBy (虽然表里没强制要求, 但便于审计) + if (createBy == null) createBy = u.getUserName(); + } + } catch (Exception ignore) { /* 表不存在等 */ } + } + // 写入 + int n; + if (rawIntent instanceof BizPublicitySupportIntent) { + BizPublicitySupportIntent i = (BizPublicitySupportIntent) rawIntent; + i.setProjectNo(proj.getProjectNo()); + i.setProjectName(proj.getProjectName()); + i.setSource(SOURCE_PUBLICITY); + i.setIntentStatus("待审核"); + i.setUserId(userId); + i.setCreateBy(createBy); + n = supportIntentService.insert(i); + return n > 0 ? success(i) : error("提交失败"); + } else { + BizPublicityExecutionIntent i = (BizPublicityExecutionIntent) rawIntent; + i.setProjectNo(proj.getProjectNo()); + i.setProjectName(proj.getProjectName()); + i.setSource(SOURCE_PUBLICITY); + i.setIntentStatus("待审核"); + i.setUserId(userId); + i.setCreateBy(createBy); + n = executionIntentService.insert(i); + return n > 0 ? success(i) : error("提交失败"); + } + } + + /** + * 持久化"已提交"查询 (公开) + * GET /business/publicity/hasIntent?projectId=&phone=&type=support|execution + * 按 (project_id, phone, source='publicity') 查重 + */ + @GetMapping("/business/publicity/hasIntent") + public AjaxResult hasIntent(@RequestParam("projectId") Long projectId, + @RequestParam("phone") String phone, + @RequestParam("type") String type) { + if (projectId == null || phone == null || phone.isEmpty()) return success(false); + boolean exists; + if ("execution".equalsIgnoreCase(type)) { + exists = executionIntentService.findDuplicate(projectId, phone, SOURCE_PUBLICITY) != null; + } else { + // 默认 support + exists = supportIntentService.findDuplicate(projectId, phone, SOURCE_PUBLICITY) != null; + } + return success(exists); + } + + // ============== 管理端点: 列表 + CRUD (manager / admin 后台) ============== + + /** 支持意向列表 (分页, 与现有 /business/supportIntent/list 一致格式) */ + @GetMapping("/business/publicitySupportIntent/list") + public TableDataInfo listSupport(BizPublicitySupportIntent intent) { + startPage(); + List list = supportIntentService.selectList(intent); + return getDataTable(list); + } + @GetMapping("/business/publicitySupportIntent/{intentId}") + public AjaxResult getSupport(@PathVariable("intentId") Long intentId) { + return success(supportIntentService.getById(intentId)); + } + @Log(title = "公示页-支持意向", businessType = BusinessType.UPDATE) + @PutMapping("/business/publicitySupportIntent") + public AjaxResult editSupport(@RequestBody BizPublicitySupportIntent intent) { + try { intent.setUpdateBy(SecurityUtils.getUsername()); } catch (Exception ignore) {} + return toAjax(supportIntentService.updateByPrimaryKey(intent)); + } + @Log(title = "公示页-支持意向", businessType = BusinessType.DELETE) + @DeleteMapping("/business/publicitySupportIntent/{ids}") + public AjaxResult removeSupport(@PathVariable Long[] ids) { + return toAjax(supportIntentService.deleteByPrimaryKeys(ids)); + } + + /** 执行意向列表 */ + @GetMapping("/business/publicityExecutionIntent/list") + public TableDataInfo listExecution(BizPublicityExecutionIntent intent) { + startPage(); + List list = executionIntentService.selectList(intent); + return getDataTable(list); + } + @GetMapping("/business/publicityExecutionIntent/{intentId}") + public AjaxResult getExecution(@PathVariable("intentId") Long intentId) { + return success(executionIntentService.getById(intentId)); + } + @Log(title = "公示页-执行意向", businessType = BusinessType.UPDATE) + @PutMapping("/business/publicityExecutionIntent") + public AjaxResult editExecution(@RequestBody BizPublicityExecutionIntent intent) { + try { intent.setUpdateBy(SecurityUtils.getUsername()); } catch (Exception ignore) {} + return toAjax(executionIntentService.updateByPrimaryKey(intent)); + } + @Log(title = "公示页-执行意向", businessType = BusinessType.DELETE) + @DeleteMapping("/business/publicityExecutionIntent/{ids}") + public AjaxResult removeExecution(@PathVariable Long[] ids) { + return toAjax(executionIntentService.deleteByPrimaryKeys(ids)); + } +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizPublicityExecutionIntent.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizPublicityExecutionIntent.java new file mode 100644 index 0000000..7f649d2 --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizPublicityExecutionIntent.java @@ -0,0 +1,86 @@ +package com.ruoyi.business.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 公示页-执行意向 (匿名快照, 与 sys_user 解耦) + * 数据源: /publicity/:projectId 页面 "表达执行意向" 按钮 + * 与 biz_execution_intent (旧表, 已登录专家报名流程) 语义不同, 物理表独立 + */ +public class BizPublicityExecutionIntent extends BaseEntity { + private static final long serialVersionUID = 1L; + /** intent_id */ + private Long intentId; + /** project_id (biz_project.project_id) */ + @Excel(name = "project_id") + private Long projectId; + /** project_no (冗余) */ + @Excel(name = "project_no") + private String projectNo; + /** project_name (冗余) */ + @Excel(name = "project_name") + private String projectName; + /** user_id (已登录时回填 sys_user.user_id, 未登录 NULL) */ + @Excel(name = "user_id") + private Long userId; + /** name */ + @Excel(name = "name") + private String name; + /** phone */ + @Excel(name = "phone") + private String phone; + /** work_unit 工作单位名称 */ + @Excel(name = "work_unit") + private String workUnit; + /** department 部门 */ + @Excel(name = "department") + private String department; + /** position 职务 */ + @Excel(name = "position") + private String position; + /** source 来源 publicity=公示页 */ + @Excel(name = "source") + private String source; + /** intent_status 状态 (待审核/已采纳/已拒绝) */ + @Excel(name = "intent_status") + private String intentStatus; + /** remark 备注 */ + private String remark; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + public Long getIntentId() { return intentId; } + public void setIntentId(Long intentId) { this.intentId = intentId; } + public Long getProjectId() { return projectId; } + public void setProjectId(Long projectId) { this.projectId = projectId; } + public String getProjectNo() { return projectNo; } + public void setProjectNo(String projectNo) { this.projectNo = projectNo; } + public String getProjectName() { return projectName; } + public void setProjectName(String projectName) { this.projectName = projectName; } + public Long getUserId() { return userId; } + public void setUserId(Long userId) { this.userId = userId; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + public String getWorkUnit() { return workUnit; } + public void setWorkUnit(String workUnit) { this.workUnit = workUnit; } + public String getDepartment() { return department; } + public void setDepartment(String department) { this.department = department; } + public String getPosition() { return position; } + public void setPosition(String position) { this.position = position; } + public String getSource() { return source; } + public void setSource(String source) { this.source = source; } + public String getIntentStatus() { return intentStatus; } + public void setIntentStatus(String intentStatus) { this.intentStatus = intentStatus; } + public String getRemark() { return remark; } + public void setRemark(String remark) { this.remark = remark; } + public Date getCreateTime() { return createTime; } + public void setCreateTime(Date createTime) { this.createTime = createTime; } + public Date getUpdateTime() { return updateTime; } + public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizPublicitySupportIntent.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizPublicitySupportIntent.java new file mode 100644 index 0000000..4b7a43e --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/domain/BizPublicitySupportIntent.java @@ -0,0 +1,86 @@ +package com.ruoyi.business.domain; + +import java.util.Date; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 公示页-支持意向 (匿名快照, 与 sys_user 解耦) + * 数据源: /publicity/:projectId 页面 "表达支持意向" 按钮 + * 与 biz_support_intent (旧表, 已登录用户流程) 语义不同, 物理表独立 + */ +public class BizPublicitySupportIntent extends BaseEntity { + private static final long serialVersionUID = 1L; + /** intent_id */ + private Long intentId; + /** project_id (biz_project.project_id) */ + @Excel(name = "project_id") + private Long projectId; + /** project_no (冗余) */ + @Excel(name = "project_no") + private String projectNo; + /** project_name (冗余) */ + @Excel(name = "project_name") + private String projectName; + /** user_id (已登录时回填 sys_user.user_id, 未登录 NULL) */ + @Excel(name = "user_id") + private Long userId; + /** name */ + @Excel(name = "name") + private String name; + /** phone */ + @Excel(name = "phone") + private String phone; + /** work_unit 工作单位名称 */ + @Excel(name = "work_unit") + private String workUnit; + /** department 部门 */ + @Excel(name = "department") + private String department; + /** position 职务 */ + @Excel(name = "position") + private String position; + /** source 来源 publicity=公示页 */ + @Excel(name = "source") + private String source; + /** intent_status 状态 (待审核/已采纳/已拒绝) */ + @Excel(name = "intent_status") + private String intentStatus; + /** remark 备注 */ + private String remark; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + public Long getIntentId() { return intentId; } + public void setIntentId(Long intentId) { this.intentId = intentId; } + public Long getProjectId() { return projectId; } + public void setProjectId(Long projectId) { this.projectId = projectId; } + public String getProjectNo() { return projectNo; } + public void setProjectNo(String projectNo) { this.projectNo = projectNo; } + public String getProjectName() { return projectName; } + public void setProjectName(String projectName) { this.projectName = projectName; } + public Long getUserId() { return userId; } + public void setUserId(Long userId) { this.userId = userId; } + public String getName() { return name; } + public void setName(String name) { this.name = name; } + public String getPhone() { return phone; } + public void setPhone(String phone) { this.phone = phone; } + public String getWorkUnit() { return workUnit; } + public void setWorkUnit(String workUnit) { this.workUnit = workUnit; } + public String getDepartment() { return department; } + public void setDepartment(String department) { this.department = department; } + public String getPosition() { return position; } + public void setPosition(String position) { this.position = position; } + public String getSource() { return source; } + public void setSource(String source) { this.source = source; } + public String getIntentStatus() { return intentStatus; } + public void setIntentStatus(String intentStatus) { this.intentStatus = intentStatus; } + public String getRemark() { return remark; } + public void setRemark(String remark) { this.remark = remark; } + public Date getCreateTime() { return createTime; } + public void setCreateTime(Date createTime) { this.createTime = createTime; } + public Date getUpdateTime() { return updateTime; } + public void setUpdateTime(Date updateTime) { this.updateTime = updateTime; } +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BizPublicityExecutionIntentMapper.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BizPublicityExecutionIntentMapper.java new file mode 100644 index 0000000..dc13980 --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BizPublicityExecutionIntentMapper.java @@ -0,0 +1,18 @@ +package com.ruoyi.business.mapper; + +import java.util.List; +import com.ruoyi.business.domain.BizPublicityExecutionIntent; + +/** + * 公示页-执行意向 Mapper + */ +public interface BizPublicityExecutionIntentMapper { + BizPublicityExecutionIntent selectByPrimaryKey(Long intentId); + List selectList(BizPublicityExecutionIntent entity); + /** 查重: 按 (project_id, phone, source) 已存在则返回记录, 否则 null */ + BizPublicityExecutionIntent selectDuplicate(BizPublicityExecutionIntent entity); + int insert(BizPublicityExecutionIntent entity); + int updateByPrimaryKey(BizPublicityExecutionIntent entity); + int deleteByPrimaryKey(Long intentId); + int deleteByPrimaryKeys(Long[] intentIds); +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BizPublicitySupportIntentMapper.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BizPublicitySupportIntentMapper.java new file mode 100644 index 0000000..5e66884 --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/mapper/BizPublicitySupportIntentMapper.java @@ -0,0 +1,18 @@ +package com.ruoyi.business.mapper; + +import java.util.List; +import com.ruoyi.business.domain.BizPublicitySupportIntent; + +/** + * 公示页-支持意向 Mapper + */ +public interface BizPublicitySupportIntentMapper { + BizPublicitySupportIntent selectByPrimaryKey(Long intentId); + List selectList(BizPublicitySupportIntent entity); + /** 查重: 按 (project_id, phone, source) 已存在则返回记录, 否则 null */ + BizPublicitySupportIntent selectDuplicate(BizPublicitySupportIntent entity); + int insert(BizPublicitySupportIntent entity); + int updateByPrimaryKey(BizPublicitySupportIntent entity); + int deleteByPrimaryKey(Long intentId); + int deleteByPrimaryKeys(Long[] intentIds); +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/IBizPublicityExecutionIntentService.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/IBizPublicityExecutionIntentService.java new file mode 100644 index 0000000..3a95dfb --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/IBizPublicityExecutionIntentService.java @@ -0,0 +1,15 @@ +package com.ruoyi.business.service; + +import java.util.List; +import com.ruoyi.business.domain.BizPublicityExecutionIntent; + +public interface IBizPublicityExecutionIntentService { + BizPublicityExecutionIntent getById(Long intentId); + List selectList(BizPublicityExecutionIntent entity); + /** 按 (projectId, phone, source) 查重 */ + BizPublicityExecutionIntent findDuplicate(Long projectId, String phone, String source); + int insert(BizPublicityExecutionIntent entity); + int updateByPrimaryKey(BizPublicityExecutionIntent entity); + int deleteByPrimaryKey(Long intentId); + int deleteByPrimaryKeys(Long[] intentIds); +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/IBizPublicitySupportIntentService.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/IBizPublicitySupportIntentService.java new file mode 100644 index 0000000..4f75412 --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/IBizPublicitySupportIntentService.java @@ -0,0 +1,15 @@ +package com.ruoyi.business.service; + +import java.util.List; +import com.ruoyi.business.domain.BizPublicitySupportIntent; + +public interface IBizPublicitySupportIntentService { + BizPublicitySupportIntent getById(Long intentId); + List selectList(BizPublicitySupportIntent entity); + /** 按 (projectId, phone, source) 查重, 已存在返回记录 */ + BizPublicitySupportIntent findDuplicate(Long projectId, String phone, String source); + int insert(BizPublicitySupportIntent entity); + int updateByPrimaryKey(BizPublicitySupportIntent entity); + int deleteByPrimaryKey(Long intentId); + int deleteByPrimaryKeys(Long[] intentIds); +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizPublicityExecutionIntentServiceImpl.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizPublicityExecutionIntentServiceImpl.java new file mode 100644 index 0000000..df2e25d --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizPublicityExecutionIntentServiceImpl.java @@ -0,0 +1,26 @@ +package com.ruoyi.business.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.business.domain.BizPublicityExecutionIntent; +import com.ruoyi.business.mapper.BizPublicityExecutionIntentMapper; +import com.ruoyi.business.service.IBizPublicityExecutionIntentService; + +@Service +public class BizPublicityExecutionIntentServiceImpl implements IBizPublicityExecutionIntentService { + @Autowired + private BizPublicityExecutionIntentMapper mapper; + + @Override public BizPublicityExecutionIntent getById(Long intentId) { return mapper.selectByPrimaryKey(intentId); } + @Override public List selectList(BizPublicityExecutionIntent entity) { return mapper.selectList(entity); } + @Override public BizPublicityExecutionIntent findDuplicate(Long projectId, String phone, String source) { + BizPublicityExecutionIntent q = new BizPublicityExecutionIntent(); + q.setProjectId(projectId); q.setPhone(phone); q.setSource(source); + return mapper.selectDuplicate(q); + } + @Override public int insert(BizPublicityExecutionIntent entity) { return mapper.insert(entity); } + @Override public int updateByPrimaryKey(BizPublicityExecutionIntent entity) { return mapper.updateByPrimaryKey(entity); } + @Override public int deleteByPrimaryKey(Long intentId) { return mapper.deleteByPrimaryKey(intentId); } + @Override public int deleteByPrimaryKeys(Long[] intentIds) { return mapper.deleteByPrimaryKeys(intentIds); } +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizPublicitySupportIntentServiceImpl.java b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizPublicitySupportIntentServiceImpl.java new file mode 100644 index 0000000..6ee9c92 --- /dev/null +++ b/ry-api/ruoyi-business/src/main/java/com/ruoyi/business/service/impl/BizPublicitySupportIntentServiceImpl.java @@ -0,0 +1,26 @@ +package com.ruoyi.business.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.business.domain.BizPublicitySupportIntent; +import com.ruoyi.business.mapper.BizPublicitySupportIntentMapper; +import com.ruoyi.business.service.IBizPublicitySupportIntentService; + +@Service +public class BizPublicitySupportIntentServiceImpl implements IBizPublicitySupportIntentService { + @Autowired + private BizPublicitySupportIntentMapper mapper; + + @Override public BizPublicitySupportIntent getById(Long intentId) { return mapper.selectByPrimaryKey(intentId); } + @Override public List selectList(BizPublicitySupportIntent entity) { return mapper.selectList(entity); } + @Override public BizPublicitySupportIntent findDuplicate(Long projectId, String phone, String source) { + BizPublicitySupportIntent q = new BizPublicitySupportIntent(); + q.setProjectId(projectId); q.setPhone(phone); q.setSource(source); + return mapper.selectDuplicate(q); + } + @Override public int insert(BizPublicitySupportIntent entity) { return mapper.insert(entity); } + @Override public int updateByPrimaryKey(BizPublicitySupportIntent entity) { return mapper.updateByPrimaryKey(entity); } + @Override public int deleteByPrimaryKey(Long intentId) { return mapper.deleteByPrimaryKey(intentId); } + @Override public int deleteByPrimaryKeys(Long[] intentIds) { return mapper.deleteByPrimaryKeys(intentIds); } +} \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/resources/mapper/business/BizPublicityExecutionIntentMapper.xml b/ry-api/ruoyi-business/src/main/resources/mapper/business/BizPublicityExecutionIntentMapper.xml new file mode 100644 index 0000000..d224534 --- /dev/null +++ b/ry-api/ruoyi-business/src/main/resources/mapper/business/BizPublicityExecutionIntentMapper.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + select intent_id, project_id, project_no, project_name, user_id, name, phone, work_unit, department, position, source, intent_status, remark, create_by, create_time, update_by, update_time + from biz_publicity_execution_intent + + + + + + + insert into biz_publicity_execution_intent + + intent_id, + project_id, + project_no, + project_name, + user_id, + name, + phone, + work_unit, + department, + position, + source, + intent_status, + remark, + create_by, + create_time, + + + #{intentId}, + #{projectId}, + #{projectNo}, + #{projectName}, + #{userId}, + #{name}, + #{phone}, + #{workUnit}, + #{department}, + #{position}, + #{source}, + #{intentStatus}, + #{remark}, + #{createBy}, + sysdate(), + + + + update biz_publicity_execution_intent + + intent_status = #{intentStatus}, + remark = #{remark}, + name = #{name}, + phone = #{phone}, + work_unit = #{workUnit}, + department = #{department}, + position = #{position}, + update_by = #{updateBy}, + update_time = sysdate(), + + where intent_id = #{intentId} + + + delete from biz_publicity_execution_intent where intent_id = #{intentId} + + + delete from biz_publicity_execution_intent where intent_id in + + #{id} + + + \ No newline at end of file diff --git a/ry-api/ruoyi-business/src/main/resources/mapper/business/BizPublicitySupportIntentMapper.xml b/ry-api/ruoyi-business/src/main/resources/mapper/business/BizPublicitySupportIntentMapper.xml new file mode 100644 index 0000000..16bbc1e --- /dev/null +++ b/ry-api/ruoyi-business/src/main/resources/mapper/business/BizPublicitySupportIntentMapper.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + select intent_id, project_id, project_no, project_name, user_id, name, phone, work_unit, department, position, source, intent_status, remark, create_by, create_time, update_by, update_time + from biz_publicity_support_intent + + + + + + + insert into biz_publicity_support_intent + + intent_id, + project_id, + project_no, + project_name, + user_id, + name, + phone, + work_unit, + department, + position, + source, + intent_status, + remark, + create_by, + create_time, + + + #{intentId}, + #{projectId}, + #{projectNo}, + #{projectName}, + #{userId}, + #{name}, + #{phone}, + #{workUnit}, + #{department}, + #{position}, + #{source}, + #{intentStatus}, + #{remark}, + #{createBy}, + sysdate(), + + + + update biz_publicity_support_intent + + intent_status = #{intentStatus}, + remark = #{remark}, + name = #{name}, + phone = #{phone}, + work_unit = #{workUnit}, + department = #{department}, + position = #{position}, + update_by = #{updateBy}, + update_time = sysdate(), + + where intent_id = #{intentId} + + + delete from biz_publicity_support_intent where intent_id = #{intentId} + + + delete from biz_publicity_support_intent where intent_id in + + #{id} + + + \ No newline at end of file diff --git a/ry-api/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ry-api/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index b1231b2..71a1cef 100644 --- a/ry-api/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ry-api/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -61,7 +61,7 @@ public class SecurityConfig // OSS 文件代理 (PDF/图片内嵌预览, 重写 Content-Disposition 为 inline) .requestMatchers(HttpMethod.GET, "/common/oss/proxy").permitAll() // 业务公开门户与注册入口可匿名访问; 字典 active/单查公开, 写操作需登录+权限 - .requestMatchers("/business/public/**", "/business/auth/**", "/business/sms/**").permitAll() + .requestMatchers("/business/public/**", "/business/publicity/**", "/business/auth/**", "/business/sms/**").permitAll() // 字典 active (只读) + 按 ID 查 公开给前端拉下拉数据 .requestMatchers(HttpMethod.GET, "/business/dict/department/active", "/business/dict/title/active", "/business/dict/department/*", "/business/dict/title/*").permitAll() diff --git a/ry-vue3/src/api/public.js b/ry-vue3/src/api/public.js index 49934a6..47917b2 100644 --- a/ry-vue3/src/api/public.js +++ b/ry-vue3/src/api/public.js @@ -107,3 +107,40 @@ export const downloadImportTemplate = (unitType) => // 专家导入模板下载 export const downloadExpertTemplate = () => request.get('/business/expert/importTemplate', { responseType: 'blob' }) + +// ========== 公示页意向 (公开匿名提交, 已在登录或未登录时均可调) ========== +// 提交支持意向: body { projectId, name, phone, workUnit, department?, position? } +export function submitPublicitySupportIntent(data) { + return request.post('/business/publicity/supportIntent', data) +} +// 提交执行意向 +export function submitPublicityExecutionIntent(data) { + return request.post('/business/publicity/executionIntent', data) +} +// 持久化查重: GET /business/publicity/hasIntent?projectId=&phone=&type=support|execution +export function hasPublicityIntent(projectId, phone, type) { + return request.get('/business/publicity/hasIntent', { params: { projectId, phone, type } }) +} + +// ========== 公示页意向 管理端 (manager / admin 后台) ========== +// 列表分页 (后端 startPage 模式) +export function listPublicitySupportIntent(params) { + return request.get('/business/publicitySupportIntent/list', { params }) +} +export function listPublicityExecutionIntent(params) { + return request.get('/business/publicityExecutionIntent/list', { params }) +} +// 编辑 (改 intentStatus / remark) +export function updatePublicitySupportIntent(data, opts) { + return request.put('/business/publicitySupportIntent', data, opts) +} +export function updatePublicityExecutionIntent(data, opts) { + return request.put('/business/publicityExecutionIntent', data, opts) +} +// 删除 (单/多) +export function deletePublicitySupportIntent(ids) { + return request.delete(`/business/publicitySupportIntent/${Array.isArray(ids) ? ids.join(',') : ids}`) +} +export function deletePublicityExecutionIntent(ids) { + return request.delete(`/business/publicityExecutionIntent/${Array.isArray(ids) ? ids.join(',') : ids}`) +} diff --git a/ry-vue3/src/views/manager/ExecIntent.vue b/ry-vue3/src/views/manager/ExecIntent.vue index e78237c..b6129af 100644 --- a/ry-vue3/src/views/manager/ExecIntent.vue +++ b/ry-vue3/src/views/manager/ExecIntent.vue @@ -2,24 +2,30 @@
- + - - - - + + + + + - 查找重置 + + 查找 + 重置 + 导出CSV + - - + + + @@ -28,14 +34,30 @@ - + + + + + + +
+
+ 批量删除 ({{ selected.length }}) +
@@ -43,30 +65,109 @@ \ No newline at end of file +.pager { display: flex; justify-content: space-between; align-items: center; margin-top: 12px; } +.pager-left { display: flex; gap: 8px; } + diff --git a/ry-vue3/src/views/manager/SupportIntent.vue b/ry-vue3/src/views/manager/SupportIntent.vue index 7f9ccad..2521a81 100644 --- a/ry-vue3/src/views/manager/SupportIntent.vue +++ b/ry-vue3/src/views/manager/SupportIntent.vue @@ -2,42 +2,69 @@
- +
-

*项目公示中点击支持意向后,显示在此

-

*支持意向不需要注册,但是如果已经注册账号,则显示账号状态

+

*项目公示中点击"表达支持意向"后,显示在此

+

*支持意向不需要注册;已注册账号时,自动回填用户状态

*根据手机号与系统账号进行匹配

- + + + + + + + + + 查找 重置 + 导出CSV - - + + + - - + + - + + + + + + + +
+
+ 批量删除 ({{ selected.length }}) +
@@ -45,34 +72,113 @@