Lin Qilong пре 18 часа
родитељ
комит
2d2b120d6d

+ 10 - 0
gw-admin/src/main/java/com/goldenwater/web/controller/hzz/WorkPlanController.java

@@ -1,6 +1,7 @@
 package com.goldenwater.web.controller.hzz;
 import com.goldenwater.common.core.controller.BaseController;
 import com.goldenwater.common.core.domain.AjaxResult;
+import com.goldenwater.hzz.domain.AttWorkPlanDTO;
 import com.goldenwater.hzz.service.WorkPlanService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -11,4 +12,13 @@ public class WorkPlanController extends BaseController {
     @Autowired private WorkPlanService service;
     @GetMapping("/list")
     public AjaxResult list(@RequestParam(defaultValue = "") String adCode) { return success(service.getWorkPlanList(adCode)); }
+
+    @PostMapping
+    public AjaxResult add(@RequestBody AttWorkPlanDTO params) { return toAjax(service.addWorkPlan(params)); }
+
+    @PutMapping
+    public AjaxResult update(@RequestBody AttWorkPlanDTO params) { return toAjax(service.updateWorkPlan(params)); }
+
+    @DeleteMapping("/{wpCode}")
+    public AjaxResult delete(@PathVariable String wpCode) { return toAjax(service.deleteWorkPlan(wpCode)); }
 }

+ 14 - 0
gw-hzz/src/main/java/com/goldenwater/hzz/domain/AttWorkPlanDTO.java

@@ -15,6 +15,12 @@ public class AttWorkPlanDTO implements Serializable {
     private String releWiunName;
     private String attc;
 
+    // 以下为 ATT_WORK_PLAN 表中 NOT NULL 约束所需字段
+    private String wpProgress;   // WP_PROGRESS CHAR(1) NOT NULL
+    private String wrWriter;     // WR_WRITER VARCHAR2(32) NOT NULL
+    private String wrMobile;     // WR_MOBILE VARCHAR2(15) NOT NULL
+    private Integer verMark;     // VER_MARK NUMBER NOT NULL
+
     public String getGuid() { return guid; }
     public void setGuid(String guid) { this.guid = guid; }
     public String getWpCode() { return wpCode; }
@@ -35,4 +41,12 @@ public class AttWorkPlanDTO implements Serializable {
     public void setReleWiunName(String releWiunName) { this.releWiunName = releWiunName; }
     public String getAttc() { return attc; }
     public void setAttc(String attc) { this.attc = attc; }
+    public String getWpProgress() { return wpProgress; }
+    public void setWpProgress(String wpProgress) { this.wpProgress = wpProgress; }
+    public String getWrWriter() { return wrWriter; }
+    public void setWrWriter(String wrWriter) { this.wrWriter = wrWriter; }
+    public String getWrMobile() { return wrMobile; }
+    public void setWrMobile(String wrMobile) { this.wrMobile = wrMobile; }
+    public Integer getVerMark() { return verMark; }
+    public void setVerMark(Integer verMark) { this.verMark = verMark; }
 }

+ 23 - 0
gw-hzz/src/main/java/com/goldenwater/hzz/mapper/WorkPlanMapper.java

@@ -6,4 +6,27 @@ import java.util.List;
 
 public interface WorkPlanMapper {
     List<AttWorkPlanDTO> getWorkPlan(@Param("adCode") String adCode);
+
+    int insertWorkPlan(AttWorkPlanDTO p);
+
+    int insertMdBase(@Param("mdGuid") String mdGuid, @Param("mdCode") String mdCode,
+                     @Param("mdName") String mdName, @Param("fileNm") String fileNm,
+                     @Param("releDate") String releDate,
+                     @Param("releWiunName") String releWiunName, @Param("filePath") String filePath);
+
+    int insertRelMdObj(@Param("guid") String guid, @Param("objGuid") String objGuid, @Param("mdGuid") String mdGuid);
+
+    int insertRelWorkAd(@Param("guid") String guid, @Param("wpCode") String wpCode, @Param("adCode") String adCode);
+
+    int updateWorkPlan(AttWorkPlanDTO p);
+
+    int updateMdBaseByWpCode(AttWorkPlanDTO p);
+
+    int deleteRelWorkAd(@Param("wpCode") String wpCode);
+
+    int deleteRelMdObj(@Param("wpCode") String wpCode);
+
+    int deleteMdBase(@Param("wpCode") String wpCode);
+
+    int deleteWorkPlan(@Param("wpCode") String wpCode);
 }

+ 72 - 3
gw-hzz/src/main/java/com/goldenwater/hzz/service/WorkPlanService.java

@@ -1,12 +1,81 @@
 package com.goldenwater.hzz.service;
+
+import com.goldenwater.common.core.domain.entity.SysUser;
+import com.goldenwater.common.utils.SecurityUtils;
 import com.goldenwater.hzz.domain.AttWorkPlanDTO;
 import com.goldenwater.hzz.mapper.WorkPlanMapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import java.util.List;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.UUID;
 
 @Service
 public class WorkPlanService {
-    @Autowired private WorkPlanMapper mapper;
-    public List<AttWorkPlanDTO> getWorkPlanList(String adCode) { return mapper.getWorkPlan(adCode); }
+    @Autowired
+    private WorkPlanMapper mapper;
+
+    /**
+     * 32位无横线UUID,与 RuleService 等现有表主键长度保持一致
+     */
+    private String uuid() {
+        return UUID.randomUUID().toString().replace("-", "");
+    }
+
+    /**
+     * WP_CODE 为 char(12),固定为 "WP" + yyMMddHHmmss(10位) 共12位
+     */
+    private static final java.time.format.DateTimeFormatter WP_CODE_FMT =
+            java.time.format.DateTimeFormatter.ofPattern("yyMMddHHmmss");
+
+    public java.util.List<AttWorkPlanDTO> getWorkPlanList(String adCode) {
+        return mapper.getWorkPlan(adCode);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public int addWorkPlan(AttWorkPlanDTO p) {
+        if (p.getRlsTm() != null && p.getRlsTm().isEmpty()) p.setRlsTm(null);
+        String guid = uuid();
+        String wpCode = java.time.LocalDateTime.now().format(WP_CODE_FMT);
+        String mdGuid = uuid();
+        String mdCode = uuid();
+
+        // 撰写人/手机号取当前登录用户;手机号可能为空,NOT NULL 约束下兜底为 "0"
+        SysUser cur = SecurityUtils.getLoginUser().getUser();
+        String writer = cur.getNickName() != null ? cur.getNickName() : cur.getUserName();
+        String mobile = cur.getPhonenumber();
+        if (mobile == null || mobile.isEmpty()) mobile = "0";
+
+        p.setGuid(guid);
+        p.setWpCode(wpCode);
+        // ATT_WORK_PLAN 中 NOT NULL 约束字段
+        p.setWpProgress("7");   // 撰写进度(用户指定)
+        p.setWrWriter(writer);
+        p.setWrMobile(mobile);
+        p.setVerMark(1);        // 初始版本标记
+        mapper.insertWorkPlan(p);
+        mapper.insertMdBase(mdGuid, mdCode, p.getWpName(), p.getWpName(), p.getRlsTm(), p.getReleWiunName(), p.getAttc());
+        String relMdObjGuid = uuid();
+        mapper.insertRelMdObj(relMdObjGuid, guid, mdGuid);
+        String relWorkAdGuid = uuid();
+        mapper.insertRelWorkAd(relWorkAdGuid, wpCode, p.getAdCode());
+        return 1;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public int updateWorkPlan(AttWorkPlanDTO p) {
+        if (p.getRlsTm() != null && p.getRlsTm().isEmpty()) p.setRlsTm(null);
+        mapper.updateWorkPlan(p);
+        mapper.updateMdBaseByWpCode(p);
+        return 1;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public int deleteWorkPlan(String wpCode) {
+        mapper.deleteRelWorkAd(wpCode);
+        mapper.deleteRelMdObj(wpCode);
+        mapper.deleteMdBase(wpCode);
+        mapper.deleteWorkPlan(wpCode);
+        return 1;
+    }
 }

+ 91 - 7
gw-hzz/src/main/resources/mapper/hzz/WorkPlanMapper.xml

@@ -2,13 +2,97 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.goldenwater.hzz.mapper.WorkPlanMapper">
     <select id="getWorkPlan" resultType="com.goldenwater.hzz.domain.AttWorkPlanDTO">
-        SELECT A.WP_CODE AS "wpCode", A.WP_NAME AS "wpName", A.FILE_NUM AS "fileNum",
-               TO_CHAR(C.RELE_DATE,'YYYY-MM-DD') AS "rlsTm", C.RELE_WIUN_NAME AS "releWiunName",
-               C.FILE_PATH AS "attc"
+        SELECT A.WP_CODE                          AS "wpCode",
+               A.WP_NAME                          AS "wpName",
+               A.FILE_NUM                         AS "fileNum",
+               TO_CHAR(C.RELE_DATE, 'YYYY-MM-DD') AS "rlsTm",
+               C.RELE_WIUN_NAME                   AS "releWiunName",
+               C.FILE_PATH                        AS "attc"
         FROM ATT_WORK_PLAN A
-        LEFT JOIN REL_MD_OBJ B ON A.GUID = B.OBJ_GUID AND B.TO_DATE IS NULL
-        LEFT JOIN ATT_MD_BASE C ON B.MD_GUID = C.GUID AND C.TO_DATE IS NULL
-        LEFT JOIN REL_WORK_AD D ON A.WP_CODE = D.WP_CODE AND D.TO_DATE IS NULL
-        WHERE A.EXPR_DATE IS NULL AND D.AD_CODE = #{adCode}
+                 LEFT JOIN REL_MD_OBJ B ON A.GUID = B.OBJ_GUID AND B.TO_DATE IS NULL
+                 LEFT JOIN ATT_MD_BASE C ON B.MD_GUID = C.GUID AND C.TO_DATE IS NULL
+                 LEFT JOIN REL_WORK_AD D ON A.WP_CODE = D.WP_CODE AND D.TO_DATE IS NULL
+        WHERE A.EXPR_DATE IS NULL
+          AND D.AD_CODE = #{adCode}
     </select>
+
+    <!-- 新增工作方案:写入 ATT_WORK_PLAN -->
+    <insert id="insertWorkPlan" parameterType="com.goldenwater.hzz.domain.AttWorkPlanDTO">
+        INSERT INTO ATT_WORK_PLAN(GUID, WP_CODE, WP_NAME, FILE_NUM, WP_PROGRESS, WR_WRITER, WR_DATE, WR_MOBILE,
+                                  EFF_DATE, VER_MARK)
+        VALUES (#{guid}, #{wpCode}, #{wpName}, #{fileNum}, #{wpProgress}, #{wrWriter}, SYSDATE, #{wrMobile}, SYSDATE,
+                #{verMark})
+    </insert>
+
+    <!-- 新增工作方案:写入 ATT_MD_BASE(附件/发布元数据) -->
+    <insert id="insertMdBase">
+        INSERT INTO ATT_MD_BASE(GUID, MD_CODE, MD_NAME, FILE_NM, FILE_TITL, FILE_PATH, RELE_DATE, RELE_WIUN_NAME,
+                                FROM_DATE, TO_DATE)
+        VALUES (#{mdGuid}, #{mdCode}, #{mdName}, #{fileNm}, #{mdName}, #{filePath},
+                TO_DATE(#{releDate}, 'YYYY-MM-DD'), #{releWiunName}, SYSDATE, NULL)
+    </insert>
+
+    <!-- 新增工作方案:关联对象与元数据 REL_MD_OBJ -->
+    <insert id="insertRelMdObj">
+        INSERT INTO REL_MD_OBJ(GUID, OBJ_GUID, OBJ_TAB_CODE, MD_GUID, FROM_DATE, TO_DATE)
+        VALUES (#{guid}, #{objGuid}, 'ATT_WORK_PLAN', #{mdGuid}, SYSDATE, NULL)
+    </insert>
+
+    <!-- 新增工作方案:关联工作方案与行政区划 REL_WORK_AD -->
+    <insert id="insertRelWorkAd">
+        INSERT INTO REL_WORK_AD(GUID, WP_CODE, AD_CODE, FROM_DATE, TO_DATE)
+        VALUES (#{guid}, #{wpCode}, #{adCode}, SYSDATE, NULL)
+    </insert>
+
+    <!-- 修改工作方案:更新 ATT_WORK_PLAN -->
+    <update id="updateWorkPlan" parameterType="com.goldenwater.hzz.domain.AttWorkPlanDTO">
+        UPDATE ATT_WORK_PLAN
+        SET WP_NAME  = #{wpName},
+            FILE_NUM = #{fileNum}
+        WHERE WP_CODE = #{wpCode}
+    </update>
+
+    <!-- 修改工作方案:更新关联的 ATT_MD_BASE 元数据 -->
+    <update id="updateMdBaseByWpCode" parameterType="com.goldenwater.hzz.domain.AttWorkPlanDTO">
+        UPDATE ATT_MD_BASE
+        SET RELE_DATE      = TO_DATE(#{rlsTm}, 'YYYY-MM-DD'),
+            RELE_WIUN_NAME = #{releWiunName},
+            FILE_PATH      = #{attc},
+            MD_NAME        = #{wpName},
+            FILE_TITL      = #{wpName}
+        WHERE GUID IN (SELECT B.MD_GUID
+                       FROM REL_MD_OBJ B
+                       WHERE B.OBJ_GUID IN (SELECT GUID FROM ATT_WORK_PLAN WHERE WP_CODE = #{wpCode})
+                         AND B.TO_DATE IS NULL)
+    </update>
+
+    <!-- 删除工作方案:删除 REL_WORK_AD -->
+    <delete id="deleteRelWorkAd">
+        DELETE
+        FROM REL_WORK_AD
+        WHERE WP_CODE = #{wpCode}
+    </delete>
+
+    <!-- 删除工作方案:删除 REL_MD_OBJ -->
+    <delete id="deleteRelMdObj">
+        DELETE
+        FROM REL_MD_OBJ
+        WHERE OBJ_GUID IN (SELECT GUID FROM ATT_WORK_PLAN WHERE WP_CODE = #{wpCode})
+    </delete>
+
+    <!-- 删除工作方案:删除 ATT_MD_BASE -->
+    <delete id="deleteMdBase">
+        DELETE
+        FROM ATT_MD_BASE
+        WHERE GUID IN (SELECT B.MD_GUID
+                       FROM REL_MD_OBJ B
+                       WHERE B.OBJ_GUID IN (SELECT GUID FROM ATT_WORK_PLAN WHERE WP_CODE = #{wpCode}))
+    </delete>
+
+    <!-- 删除工作方案:删除 ATT_WORK_PLAN -->
+    <delete id="deleteWorkPlan">
+        DELETE
+        FROM ATT_WORK_PLAN
+        WHERE WP_CODE = #{wpCode}
+    </delete>
 </mapper>

+ 1 - 1
gw-ui/src/api/hzz/rule.js

@@ -18,7 +18,7 @@ function convertToCamelCase(data) {
 
 // ==================== 制度规则 ====================
 export function listRule(adCode, ruleType) {
-    return request({url: '/hzz/rule/list', method: 'get', params: {adCode, ruleType}, timeout: 60 * 1000 * 5})
+    return request({url: '/hzz/rule/list', method: 'get', params: {adCode, ruleType}, timeout: 60 * 1000 * 10})
 }
 
 // ==================== 制度文件 ====================

+ 26 - 0
gw-ui/src/api/hzz/workplan.js

@@ -9,3 +9,29 @@ export function listWorkPlan(adCode) {
     timeout: 60 * 1000 * 5
   })
 }
+
+// 新增工作方案
+export function addWorkPlan(data) {
+  return request({
+    url: '/hzz/workplan',
+    method: 'post',
+    data
+  })
+}
+
+// 修改工作方案
+export function updateWorkPlan(data) {
+  return request({
+    url: '/hzz/workplan',
+    method: 'put',
+    data
+  })
+}
+
+// 删除工作方案
+export function deleteWorkPlan(wpCode) {
+  return request({
+    url: '/hzz/workplan/' + wpCode,
+    method: 'delete'
+  })
+}

+ 0 - 3
gw-ui/src/layout/components/Navbar.vue

@@ -39,9 +39,6 @@
             <router-link to="/user/profile">
               <el-dropdown-item>个人中心</el-dropdown-item>
             </router-link>
-            <el-dropdown-item command="lockScreen">
-                <span>锁定屏幕</span>
-            </el-dropdown-item>
             <el-dropdown-item divided command="logout">
               <span>退出登录</span>
             </el-dropdown-item>

+ 0 - 3
gw-ui/src/layout/components/TopNavbar/index.vue

@@ -54,9 +54,6 @@
             <router-link to="/user/profile">
               <el-dropdown-item>个人中心</el-dropdown-item>
             </router-link>
-            <el-dropdown-item command="lockScreen">
-              <span>锁定屏幕</span>
-            </el-dropdown-item>
             <el-dropdown-item divided command="logout">
               <span>退出登录</span>
             </el-dropdown-item>

+ 22 - 9
gw-ui/src/views/hlgl/bankline/index.vue

@@ -204,7 +204,7 @@
 import { ref, reactive, computed, onMounted, watch } from 'vue'
 import { ElMessage, ElMessageBox } from 'element-plus'
 import { Plus } from '@element-plus/icons-vue'
-import { listWorkPlan } from '@/api/hzz/workplan'
+import { listWorkPlan, addWorkPlan, updateWorkPlan, deleteWorkPlan } from '@/api/hzz/workplan'
 import { listFile, addFile, updateFile, delFile, listArticle, addArticle, updateArticle, delArticle } from '@/api/hzz/rule'
 import { getChildren } from '@/api/hzz/adtree'
 import FileUpload from '@/components/FileUpload'
@@ -260,23 +260,36 @@ const handleAdd = () => {
 
 const handleEdit = (row) => {
   wpDialogTitle.value = '编辑工作方案'
-  Object.assign(wpForm, { ...row })
+  Object.assign(wpForm, { ...row, adCode: currentAdCode.value })
   wpDialogVisible.value = true
 }
 
 const submitWpForm = async () => {
   await wpFormRef.value.validate()
-  // TODO: 调用后端API保存
-  ElMessage.success('保存成功(待实现后端接口)')
-  wpDialogVisible.value = false
-  loadWorkPlans()
+  try {
+    if (wpForm.wpCode) {
+      await updateWorkPlan({ ...wpForm })
+      ElMessage.success('修改成功')
+    } else {
+      await addWorkPlan({ ...wpForm })
+      ElMessage.success('新增成功')
+    }
+    wpDialogVisible.value = false
+    loadWorkPlans()
+  } catch (e) {
+    ElMessage.error('操作失败')
+  }
 }
 
 const handleDelete = (row) => {
   ElMessageBox.confirm('确认删除该工作方案吗?', '警告', { type: 'warning' }).then(async () => {
-    // TODO: 调用后端API删除
-    ElMessage.success('删除成功(待实现后端接口)')
-    loadWorkPlans()
+    try {
+      await deleteWorkPlan(row.wpCode)
+      ElMessage.success('删除成功')
+      loadWorkPlans()
+    } catch (e) {
+      ElMessage.error('删除失败')
+    }
   })
 }
 

+ 8 - 0
gw-ui/src/views/hlgl/gzfa/index.vue

@@ -88,6 +88,7 @@ import {listFile, listRule} from '@/api/hzz/rule'
 import {getChildren} from '@/api/hzz/adtree'
 import {listWorkPlan} from '@/api/hzz/workplan'
 import iFrame from '@/components/iFrame'
+import {isHttp} from "@/utils/validate.js";
 
 const loading = ref(false)
 const treeRef = ref(null)
@@ -214,6 +215,13 @@ const ruleProgressFilter = (item) => {
 
 const showDetail = (item) => {
   detailVisible.value = true
+  if (!item.url) {
+    if (item.attc && !isHttp(item.attc)) {
+      item.url = import.meta.env.VITE_SERVICE_BASE_TITLE + item.attc
+    } else {
+      item.url = item.attc
+    }
+  }
   detailItem.value = item
   // if (item.url.substring(item.url.length - 3) === 'doc' || item.url.substring(item.url.length - 4) === 'docx') {
   //   detailVisible.value = false;