瀏覽代碼

提交随访模版设计

wangshuangpan 1 月之前
父節點
當前提交
05048c8ec9
共有 20 個文件被更改,包括 9794 次插入36 次删除
  1. 163 23
      health-admin/src/main/java/com/bzd/web/controller/gxhpz/FollowTaskController.java
  2. 582 0
      health-admin/src/main/java/com/bzd/web/controller/gxhpz/FollowTemplateConfigController.java
  3. 1 1
      health-admin/src/main/resources/templates/dtp/followUp/followUpEditAll.html
  4. 1146 0
      health-admin/src/main/resources/templates/dtp/followUp/followUpEditDynamic.html
  5. 4396 0
      health-admin/src/main/resources/templates/dtp/followUp/follwUpDynamic.html
  6. 78 0
      health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/add.html
  7. 219 0
      health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/addField.html
  8. 97 0
      health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/edit.html
  9. 632 0
      health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/fields.html
  10. 288 0
      health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/followTemplateConfig.html
  11. 406 0
      health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/preview.html
  12. 640 0
      health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/rules.html
  13. 302 0
      health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/testRule.html
  14. 4 4
      health-admin/src/main/resources/templates/gxhpz/template.html
  15. 2 2
      health-admin/src/main/resources/templates/index-topnav.html
  16. 2 2
      health-admin/src/main/resources/templates/index.html
  17. 2 2
      health-admin/src/main/resources/templates/login.html
  18. 2 2
      health-admin/src/main/resources/templates/register.html
  19. 499 0
      health-system/src/main/java/com/bzd/system/service/gxhpz/FollowTemplateConfigService.java
  20. 333 0
      health-system/src/main/resources/mapper/gxhpz/followTemplateConfigMapper.xml

+ 163 - 23
health-admin/src/main/java/com/bzd/web/controller/gxhpz/FollowTaskController.java

@@ -12,6 +12,7 @@ import com.bzd.system.service.PharmaceuticalService;
 import com.bzd.system.service.gxhpz.CosePlanService;
 import com.bzd.system.service.gxhpz.FollowPlanService;
 import com.bzd.system.service.gxhpz.FollowTaskService;
+import com.bzd.system.service.gxhpz.FollowTemplateConfigService;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
@@ -44,7 +45,8 @@ public class FollowTaskController extends BaseController {
 
     @Autowired
     private CosePlanService cosePlanService;
-
+    @Autowired
+    private FollowTemplateConfigService followTemplateConfigService;
     // 随访任务
     private String prefix_followUp = "dtp/followUp";
     /**
@@ -185,6 +187,7 @@ public class FollowTaskController extends BaseController {
         String id = (String) pd.get("id");
         String patientId = (String)pd.get("patientId");
         String confirmFlag = (String)pd.get("confirmFlag");
+        String templateConfigId = (String) pd.get("templateConfigId");
         boolean newTask = false;
         if(StringUtils.isNotEmpty(patientId) && StringUtils.isNotEmpty(id)){
             pd.put("taskStatus", "已完成");//任务状态:\r\n,0待执行,\r\n1已完成,\r\n2未完成,\r\n3已下发,\r\n4已取消
@@ -192,33 +195,23 @@ public class FollowTaskController extends BaseController {
         String next_follow_time = (String) pd.get("next_follow_time");
         if (StringUtils.isNotEmpty(next_follow_time)) {
             try {
-                // 获取当前时间
-                String currentTime = DateUtils.getTime(); // 假设返回格式为 "yyyy-MM-dd HH:mm:ss"
-                // 解析日期字符串
+                String currentTime = DateUtils.getTime();
                 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                 Date nextFollowTimeDate = dateFormat.parse(next_follow_time);
                 Date currentDateTime = dateFormat.parse(currentTime);
-                // 比较两个日期
+
                 if (nextFollowTimeDate.after(currentDateTime)) {
-                    // 如果下次随访时间大于当前时间,则任务状态为“待执行”
                     pd.put("taskStatus", "待执行");
-                    // 计算间隔天数
                     long diffInMillies = Math.abs(nextFollowTimeDate.getTime() - currentDateTime.getTime());
                     long intervalDays = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);
-
-                    // 将间隔天数放入 pd 中
                     pd.put("interval_this_time", (int) intervalDays);
-
-                    newTask=true;//=true符合条件 下次任务随访时间 意味着生成一个新的任务
-
+                    newTask = true;
                 } else {
-                    // 如果下次随访时间小于或等于当前时间,则任务状态为“已完成”
                     pd.put("taskStatus", "已完成");
-                    pd.put("interval_this_time", 0); // 已完成的任务不需要显示间隔天数
+                    pd.put("interval_this_time", 0);
                 }
             } catch (ParseException e) {
                 e.printStackTrace();
-                // 处理日期解析异常
                 pd.put("taskStatus", "解析错误");
                 pd.put("interval_this_time", null);
             }
@@ -229,6 +222,10 @@ public class FollowTaskController extends BaseController {
         pd.put("updatedAt", DateUtils.getTime());//更新时间
         pd.put("actualFollowUpTime", DateUtils.getTime());//实际随访时间
         pd.put("completionTime", DateUtils.getTime());//完成时间
+        // 如果使用了模版配置,保存模版ID
+        if (StringUtils.isNotEmpty(templateConfigId)) {
+            pd.put("templateConfigId", templateConfigId);
+        }
         PageData pdTask=new PageData();
         if(StringUtils.isNotEmpty(id)){
             pdTask.put("id", id);
@@ -271,6 +268,45 @@ public class FollowTaskController extends BaseController {
         }
 
     }
+    /**
+     * 验证动态表单字段
+     */
+    private boolean validateDynamicFields(PageData pd, String templateConfigId) throws Exception {
+        if (StringUtils.isEmpty(templateConfigId)) {
+            return true; // 不使用模版配置时,跳过验证
+        }
+
+        // 获取模版配置
+        PageData templateQuery = new PageData();
+        templateQuery.put("id", templateConfigId);
+        Map<String, Object> templateConfig = followTemplateConfigService.getTemplateConfig(templateQuery);
+
+        if (templateConfig == null) {
+            return true;
+        }
+
+        // 获取字段配置
+        Map<String, List<PageData>> fieldsByTab = (Map<String, List<PageData>>) templateConfig.get("fieldsByTab");
+        if (fieldsByTab == null) {
+            return true;
+        }
+
+        // 验证必填字段
+        for (List<PageData> fields : fieldsByTab.values()) {
+            for (PageData field : fields) {
+                if ("1".equals(String.valueOf(field.get("isRequired")))) {
+                    String fieldCode = (String) field.get("fieldCode");
+                    String fieldValue = (String) pd.get(fieldCode);
+
+                    if (StringUtils.isEmpty(fieldValue)) {
+                        return false; // 必填字段为空
+                    }
+                }
+            }
+        }
+
+        return true;
+    }
     // 自动关闭计划条件判断
     private boolean isAutoCloseCondition(PageData pd) {
         return "2".equals(pd.getString("iscoordinate")) &&
@@ -316,7 +352,23 @@ public class FollowTaskController extends BaseController {
         PageData pageData = followTaskService.selectOneById(pd);//根据任务id查询随访任务数据
        String pagIndex="精简表单";//默认为精简表单
         if (StringUtils.isNotNull(pageData)) {
-            String useForm= (String) pageData.get("useForm");
+            // 获取模版配置ID
+            String templateConfigId = (String) pageData.get("templateConfigId");
+            String useForm = (String) pageData.get("useForm");
+
+            // 如果任务中有模版配置ID,则使用配置的模版
+            if (StringUtils.isNotEmpty(templateConfigId)) {
+                // 获取模版配置详情
+                PageData templateQuery = new PageData();
+                templateQuery.put("id", templateConfigId);
+                Map<String, Object> templateConfig = followTemplateConfigService.getTemplateConfig(templateQuery);
+
+                if (templateConfig != null) {
+                    mmap.put("templateConfig", templateConfig);
+                    mmap.put("useConfiguredTemplate", true);
+                    mmap.put("templateConfigId", templateConfigId);
+                }
+            }
             if(StringUtils.isNotEmpty(useForm)){
                 pagIndex=useForm;
             }
@@ -388,17 +440,105 @@ public class FollowTaskController extends BaseController {
 
             pageData.put("bc_taskStatus",pageData.get("taskStatus"));//任务状态 0待执行,\r\n1已完成,\r\n2未完成,\r\n3已下发,\r\n4已取消
             mmap.putAll(pageData);
-        }else{
-            mmap.put("未查询到数据 id",id);
-        }
-        if(pagIndex.equals("全量表单")){
-            return prefix_followUp + "/followUpEditAll";//全量表单
-        }else {
-            return prefix_followUp + "/followUpEdit";//followUpEdit 精简的表单
+            // 添加这部分代码
+            processTaskData(pageData, mmap);
+
+            // 根据模版配置决定使用哪个页面
+            if (StringUtils.isNotEmpty(templateConfigId)) {
+                return prefix_followUp + "/followUpEditDynamic"; // 使用动态配置页面
+            } else if ("全量表单".equals(useForm)) {
+                return prefix_followUp + "/followUpEditAll"; // 全量表单
+            } else {
+                return prefix_followUp + "/followUpEdit"; // 精简表单
+            }
+
+
+    } else {
+        mmap.put("error", "未查询到数据 id: " + id);
+        return prefix_followUp + "/followUpEdit";
+    }
+
+    }
+/**
+ * 处理任务数据的通用方法
+ */
+private void processTaskData(PageData pageData, ModelMap mmap) throws Exception {
+    PageData pd2 = new PageData();
+    PageData pd3 = new PageData();
+    PageData pd4 = new PageData();
+    PageData pd5 = new PageData();
+    PageData pd6 = new PageData();
+
+    pd2.put("patientId", pageData.get("patientId"));
+    pd2.put("storeId", getSysUser().getDeptId());
+    pd3.put("patientId", pageData.get("patientId"));
+    pd3.put("mdmCode", pageData.get("mdmCode"));
+    pd3.put("businessBelonging", "常规随访");
+
+    pd4.put("patientId", pageData.get("patientId"));
+    pd4.put("mdmCode", pageData.get("mdmCode"));
+    pd4.put("businessBelonging", "脱落召回");
+
+    pd5.put("id", pageData.get("patientId"));
+
+    List<PageData> Plan1 = followPlanService.selectPlanByCPBList(pd3);
+    PageData pd1 = pharmaceuticalService.selectFollowUpPerson(pd2);
+
+    if (StringUtils.isNotNull(Plan1)) {
+        pageData.put("planListCG", Plan1);
+    }
+
+    List<PageData> Plan2 = followPlanService.selectPlanByCPBList(pd4);
+    if (StringUtils.isNotNull(Plan2)) {
+        pageData.put("planListTL", Plan2);
+    }
+
+    pd6.put("patientId", pageData.get("patientId"));
+    pd6.put("storeId", getSysUser().getDeptId().toString());
+    List<PageData> dValueList = pharmaceuticalService.getPatienDvalueList2(pd6);
+    pageData.put("dValueList", dValueList);
+
+    PageData Degree = followPlanService.getPerfectionDegree(pd2);
+    List<PageData> records = pharmaceuticalService.getDrugPurchaseList(pd5);
+
+    if (StringUtils.isNotNull(Degree)) {
+        pageData.put("filledFieldsCount", Degree.get("filledFieldsCount"));
+        Object completenessObj = Degree.get("completenessPercentage");
+        if (completenessObj instanceof BigDecimal) {
+            BigDecimal completenessPercentage = (BigDecimal) completenessObj;
+            BigDecimal roundedPercentage = completenessPercentage.setScale(0, BigDecimal.ROUND_HALF_UP);
+            pageData.put("completenessPercentage", roundedPercentage.intValue());
         }
+    }
 
+    if (records.size() > 0) {
+        pageData.put("recordsData", records);
+        pageData.put("dl", records.get(0).get("dl"));
     }
 
+    if (StringUtils.isNotNull(pd1)) {
+        pageData.put("followUpPersonName", pd1.get("followUpPersonName"));
+        pageData.put("followUpPersonId", pd1.get("id"));
+    }
+
+    // 设置任务相关信息
+    pageData.put("bc_id", pageData.get("id"));
+    pageData.put("bc_planId", pageData.get("planId"));
+    pageData.put("bc_appointmentDate", pageData.get("appointmentDate1"));
+    pageData.put("bc_businessBelonging", pageData.get("businessBelonging"));
+    pageData.put("bc_taskName", pageData.get("taskName"));
+    pageData.put("bc_taskTheme", pageData.get("taskTheme"));
+    pageData.put("bc_productName", pageData.get("productName"));
+    pageData.put("bc_taskFollower", pageData.get("taskFollower"));
+    pageData.put("timeFirstDiagnosis", pageData.get("timeFirstDiagnosis2"));
+    pageData.put("FirstDiagnosis", pageData.get("FirstDiagnosis"));
+    pageData.put("bc_next_follow_time", pageData.get("next_follow_time2"));
+    pageData.put("bc_next_taskTheme", pageData.get("next_taskTheme"));
+    pageData.put("interval_this_time", pageData.get("interval_this_time"));
+    pageData.put("bc_taskStatus", pageData.get("taskStatus"));
+
+    mmap.putAll(pageData);
+}
     /**
      * 保存计划修改信息
      */

+ 582 - 0
health-admin/src/main/java/com/bzd/web/controller/gxhpz/FollowTemplateConfigController.java

@@ -0,0 +1,582 @@
+package com.bzd.web.controller.gxhpz;
+
+import com.bzd.common.annotation.Log;
+import com.bzd.common.config.dao.PageData;
+import com.bzd.common.core.controller.BaseController;
+import com.bzd.common.core.domain.AjaxResult;
+import com.bzd.common.core.page.TableDataInfo;
+import com.bzd.common.enums.BusinessType;
+import com.bzd.common.utils.DateUtils;
+import com.bzd.common.utils.StringUtils;
+import com.bzd.system.service.gxhpz.FollowTemplateConfigService;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 随访模版配置控制器
+ * @author system
+ */
+@Controller
+@RequestMapping("/gxhpz/followTemplateConfig")
+public class FollowTemplateConfigController extends BaseController {
+    
+    private String prefix = "gxhpz/followTemplateConfig";
+    
+    @Autowired
+    private FollowTemplateConfigService followTemplateConfigService;
+
+    /**
+     * 模版配置管理页面
+     */
+    @RequiresPermissions("gxhpz:followTemplate:view")
+    @GetMapping()
+    public String followTemplateConfig() {
+        return prefix + "/followTemplateConfig";
+    }
+
+    /**
+     * 查询模版配置列表
+     */
+    @RequiresPermissions("gxhpz:followTemplate:list")
+    @PostMapping("/list")
+    @ResponseBody
+    public TableDataInfo list() throws Exception {
+        PageData pd = this.getPageData();
+        startPage();
+        pd.put("storeId", getSysUser().getDeptId());
+        List<PageData> list = followTemplateConfigService.selectTemplateList(pd);
+        return getDataTable(list);
+    }
+
+    /**
+     * 新增模版配置页面
+     */
+    @RequiresPermissions("gxhpz:followTemplate:add")
+    @GetMapping("/add")
+    public String add(ModelMap mmap) {
+        return prefix + "/add";
+    }
+
+    /**
+     * 新增保存模版配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:add")
+    @Log(title = "模版配置", businessType = BusinessType.INSERT)
+    @PostMapping("/add")
+    @ResponseBody
+    public AjaxResult addSave() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("storeId", getSysUser().getDeptId());
+        pd.put("createdBy", getSysUser().getLoginName());
+        pd.put("createdTime", DateUtils.getTime());
+        pd.put("status", 1);
+        
+        Integer result = followTemplateConfigService.insertTemplate(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 修改模版配置页面
+     */
+    @RequiresPermissions("gxhpz:followTemplate:edit")
+    @GetMapping("/edit/{id}")
+    public String edit(@PathVariable("id") Long id, ModelMap mmap) throws Exception {
+        PageData pd = new PageData();
+        pd.put("id", id);
+        PageData template = followTemplateConfigService.selectTemplateById(pd);
+        mmap.putAll(template);
+        return prefix + "/edit";
+    }
+
+    /**
+     * 修改保存模版配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:edit")
+    @Log(title = "模版配置", businessType = BusinessType.UPDATE)
+    @PostMapping("/edit")
+    @ResponseBody
+    public AjaxResult editSave() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("updatedBy", getSysUser().getLoginName());
+        pd.put("updatedTime", DateUtils.getTime());
+        
+        Integer result = followTemplateConfigService.updateTemplate(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 删除模版配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:remove")
+    @Log(title = "模版配置", businessType = BusinessType.DELETE)
+    @PostMapping("/remove")
+    @ResponseBody
+    public AjaxResult remove() throws Exception {
+        PageData pd = this.getPageData();
+        String ids = (String) pd.get("ids");
+        if (StringUtils.isNotEmpty(ids)) {
+            String[] idArray = ids.split(",");
+            Integer result = followTemplateConfigService.deleteTemplateByIds(idArray);
+            return toAjax(result);
+        }
+        return error("请选择要删除的数据");
+    }
+
+    /**
+     * 模版字段配置页面
+     */
+    @RequiresPermissions("gxhpz:followTemplate:field")
+    @GetMapping("/fields/{templateId}")
+    public String fields(@PathVariable("templateId") Long templateId, ModelMap mmap) throws Exception {
+        PageData pd = new PageData();
+        pd.put("id", templateId);
+        PageData template = followTemplateConfigService.selectTemplateById(pd);
+        mmap.put("template", template);
+        mmap.put("templateId", templateId);
+        return prefix + "/fields";
+    }
+
+    /**
+     * 查询模版字段配置列表
+     */
+    @RequiresPermissions("gxhpz:followTemplate:field")
+    @PostMapping("/fieldList")
+    @ResponseBody
+    public TableDataInfo fieldList() throws Exception {
+        PageData pd = this.getPageData();
+        startPage();
+        List<PageData> list = followTemplateConfigService.selectFieldList(pd);
+        return getDataTable(list);
+    }
+
+    /**
+     * 新增字段配置页面
+     */
+    @RequiresPermissions("gxhpz:followTemplate:field")
+    @GetMapping("/addField/{templateId}")
+    public String addField(@PathVariable("templateId") Long templateId, ModelMap mmap) throws Exception {
+        // 获取所有可用字段
+        List<PageData> availableFields = followTemplateConfigService.getAvailableFields();
+        mmap.put("availableFields", availableFields);
+        mmap.put("templateId", templateId);
+        return prefix + "/addField";
+    }
+
+    /**
+     * 保存字段配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:field")
+    @Log(title = "字段配置", businessType = BusinessType.INSERT)
+    @PostMapping("/saveField")
+    @ResponseBody
+    public AjaxResult saveField() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("createdTime", DateUtils.getTime());
+        
+        Integer result = followTemplateConfigService.insertField(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 删除字段配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:field")
+    @Log(title = "字段配置", businessType = BusinessType.DELETE)
+    @PostMapping("/removeField")
+    @ResponseBody
+    public AjaxResult removeField() throws Exception {
+        PageData pd = this.getPageData();
+        String ids = (String) pd.get("ids");
+        if (StringUtils.isNotEmpty(ids)) {
+            String[] idArray = ids.split(",");
+            Integer result = followTemplateConfigService.deleteFieldByIds(idArray);
+            return toAjax(result);
+        }
+        return error("请选择要删除的数据");
+    }
+
+    /**
+     * 字段规则配置页面
+     */
+    @RequiresPermissions("gxhpz:followTemplate:rule")
+    @GetMapping("/rules/{templateId}")
+    public String rules(@PathVariable("templateId") Long templateId, ModelMap mmap) throws Exception {
+        PageData pd = new PageData();
+        pd.put("id", templateId);
+        PageData template = followTemplateConfigService.selectTemplateById(pd);
+        mmap.put("template", template);
+        mmap.put("templateId", templateId);
+        return prefix + "/rules";
+    }
+
+    /**
+     * 查询字段规则列表
+     */
+    @RequiresPermissions("gxhpz:followTemplate:rule")
+    @PostMapping("/ruleList")
+    @ResponseBody
+    public TableDataInfo ruleList() throws Exception {
+        PageData pd = this.getPageData();
+        startPage();
+        List<PageData> list = followTemplateConfigService.selectRuleList(pd);
+        return getDataTable(list);
+    }
+
+
+    /**
+     * 获取可用字段列表
+     */
+    @GetMapping("/getAvailableFields")
+    @ResponseBody
+    public AjaxResult getAvailableFields() {
+        try {
+            List<PageData> fields = followTemplateConfigService.getAvailableFields();
+            return AjaxResult.success(fields);
+        } catch (Exception e) {
+            return AjaxResult.error("获取可用字段失败");
+        }
+    }
+    /**
+     * 获取模版配置详情(用于任务表单渲染)
+     */
+    @PostMapping("/getTemplateConfig")
+    @ResponseBody
+    public AjaxResult getTemplateConfig() throws Exception {
+        PageData pd = this.getPageData();
+        Map<String, Object> templateConfig = followTemplateConfigService.getTemplateConfig(pd);
+        return AjaxResult.success(templateConfig);
+    }
+
+    /**
+     * 获取可用模版列表(用于任务创建时选择)
+     */
+    @PostMapping("/getAvailableTemplates")
+    @ResponseBody
+    public AjaxResult getAvailableTemplates() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("storeId", getSysUser().getDeptId());
+        pd.put("status", 1);
+        List<PageData> templates = followTemplateConfigService.selectTemplateList(pd);
+        return AjaxResult.success(templates);
+    }
+
+    /**
+     * 复制模版
+     */
+    @RequiresPermissions("gxhpz:followTemplate:add")
+    @Log(title = "复制模版", businessType = BusinessType.INSERT)
+    @PostMapping("/copy")
+    @ResponseBody
+    public AjaxResult copyTemplate() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("createdBy", getSysUser().getLoginName());
+        pd.put("createdTime", DateUtils.getTime());
+        pd.put("storeId", getSysUser().getDeptId());
+        
+        Integer result = followTemplateConfigService.copyTemplate(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 启用/禁用模版
+     */
+    @RequiresPermissions("gxhpz:followTemplate:edit")
+    @Log(title = "模版状态", businessType = BusinessType.UPDATE)
+    @PostMapping("/changeStatus")
+    @ResponseBody
+    public AjaxResult changeStatus() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("updatedBy", getSysUser().getLoginName());
+        pd.put("updatedTime", DateUtils.getTime());
+        
+        Integer result = followTemplateConfigService.updateTemplateStatus(pd);
+        return toAjax(result);
+    }
+
+
+
+    /**
+     * 保存模版配置(Tab和字段配置)
+     */
+    @RequiresPermissions("gxhpz:followTemplate:field")
+    @Log(title = "模版配置", businessType = BusinessType.UPDATE)
+    @PostMapping("/saveConfig")
+    @ResponseBody
+    public AjaxResult saveConfig() throws Exception {
+        PageData pd = this.getPageData();
+
+        // 保存Tab配置
+        String tabConfig = (String) pd.get("tabConfig");
+        if (StringUtils.isNotEmpty(tabConfig)) {
+            pd.put("tabConfigData", tabConfig);
+        }
+
+        // 保存字段配置
+        String fieldConfig = (String) pd.get("fieldConfig");
+        if (StringUtils.isNotEmpty(fieldConfig)) {
+            pd.put("fieldConfigData", fieldConfig);
+        }
+
+        pd.put("updatedBy", getSysUser().getLoginName());
+        pd.put("updatedTime", DateUtils.getTime());
+
+        Integer result = followTemplateConfigService.saveTemplateConfig(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 获取模版的字段列表
+     */
+    @PostMapping("/getTemplateFields")
+    @ResponseBody
+    public AjaxResult getTemplateFields() throws Exception {
+        PageData pd = this.getPageData();
+        List<PageData> fields = followTemplateConfigService.getTemplateFields(pd);
+        return AjaxResult.success(fields);
+    }
+
+    /**
+     * 更新规则状态
+     */
+    @RequiresPermissions("gxhpz:followTemplate:rule")
+    @Log(title = "规则状态", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateRuleStatus")
+    @ResponseBody
+    public AjaxResult updateRuleStatus() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("updatedBy", getSysUser().getLoginName());
+        pd.put("updatedTime", DateUtils.getTime());
+
+        Integer result = followTemplateConfigService.updateRuleStatus(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 删除规则
+     */
+    @RequiresPermissions("gxhpz:followTemplate:rule")
+    @Log(title = "删除规则", businessType = BusinessType.DELETE)
+    @PostMapping("/deleteRule")
+    @ResponseBody
+    public AjaxResult deleteRule() throws Exception {
+        PageData pd = this.getPageData();
+        String id = (String) pd.get("id");
+        if (StringUtils.isNotEmpty(id)) {
+            Integer result = followTemplateConfigService.deleteRuleById(id);
+            return toAjax(result);
+        }
+        return error("请选择要删除的规则");
+    }
+
+    /**
+     * 规则测试页面
+     */
+    @RequiresPermissions("gxhpz:followTemplate:rule")
+    @GetMapping("/testRule/{ruleId}")
+    public String testRule(@PathVariable("ruleId") Long ruleId, ModelMap mmap) throws Exception {
+        PageData pd = new PageData();
+        pd.put("id", ruleId);
+        PageData rule = followTemplateConfigService.selectRuleById(pd);
+        mmap.put("rule", rule);
+        return prefix + "/testRule";
+    }
+
+    /**
+     * 模版预览页面
+     */
+    @RequiresPermissions("gxhpz:followTemplate:view")
+    @GetMapping("/preview/{templateId}")
+    public String preview(@PathVariable("templateId") Long templateId, ModelMap mmap) throws Exception {
+        PageData pd = new PageData();
+        pd.put("id", templateId);
+        PageData template = followTemplateConfigService.selectTemplateById(pd);
+
+        // 获取模版配置
+        Map<String, Object> templateConfig = followTemplateConfigService.getTemplateConfig(pd);
+
+        mmap.put("template", template);
+        mmap.put("templateConfig", templateConfig);
+        mmap.put("templateId", templateId);
+
+        // 检查是否包含规则预览
+        String withRules = getRequest().getParameter("withRules");
+        if ("true".equals(withRules)) {
+            List<PageData> rules = followTemplateConfigService.selectRuleList(pd);
+            mmap.put("rules", rules);
+        }
+
+        return prefix + "/preview";
+    }
+
+    /**
+     * 获取字段选项配置
+     */
+    @PostMapping("/getFieldOptions")
+    @ResponseBody
+    public AjaxResult getFieldOptions() throws Exception {
+        PageData pd = this.getPageData();
+        String fieldCode = (String) pd.get("fieldCode");
+
+        if (StringUtils.isEmpty(fieldCode)) {
+            return AjaxResult.error("字段编码不能为空");
+        }
+
+        List<PageData> options = followTemplateConfigService.getFieldOptions(fieldCode);
+        return AjaxResult.success(options);
+    }
+
+    /**
+     * 保存字段选项配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:field")
+    @Log(title = "字段选项", businessType = BusinessType.UPDATE)
+    @PostMapping("/saveFieldOptions")
+    @ResponseBody
+    public AjaxResult saveFieldOptions() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("updatedBy", getSysUser().getLoginName());
+        pd.put("updatedTime", DateUtils.getTime());
+
+        Integer result = followTemplateConfigService.saveFieldOptions(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 批量更新字段配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:field")
+    @Log(title = "批量字段配置", businessType = BusinessType.UPDATE)
+    @PostMapping("/batchUpdateFields")
+    @ResponseBody
+    public AjaxResult batchUpdateFields() throws Exception {
+        PageData pd = this.getPageData();
+        String fieldsData = (String) pd.get("fieldsData");
+
+        if (StringUtils.isEmpty(fieldsData)) {
+            return AjaxResult.error("字段配置数据不能为空");
+        }
+
+        pd.put("updatedBy", getSysUser().getLoginName());
+        pd.put("updatedTime", DateUtils.getTime());
+
+        Integer result = followTemplateConfigService.batchUpdateFields(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 导出模版配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:export")
+    @Log(title = "导出模版", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    @ResponseBody
+    public AjaxResult exportTemplate() throws Exception {
+        PageData pd = this.getPageData();
+        String templateId = (String) pd.get("templateId");
+
+        if (StringUtils.isEmpty(templateId)) {
+            return AjaxResult.error("请选择要导出的模版");
+        }
+
+        Map<String, Object> exportData = followTemplateConfigService.exportTemplate(pd);
+        return AjaxResult.success(exportData);
+    }
+
+    /**
+     * 导入模版配置
+     */
+    @RequiresPermissions("gxhpz:followTemplate:import")
+    @Log(title = "导入模版", businessType = BusinessType.IMPORT)
+    @PostMapping("/import")
+    @ResponseBody
+    public AjaxResult importTemplate() throws Exception {
+        PageData pd = this.getPageData();
+        String importData = (String) pd.get("importData");
+
+        if (StringUtils.isEmpty(importData)) {
+            return AjaxResult.error("导入数据不能为空");
+        }
+
+        pd.put("storeId", getSysUser().getDeptId());
+        pd.put("createdBy", getSysUser().getLoginName());
+        pd.put("createdTime", DateUtils.getTime());
+
+        Integer result = followTemplateConfigService.importTemplate(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 获取模版使用统计
+     */
+    @PostMapping("/getTemplateStats")
+    @ResponseBody
+    public AjaxResult getTemplateStats() throws Exception {
+        PageData pd = this.getPageData();
+        Map<String, Object> stats = followTemplateConfigService.getTemplateStats(pd);
+        return AjaxResult.success(stats);
+    }
+
+    /**
+     * 检查模版名称是否重复
+     */
+    @PostMapping("/checkTemplateName")
+    @ResponseBody
+    public AjaxResult checkTemplateName() throws Exception {
+        PageData pd = this.getPageData();
+        String templateName = (String) pd.get("templateName");
+        String templateId = (String) pd.get("templateId");
+
+        if (StringUtils.isEmpty(templateName)) {
+            return AjaxResult.error("模版名称不能为空");
+        }
+
+        pd.put("storeId", getSysUser().getDeptId());
+        boolean exists = followTemplateConfigService.checkTemplateNameExists(pd);
+
+        if (exists) {
+            return AjaxResult.error("模版名称已存在");
+        } else {
+            return AjaxResult.success("模版名称可用");
+        }
+    }
+
+
+    /**
+     * 保存字段规则
+     */
+    @RequiresPermissions("gxhpz:followTemplate:rule")
+    @Log(title = "字段规则", businessType = BusinessType.INSERT)
+    @PostMapping("/saveRule")
+    @ResponseBody
+    public AjaxResult saveRule() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("createdTime", DateUtils.getTime());
+
+        Integer result = followTemplateConfigService.insertRule(pd);
+        return toAjax(result);
+    }
+
+    /**
+     * 更新字段规则
+     */
+    @RequiresPermissions("gxhpz:followTemplate:rule")
+    @Log(title = "字段规则", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateRule")
+    @ResponseBody
+    public AjaxResult updateRule() throws Exception {
+        PageData pd = this.getPageData();
+        pd.put("updatedTime", DateUtils.getTime());
+
+        Integer result = followTemplateConfigService.updateRule(pd);
+        return toAjax(result);
+    }
+
+
+
+}

+ 1 - 1
health-admin/src/main/resources/templates/dtp/followUp/followUpEditAll.html

@@ -546,7 +546,7 @@
             </div>
             <div class="customize-form-group info-display">
                 <label>姓名:</label>
-                <span class="info-value" th:text="${name}">张三</span>
+                <span class="info-value" th:text="${name}"></span>
                 &nbsp;&nbsp;
                 <i class="fa" th:class="${realNameStatus == 1 ? 'fa fa-check text-success' : 'fa fa-close text-danger'}" id="checkName"></i>
                 &nbsp;

+ 1146 - 0
health-admin/src/main/resources/templates/dtp/followUp/followUpEditDynamic.html

@@ -0,0 +1,1146 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: footer" />
+    <!-- 继承原有样式 -->
+    <style type="text/css">
+        /* 保持原有样式,添加动态显示控制 */
+        .dynamic-tab {
+            display: none;
+        }
+        .dynamic-tab.enabled {
+            display: block;
+        }
+        .dynamic-field {
+            display: none;
+        }
+        .dynamic-field.enabled {
+            display: block;
+        }
+        .template-indicator {
+            position: fixed;
+            top: 10px;
+            right: 10px;
+            background: #1ab394;
+            color: white;
+            padding: 5px 10px;
+            border-radius: 3px;
+            font-size: 12px;
+            z-index: 9999;
+        }
+
+        /* 其他原有样式保持不变 */
+        .toggle-icon {
+            transition: transform 0.3s ease;
+        }
+        .collapsing .toggle-icon {
+            transform: rotate(90deg);
+        }
+        .plan-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 15px;
+            border-bottom: 1px solid #eee;
+        }
+        /* ... 其他样式保持原有不变 ... */
+
+
+
+
+        .toggle-icon {
+            transition: transform 0.3s ease;
+        }
+
+        .collapsing .toggle-icon {
+            transform: rotate(90deg);
+        }
+
+
+        .plan-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 15px;
+            border-bottom: 1px solid #eee;
+        }
+
+        .product-info {
+            display: flex;
+            flex-direction: column;
+        }
+
+        .product-name,
+        .specification {
+            font-size: 1.5rem;
+            margin-bottom: 5px;
+            color: #333;
+        }
+
+        .status-and-actions {
+            display: flex;
+            align-items: center;
+            gap: 15px;
+        }
+
+        .business-belonging {
+            font-size: 1.3rem;
+            color: #00B83F;
+        }
+
+        .status-tag {
+            font-weight: bold;
+            padding: 4px 10px;
+            border-radius: 5px;
+            font-size: 1.2rem;
+        }
+
+        .status-0 { background-color: #F04E53FF; color: white; } /* 已关闭 */
+        .status-1 { background-color: #5cb85c; color: white; } /* 进行中 */
+        .status-2 { background-color: #5bc0de; color: white; } /* 已创建 */
+
+        .btn-plan-action {
+            text-decoration: none;
+            font-weight: bold;
+            margin-left: 10px;
+            transition: color 0.3s ease;
+        }
+
+        .btn-plan-action:hover {
+            color: #0056b3;
+        }
+
+        .meta-info {
+            display: grid;
+            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+            gap: 10px;
+            padding: 10px 0;
+        }
+
+        .meta-item .label {
+            font-weight: bold;
+            color: #555;
+            margin-right: 5px;
+        }
+
+        .meta-item .value {
+            color: #2E2D3C;
+            font-size: 14px;
+        }
+
+        .ibox-content {
+            background-color: #f9f9f9;
+            border-radius: 8px;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.05);
+            margin-bottom: 15px;
+        }
+
+
+
+
+
+        .plan-info {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            padding: 10px;
+            border-bottom: 1px solid #ddd;
+        }
+
+        .product-details {
+            display: flex;
+            align-items: center;
+        }
+
+        .product-name, .specification {
+            font-size: 1.5rem;
+            margin-right: 20px;
+        }
+
+        .status-and-actions {
+            display: flex;
+            align-items: center;
+        }
+
+        .business-belonging, .status {
+            font-size: 1.5rem;
+            color: #00B83F;
+            margin-right: 20px;
+        }
+
+        .close-plan, .restart-plan {
+            margin-left: 10px;
+            text-decoration: none;
+            color: #007bff;
+        }
+
+        .creator-info {
+            display: grid;
+            grid-template-columns: repeat(4, 1fr);
+            gap: 10px;
+            padding: 10px;
+            border-bottom: 1px solid #ddd;
+        }
+
+        .label {
+            font-weight: bold;
+        }
+
+        .value {
+            color: #2E2D3C;
+        }
+
+
+
+
+
+
+
+        #myTabs2 {
+            z-index: 0;
+        }
+        .fileinput-preview.thumbnail {
+            display: flex;
+            justify-content: center; /* 水平居中 */
+            align-items: center; /* 垂直居中 */
+            text-align: center; /* 确保文本内部也居中 */
+            position: relative;
+            background-color: #f5f5f5; /* 设置背景颜色以更好地区分 */
+            border: 2px dashed #ccc; /* 添加虚线边框 */
+            color: #999; /* 文字颜色 */
+            font-size: 14px; /* 文字大小 */
+        }
+
+        .centered-content {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+        }
+
+        .plus-sign {
+            margin-top: 5px;
+            font-size: 24px;
+            font-weight: bold;
+        }
+        /* 隐藏初始的大图 */
+        .preview-large {
+            display: none;
+            position: absolute;
+            border: 1px solid #ccc;
+            background-color: #fff;
+            z-index: 1000;
+        }
+
+        /* 确保预览框在特定容器内 */
+        .customize-form-group-container {
+            position: relative;
+        }
+        .fileinput .fileinput-preview {
+            background-image: none !important;
+            background-color: transparent !important;
+        }
+
+        .expired-label {
+            color: red;
+            font-weight: bold;
+        }
+        /* 统一所有表单元素的基线对齐 */
+        .input-groups * {
+            vertical-align: baseline;  /* 或 middle 根据情况选择 */
+        }
+        .form-group {
+            margin-bottom: -1px;
+        }
+        /* 精确控制自定义单选按钮 */
+        .form-check-radio {
+            width: 18px;
+            height: 18px;
+            position: relative;
+            top: 2px;  /* 根据实际字体大小调整 */
+            margin: 0 6px 0 0;
+            cursor: pointer;
+        }
+
+        /* 标签文字精确调整 */
+        .input-groups label {
+            font-size: 16px;
+            position: relative;
+            top: 1px;  /* 补偿字体渲染的视觉偏差 */
+        }
+
+
+        .form-check-radio:checked::before {
+            background: #1890ff;
+        }
+
+        .input-groups div {
+            white-space: normal;
+            min-width: 150px; /* 设置最小宽度控制换行节奏 */
+        }
+        /* 问号图标的样式 */
+        .question-mark {
+            width: 20px; /* 根据需要调整大小 */
+            height: 20px;
+            cursor: pointer;
+        }
+
+        /* 工具提示内容的默认状态:隐藏 */
+        .tooltip-content {
+            visibility: hidden;
+            opacity: 0;
+            transition: visibility 0s, opacity 0.5s;
+            position: absolute;
+            top: -30px; /* 根据实际情况调整 */
+            left: 300px; /* 根据实际情况调整 */
+            z-index: 1000;
+        }
+
+        /* 当悬停在问号图标上时,显示工具提示内容 */
+        .question-mark:hover + .tooltip-content,
+        .tooltip-content:hover {
+            visibility: visible;
+            opacity: 1;
+        }
+
+        /* 图片缩放效果 */
+        .tooltip-image {
+            width: 400px; /* 初始大小 */
+            transition: transform 0.3s ease;
+        }
+
+        /* 当悬停在图片上时放大图片 */
+        .tooltip-image:hover {
+            transform: scale(1.5); /* 放大倍数 */
+        }
+
+
+        .select2-dropdown {
+            z-index: 9999 !important;
+        }
+        .tabs-container {
+            position: relative;
+        }
+        label {
+            display: inline-block;
+            max-width: 100%;
+            margin-bottom: 0px;
+            font-weight: 700;
+        }
+        input {
+            width: 40px;
+        }
+        .customize-form-group label {
+            width: 250px;
+            text-align: right;
+            margin-right: 0.5em;
+        }
+        .font {
+            font-size: 16px; /* 字体大小 */
+        }
+        .form-groupBottom {
+            margin-bottom: 30px; /* 调整这个值以改变间距 */
+        }
+
+
+        .content-area {
+            margin-top: 50px; /* 调整这个值以确保内容不会被导航栏遮挡 */
+        }
+        .nav-tabs {
+            position: sticky;
+            top: 0; /* 距离顶部的距离 */
+            background-color: #fff; /* 设置背景颜色,以便覆盖下方的内容 */
+            z-index: 1020; /* 确保它位于其他内容之上 */
+        }
+
+        .tabs-container {
+            position: relative;
+        }
+
+        .btn {
+            background-color: #f2f2f2;
+            border: none;
+            color: black;
+            padding: 5px 10px;
+            text-align: center;
+            text-decoration: none;
+            display: inline-block;
+            font-size: 16px;
+            margin: 4px 2px;
+            cursor: pointer;
+        }
+
+        .btn-primary {
+            background-color: #1a7bb9;
+            color: white;
+        }
+
+        .btn-w-m {
+            width: max-content;
+        }
+
+        .btn-default {
+            background-color: #f2f2f2;
+            color: black;
+        }
+        .btn:hover {
+            opacity: 0.8;
+        }
+        .tab-1a {
+            padding-left: 50px;
+            width: 100px;
+            font-size: 15px
+        }
+        .tab-1b {
+            width: 100px;
+            color: blue;
+            font-size:15px;
+        }
+        .task-follow-up {
+            display: flex;
+            align-items: center;
+        }
+
+        .follow-up-person, .plan-buttons {
+            flex: 1;
+        }
+
+        .plan-buttons {
+            text-align: right;
+        }
+        .ibox-title2 {
+            display: flex;
+            align-items: center;
+            justify-content: start;
+            padding: 6px;
+            border-bottom: 1px solid #ddd;
+        }
+        .right-aligned-link {
+            float: right;
+            margin-left: 20px; /* 增加左侧边距 */
+        }
+
+        .right-aligned-link::after {
+            content: ">";
+            color: blue;
+        }
+        .task-info {
+            flex: 1;
+        }
+
+        .task-details {
+            flex: 2;
+            display: flex;
+            align-items: center;
+            gap: 0px;
+        }
+
+        .task-buttons {
+            flex: 1;
+            display: flex;
+            align-items: center;
+            justify-content: flex-end;
+            gap: 10px;
+        }
+
+        .task-buttons span {
+            margin-left: 10px;
+        }
+
+        .task-details span {
+            display: flex;
+            align-items: center;
+            gap: 1px;
+        }
+        .custom-file-upload {
+            position: relative;
+            overflow: hidden;
+            cursor: pointer;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+        }
+
+        .custom-file-upload input[type=file] {
+            opacity: 0;
+            width: 100%;
+            height: 100%;
+            top: 0;
+            left: 0;
+            position: absolute;
+        }
+
+        .custom-file-upload label {
+            background-color: white;
+            border: 2px dashed #007bff;
+            color: #007bff;
+            padding: 20px;
+            text-align: center;
+            display: block;
+            min-height: 150px;
+        }
+        #hbyyjlTable {
+            width: 100%;
+            border-collapse: collapse;
+        }
+
+        th,
+        td {
+            padding: 10px;
+            text-align: center;
+            border-bottom: 1px solid #ddd;
+        }
+
+        thead th {
+            background-color: #f2f2f2;
+            font-weight: bold;
+        }
+
+        tbody tr:hover {
+            background-color: #f5f5f5;
+        }
+
+        .no-data {
+            text-align: center;
+            padding: 0px;
+        }
+
+        .btn-primarys {
+            margin-left: 10px;
+            color: green;
+        }
+
+
+        .radio-item label {
+            /*margin-left: 5px;*/
+        }
+        .hidden {
+            display: none;
+        }
+        .shown {
+            display: block;
+        }
+
+
+
+
+
+        .info-display {
+            display: flex;
+            align-items: center;
+            flex-wrap: wrap; /* 自动换行 */
+            padding: 10px 0;
+        }
+
+        .info-display label {
+            font-weight: bold;
+            margin-right: 8px;
+            min-width: 60px;
+        }
+
+        .info-value,
+        .info-age {
+            border: 1px solid #e4e4e4;
+            background-color: #f9f9f9;
+            padding: 4px 10px;
+            border-radius: 4px;
+            margin-right: 15px;
+            min-width: 80px;
+            max-width: 200px;
+            overflow: hidden;
+            white-space: nowrap;
+            text-align: left;
+            font-size: 14px;
+        }
+
+        .info-status {
+            padding: 4px 10px;
+            border-radius: 4px;
+            font-weight: bold;
+            font-size: 13px;
+        }
+
+        .status.success {
+            background-color: #d4edda;
+            color: #155724;
+        }
+
+        .status.danger {
+            background-color: #f8d7da;
+            color: #721c24;
+        }
+
+        .fa-check {
+            color: #28a745;
+        }
+
+        .fa-close {
+            color: #dc3545;
+        }
+    </style>
+</head>
+<body>
+<!-- 模版指示器 -->
+<div class="template-indicator" id="templateIndicator">
+    模版: 加载中...
+</div>
+
+<div class="font">
+    <div class="ibox">
+        <form id="form-followUp-edit1">
+            <!-- 原有头部信息保持不变 -->
+            <div class="ibox-title">
+                <button class="btn btn-w-m btn-primary" onclick="editArchives()">完善档案</button>
+                <button type="button" class="btn btn-sm btn-danger pull-right" onclick="closeItem()">返回上一级</button>
+            </div>
+
+            <!-- 基本信息区域保持不变 -->
+            <div class="customize-form-group info-display">
+                <label>姓名:</label>
+                <span class="info-value" th:text="${name}">张三</span>
+                <!-- 其他基本信息字段保持不变 -->
+            </div>
+
+            <!-- 用药信息区域保持不变 -->
+            <div class="customize-form-group" id="drug-info-container">
+                <!-- 用药信息内容保持不变 -->
+            </div>
+
+            <!-- 档案完善度保持不变 -->
+            <div class="ibox-content">
+                <!-- 档案完善度内容保持不变 -->
+            </div>
+        </form>
+    </div>
+
+    <!-- 主要Tab导航区域 - 保持不变 -->
+    <div class="ui-layout-center">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="tabs-container">
+                    <ul class="nav nav-tabs" id="myUlTabs">
+                        <li class="active"><a data-toggle="tab" href="#tab-1" aria-expanded="true">基本信息</a></li>
+                        <li class=""><a data-toggle="tab" href="#tab-2" aria-expanded="false">用药购药</a></li>
+                        <li class=""><a data-toggle="tab" href="#tab-3" aria-expanded="false">随访计划</a></li>
+                    </ul>
+                    <!-- Tab内容保持不变 -->
+                    <div class="tab-content">
+                        <div id="tab-1" class="tab-pane active">
+                            <!-- 基本信息内容保持不变 -->
+                        </div>
+                        <div id="tab-2" class="tab-pane">
+                            <!-- 用药购药内容保持不变 -->
+                        </div>
+                        <div id="tab-3" class="tab-pane">
+                            <!-- 随访计划内容保持不变 -->
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- 本次任务信息保持不变 -->
+    <div class="ibox-content">
+        <div class="ibox-title2">
+            <div class="task-info">
+                <h4>本次任务 <code style="font-size: 1.5rem;" th:text="${bc_taskStatus}"></code></h4>
+            </div>
+            <!-- 任务信息内容保持不变 -->
+        </div>
+    </div>
+
+    <!-- 动态表单区域 -->
+    <form id="form-followUp-edit3" class="form-horizontal">
+        <div class="row">
+            <div class="col-sm-12">
+                <!-- 动态生成的Tab导航 -->
+                <ul class="nav nav-tabs" id="dynamicTabs">
+                    <li class="active">
+                        <a data-toggle="tab" href="#tab-4" aria-expanded="true">本次任务</a>
+                    </li>
+                    <!-- 其他Tab将通过JavaScript动态生成 -->
+                </ul>
+
+                <div class="panel-body">
+                    <div class="tab-content content-area" id="dynamicTabContent">
+                        <!-- 本次任务Tab - 必选 -->
+                        <div id="tab-4" class="tab-pane active dynamic-tab enabled">
+                            <strong><h4 style="color: #1E9FFF;">| 本次任务</h4></strong>
+                            <div id="tab-4-fields">
+                                <!-- 字段将通过JavaScript动态生成 -->
+                            </div>
+                        </div>
+
+                        <!-- 其他Tab内容将通过JavaScript动态生成 -->
+                        <div id="tab-6" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 用药依从性</h4></strong>
+                            <div id="tab-6-fields"></div>
+                        </div>
+
+                        <div id="tab-7" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 药物安全性</h4></strong>
+                            <div id="tab-7-fields"></div>
+                        </div>
+
+                        <div id="tab-8" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 药物有效性</h4></strong>
+                            <div id="tab-8-fields"></div>
+                        </div>
+
+                        <div id="tab-9" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 治疗方案</h4></strong>
+                            <div id="tab-9-fields"></div>
+                        </div>
+
+                        <div id="tab-10" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 适宜性评估</h4></strong>
+                            <div id="tab-10-fields"></div>
+                        </div>
+
+                        <div id="tab-11" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 用药记录</h4></strong>
+                            <div id="tab-11-fields"></div>
+                        </div>
+
+                        <div id="tab-12" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 量表测评</h4></strong>
+                            <div id="tab-12-fields"></div>
+                        </div>
+
+                        <div id="tab-13" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 患者咨询</h4></strong>
+                            <div id="tab-13-fields"></div>
+                        </div>
+
+                        <div id="tab-14" class="tab-pane dynamic-tab">
+                            <strong><h4 style="color: #1E9FFF;">| 其他</h4></strong>
+                            <div id="tab-14-fields"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <!-- 底部操作区域保持不变 -->
+        <div class="ibox-content" style="background-color: #f5f3f3;">
+            <div class="ibox-title2">
+                <div class="task-info">
+                    <h4>下次随访时间
+                        <input name="next_follow_time" id="next_follow_time" placeholder="下次随访时间" class="time-input-new styled-input" type="text" th:value="${bc_next_follow_time}"/>
+                    </h4>
+                </div>
+                <div class="task-details">
+                    <h4><span>下次任务主题:<span style="color: #1a7bb9;">
+                            <select name="next_taskTheme" class="styled-input" th:with="type=${@dict.getType('sys_select_dtp_sfrw_rwzt')}">
+                                <option value="">请选择</option>
+                                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictLabel}" th:selected="${dict.dictLabel}==${bc_next_taskTheme}"></option>
+                            </select>
+                        </span></span></h4>
+                </div>
+                <div class="task-buttons">
+                    <div class="ibox-title2">
+                        <button type="button" class="btn btn-warning" style="background-color: #f56666;" onclick="closeItem()">关闭</button>
+                        <div class="task-buttons" id="TJ1">
+                            <button type="button" class="btn btn-primary" onclick="handleButtonClick()">保存</button>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </form>
+</div>
+
+<!-- JavaScript部分 -->
+<script th:inline="javascript">
+    var templateConfigId = /*[[${template_config_id}]]*/ null;
+    var templateConfig = null;
+    var fieldDefinitions = {}; // 存储字段定义
+
+    // 页面加载完成后初始化
+    $(document).ready(function() {
+        initializeTemplate();
+        loadFieldDefinitions();
+    });
+
+    // 初始化模版配置
+    function initializeTemplate() {
+        if (templateConfigId) {
+            loadTemplateConfig();
+        } else {
+            // 使用默认全量表单
+            loadDefaultTemplate();
+        }
+    }
+
+    // 加载模版配置
+    function loadTemplateConfig() {
+        $.ajax({
+            url: ctx + "gxhpz/followTemplateConfig/getTemplateConfig",
+            type: "POST",
+            data: { id: templateConfigId },
+            success: function(result) {
+                if (result.code == 0) {
+                    templateConfig = result.data;
+                    $('#templateIndicator').text('模版: ' + templateConfig.template.templateName);
+                    renderDynamicForm();
+                } else {
+                    console.error("加载模版配置失败:", result.msg);
+                    loadDefaultTemplate();
+                }
+            },
+            error: function() {
+                console.error("加载模版配置异常");
+                loadDefaultTemplate();
+            }
+        });
+    }
+
+    // 加载默认模版(全量表单)
+    function loadDefaultTemplate() {
+        $('#templateIndicator').text('模版: 全量表单 (默认)');
+        // 显示所有Tab和字段
+        $('.dynamic-tab').addClass('enabled');
+        $('.dynamic-field').addClass('enabled');
+
+        // 生成默认Tab导航
+        generateDefaultTabs();
+    }
+
+    // 生成默认Tab导航
+    function generateDefaultTabs() {
+        var defaultTabs = [
+            { code: 'tab-6', name: '用药依从性' },
+            { code: 'tab-7', name: '药物安全性' },
+            { code: 'tab-8', name: '药物有效性' },
+            { code: 'tab-9', name: '治疗方案' },
+            { code: 'tab-10', name: '适宜性评估' },
+            { code: 'tab-11', name: '用药记录' },
+            { code: 'tab-12', name: '量表测评' },
+            { code: 'tab-13', name: '患者咨询' },
+            { code: 'tab-14', name: '其他' }
+        ];
+
+        var tabHtml = '';
+        defaultTabs.forEach(function(tab) {
+            tabHtml += '<li><a data-toggle="tab" href="#' + tab.code + '">' + tab.name + '</a></li>';
+        });
+
+        $('#dynamicTabs').append(tabHtml);
+    }
+
+    // 渲染动态表单
+    function renderDynamicForm() {
+        if (!templateConfig) return;
+
+        // 渲染Tab导航
+        renderTabNavigation();
+
+        // 渲染字段
+        renderFields();
+
+        // 绑定字段事件
+        bindFieldEvents();
+    }
+
+    // 渲染Tab导航
+    function renderTabNavigation() {
+        var tabs = templateConfig.tabs;
+        if (!tabs || tabs.length === 0) return;
+
+        var tabHtml = '';
+        tabs.forEach(function(tab) {
+            if (tab.tabCode !== 'tab-4') { // 本次任务Tab已经存在
+                tabHtml += '<li><a data-toggle="tab" href="#' + tab.tabCode + '">' + tab.tabName + '</a></li>';
+                $('#' + tab.tabCode).addClass('enabled');
+            }
+        });
+
+        $('#dynamicTabs').append(tabHtml);
+    }
+
+    // 渲染字段
+    function renderFields() {
+        var fieldsByTab = templateConfig.fieldsByTab;
+        if (!fieldsByTab) return;
+
+        Object.keys(fieldsByTab).forEach(function(tabCode) {
+            var fields = fieldsByTab[tabCode];
+            var fieldsHtml = '';
+
+            // 按显示顺序排序
+            fields.sort(function(a, b) {
+                return (a.displayOrder || 0) - (b.displayOrder || 0);
+            });
+
+            fields.forEach(function(field) {
+                fieldsHtml += generateFieldHtml(field);
+            });
+
+            $('#' + tabCode + '-fields').html(fieldsHtml);
+        });
+    }
+
+    // 生成字段HTML
+    function generateFieldHtml(field) {
+        var fieldHtml = '';
+        var isRequired = field.isRequired == 1;
+        var requiredClass = isRequired ? 'is-required' : '';
+        var requiredText = isRequired ? ' <span style="color: red;">*</span>' : '';
+
+        switch (field.fieldType) {
+            case 'input':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <input name="${field.fieldCode}" id="${field.fieldCode}"
+                                   placeholder="${field.placeholder || ''}"
+                                   class="styled-input" type="text">
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'radio':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <div class="input-groups" id="${field.fieldCode}-options">
+                                <!-- 单选选项将通过JavaScript动态加载 -->
+                            </div>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'checkbox':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <div class="input-groups" id="${field.fieldCode}-options">
+                                <!-- 复选选项将通过JavaScript动态加载 -->
+                            </div>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'select':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <select name="${field.fieldCode}" id="${field.fieldCode}" class="styled-input">
+                                <option value="">请选择</option>
+                                <!-- 下拉选项将通过JavaScript动态加载 -->
+                            </select>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'textarea':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <textarea name="${field.fieldCode}" id="${field.fieldCode}"
+                                      placeholder="${field.placeholder || ''}"
+                                      class="styled-input edit_inputs textareas"
+                                      style="width: auto;height: 140px ;border: 1px solid;"
+                                      rows="1.9" cols="112"></textarea>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'datetime':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <input name="${field.fieldCode}" id="${field.fieldCode}"
+                                   placeholder="${field.placeholder || ''}"
+                                   class="time-input time-input2 styled-input" type="text">
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'file':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <div class="fileinput fileinput-new" data-provides="fileinput">
+                                <div class="fileinput-preview thumbnail" data-trigger="fileinput" style="width: 200px; height: 150px;">
+                                    <div class="centered-content">
+                                        <span class="plus-sign">+</span>
+                                    </div>
+                                </div>
+                                <div>
+                                    <input style="display: none;" id="${field.fieldCode}" name="${field.fieldCode}" type="file">
+                                    <a href="javascript:;" class="btn btn-white" data-dismiss="fileinput">清除图片</a>
+                                </div>
+                            </div>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            default:
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label>${field.fieldName}:</label>
+                            <span>字段类型 ${field.fieldType} 暂不支持</span>
+                        </div>`;
+        }
+
+        return fieldHtml;
+    }
+
+    // 加载字段定义和选项
+    function loadFieldDefinitions() {
+        // 这里可以加载字段的选项数据,比如字典数据
+        // 示例:为单选和复选框字段加载选项
+        setTimeout(function() {
+            loadFieldOptions();
+        }, 1000);
+    }
+
+    // 加载字段选项
+    function loadFieldOptions() {
+        // 为动态生成的字段加载选项数据
+        // 这里应该根据实际的字典配置来加载
+
+        // 示例:回访方式选项
+        loadRadioOptions('returnMethod', [
+            { value: '电话', text: '电话' },
+            { value: '微信', text: '微信' },
+            { value: '面访', text: '面访' }
+        ]);
+
+        // 示例:是否配合选项
+        loadRadioOptions('iscoordinate', [
+            { value: '1', text: '是' },
+            { value: '2', text: '否' }
+        ]);
+
+        // 可以继续添加其他字段的选项加载
+    }
+
+    // 加载单选选项
+    function loadRadioOptions(fieldCode, options) {
+        var container = $('#' + fieldCode + '-options');
+        if (container.length === 0) return;
+
+        var html = '';
+        options.forEach(function(option) {
+            html += `<input type="radio" class="form-check-radio" name="${fieldCode}"
+                               value="${option.value}" id="${fieldCode}_${option.value}"> ${option.text}`;
+        });
+        container.html(html);
+    }
+
+    // 绑定字段事件
+    function bindFieldEvents() {
+        // 根据模版配置中的规则绑定字段联动事件
+        if (templateConfig.rules) {
+            templateConfig.rules.forEach(function(rule) {
+                bindFieldRule(rule);
+            });
+        }
+    }
+
+    // 绑定字段规则
+    function bindFieldRule(rule) {
+        var triggerField = $('input[name="' + rule.triggerFieldCode + '"], select[name="' + rule.triggerFieldCode + '"]');
+
+        triggerField.on('change', function() {
+            var currentValue = $(this).val();
+            var targetFields = rule.targetFieldCodes.split(',');
+
+            var shouldExecute = false;
+            switch (rule.ruleLogic) {
+                case 'equal':
+                    shouldExecute = currentValue === rule.triggerFieldValue;
+                    break;
+                case 'not_equal':
+                    shouldExecute = currentValue !== rule.triggerFieldValue;
+                    break;
+                case 'contains':
+                    shouldExecute = currentValue.indexOf(rule.triggerFieldValue) !== -1;
+                    break;
+                case 'in':
+                    var values = rule.triggerFieldValue.split(',');
+                    shouldExecute = values.indexOf(currentValue) !== -1;
+                    break;
+            }
+
+            targetFields.forEach(function(targetFieldCode) {
+                var targetElement = $('[name="' + targetFieldCode.trim() + '"]').closest('.customize-form-group');
+
+                if (shouldExecute) {
+                    if (rule.actionType === 'show') {
+                        targetElement.removeClass('hidden').addClass('shown');
+                    } else if (rule.actionType === 'hide') {
+                        targetElement.removeClass('shown').addClass('hidden');
+                    } else if (rule.actionType === 'required') {
+                        targetElement.find('label').addClass('is-required');
+                        targetElement.find('input, select, textarea').attr('required', true);
+                    } else if (rule.actionType === 'optional') {
+                        targetElement.find('label').removeClass('is-required');
+                        targetElement.find('input, select, textarea').removeAttr('required');
+                    }
+                } else {
+                    // 反向操作
+                    if (rule.actionType === 'show') {
+                        targetElement.removeClass('shown').addClass('hidden');
+                    } else if (rule.actionType === 'hide') {
+                        targetElement.removeClass('hidden').addClass('shown');
+                    }
+                }
+            });
+        });
+    }
+
+    // 保持原有的其他JavaScript函数
+    function handleButtonClick() {
+        // 验证配置的必填字段
+        var isValid = validateRequiredFields();
+        if (!isValid) {
+            return false;
+        }
+
+        // 其他原有逻辑...
+        if (submitHandler()) {
+            $('#myModalClosePlan').modal('show');
+        }
+    }
+
+    // 验证必填字段
+    function validateRequiredFields() {
+        var isValid = true;
+        $('.dynamic-field.enabled').each(function() {
+            var field = $(this);
+            if (field.find('label.is-required').length > 0) {
+                var input = field.find('input, select, textarea');
+                if (input.length > 0) {
+                    var value = input.val();
+                    if (!value || value.trim() === '') {
+                        var fieldName = field.find('label').text().replace(':', '').replace('*', '').trim();
+                        $.modal.alertWarning(fieldName + ' 为必填项,请填写!');
+                        isValid = false;
+                        return false;
+                    }
+                }
+            }
+        });
+        return isValid;
+    }
+
+    // 其他原有函数保持不变...
+    function submitHandler() {
+        // 原有提交逻辑,需要适配动态字段的验证
+        return true;
+    }
+
+    function closeItem() {
+        // 原有关闭逻辑
+        window.history.back();
+    }
+
+    function editArchives() {
+        // 原有编辑档案逻辑
+    }
+</script>
+</body>
+</html>

+ 4396 - 0
health-admin/src/main/resources/templates/dtp/followUp/follwUpDynamic.html

@@ -0,0 +1,4396 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" >
+<head>
+    <th:block th:include="include :: footer" />
+</head>
+<style type="text/css">
+    .toggle-icon {
+        transition: transform 0.3s ease;
+    }
+
+    .collapsing .toggle-icon {
+        transform: rotate(90deg);
+    }
+
+
+    .plan-header {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 15px;
+        border-bottom: 1px solid #eee;
+    }
+
+    .product-info {
+        display: flex;
+        flex-direction: column;
+    }
+
+    .product-name,
+    .specification {
+        font-size: 1.5rem;
+        margin-bottom: 5px;
+        color: #333;
+    }
+
+    .status-and-actions {
+        display: flex;
+        align-items: center;
+        gap: 15px;
+    }
+
+    .business-belonging {
+        font-size: 1.3rem;
+        color: #00B83F;
+    }
+
+    .status-tag {
+        font-weight: bold;
+        padding: 4px 10px;
+        border-radius: 5px;
+        font-size: 1.2rem;
+    }
+
+    .status-0 { background-color: #F04E53FF; color: white; } /* 已关闭 */
+    .status-1 { background-color: #5cb85c; color: white; } /* 进行中 */
+    .status-2 { background-color: #5bc0de; color: white; } /* 已创建 */
+
+    .btn-plan-action {
+        text-decoration: none;
+        font-weight: bold;
+        margin-left: 10px;
+        transition: color 0.3s ease;
+    }
+
+    .btn-plan-action:hover {
+        color: #0056b3;
+    }
+
+    .meta-info {
+        display: grid;
+        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+        gap: 10px;
+        padding: 10px 0;
+    }
+
+    .meta-item .label {
+        font-weight: bold;
+        color: #555;
+        margin-right: 5px;
+    }
+
+    .meta-item .value {
+        color: #2E2D3C;
+        font-size: 14px;
+    }
+
+    .ibox-content {
+        background-color: #f9f9f9;
+        border-radius: 8px;
+        box-shadow: 0 1px 3px rgba(0,0,0,0.05);
+        margin-bottom: 15px;
+    }
+
+
+
+
+
+    .plan-info {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        padding: 10px;
+        border-bottom: 1px solid #ddd;
+    }
+
+    .product-details {
+        display: flex;
+        align-items: center;
+    }
+
+    .product-name, .specification {
+        font-size: 1.5rem;
+        margin-right: 20px;
+    }
+
+    .status-and-actions {
+        display: flex;
+        align-items: center;
+    }
+
+    .business-belonging, .status {
+        font-size: 1.5rem;
+        color: #00B83F;
+        margin-right: 20px;
+    }
+
+    .close-plan, .restart-plan {
+        margin-left: 10px;
+        text-decoration: none;
+        color: #007bff;
+    }
+
+    .creator-info {
+        display: grid;
+        grid-template-columns: repeat(4, 1fr);
+        gap: 10px;
+        padding: 10px;
+        border-bottom: 1px solid #ddd;
+    }
+
+    .label {
+        font-weight: bold;
+    }
+
+    .value {
+        color: #2E2D3C;
+    }
+
+
+
+
+
+
+
+    #myTabs2 {
+        z-index: 0;
+    }
+    .fileinput-preview.thumbnail {
+        display: flex;
+        justify-content: center; /* 水平居中 */
+        align-items: center; /* 垂直居中 */
+        text-align: center; /* 确保文本内部也居中 */
+        position: relative;
+        background-color: #f5f5f5; /* 设置背景颜色以更好地区分 */
+        border: 2px dashed #ccc; /* 添加虚线边框 */
+        color: #999; /* 文字颜色 */
+        font-size: 14px; /* 文字大小 */
+    }
+
+    .centered-content {
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+    }
+
+    .plus-sign {
+        margin-top: 5px;
+        font-size: 24px;
+        font-weight: bold;
+    }
+    /* 隐藏初始的大图 */
+    .preview-large {
+        display: none;
+        position: absolute;
+        border: 1px solid #ccc;
+        background-color: #fff;
+        z-index: 1000;
+    }
+
+    /* 确保预览框在特定容器内 */
+    .customize-form-group-container {
+        position: relative;
+    }
+    .fileinput .fileinput-preview {
+        background-image: none !important;
+        background-color: transparent !important;
+    }
+
+    .expired-label {
+        color: red;
+        font-weight: bold;
+    }
+    /* 统一所有表单元素的基线对齐 */
+    .input-groups * {
+        vertical-align: baseline;  /* 或 middle 根据情况选择 */
+    }
+    .form-group {
+        margin-bottom: -1px;
+    }
+    /* 精确控制自定义单选按钮 */
+    .form-check-radio {
+        width: 18px;
+        height: 18px;
+        position: relative;
+        top: 2px;  /* 根据实际字体大小调整 */
+        margin: 0 6px 0 0;
+        cursor: pointer;
+    }
+
+    /* 标签文字精确调整 */
+    .input-groups label {
+        font-size: 16px;
+        position: relative;
+        top: 1px;  /* 补偿字体渲染的视觉偏差 */
+    }
+
+
+    .form-check-radio:checked::before {
+        background: #1890ff;
+    }
+
+    .input-groups div {
+        white-space: normal;
+        min-width: 150px; /* 设置最小宽度控制换行节奏 */
+    }
+    /* 问号图标的样式 */
+    .question-mark {
+        width: 20px; /* 根据需要调整大小 */
+        height: 20px;
+        cursor: pointer;
+    }
+
+    /* 工具提示内容的默认状态:隐藏 */
+    .tooltip-content {
+        visibility: hidden;
+        opacity: 0;
+        transition: visibility 0s, opacity 0.5s;
+        position: absolute;
+        top: -30px; /* 根据实际情况调整 */
+        left: 300px; /* 根据实际情况调整 */
+        z-index: 1000;
+    }
+
+    /* 当悬停在问号图标上时,显示工具提示内容 */
+    .question-mark:hover + .tooltip-content,
+    .tooltip-content:hover {
+        visibility: visible;
+        opacity: 1;
+    }
+
+    /* 图片缩放效果 */
+    .tooltip-image {
+        width: 400px; /* 初始大小 */
+        transition: transform 0.3s ease;
+    }
+
+    /* 当悬停在图片上时放大图片 */
+    .tooltip-image:hover {
+        transform: scale(1.5); /* 放大倍数 */
+    }
+
+
+    .select2-dropdown {
+        z-index: 9999 !important;
+    }
+    .tabs-container {
+        position: relative;
+    }
+    label {
+        display: inline-block;
+        max-width: 100%;
+        margin-bottom: 0px;
+        font-weight: 700;
+    }
+    input {
+        width: 40px;
+    }
+    .customize-form-group label {
+        width: 250px;
+        text-align: right;
+        margin-right: 0.5em;
+    }
+    .font {
+        font-size: 16px; /* 字体大小 */
+    }
+    .form-groupBottom {
+        margin-bottom: 30px; /* 调整这个值以改变间距 */
+    }
+
+
+    .content-area {
+        margin-top: 50px; /* 调整这个值以确保内容不会被导航栏遮挡 */
+    }
+    .nav-tabs {
+        position: sticky;
+        top: 0; /* 距离顶部的距离 */
+        background-color: #fff; /* 设置背景颜色,以便覆盖下方的内容 */
+        z-index: 1020; /* 确保它位于其他内容之上 */
+    }
+
+    .tabs-container {
+        position: relative;
+    }
+
+    .btn {
+        background-color: #f2f2f2;
+        border: none;
+        color: black;
+        padding: 5px 10px;
+        text-align: center;
+        text-decoration: none;
+        display: inline-block;
+        font-size: 16px;
+        margin: 4px 2px;
+        cursor: pointer;
+    }
+
+    .btn-primary {
+        background-color: #1a7bb9;
+        color: white;
+    }
+
+    .btn-w-m {
+        width: max-content;
+    }
+
+    .btn-default {
+        background-color: #f2f2f2;
+        color: black;
+    }
+    .btn:hover {
+        opacity: 0.8;
+    }
+    .tab-1a {
+        padding-left: 50px;
+        width: 100px;
+        font-size: 15px
+    }
+    .tab-1b {
+        width: 100px;
+        color: blue;
+        font-size:15px;
+    }
+    .task-follow-up {
+        display: flex;
+        align-items: center;
+    }
+
+    .follow-up-person, .plan-buttons {
+        flex: 1;
+    }
+
+    .plan-buttons {
+        text-align: right;
+    }
+    .ibox-title2 {
+        display: flex;
+        align-items: center;
+        justify-content: start;
+        padding: 6px;
+        border-bottom: 1px solid #ddd;
+    }
+    .right-aligned-link {
+        float: right;
+        margin-left: 20px; /* 增加左侧边距 */
+    }
+
+    .right-aligned-link::after {
+        content: ">";
+        color: blue;
+    }
+    .task-info {
+        flex: 1;
+    }
+
+    .task-details {
+        flex: 2;
+        display: flex;
+        align-items: center;
+        gap: 0px;
+    }
+
+    .task-buttons {
+        flex: 1;
+        display: flex;
+        align-items: center;
+        justify-content: flex-end;
+        gap: 10px;
+    }
+
+    .task-buttons span {
+        margin-left: 10px;
+    }
+
+    .task-details span {
+        display: flex;
+        align-items: center;
+        gap: 1px;
+    }
+    .custom-file-upload {
+        position: relative;
+        overflow: hidden;
+        cursor: pointer;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .custom-file-upload input[type=file] {
+        opacity: 0;
+        width: 100%;
+        height: 100%;
+        top: 0;
+        left: 0;
+        position: absolute;
+    }
+
+    .custom-file-upload label {
+        background-color: white;
+        border: 2px dashed #007bff;
+        color: #007bff;
+        padding: 20px;
+        text-align: center;
+        display: block;
+        min-height: 150px;
+    }
+    #hbyyjlTable {
+        width: 100%;
+        border-collapse: collapse;
+    }
+
+    th,
+    td {
+        padding: 10px;
+        text-align: center;
+        border-bottom: 1px solid #ddd;
+    }
+
+    thead th {
+        background-color: #f2f2f2;
+        font-weight: bold;
+    }
+
+    tbody tr:hover {
+        background-color: #f5f5f5;
+    }
+
+    .no-data {
+        text-align: center;
+        padding: 0px;
+    }
+
+    .btn-primarys {
+        margin-left: 10px;
+        color: green;
+    }
+
+
+    .radio-item label {
+        /*margin-left: 5px;*/
+    }
+    .hidden {
+        display: none;
+    }
+    .shown {
+        display: block;
+    }
+
+
+
+
+
+    .info-display {
+        display: flex;
+        align-items: center;
+        flex-wrap: wrap; /* 自动换行 */
+        padding: 10px 0;
+    }
+
+    .info-display label {
+        font-weight: bold;
+        margin-right: 8px;
+        min-width: 60px;
+    }
+
+    .info-value,
+    .info-age {
+        border: 1px solid #e4e4e4;
+        background-color: #f9f9f9;
+        padding: 4px 10px;
+        border-radius: 4px;
+        margin-right: 15px;
+        min-width: 80px;
+        max-width: 200px;
+        overflow: hidden;
+        white-space: nowrap;
+        text-align: left;
+        font-size: 14px;
+    }
+
+    .info-status {
+        padding: 4px 10px;
+        border-radius: 4px;
+        font-weight: bold;
+        font-size: 13px;
+    }
+
+    .status.success {
+        background-color: #d4edda;
+        color: #155724;
+    }
+
+    .status.danger {
+        background-color: #f8d7da;
+        color: #721c24;
+    }
+
+    .fa-check {
+        color: #28a745;
+    }
+
+    .fa-close {
+        color: #dc3545;
+    }
+</style>
+<script>
+
+</script>
+<body>
+<div class="font">
+    <div class="ibox">
+        <form id="form-followUp-edit1">
+            <div class="ibox-title">
+                <button class="btn btn-w-m btn-primary"  onclick="editArchives()">完善档案</button>
+                <button type="button" class="btn btn-sm btn-danger pull-right" onclick="closeItem()">返回上一级</button>
+            </div>
+            <div class="customize-form-group info-display">
+                <label>姓名:</label>
+                <span class="info-value" th:text="${name}"></span>
+                &nbsp;&nbsp;
+                <i class="fa" th:class="${realNameStatus == 1 ? 'fa fa-check text-success' : 'fa fa-close text-danger'}" id="checkName"></i>
+                &nbsp;
+                <span class="info-status"
+                      th:class="${realNameStatus == 1 ? 'status success' : 'status danger'}"
+                      th:text="${realNameStatus == 1 ? '已实名' : (realNameStatus == 0 ? '未实名' : '')}">未实名
+                </span>
+
+                <label>性别:</label>
+                <span class="info-value" th:text="${gender == 1 ? '女' : (gender == 0 ? '男' : '')}">男</span>
+
+                <!-- 隐藏字段保留不变 -->
+                <input type="hidden" name="genderv" id="genderv" th:value="${gender}" />
+
+                <label>出生年月:</label>
+                <span class="info-value" th:text="${dateBirth}">2025-01-01</span>
+
+                <label>年龄:</label>
+                <span class="info-age" th:text="${age}">30</span><span>岁</span>
+            </div>
+            <div class="customize-form-group" id="drug-info-container">
+                <div th:each="item : ${dValueList}" style="margin-bottom: 10px; border: 1px solid #ccc; padding: 10px;">
+            <span>
+                <strong>药品: <code th:text="${item.genericName}"></code></strong><br>
+                <strong>用药状态: <code th:text="${item.medication_status}"></code></strong><br>
+                <!--                <strong>剩余用药天数: <code th:text="${item.sum_total}"></code>天</strong><br>-->
+                <strong>剩余用药天数: <code th:text="${item.adjusted_sum_total}"></code>天</strong><br>
+            </span>
+                </div>
+            </div>
+
+            <div class="ibox-content">
+                <div>
+                    <span>档案完善度:已完善---><div></div></span>
+                    <div class="stat-percent" th:text="${completenessPercentage} + ' %'"></div>
+                    <div class="progress progress-mini">
+                        <!-- 使用 Thymeleaf 的 th:style 属性动态设置样式 -->
+                        <div class="progress-bar" th:style="'width: ' + ${completenessPercentage} + '%;'"></div>
+                    </div>
+                </div>
+            </div>
+        </form>
+        <div class="modal inmodal fade" id="myModalClosePlan" tabindex="-1" role="dialog" aria-hidden="true">
+            <div class="modal-dialog modal-lg" style="width: 1200px">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span>
+                        </button>
+                        <h4 class="modal-title">关闭随访计划</h4>
+                        <!--<small class="font-bold">这里可以显示副标题。</small>-->
+                    </div>
+                    <div class="modal-body">
+                        <div id="ClosePlan" class="row">
+                            <form id="ClosePlanForm" class="form-horizontal" style="font-size: 15px;">
+                                <div class="col-sm-12">
+                                    <div >
+                                        <h2><code>关闭原因</code></h2>
+                                    </div>
+                                    <label class="is-required">原因</label>
+                                    <div class="form-groupBottom"
+                                         th:with="type=${@dict.getType('sys_hzgl_sfrw_closeplan_reason')}"
+                                         style="width: 900px; display: flex; flex-wrap: wrap; gap: 10px; align-items: center;">
+                                        <div  th:each="dict : ${type}" style="white-space: nowrap;">
+                                            <input  type="radio"
+                                                    name="reason"
+                                                    class="form-check-radio"
+                                                    th:id="'reason_' + ${dict.dictCode}"
+                                                    th:text="${dict.dictLabel}"
+                                                    th:value="${dict.dictValue}">
+                                        </div>
+                                    </div>
+
+                                    <div class="form-group hidden" id="drugsStatusDiv" >
+                                        <label class="is-required">用药状态调整为</label>
+                                        <div class="input-groups"  th:with="type=${@dict.getType('sys_gxhpz_yyycx')}" style="width: 900px;">
+                                            <input type="radio" name="drugsStatus" class="form-check-radio"  th:each="dict : ${type}"  id="drugsStatus" th:text="${dict.dictLabel}" th:value="${dict.dictLabel}">
+                                        </div>
+                                    </div>
+                                    <div class="form-group hidden form-groupBottom" id="drugsStopDiv ">
+                                        <label class="is-required">永久停药类型</label>
+                                        <div class="input-groups hidden"  th:with="type=${@dict.getType('sys_hzgl_sfrw_closeplan_yjstop')}" style="width: 1200px;">
+                                            <input type="radio" name="drugsStop" class="form-check-radio"  th:each="dict : ${type}"  id="drugsStop" th:text="${dict.dictLabel}" th:value="${dict.dictLabel}">
+                                        </div>
+                                    </div>
+
+                                    <div class="form-group hidden" id="flowNoDiv">
+                                        <label class="is-required">随访不配合原因:</label>
+                                        <div class=""
+                                             th:with="type=${@dict.getType('sys_gxhpz_ysfw_sfbphyy')}"
+                                             style="width: 900px; display: flex; flex-wrap: wrap; gap: 10px; align-items: center;">
+                                            <div  th:each="dict : ${type}" style="white-space: nowrap;">
+                                                <input  type="radio"
+                                                        name="flowNo"
+                                                        class="form-check-radio"
+                                                        th:id="'flowNo_' + ${dict.dictLabel}"
+                                                        th:text="${dict.dictLabel}"
+                                                        th:value="${dict.dictLabel}">
+                                            </div>
+                                        </div>
+                                        <span class="status"></span>
+                                    </div>
+                                    <div class="form-group hidden form-groupBottom" id="otherReasonDiv">
+                                        <label class="is-required">其他原因请补充</label>
+                                        <div>
+                                            <input id="otherReason" name="otherReason" placeholder="这里可以输入...其他原因请补充到这里"
+                                                   class="styled-input"
+                                                   style="width: 800px;height: 40px;">
+                                        </div>
+                                    </div>
+
+                                </div>
+                                <div class="col-sm-12">
+                                    <div class="form-group">
+                                        <div class="form-group">
+                                            <h2><code>关闭范围</code></h2>
+                                        </div>
+                                        <div class="input-groups hidden" th:with="type=${@dict.getType('sys_hzgl_sfrw_follow_up_planning_strategy')}" style="width: 900px;" id="follow_up_planning_strategy_Div">
+                                            <label class="is-required">随访计划策略</label>
+                                            <input type="radio" name="planningStrategy" class="form-check-radio"  th:each="dict : ${type}"  id="planningStrategy" th:text="${dict.dictLabel}" th:value="${dict.dictValue}">
+                                        </div>
+                                        <div class="input-groups" th:with="type=${@dict.getType('sys_hzgl_sfrw_closeplan_scope')}" style="width: 900px;">
+                                            <label class="is-required">关闭计划</label>
+                                            <input type="radio" name="closePlanScope" class="form-check-radio"  th:each="dict : ${type}"  id="closePlanScope" th:text="${dict.dictLabel}" th:value="${dict.dictLabel}">
+                                        </div>
+
+                                    </div>
+                                </div>
+
+                                <div class="col-sm-12 hidden" id="closeplan_isnoDiv">
+                                    <div class="form-group" >
+                                        <div class="input-groups" th:with="type=${@dict.getType('sys_hzgl_sfrw_closeplan_isno')}" style="width: 900px;">
+                                            <label class="is-required">是否禁用此品的计划</label>
+                                            <input type="radio" name="forbidden" class="form-check-radio"  th:each="dict : ${type}"  id="forbidden" th:text="${dict.dictLabel}" th:value="${dict.dictLabel}">
+                                            <label style="color: grey;font-size: 11px;">&nbsp;&nbsp;&nbsp;选择是,购买相同D值品不会自动触发新计划</label>
+                                        </div>
+
+                                    </div>
+
+                                </div>
+
+                                <div class="col-sm-12" id="closeTypeDiv">
+                                    <div class="form-group">
+                                        <div class="input-groups" th:with="type=${@dict.getType('sys_hzgl_sfrw_closepan_type')}" style="width: 900px;">
+                                            <label class="is-required">关闭类型</label>
+                                            <div th:each="dict : ${type}">
+                                                <input type="radio" name="closeType" class="form-check-radio"
+                                                       th:id="'closeType_' + ${dict.dictLabel}"
+                                                       th:value="${dict.dictLabel}"
+                                                       th:text="${dict.dictLabel}"
+                                                       onclick="handleCloseTypeChange(this)">
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+
+                                <div class="col-sm-12" id="specifiedTypeDiv" style="display: none;">
+                                    <div class="form-group">
+                                        <label class="is-required">指定类型</label>
+                                        <div class="input-groups" th:with="type=${@dict.getType('sys_hzgl_sfrw_closepan_istype')}" style="width: 900px;">
+                                            <div th:each="dict, iterStat : ${type}">
+                                                <input type="checkbox" name="specifiedType"
+                                                       class="form-check-radio"
+                                                       th:id="'specifiedType_' + ${iterStat.index}"
+                                                       th:value="${dict.dictLabel}"
+                                                       th:text="${dict.dictLabel}"
+                                                       onclick="handleSpecifiedTypeChange()">
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </form>
+                        </div>
+                    </div>
+
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-white" data-dismiss="modal">无需关闭 退出操作</button>
+                        <button type="button" class="btn btn-primary"  onclick="submitClosePlan(flagStatus)">提交</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div class="ui-layout-center">
+        <div class="row">
+            <div class="col-sm-12">
+                <div class="tabs-container">
+                    <ul class="nav nav-tabs" id="myUlTabs">
+                        <li class="active"><a data-toggle="tab" href="#tab-1" aria-expanded="true"> 基本信息</a>
+                        </li>
+                        <li class=""><a data-toggle="tab" href="#tab-2" aria-expanded="false">用药购药</a>
+                        </li>
+                        <li class=""><a data-toggle="tab" href="#tab-3" aria-expanded="false">随访计划</a>
+                        </li>
+                    </ul>
+                    <div class="tab-content">
+                        <div id="tab-1" class="tab-pane active">
+                            <form class="customize-search-form" id="form-followUp-edit2" >
+
+                                <div class="customize-form-group edit">
+                                    <label>手机号码:</label>
+                                    <input name="phoneNumber" id="phoneNumber" class="styled-input" type="text" maxlength="30" th:value="${phoneNumber}" disabled="true">
+                                    <span class="span_line" readonly></span>
+                                </div>
+
+                                <div class="customize-form-group">
+                                    <label>配送地址:</label>
+                                    <input name="addr" disabled="true"  id="addr" class="styled-input " type="text" th:value="${addr}">
+                                    <span class="span_line" readonly></span>
+                                </div>
+                                <div class="customize-form-group">
+                                    <label>联系人手机号:</label>
+                                    <input name="contactPhone" disabled="true"  id="contactPhone" class="styled-input" type="text" th:value="${contactPhone}">
+                                    <span class="span_line" readonly></span>
+                                </div>
+                                <div class="customize-form-group">
+                                    <label>联系人姓名:</label>
+                                    <input name="contactName"disabled="true"  id="contactName" class="styled-input" type="text" th:value="${contactName}">
+                                    <span class="span_line" readonly></span>
+                                </div>
+                                <!--                                <div class="customize-form-group edit">-->
+                                <!--                                    <label>D值品名称:</label>-->
+                                <!--                                    <input name="dvalueName" id="dvalueName" class="styled-input" type="text"  th:value="${dvalueName}" disabled="true">-->
+                                <!--                                    <span class="span_line" readonly></span>-->
+                                <!--                                </div>-->
+                                <!--                                <div class="customize-form-group edit">-->
+                                <!--                                    <label>D值品天数:</label>-->
+                                <!--                                    <input name="dvalueDay" id="dvalueDay" class="styled-input" type="text" th:value="${dvalueDay}" disabled="true">-->
+                                <!--                                    <span class="span_line" readonly></span>-->
+                                <!--                                </div>-->
+                                <div class="customize-form-group edit select-time">
+                                    <label>首次确诊时间:</label>
+                                    <input name="timeFirstDiagnosis" disabled="true" class="styled-input"  type="text"  th:value="${timeFirstDiagnosis}">
+                                    <span class="span_line" readonly></span>
+                                </div>
+                                <div class="customize-form-group edit">
+                                    <label class="is-required">证件号码:</label>
+                                    <input name="documentType" placeholder="证件类型" class="styled-input short" style="font-size: 13px" type="text"  th:value="${documentType}" disabled="true">
+                                    <input name="documentNumber" placeholder="请输入证件号码" class="styled-input" type="text" maxlength="30" th:value="${documentNumber}" disabled="true">
+                                    <span class="span_line" readonly></span>
+                                </div>
+                                <div class="customize-search-form">
+                                    <div class="customize-form-group">
+                                        <label class="col-sm-1 control-label">肿瘤发病部位疾病:</label>
+                                        <select id="category-select1" class="styled-input edit_inputs select2-multiple" multiple onmousedown="return false;" >
+                                        </select>
+                                    </div>
+                                    <div class="customize-form-group">
+                                        <label class="col-sm-1 control-label">肿瘤治疗并发症与合并症:</label>
+                                        <select id="category-select2" class="styled-input edit_inputs select2-multiple" multiple onmousedown="return false;" >
+                                        </select>
+                                    </div>
+                                    <div class="customize-form-group">
+                                        <label class="col-sm-1 control-label">风湿免疫疾病名称:</label>
+                                        <select id="category-select3"   class="styled-input edit_inputs select2-multiple" multiple  onmousedown="return false;" >
+                                        </select>
+                                    </div>
+                                    <div class="customize-form-group">
+                                        <label class="col-sm-1 control-label">罕见病疾病:</label>
+                                        <select id="category-select4" class="styled-input edit_inputs select2-multiple" multiple  onmousedown="return false;">
+                                        </select>
+                                    </div>
+                                    <div class="customize-form-group">
+                                        <label class="col-sm-1 control-label">感染类疾病:</label>
+                                        <select id="category-select5"   class="styled-input edit_inputs select2-multiple" multiple  onmousedown="return false;" >
+                                        </select>
+                                    </div>
+                                    <div class="customize-form-group">
+                                        <label class="col-sm-1 control-label">临时慢病:</label>
+                                        <select id="category-select6"   class="styled-input edit_inputs select2-multiple" multiple onmousedown="return false;">
+                                        </select>
+                                    </div>
+                                </div>
+                            </form>
+                        </div>
+                        <div id="tab-2" class="tab-pane">
+                            <div class="panel-body">
+                                <div class="row">
+                                    <div class="col-sm-12 select-table table-striped">
+                                        <table id="bootstrap-table-2"></table>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div id="tab-3" class="tab-pane">
+                            <div class="task-follow-up">
+                                <div class="follow-up-person">
+                                    <label  style="padding-left: 10px;">随访跟进人:</label>
+                                    <!--                                    <code style="font-size: 1.5rem;width: 200px;padding-left: 15px;">-->
+                                    <!--                                        随访跟进人:-->
+                                    <!--                                    </code>-->
+                                    <code id="followUpPersonNameCode" style="font-size: 1.5rem;width: 200px;padding-left: 15px;" th:text="${followUpPersonName}">
+                                    </code>
+                                    <!--                                    <code type="text" id="follow_up_person"  style="border: none; width: 55px; color: red;"  th:value="${follow_up_person}">-->
+                                    <!--                                    </code>-->
+                                    <input type="hidden" id="followUpPersonId" name="followUpPersonId" th:value="${followUpPersonId}"/>
+                                    <input type="hidden" id="followUpPersonName" name="followUpPersonName" th:value="${followUpPersonName}"/>
+                                    <a href="#" onclick="editSFGenJinRen()">修改<i class="glyphicon glyphicon-pencil"></i></a>
+                                </div>
+                                <div class="plan-buttons">
+                                    <!--                                    <button class="btn btn-w-m btn-primary" onclick="showAllPlan()">查看全部计划</button>-->
+                                    <button class="btn btn-w-m btn-info" onclick="createPlan()">创建计划</button>
+                                </div>
+                            </div>
+                            <div id="cgsfnormal"></div>
+                            <div id="tlzhback"></div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="ibox-content">
+                <div class="ibox-title2">
+                    <div class="task-info">
+                        <h4>本次任务 <code style="font-size: 1.5rem;" th:text="${bc_taskStatus}"></code></h4>
+                    </div>
+                    <span style="font-size:15px;">任务名称:
+                        <span style="font-size:15px;" th:text="${bc_taskName}"></span> &nbsp;&nbsp;&nbsp;&nbsp;
+                    </span>
+                    <span style="font-size:15px;">药品:
+                        <span style="font-size:15px;" th:text="${bc_productName}"></span> &nbsp;&nbsp;&nbsp;&nbsp;
+                    </span>
+                    <span style="font-size:15px;">任务主题:
+                            <span>
+                                <select name="taskTheme" class="styled-input" th:with="type=${@dict.getType('sys_select_dtp_sfrw_rwzt')}">
+                                    <option value="">请选择</option>
+                                    <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictLabel}" th:selected="${dict.dictLabel}==${bc_taskTheme}"></option>
+                                </select>
+                           </span> &nbsp;&nbsp;&nbsp;&nbsp;
+                       </span>
+                    <span style="font-size:15px;">任务跟进人:
+                        <input type="hidden" id="bc_taskFollower" name="bc_taskFollower" th:value="bc_taskFollower"/>
+                        <span id="bc_taskFollowerCode" style="color: #2E2D3C;font-size:15px;"><code style="font-size: 1.4rem;font-size:15px;" th:text="${bc_taskFollower}" ></code></span>
+                       <a onclick="editTaskGenJinRen()" style="font-size:15px;"> 修改 <i class="glyphicon glyphicon-pencil"></i></a>
+                    </span>
+
+                    <div class="task-buttons">
+                        <!--                    <button class="btn btn-w-m btn-primary" onclick="showDetailHistory()">查看历史随访</button>-->
+                    </div>
+                </div>
+                <form id="form-defaultValue" class="form-horizontal">
+                    <input type="hidden" id="id" name="id" th:value="${bc_id}">
+                    <input type="hidden" id="planId" name="planId" th:value="${planId}">
+                    <input type="hidden" id="bc_planId" name="bc_planId" th:value="${bc_planId}">
+                    <input type="hidden" id="planId_cg" name="planId_cg" th:value="${planId_cg}">
+                    <input type="hidden" id="planId_tl" name="planId_tl" th:value="${planId_tl}">
+                    <input type="hidden" id="patientId" name="patientId" th:value="${patientId}">
+                    <input type="hidden" id="mdmCode_tl" name="mdmCode_tl" th:value="${mdmCode_tl}">
+                    <input type="hidden" id="mdmCode_cg" name="mdmCode_cg" th:value="${mdmCode_cg}">
+                </form>
+            </div>
+
+            <form id="form-followUp-edit3" class="form-horizontal">
+                <div class="row">
+                    <div class="col-sm-12" >
+                        <!-- 动态生成的Tab导航 -->
+                        <ul class="nav nav-tabs" id="dynamicTabs">
+                            <li class="active">
+                                <a data-toggle="tab" href="#tab-4" aria-expanded="true">本次任务</a>
+                            </li>
+                            <!-- 其他Tab将通过JavaScript动态生成 -->
+                        </ul>
+
+                        <div class="panel-body">
+                            <div class="tab-content content-area" id="dynamicTabContent">
+                                <!-- 本次任务Tab - 必选 -->
+                                <div id="tab-4" class="tab-pane active dynamic-tab enabled">
+                                    <strong><h4 style="color: #1E9FFF;">| 本次任务</h4></strong>
+                                    <div id="tab-4-fields">
+                                        <!-- 字段将通过JavaScript动态生成 -->
+                                    </div>
+                                </div>
+
+                                <!-- 其他Tab内容将通过JavaScript动态生成 -->
+                                <div id="tab-6" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 用药依从性</h4></strong>
+                                    <div id="tab-6-fields"></div>
+                                </div>
+
+                                <div id="tab-7" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 药物安全性</h4></strong>
+                                    <div id="tab-7-fields"></div>
+                                </div>
+
+                                <div id="tab-8" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 药物有效性</h4></strong>
+                                    <div id="tab-8-fields"></div>
+                                </div>
+
+                                <div id="tab-9" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 治疗方案</h4></strong>
+                                    <div id="tab-9-fields"></div>
+                                </div>
+
+                                <div id="tab-10" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 适宜性评估</h4></strong>
+                                    <div id="tab-10-fields"></div>
+                                </div>
+
+                                <div id="tab-11" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 用药记录</h4></strong>
+                                    <div id="tab-11-fields"></div>
+                                </div>
+
+                                <div id="tab-12" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 量表测评</h4></strong>
+                                    <div id="tab-12-fields"></div>
+                                </div>
+
+                                <div id="tab-13" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 患者咨询</h4></strong>
+                                    <div id="tab-13-fields"></div>
+                                </div>
+
+                                <div id="tab-14" class="tab-pane dynamic-tab">
+                                    <strong><h4 style="color: #1E9FFF;">| 其他</h4></strong>
+                                    <div id="tab-14-fields"></div>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="ibox-content" style="background-color: #f5f3f3;">
+                    <div class="ibox-title2">
+                        <div class="task-info">
+                            <h4>下次随访时间
+                                <input name="next_follow_time"  id="next_follow_time" placeholder="下次随访时间" class="time-input-new styled-input" type="text"  th:value="${bc_next_follow_time}"/>
+                            </h4>
+                        </div>
+                        <div class="task-details">
+                            <!--                        <h4> <span>间隔本次任务:<span id="interval_this_time" style="color: #1a7bb9;" th:text="${interval_this_time}"></span >天</span></h4>-->
+                            <span class="status">&nbsp;&nbsp;&nbsp;&nbsp;</span>
+                            <h4> <span>下次任务主题:<span style="color: #1a7bb9;">
+                                    <select name="next_taskTheme" class="styled-input" th:with="type=${@dict.getType('sys_select_dtp_sfrw_rwzt')}">
+                                      <option value="">请选择</option>
+                                      <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictLabel}" th:selected="${dict.dictLabel}==${bc_next_taskTheme}"></option>
+                                    </select>
+                                </span>
+                                </span></h4>
+                        </div>
+                        <div class="task-buttons">
+                            <div class="ibox-title2">
+                                <button type="button" class="btn btn-warning" style="background-color: #f56666;" onclick="closeItem()">关闭</button>
+                                <div class="task-buttons" id="TJ1">
+                                    <button type="button" class="btn btn-primary"   onclick="handleButtonClick()">保 存</button>
+                                </div>
+
+                            </div>
+                        </div>
+                    </div>
+                </div>
+        </div>
+        </form>
+    </div>
+</div>
+</div>
+<th:block th:include="include :: header('随访任务详情')" />
+<th:block th:include="include :: layout-latest-css" />
+<th:block th:include="include :: jasny-bootstrap-css" />
+<th:block th:include="include :: select2-js" />
+<th:block th:include="include :: select2-css" />
+<th:block th:include="include :: bootstrap-select-js" />
+<th:block th:include="include :: bootstrap-select-css" />
+
+<th:block th:include="include :: bootstrap-editable-css" />
+<th:block th:include="include :: bootstrap-fileinput-css" />
+<th:block th:include="include :: jquery-cxselect-js" />
+<th:block th:include="include :: layout-latest-js" />
+<th:block th:include="include :: bootstrap-table-fixed-columns-js" />
+<!--<th:block th:include="include :: ztree-js" />-->
+<!--<th:block th:include="include :: ztree-css" />-->
+<th:block th:include="include :: bootstrap-table-editable-js" />
+<th:block th:include="include :: jasny-bootstrap-js" />
+
+
+
+
+</body>
+
+</html>
+
+<script th:inline="javascript">
+    var templateConfigId = /*[[${template_config_id}]]*/ null;
+    var templateConfig = null;
+    var fieldDefinitions = {}; // 存储字段定义
+
+
+
+    var formSubmitted = true;
+    var prefix = ctx + "dtp/pmService";
+    var prefix_task = ctx + "task/followTask";
+    var prefix_recipe = ctx + "dtp/recipe";
+    var blfyindex = 0;
+    var closePlanFlag;
+    var flag=false
+    var flagStatus2=0;
+    var flagStatus=false;
+    var TJFlag=false;
+    var formCheck=true;
+    var planId_close;
+    //购药记录
+    var recordsData;
+    // 回显数据随访计划
+    var listPlan1;
+    var listPlan2;
+    // 回显数据随访任务
+    var listTask1;
+    var listTask2;
+    var pcTypes = [];
+    var dosageFrequencyOptions;
+    var dosageFrequencyLookup = {};
+    var planId;
+    var mdmCode
+    var confirmFlag="999";//关闭弹框确认标记
+
+    var preMedicationPlans = [];
+    var currentTreatmentPlans = [];
+    var postProgressionTreatmentPlans = [];
+    var medicationRecords = [];
+    var combinedMedicationRecords = [];
+    var good_response_symptom_ids = [];
+    const sensitiveValues = [
+        '电话号码错误',
+        '本人拒绝',
+        '家属拒绝',
+        '客户拒绝',
+        '接通后配合度差无法获知信息',
+        '领取慈善赠药'
+    ];
+
+
+    document.addEventListener('DOMContentLoaded', function () {
+        // 初始化所有 .fileinput 区域
+        document.querySelectorAll('.fileinput').forEach(function (fileInputWrapper) {
+            initializeImagePreview2(fileInputWrapper);
+        });
+    });
+
+    function initializeImagePreview2(fileInputWrapper) {
+        var fileInput = fileInputWrapper.querySelector('input[type="file"]');
+        var previewThumbnail = fileInputWrapper.querySelector('.fileinput-preview.thumbnail');
+        var largePreview;
+        var clearButton = fileInputWrapper.querySelector('.btn-white[data-dismiss="fileinput"]');
+
+        // 创建大图预览
+        function createLargePreview(imageSrc) {
+            if (largePreview) {
+                largePreview.style.display = 'none';
+                largePreview.remove();
+            }
+            largePreview = document.createElement('div');
+            largePreview.className = 'preview-large';
+            largePreview.style.backgroundImage = 'url(' + imageSrc + ')';
+            largePreview.style.width = '1000px'; // 根据需要调整宽度
+            largePreview.style.height = '900px'; // 根据需要调整高度
+            largePreview.style.backgroundSize = 'contain';
+            largePreview.style.backgroundRepeat = 'no-repeat';
+            largePreview.style.backgroundPosition = 'center';
+            largePreview.style.position = 'absolute';
+            largePreview.style.zIndex = '1000';
+            largePreview.style.display = 'none'; // 初始状态下不显示
+
+            // 添加到DOM
+            fileInputWrapper.appendChild(largePreview);
+
+            // 为大图预览添加事件监听器
+            largePreview.onmouseover = function () {
+                this.style.display = 'block';
+            };
+
+            largePreview.onmousemove = function (e) {
+                updateLargePreviewPosition(e, previewThumbnail);
+            };
+
+            largePreview.onmouseout = function (e) {
+                if (!previewThumbnail.contains(e.relatedTarget)) {
+                    hideLargePreview();
+                }
+            };
+        }
+
+        // 悬停时显示大图
+        function handleMouseOver(e) {
+            /*if (previewThumbnail.style.backgroundImage && !largePreview) {
+                createLargePreview(previewThumbnail.style.backgroundImage.replace(/^url$["']?/, '').replace(/["']?$$/, ''));
+            }*/
+            if (largePreview) {
+                showLargePreview(e);
+            }
+        }
+
+        // 鼠标移动时更新大图位置
+        function handleMouseMove(e) {
+            if (largePreview) {
+                updateLargePreviewPosition(e, previewThumbnail);
+            }
+        }
+
+        // 缩略图移出事件处理
+        function handleMouseOut(e) {
+            if (!largePreview || !largePreview.contains(e.relatedTarget)) {
+                hideLargePreview();
+            }
+        }
+
+        // 显示大图预览
+        function showLargePreview(e) {
+            largePreview.style.display = 'block';
+            updateLargePreviewPosition(e, previewThumbnail);
+        }
+
+        // 更新大图预览位置
+        function updateLargePreviewPosition(e, referenceElement) {
+            const rect = referenceElement.getBoundingClientRect();
+            const winWidth = window.innerWidth;
+            const winHeight = window.innerHeight;
+            const largePreviewWidth = largePreview.offsetWidth;
+            const largePreviewHeight = largePreview.offsetHeight;
+
+            let left = e.pageX ; // 尝试放置在鼠标右侧
+            let top = e.pageY + 150; // 尝试放置在鼠标下方
+
+            // 确保大图预览不超出浏览器窗口边界
+            //if (left + largePreviewWidth > winWidth) left = e.pageX - largePreviewWidth - 150; // 如果右侧空间不足,则放在左侧
+            if (top + largePreviewHeight > winHeight) top = e.pageY - largePreviewHeight; // 如果底部空间不足,则放在上方
+
+            largePreview.style.left = left+100 + 'px';
+            largePreview.style.top = top-200 + 'px';
+        }
+
+        // 隐藏大图预览
+        function hideLargePreview() {
+            if (largePreview) {
+                largePreview.style.display = 'none';
+            }
+        }
+
+        // 移除图片和大图预览
+        function removeImageAndPreview() {
+            previewThumbnail.style.backgroundImage = ''; // 清空缩略图背景图片
+            if (largePreview) {
+                largePreview.style.display = 'none';
+                largePreview.remove(); // 从 DOM 中移除 largePreview
+                largePreview = null;
+            }
+            updateClearButtonVisibility(); // 更新清除按钮的可见性
+        }
+
+        // 更新清除按钮的可见性
+        function updateClearButtonVisibility() {
+            /*if (clearButton) {
+                clearButton.style.display = previewThumbnail.style.backgroundImage ? 'inline-block' : 'none';
+            }*/
+        }
+
+        // 监听文件上传变化事件
+        fileInput.addEventListener('change', function (e) {
+            // 清除现有的大图预览
+            removeImageAndPreview();
+
+            // 读取新文件并更新缩略图背景图片
+            if (this.files && this.files[0]) {
+                var reader = new FileReader();
+                reader.onload = function (event) {
+                    previewThumbnail.style.backgroundImage = 'url(' + event.target.result + ')';
+                    // 立即创建大图预览以反映新图片
+                    createLargePreview(event.target.result);
+                    setupEventListeners(); // 重新设置事件监听器
+                    updateClearButtonVisibility(); // 更新清除按钮的可见性
+                };
+                reader.readAsDataURL(this.files[0]);
+            } else {
+                updateClearButtonVisibility(); // 更新清除按钮的可见性
+            }
+        });
+
+        // 初始化事件监听器
+        function setupEventListeners() {
+            previewThumbnail.onmouseover = handleMouseOver;
+            previewThumbnail.onmousemove = handleMouseMove;
+            previewThumbnail.onmouseout = handleMouseOut;
+
+            // 监听清除按钮点击事件
+            if (clearButton) {
+                clearButton.addEventListener('click', function () {
+                    removeImageAndPreview(); // 清除图片及大图预览
+                });
+            }
+        }
+
+        // 对于回显的图片,确保初始化时创建大图预览并更新清除按钮的可见性
+        if (previewThumbnail.style.backgroundImage) {
+            createLargePreview(previewThumbnail.style.backgroundImage.replace(/^url$["']?/, '').replace(/["']?$$/, ''));
+            updateClearButtonVisibility();
+        } else {
+            updateClearButtonVisibility();
+        }
+
+        // 初始化事件监听器
+        setupEventListeners();
+    }
+    document.addEventListener('DOMContentLoaded', function () {
+        // 初始化所有 .fileinput 区域
+        document.querySelectorAll('.fileinput').forEach(function (fileInputWrapper) {
+            initializeImagePreview(fileInputWrapper);
+        });
+    });
+
+    function initializeImagePreview(fileInputWrapper) {
+        var previewThumbnail = fileInputWrapper.querySelector('.fileinput-preview.thumbnail');
+        var imgElement = previewThumbnail.querySelector('.preview-image');
+        var largePreview;
+        var clearButton = fileInputWrapper.querySelector('.btn-white[data-dismiss="fileinput"]');
+
+        if (!imgElement || !clearButton) return; // 如果没有img元素或清除按钮,则不执行后续操作
+
+        // 创建大图预览
+        function createLargePreview(img) {
+            if (largePreview) {
+                largePreview.style.display = 'none';
+                largePreview.remove();
+            }
+            largePreview = document.createElement('div');
+            largePreview.className = 'preview-large';
+            largePreview.style.backgroundImage = 'url(' + img.src + ')';
+            largePreview.style.width = '1000px'; // 根据需要调整宽度
+            largePreview.style.height = '900px'; // 根据需要调整高度
+            largePreview.style.backgroundSize = 'contain';
+            largePreview.style.backgroundRepeat = 'no-repeat';
+            largePreview.style.backgroundPosition = 'center';
+            largePreview.style.position = 'absolute';
+            largePreview.style.zIndex = '1000';
+            largePreview.style.display = 'none'; // 初始状态下不显示
+
+            // 添加到DOM
+            fileInputWrapper.appendChild(largePreview);
+        }
+
+        // 悬停时显示大图
+        function handleMouseOver(e) {
+            if (imgElement.src && !largePreview) {
+                createLargePreview(imgElement);
+            }
+            if (largePreview) {
+                showLargePreview(e);
+            }
+        }
+
+        // 鼠标移动时更新大图位置
+        function handleMouseMove(e) {
+            if (largePreview) {
+                updateLargePreviewPosition(e, previewThumbnail);
+            }
+        }
+
+        // 缩略图移出事件处理
+        function handleMouseOut(e) {
+            if (!largePreview || !largePreview.contains(e.relatedTarget)) {
+                hideLargePreview();
+            }
+        }
+
+        // 显示大图预览
+        function showLargePreview(e) {
+            largePreview.style.display = 'block';
+            updateLargePreviewPosition(e, previewThumbnail);
+        }
+
+        // 更新大图预览位置
+        function updateLargePreviewPosition(e, referenceElement) {
+            const rect = referenceElement.getBoundingClientRect();
+            const winWidth = window.innerWidth;
+            const winHeight = window.innerHeight;
+            const largePreviewWidth = largePreview.offsetWidth;
+            const largePreviewHeight = largePreview.offsetHeight;
+
+            let left = e.pageX + 150; // 尝试放置在鼠标右侧
+            let top = e.pageY + 150; // 尝试放置在鼠标下方
+
+            // 确保大图预览不超出浏览器窗口边界
+            //if (left + largePreviewWidth > winWidth) left = e.pageX - largePreviewWidth - 150; // 如果右侧空间不足,则放在左侧
+            if (top + largePreviewHeight > winHeight) top = e.pageY - largePreviewHeight; // 如果底部空间不足,则放在上方
+
+            largePreview.style.left = left+100 + 'px';
+            largePreview.style.top = top-200 + 'px'; // 保持原有的偏移量
+        }
+
+        // 隐藏大图预览
+        function hideLargePreview() {
+            if (largePreview) {
+                largePreview.style.display = 'none';
+            }
+        }
+
+        // 初始化事件监听器
+        function setupEventListeners() {
+            previewThumbnail.onmouseover = handleMouseOver;
+            previewThumbnail.onmousemove = handleMouseMove;
+            previewThumbnail.onmouseout = handleMouseOut;
+
+            // 监听清除按钮点击事件
+            clearButton.addEventListener('click', function () {
+                removeImageAndPreview(); // 清除图片及大图预览
+            });
+        }
+
+        // 移除事件监听器
+        function removeEventListeners() {
+            previewThumbnail.onmouseover = null;
+            previewThumbnail.onmousemove = null;
+            previewThumbnail.onmouseout = null;
+        }
+
+        // 监听文件上传变化事件
+        function setupFileInputChange(uploadId) {
+            let upload = fileInputWrapper.querySelector(`#${uploadId}`);
+            if (upload) {
+                upload.addEventListener('change', function (e) {
+                    // 清除现有的大图预览
+                    removeImageAndPreview();
+
+                    // 读取新文件并更新 <img> 元素的 src 属性
+                    if (this.files && this.files[0]) {
+                        var reader = new FileReader();
+                        reader.onload = function (event) {
+                            imgElement.src = event.target.result;
+                            // 立即创建大图预览以反映新图片
+                            createLargePreview(imgElement);
+                            setupEventListeners(); // 重新设置事件监听器
+                            updateClearButtonVisibility(); // 更新清除按钮的可见性
+                        };
+                        reader.readAsDataURL(this.files[0]);
+                    } else {
+                        imgElement.src = ''; // 清空图片源
+                        removeEventListeners(); // 移除事件监听器
+                        updateClearButtonVisibility(); // 更新清除按钮的可见性
+                    }
+                });
+            }
+        }
+
+        // 移除图片和大图预览并更新清除按钮的可见性
+        function removeImageAndPreview() {
+            imgElement.src = ''; // 清空图片源
+            if (largePreview) {
+                largePreview.style.display = 'none';
+                largePreview.remove(); // 从 DOM 中移除 largePreview
+                largePreview = null;
+            }
+            removeEventListeners(); // 移除事件监听器
+            updateClearButtonVisibility(); // 更新清除按钮的可见性
+        }
+
+        // 更新清除按钮的可见性
+        function updateClearButtonVisibility() {
+            if (clearButton && imgElement) {
+                clearButton.style.display = imgElement.src !== '' ? 'inline-block' : 'none';
+            }
+        }
+
+        // 初始化
+        setupEventListeners();
+
+        // 对应的文件上传控件ID
+        let fileId = fileInputWrapper.querySelector('input[type="file"]')?.id;
+        if (fileId) {
+            setupFileInputChange(fileId);
+        }
+
+        // 对于回显的图片,确保初始化时创建大图预览并更新清除按钮的可见性
+        if (imgElement.src) {
+            createLargePreview(imgElement);
+            updateClearButtonVisibility();
+        } else {
+            updateClearButtonVisibility();
+        }
+    }
+
+    function handleButtonClick(){
+        // 验证配置的必填字段
+        var isValid = validateRequiredFields();
+        if (!isValid) {
+            return false;
+        }
+        if (submitHandler()) {
+            // 如果submitHandler执行成功,则手动显示模态框
+            $('#myModalClosePlan').modal('show');
+        } else {
+            // 处理失败的情况
+            //alert("操作未成功完成,无法显示模态框。");
+        }
+    }
+    // 验证必填字段
+    function validateRequiredFields() {
+        var isValid = true;
+        $('.dynamic-field.enabled').each(function() {
+            var field = $(this);
+            if (field.find('label.is-required').length > 0) {
+                var input = field.find('input, select, textarea');
+                if (input.length > 0) {
+                    var value = input.val();
+                    if (!value || value.trim() === '') {
+                        var fieldName = field.find('label').text().replace(':', '').replace('*', '').trim();
+                        $.modal.alertWarning(fieldName + ' 为必填项,请填写!');
+                        isValid = false;
+                        return false;
+                    }
+                }
+            }
+        });
+        return isValid;
+    }
+    function submitHandler() {
+        var filteredData = []
+        var selectedValue = $('input[name="returnMethod"]:checked').val();
+        if (!selectedValue) {
+            $.modal.alertWarning('请选择回访方式!');
+            formCheck=false;
+            return false;
+        }else{
+            formCheck=true;
+        }
+        let prescriptionImageUpload2 = document.getElementById('returnImgUrlUpload');
+        if (selectedValue === '微信' && prescriptionImageUpload2 != null) {
+            $.modal.alertWarning('微信回访时,回访图片为必填项!');
+            formCheck=false;
+            return false;
+        }else{
+            formCheck=true;
+        }
+        if (selectedValue === '面访' && !$('#InterviewRecord').val()) {
+            $.modal.alertWarning('面访时,面访记录为必填项!');
+            formCheck=false;
+            return false;
+        }else{
+            formCheck=true;
+        }
+        var iscoordinate = $('input[name="iscoordinate"]:checked').val();//是否配合
+        if (!iscoordinate) {
+            $.modal.alertWarning('请选择是否配合!');
+            formCheck=false;
+            return false;
+        }else{
+            formCheck=true;
+        }
+        debugger
+        var returnObject = $("#form-followUp-edit3").serializeArray().find(item => item.name === 'returnObject');
+        if (returnObject.value === '') {
+            $.modal.alertWarning("请选择回访对象");
+            formCheck=false;
+            return false;
+        }else{
+            formCheck=true;
+        }
+        var is_adverse_reaction = $('input[name="is_adverse_reaction"]:checked').val();
+        var stoped = $('input[name="stoped"]:checked').val();
+        var stopForm = $('input[name="stopform"]:checked').val();
+        if (stoped === '不填写完整表单' || stopForm === '不填写完整表单') {
+            $('input[name="is_adverse_reaction"]').not(this).prop('checked', false);
+        }else{
+            if (is_adverse_reaction === '是') {
+                var adverse_reaction_time = $("#form-followUp-edit3").serializeArray().find(item => item.name === 'adverse_reaction_time');
+                if (adverse_reaction_time.value === '') {
+                    $.modal.alertWarning("请选择是否出现不良反应");
+                    formCheck=false;
+                    return false;
+                }else{
+                    formCheck=true;
+                }
+                const blfyTableBody = document.getElementById('blfyTableBody');
+                const rows2 = blfyTableBody.getElementsByTagName('tr');
+                if (rows2.length > 0) {
+                    const rowsbyfys = [];//不良反应table
+                    $('#blfyTableBody tr').each(function () {
+                        const row = {
+                            id: $("#id").val(),
+                            byfyData: $(this).find('td:eq(1)').text(),
+                        };
+                        rowsbyfys.push(row);
+                    });
+                    filteredData.push({name: "good_response_symptom_id", value: JSON.stringify(rowsbyfys)})
+                }else{
+                    $.modal.alertWarning("请选择不良反应症状")
+                    formCheck=false;
+                    return false;
+                }
+            }
+        }
+        // prescriptionImageUpload 处方
+        let prescriptionImageUpload = document.getElementById('returnImgUrlUpload');
+        let prescriptionImageFile = prescriptionImageUpload.files[0];
+        var fd = new FormData();
+        var prescriptionImageUrl =$("#returnImgUrlUpload").val();
+        if (prescriptionImageFile && prescriptionImageFile !== '') {
+            fd.append('file', prescriptionImageFile); // 'file' 是服务器端用来接收文件的字段名
+
+            $.ajax({
+                url: prefix_recipe + "/uploadImg",
+                data: fd,
+                type: "post",
+                processData: false,
+                contentType: false,
+                success: function(result) {
+                    if (result.msg) {
+                        filteredData.push({name: "returnImgUrl", value: result.msg});
+                    }
+                },
+                error: function(xhr, status, error) {
+                    $.modal.alertError("上传图片失败");
+                }
+            });
+        }
+        var reasons_uncooperative = $('input[name="reasons_uncooperative"]:checked').val();
+        var medicationStatus = $('input[name="medicationStatus"]:checked').val();
+        var perpetual_stopdrug_cause = $('input[name="perpetual_stopdrug_cause"]:checked').val();
+        // 需要触发确认的选项列表
+        // 定义自动关闭的条件集合
+        const AUTO_CLOSE_CAUSES = new Set([
+            "离世", "患者因疾病进展/死亡永久停药", "已结束该药治疗疗程",
+            "患者疾病康复好转", "疾病康复好转", "经济原因无购买可能",
+            "不良反应严重", "疾病进展(耐药、效果不明显)更换治疗用药",
+            "回到地级市医院购药"
+        ]);
+        const AUTO_CLOSE_ASK_CAUSES = new Set(["永久停药"]);
+
+        // 判断是否满足自动关闭计划或任务的条件
+        var isAutoCloseCondition = iscoordinate === "2" && medicationStatus === "永久停药" && AUTO_CLOSE_CAUSES.has(perpetual_stopdrug_cause);
+        var isAutoCloseTaskCondition = iscoordinate === "1" && AUTO_CLOSE_ASK_CAUSES.has(medicationStatus);
+
+        if ((sensitiveValues.includes(reasons_uncooperative) || sensitiveValues.includes(medicationStatus)) && flagStatus == false) {
+            // 设置标志位
+            flagStatus2 = 0;
+            $.modal.msg("根据您填写的表单内容,系统判断您需要填写关闭计划原因")
+            showModalAndWaitForClose(function () {
+                console.log("模态框已关闭,继续处理后续逻辑");
+            });
+            updateVisibility4_1();
+            return true;
+            // 显示模态框,并等待用户交互
+        } else{
+            if (isAutoCloseCondition || isAutoCloseTaskCondition) {
+                // 显示确认弹框
+                $.modal.confirm2({
+                    title: '确认关闭',
+                    content: '根据您填写的表单内容,需要您确定是否关闭计划或者任务?',
+                    buttons: {
+                        confirm: {
+                            text: '确认关闭',
+                            btnClass: 'btn-blue',
+                            action: function () {
+                                submitFormWithConfirmFlag(filteredData,"1");
+                            }
+                        },
+                        cancel: {
+                            text: '不关闭',
+                            action: function () {
+                                submitFormWithConfirmFlag(filteredData,"0");
+                            }
+                        }
+                    }
+                });
+            }else{
+                submitFormWithConfirmFlag(filteredData,"888");
+            }
+
+        }
+
+    }
+    function submitFormWithConfirmFlag(filteredData,flagValue) {
+        confirmFlag = flagValue;
+        filteredData.push({name: "confirmFlag", value: confirmFlag});
+        // 获取表单数据并过滤
+        var formData = $("#form-followUp-edit3").serializeArray();
+
+
+
+        $.each(formData, function (index, field) {
+            var element = $('#' + field.name);
+
+            // 检查元素本身是否隐藏或其祖先元素是否隐藏
+            if (element.closest(':hidden').length === 0 && field.value !== '') {
+                filteredData.push(field);
+            }
+        });
+
+        var defaultFormData = $("#form-defaultValue").serializeArray();
+
+        // 合并两个数据集 到这里开始写后端接口了
+        filteredData = filteredData.concat(defaultFormData);
+        $.operate.saveTab(prefix_task + "/followTaskEdit", filteredData);
+        return false;
+    }
+
+    function extractTableData(tableId) {
+        const dataRows = [];
+        if (tableId == 'preMedicationPlanTable') {
+            const tableBody = document.getElementById(tableId + 'Body');
+            if (tableBody) {
+                const rows = tableBody.getElementsByTagName('tr');
+                if (rows.length > 0) {
+                    const rowsbyfys = [];
+                    $('#preMedicationPlanTableBody tr').each(function () {
+                        const row = {
+                            taskId: $("#id").val(),
+                            id: $(this).find('td:eq(0)').text(),
+                            pre_medication_plan: $(this).find('td:eq(1)').text(),
+                            pre_medication_plan_time: $(this).find('td:eq(2)').text(),
+
+                        };
+                        dataRows.push(row);
+                    });
+                }
+            }
+        }
+        if (tableId == 'currentTreatmentPlanTable') {
+
+            const tableBody = document.getElementById(tableId + 'Body');
+            if (tableBody) {
+                const rows = tableBody.getElementsByTagName('tr');
+                if (rows.length > 0) {
+                    $('#currentTreatmentPlanTableBody tr').each(function () {
+                        const row = {
+                            taskId: $("#id").val(),
+                            id: $(this).find('td:eq(0)').text(),
+                            current_treatment_plan: $(this).find('td:eq(1)').text(),
+                            current_treatment_plan_time: $(this).find('td:eq(2)').text(),
+
+                        };
+                        dataRows.push(row);
+                    });
+                }
+            }
+
+        }
+        if (tableId == 'postProgressionTreatmentPlanTable') {
+
+            const tableBody = document.getElementById(tableId + 'Body');
+            if (tableBody) {
+                const rows = tableBody.getElementsByTagName('tr');
+                if (rows.length > 0) {
+                    $('#postProgressionTreatmentPlanTableBody tr').each(function () {
+                        const row = {
+                            taskId: $("#id").val(),
+                            id: $(this).find('td:eq(0)').text(),
+                            post_progression_treatment_plan: $(this).find('td:eq(1)').text(),
+                            post_progression_treatment_time: $(this).find('td:eq(2)').text(),
+
+                        };
+                        dataRows.push(row);
+                    });
+                }
+            }
+        }
+        if (tableId == 'medicationRecordTable') {
+
+            const tableBody = document.getElementById(tableId + 'Body');
+            if (tableBody) {
+                const rows = tableBody.getElementsByTagName('tr');
+                if (rows.length > 0) {
+                    $('#medicationRecordTableBody tr').each(function () {
+                        const row = {
+                            taskId: $("#id").val(),
+                            id: $(this).find('td:eq(0)').text(),
+                            durgName: $(this).find('td:eq(1)').text(),
+                            jiliang: $(this).find('td:eq(2)').text(),
+                            startyyTime: $(this).find('td:eq(3)').text(),
+                            tyTime: $(this).find('td:eq(4)').text(),
+                            lastsyTime: $(this).find('td:eq(5)').text(),
+                            shiypv: $(this).find('td:eq(6)').text(),
+                            zhuyishix: $(this).find('td:eq(7)').text(),
+                        };
+                        dataRows.push(row);
+                    });
+                }
+            }
+
+        }
+        if (tableId == 'combinedMedicationRecordTable') {
+            const tableBody = document.getElementById(tableId + 'Body');
+            if (tableBody) {
+                const rows = tableBody.getElementsByTagName('tr');
+                if (rows.length > 0) {
+                    $('#combinedMedicationRecordTableBody tr').each(function () {
+                        const row = {
+                            taskId: $("#id").val(),
+                            id: $(this).find('td:eq(0)').text(),
+                            hbdurgName: $(this).find('td:eq(1)').text(),
+                            hbjiliang: $(this).find('td:eq(2)').text(),
+                            hbstartyyTime: $(this).find('td:eq(3)').text(),
+                            hbtyTime: $(this).find('td:eq(4)').text(),
+                            hbhblastsyTime: $(this).find('td:eq(5)').text(),
+                            hbshiypv: $(this).find('td:eq(6)').text(),
+                            hbzhuyishix: $(this).find('td:eq(7)').text(),
+                        };
+                        dataRows.push(row);
+                    });
+                }
+            }
+
+        }
+
+        return dataRows;
+    }
+    // 定义一个函数来显示模态框,并在模态框关闭时调用回调函数
+    function showModalAndWaitForClose(callback) {
+        // 监听模态框关闭事件
+        $('#myModalClosePlan').on('close', function () {
+            callback(); // 当模态框关闭时调用回调函数
+        });
+    }
+    function deleteRow(button) {
+        const row = button.parentNode.parentNode;
+        row.remove();
+        updateIndices(); // 删除后更新所有行的序号
+    }
+
+    // 更新所有行的序号
+    function updateIndices(value) {
+        if (value == 0) {
+            $('#blfyTableBody tr').each(function (index) {
+                $(this).find('td:first-child').text(index + 1); // 设置序号为当前索引加1
+            });
+        }
+        if (value == 1) {
+            $('#preMedicationPlanTableBody tr').each(function (index) {
+                $(this).find('td:first-child').text(index + 1); // 设置序号为当前索引加1
+            });
+        }
+        if (value == 2) {
+            $('#currentTreatmentPlanTableBody tr').each(function (index) {
+                $(this).find('td:first-child').text(index + 1); // 设置序号为当前索引加1
+            });
+        }
+        if (value == 3) {
+            $('#postProgressionTreatmentPlanTableBody tr').each(function (index) {
+                $(this).find('td:first-child').text(index + 1); // 设置序号为当前索引加1
+            });
+        }
+        if (value == 4) {
+            $('#medicationRecordTableBody tr').each(function (index) {
+                $(this).find('td:first-child').text(index + 1); // 设置序号为当前索引加1
+            });
+        }
+        if (value == 5) {
+            $('#combinedMedicationRecordTableBody tr').each(function (index) {
+                $(this).find('td:first-child').text(index + 1); // 设置序号为当前索引加1
+            });
+        }
+
+    }
+
+    function selectAdverseReactions(value) {
+
+        var province = $('.province').val();
+        var city = $('.city').val();
+        var area = $('.area').val();
+        $('.province, .city, .area').val('');
+
+        // 打印不良选择的不良反应
+        console.log('Selected: ' + province + ', ' + city + ', ' + area);
+        var row = '<tr>' +
+            '<td></td>' +
+            '<td>' + province + ', ' + city + ', ' + area + '</td>' +
+            '<td><button class="btn-danger" onclick="deleteRow(this)">删除</button></td>' +
+            '</tr>';
+        $('#blfyTableBody').append(row);
+        blfyindex++; // 增加索引
+        updateIndices(0); // 添加后更新所有行的序号
+    };
+
+    function saveRow(button) {
+        if (button == 1) {
+            // 获取表单数据
+            var pre_medication_time = document.getElementById('pre_medication_time').value;
+            var pre_medication_plan = document.getElementById('pre_medication_plan').value;
+
+            // 检查数据是否为空
+            if (!pre_medication_time || !pre_medication_plan) {
+                $.modal.alertWarning('请填写方案信息!');
+                return;
+            }
+            var row = '<tr>' +
+                '<td></td>' +
+                '<td>' + pre_medication_plan + '</td>' +
+                '<td>' + pre_medication_time + '</td>' +
+                '<td><button class="btn-danger" onclick="deleteRow(this)">删除</button></td>' +
+                '</tr>';
+            $('#preMedicationPlanTableBody').append(row);
+            blfyindex++; // 增加索引
+            updateIndices(1); // 添加后更新所有行的序号
+            // 清空表单输入框
+            document.getElementById('pre_medication_time').value = '';
+            document.getElementById('pre_medication_plan').selectedIndex = 0;
+            // 关闭模态框 currentTreatmentPlanTableBody postProgressionTreatmentPlanTableBody
+            $('#myModal1').modal('hide');
+        }
+        if (button == 2) {
+            // 获取表单数据
+            var current_treatment_plan_time = document.getElementById('current_treatment_plan_time').value;
+            var current_treatment_plan = document.getElementById('current_treatment_plan').value;
+
+            // 检查数据是否为空
+            if (!current_treatment_plan || !current_treatment_plan_time) {
+                $.modal.alertWarning('请填写方案信息!');
+                return;
+            }
+            var row = '<tr>' +
+                '<td></td>' +
+                '<td>' + current_treatment_plan + '</td>' +
+                '<td>' + current_treatment_plan_time + '</td>' +
+                '<td><button class="btn-danger" onclick="deleteRow(this)">删除</button></td>' +
+                '</tr>';
+            $('#currentTreatmentPlanTableBody').append(row);
+            blfyindex++; // 增加索引
+            updateIndices(2); // 添加后更新所有行的序号
+            // 清空表单输入框
+            $("#form-mqzlfa-add")[0].reset();
+            //document.getElementById('current_treatment_plan_time').value = '';
+            //document.getElementById('current_treatment_plan').selectedIndex = 0;
+            // 关闭模态框
+            $('#myModal2').modal('hide');
+        }
+        if (button == 3) {
+            // 获取表单数据
+            var post_progression_treatment_time = document.getElementById('post_progression_treatment_time').value;
+            var post_progression_treatment_plan = document.getElementById('post_progression_treatment_plan').value;
+
+            // 检查数据是否为空
+            if (!post_progression_treatment_time || !post_progression_treatment_plan) {
+                $.modal.alertWarning('请填写方案信息!');
+                return;
+            }
+            var row = '<tr>' +
+                '<td></td>' +
+                '<td>' + post_progression_treatment_plan + '</td>' +
+                '<td>' + post_progression_treatment_time + '</td>' +
+                '<td><button class="btn-danger" onclick="deleteRow(this)">删除</button></td>' +
+                '</tr>';
+            $('#postProgressionTreatmentPlanTableBody').append(row);
+            blfyindex++; // 增加索引
+            updateIndices(3); // 添加后更新所有行的序号
+            // 清空表单输入框
+            $("#form-jzhzlfa-add")[0].reset();
+            document.getElementById('post_progression_treatment_time').value = '';
+            document.getElementById('post_progression_treatment_plan').selectedIndex = 0;
+            // 关闭模态框 currentTreatmentPlanTableBody postProgressionTreatmentPlanTableBody
+            $('#myModal3').modal('hide');
+        }
+        if (button == 4) {
+            // 获取表单数据
+            var durgName = document.getElementById('durgName').value;
+            var jiliang = document.getElementById('jiliang').value;
+            var startyyTime = document.getElementById('startyyTime').value;
+            var tyTime = document.getElementById('tyTime').value;
+            var lastsyTime = document.getElementById('lastsyTime').value;
+            var shiypv = document.getElementById('shiypv').value;
+            var zhuyishix = document.getElementById('zhuyishix').value;
+            // 检查数据是否为空
+            if (!durgName) {
+                $.modal.alertWarning('请填写名称!');
+                return;
+            }
+            if (!jiliang) {
+                $.modal.alertWarning('请填写剂量!');
+                return;
+            }
+
+            var row = '<tr>' +
+                '<td></td>' +
+                '<td>' + durgName + '</td>' +
+                '<td>' + jiliang + '</td>' +
+                '<td>' + startyyTime + '</td>' +
+                '<td>' + tyTime + '</td>' +
+                '<td>' + lastsyTime + '</td>' +
+                '<td>' + shiypv + '</td>' +
+                '<td>' + zhuyishix + '</td>' +
+                '<td><button class="btn-danger" onclick="deleteRow(this)">删除</button></td>' +
+                '</tr>';
+            $('#medicationRecordTableBody').append(row);
+            blfyindex++; // 增加索引
+            updateIndices(4); // 添加后更新所有行的序号
+            // 清空表单输入框
+            $("#form-yyjl-add")[0].reset();
+            $('#myModal4').modal('hide');
+        }
+        if (button == 5) {
+
+
+            // 获取表单数据
+            var hbdurgName = document.getElementById('hbdurgName').value;
+            var hbjiliang = document.getElementById('hbjiliang').value;
+            var hbstartyyTime = document.getElementById('hbstartyyTime').value;
+            var hbtyTime = document.getElementById('hbtyTime').value;
+            var hblastsyTime = document.getElementById('hblastsyTime').value;
+            var hbshiypv = document.getElementById('hbshiypv').value;
+            var hbzhuyishix = document.getElementById('hbzhuyishix').value;
+            // 检查数据是否为空
+            if (!hbdurgName) {
+                $.modal.alertWarning('请填写名称!');
+                return;
+            }
+            if (!hbjiliang) {
+                $.modal.alertWarning('请填写剂量!');
+                return;
+            }
+            var row = '<tr>' +
+                '<td></td>' +
+                '<td>' + hbdurgName + '</td>' +
+                '<td>' + hbjiliang + '</td>' +
+                '<td>' + hbstartyyTime + '</td>' +
+                '<td>' + hbtyTime + '</td>' +
+                '<td>' + hblastsyTime + '</td>' +
+                '<td>' + hbshiypv + '</td>' +
+                '<td>' + hbzhuyishix + '</td>' +
+                '<td><button class="btn-danger" onclick="deleteRow(this)">删除</button></td>' +
+                '</tr>';
+            $('#combinedMedicationRecordTableBody').append(row);
+            blfyindex++; // 增加索引
+            updateIndices(5); // 添加后更新所有行的序号
+            // 清空表单输入框
+            $("#form-hbyyjl-add")[0].reset();
+            $('#myModal6').modal('hide');
+        }
+
+    }
+
+    //初始化加载
+    $(document).ready(function () {
+        initializeTemplate();
+        loadFieldDefinitions();
+
+        // 通过默认url获取
+        var urlChina = prefix + '/selectAdverseReactions';
+        $.cxSelect.defaults.url = urlChina;
+        $('#element1').cxSelect({
+            selects: ['province', 'city', 'area'],
+            nodata: 'none'
+        });
+
+        // 初始化 Select2 插件
+        for (let i = 1; i <= 6; i++) {
+            $(`#category-select${i}`).select2({
+                placeholder: "请选择或直接输入搜索",
+                allowClear: true
+            }).data('readonly', true); // 设置为只读模式
+            // 阻止键盘交互
+            document.getElementById(`category-select${i}`).addEventListener('keydown', (e) => e.preventDefault());
+        }
+
+        $.ajax({
+            url: ctx + 'sp/sp/typeDate',
+            method: 'GET',
+            dataType: 'json',
+            success: function(data) {
+                console.log("Data received from server:", data); // 添加调试信息
+
+                var selects = [
+                    $('#category-select1'),
+                    $('#category-select2'),
+                    $('#category-select3'),
+                    $('#category-select4'),
+                    $('#category-select5'),
+                    $('#category-select6')
+                ];
+
+                selects.forEach(function(select) {
+                    select.find('option').not(':first').remove();
+                });
+
+                selects.forEach(function(select) {
+                    if (!select.find('option:first').length) {
+                        $('<option>', {value: '', text: '请选择疾病'}).prependTo(select);
+                    }
+                });
+
+                var dl = /*[[${dl}]]*/ '';
+                var dlParsed = JSON.parse(dl);
+                var dlIds = Array.isArray(dlParsed) ? dlParsed.map(item => item.id.toString()) : [];
+                console.log("Selected IDs to be preselected:", dlIds); // 添加调试信息
+
+                var selectedOptionsMap = {};
+                selects.forEach((_, index) => selectedOptionsMap[index] = []);
+
+                $.each(data.value || [], function(index, item) {
+                    var selectIndex = item.dict_key - 1;
+                    if (selectIndex >= 0 && selectIndex < selects.length) {
+                        $('<option>', {value: item.id, text: item.categoryName}).appendTo(selects[selectIndex]);
+                        if (dlIds.includes(item.id.toString())) {
+                            selectedOptionsMap[selectIndex].push(item.id.toString());
+                        }
+                    }
+                });
+
+                selects.forEach(function(select, index) {
+                    if (selectedOptionsMap[index].length > 0) {
+                        console.log(`Setting selected values for select ${index}:`, selectedOptionsMap[index]); // 添加调试信息
+                        select.val(selectedOptionsMap[index]).trigger('change');
+                    }
+                });
+// // 禁用下拉框以模拟只读效果
+//                 for (let i = 1; i <= 6; i++) {
+//                     let selectElement = $(`#category-select${i}`);
+//                     selectElement.prop('disabled', true).attr('aria-disabled', 'true');
+//
+//                     // 移除或调整特定的样式
+//                     let select2Container = selectElement.data('select2').$container;
+//                     select2Container.removeClass('select2-container--disabled'); // 移除禁用样式类
+//
+//                     // 或者直接设置背景颜色为透明或其它颜色
+//                     select2Container.find('.select2-selection--single').css('background-color', 'transparent');
+//                 }
+            },
+            error: function(xhr, status, error) {
+                console.error("Failed to load disease categories:", error);
+            }
+        });
+
+
+        $("#myModal5").hide();
+
+
+        // 监听点击事件,激活指定的选项卡
+        $('#myUlTabs li a').click(function (e) {
+            // 阻止默认行为
+            //e.preventDefault();
+            // 获取当前点击的选项卡链接
+            var $this = $(this);
+            if ($this.attr('href') === '#tab-1') {
+                formSubmitted = true;
+            }
+            if ($this.attr('href') === '#tab-2') {
+                formSubmitted = false;
+                // 添加 active 类到当前点击的选项卡
+                $(this).addClass('active');
+                $this.attr('aria-expanded', 'true');
+
+            }
+            // 检查是否为“用药购药”选项卡
+            if ($this.attr('href') === '#tab-2') {
+                // 初始化表格
+                initializeTableForTab('tab-2');
+            }
+            if ($this.attr('href') === '#tab-3') {
+                // 初始化表格
+                initializeTableForTab('tab-3');
+                // 初始化表格
+                initializeTableForTab('tab-4');
+            }
+
+        });
+
+        $('#myTabs2 li a').click(function (e) {
+            // 阻止默认行为
+            e.preventDefault();
+            // 获取当前点击的选项卡链接
+            var $this = $(this);
+            // 移除所有选项卡的 active 类
+            //$('#myTabs li').removeClass('active');
+            //$('.tab-pane').removeClass('active in');
+            $('#myTabs2 li a').addClass('active');
+            // 添加 active 类到当前点击的选项卡
+            $this.parent().addClass('active');
+            // 获取目标选项卡面板的 ID
+            var target = $this.attr('href');
+            // 展示对应的选项卡面板,并更新 aria-expanded
+            $(target).addClass('active in');
+            $this.attr('aria-expanded', 'true');
+            // 执行点击链接对应的动作
+            $this.tab('show');
+            // 移除所有选项卡的激活类
+            //$('.active').removeClass('active');
+            $(this).addClass('active');
+            // 滚动到目标选项卡位置
+            // 将目标内容区滚动到视口中央
+            $('html, body').animate({
+                scrollTop: $(target).offset().top - ($(window).height() / 2)
+            }, 500); // 500毫秒动画时间
+            // scrollToTab($this);
+            // 重新初始化当前选项卡内的表格
+            var tableId = target.replace('#', '');
+            // initializeTableForTab(tableId);
+        });
+
+        //疾病大类
+        //购药记录
+        recordsData = /*[[${recordsData}]]*/ [];
+        // 回显数据随访计划
+        listPlan1 = /*[[${Plan1}]]*/ '';
+        listPlan2 = /*[[${Plan2}]]*/ '';
+
+        // 回显数据随访计划
+        listTask1 = /*[[${listTask1}]]*/ [];
+        listTask2 = /*[[${listTask2}]]*/ [];
+        /*<![CDATA[*/
+        pcTypes = /*[[${@dict.getType('sys_select_dtp_ysfw_sfpx')}]]*/ [];
+        /*]]>*/
+        // 提取 dictLabel 字段
+        dosageFrequencyOptions = pcTypes.map(function (item) {
+            return {
+                value: item.dictValue, // 存储的值
+                text: item.dictLabel   // 显示的文本
+            };
+        });
+        // 提取 dictLabel 和 dictValue 字段,并创建一个查找表
+        pcTypes.forEach(function (item) {
+            dosageFrequencyLookup[item.dictValue] = {label: item.dictLabel, value: item.dictValue};
+        });
+        // 构建 options 用于 editable 插件
+        dosageFrequencyOptions = pcTypes.map(function (item) {
+            return {
+                value: item.dictValue, // 存储的值
+                text: item.dictLabel   // 显示的文本
+            };
+        });
+        console.log(pcTypes);
+        var planId_cg = /*[[${planId_cg}]]*/ '';
+        var planId_tl = /*[[${planId_tl}]]*/ '';
+        // if (planId_cg) {
+        //
+        //     $('#cgsfnormal').show();
+        // } else {
+        //     $('#cgsfnormal').hide();
+        // }
+        // if (planId_tl) {
+        //     $('#tlzhback').show();
+        // } else {
+        //     $('#tlzhback').hide();
+        // }
+
+        /*<![CDATA[*/
+        var imagingInsuranceTypeList = /*[[${imagingInsuranceType}]]*/ '[]';
+        /*]]>*/
+
+        if (imagingInsuranceTypeList && imagingInsuranceTypeList !== '[]') {
+            check(imagingInsuranceTypeList);
+        }
+
+
+        /*<![CDATA[*/
+        var tumorMarkerCheckList = /*[[${tumorMarkerCheck}]]*/ '[]';
+        /*]]>*/
+        if(tumorMarkerCheckList && tumorMarkerCheckList !== '[]'){
+            check2(tumorMarkerCheckList);
+        }
+
+
+        /*<![CDATA[*/
+        var treatmentTypeList = /*[[${treatmentType}]]*/ '[]';
+        /*]]>*/
+        if(treatmentTypeList && treatmentTypeList !== '[]'){
+            check3(treatmentTypeList);
+        }
+        // 初始化时回显 影像学检查 已选中的值
+        function check(imagingInsuranceTypeList) {
+            // 将字符串转换为数组
+            var imagingInsuranceType = JSON.parse(imagingInsuranceTypeList.replace(/'/g, '"'));
+
+            $.each(imagingInsuranceType, function(index, value) {
+                var trimmedValue = value.trim();
+                console.log("Checking for value:", trimmedValue);
+
+                // 使用 jQuery 的属性选择器函数形式来避免手动拼接字符串的问题
+                var checkbox = $('input[name="imagingInsuranceType"]').filter(function() {
+                    var checkboxValue = $(this).val().trim(); // 确保值也去除空格
+                    console.log("Checkbox value:", checkboxValue);
+                    return checkboxValue === trimmedValue;
+                });
+
+                if (checkbox.length > 0) {
+                    console.log("Found checkbox with value:", trimmedValue);
+                    checkbox.prop('checked', true);
+                } else {
+                    console.warn("No checkbox found with value:", trimmedValue);
+                }
+            });
+        }
+        // 初始化时回显 影像学检查 已选中的值
+        function check2(tumorMarkerCheckList) {
+            // 将字符串转换为数组
+            var tumorMarkerCheck = JSON.parse(tumorMarkerCheckList.replace(/'/g, '"'));
+
+            $.each(tumorMarkerCheck, function(index, value) {
+                var trimmedValue = value.trim();
+                console.log("Checking for value:", trimmedValue);
+
+                // 使用 jQuery 的属性选择器函数形式来避免手动拼接字符串的问题
+                var checkbox = $('input[name="tumorMarkerCheck"]').filter(function() {
+                    var checkboxValue = $(this).val().trim(); // 确保值也去除空格
+                    console.log("Checkbox value:", checkboxValue);
+                    return checkboxValue === trimmedValue;
+                });
+
+                if (checkbox.length > 0) {
+                    console.log("Found checkbox with value:", trimmedValue);
+                    checkbox.prop('checked', true);
+                } else {
+                    console.warn("No checkbox found with value:", trimmedValue);
+                }
+            });
+        }
+        // 初始化时回显 影像学检查 已选中的值
+        function check3(treatmentTypeList) {
+            // 将字符串转换为数组
+            var treatmentType = JSON.parse(treatmentTypeList.replace(/'/g, '"'));
+
+            $.each(treatmentType, function(index, value) {
+                var trimmedValue = value.trim();
+                console.log("Checking for value:", trimmedValue);
+
+                // 使用 jQuery 的属性选择器函数形式来避免手动拼接字符串的问题
+                var checkbox = $('input[name="treatmentType"]').filter(function() {
+                    var checkboxValue = $(this).val().trim(); // 确保值也去除空格
+                    console.log("Checkbox value:", checkboxValue);
+                    return checkboxValue === trimmedValue;
+                });
+
+                if (checkbox.length > 0) {
+                    console.log("Found checkbox with value:", trimmedValue);
+                    checkbox.prop('checked', true);
+                } else {
+                    console.warn("No checkbox found with value:", trimmedValue);
+                }
+            });
+        }
+
+
+
+
+        //表单中的几个table初始化
+        preMedicationPlans = /*[[${preMedicationPlan}]]*/ [];
+        // 如果后端传递的是JSON字符串,先解析成数组
+        if (typeof preMedicationPlans === 'string') {
+            try {
+                preMedicationPlans = JSON.parse(preMedicationPlans);
+            } catch (e) {
+                console.error("解析JSON字符串失败:", e);
+                preMedicationPlans = []; // 解析失败时初始化为空数组
+            }
+        }
+        currentTreatmentPlans = /*[[${currentTreatmentPlan}]]*/ [];
+        // 如果后端传递的是JSON字符串,先解析成数组
+        if (typeof currentTreatmentPlans === 'string') {
+            try {
+                currentTreatmentPlans = JSON.parse(currentTreatmentPlans);
+            } catch (e) {
+                console.error("解析JSON字符串失败:", e);
+                currentTreatmentPlans = []; // 解析失败时初始化为空数组
+            }
+        }
+        postProgressionTreatmentPlans = /*[[${postProgressionTreatmentPlan}]]*/ [];
+        // 如果后端传递的是JSON字符串,先解析成数组
+        if (typeof postProgressionTreatmentPlans === 'string') {
+            try {
+                postProgressionTreatmentPlans = JSON.parse(postProgressionTreatmentPlans);
+            } catch (e) {
+                console.error("解析JSON字符串失败:", e);
+                postProgressionTreatmentPlans = []; // 解析失败时初始化为空数组
+            }
+        }
+        medicationRecords = /*[[${medicationRecord}]]*/ [];
+        // 如果后端传递的是JSON字符串,先解析成数组
+        if (typeof medicationRecords === 'string') {
+            try {
+                medicationRecords = JSON.parse(medicationRecords);
+            } catch (e) {
+                console.error("解析JSON字符串失败:", e);
+                medicationRecords = []; // 解析失败时初始化为空数组
+            }
+        }
+        combinedMedicationRecords = /*[[${combinedMedicationRecord}]]*/ [];
+        // 如果后端传递的是JSON字符串,先解析成数组
+        if (typeof combinedMedicationRecords === 'string') {
+            try {
+                combinedMedicationRecords = JSON.parse(combinedMedicationRecords);
+            } catch (e) {
+                console.error("解析JSON字符串失败:", e);
+                combinedMedicationRecords = []; // 解析失败时初始化为空数组
+            }
+        }
+        good_response_symptom_ids = /*[[${good_response_symptom_id}]]*/ [];
+        // 如果后端传递的是JSON字符串,先解析成数组
+        if (typeof good_response_symptom_ids === 'string') {
+            try {
+                good_response_symptom_ids = JSON.parse(good_response_symptom_ids);
+            } catch (e) {
+                console.error("解析JSON字符串失败:", e);
+                good_response_symptom_ids = []; // 解析失败时初始化为空数组
+            }
+        }
+        addRowsToTable(preMedicationPlans,'preMedicationPlanTableBody');
+        addRowsToTable(currentTreatmentPlans,'currentTreatmentPlanTableBody');
+        addRowsToTable(postProgressionTreatmentPlans,'postProgressionTreatmentPlanTableBody');
+        addRowsToTable(medicationRecords,'medicationRecordTableBody');
+        addRowsToTable(combinedMedicationRecords,'combinedMedicationRecordTableBody');
+        addRowsToTable(good_response_symptom_ids,'blfyTableBody');
+
+
+
+
+        // 监听回访方式的选择变化
+        $('input[name="returnMethod"]').on('change', updateVisibility1);
+        //是否配合
+        $('input[name="iscoordinate"]').on('change', updateVisibility2);
+
+        // 监听不良反应的选择变化
+        $('input[name="is_adverse_reaction"]').on('change', updateVisibility3);
+        //监听合并用药是否引起不良反应
+        $('input[name="combinedMedicationAdverseReaction"]').on('change', updateVisibility3);
+
+        // 监听用药状态的选择变化
+        $('input[name="medicationStatus"]').on('change', updateVisibility4);
+        $('input[name="reasons_uncooperative"]').on('change', updateVisibility4);
+        $('input[name="perpetual_stopdrug_cause"]').on('change', updateVisibility4_2);
+        $('input[name="stoped"]').on('change', updateVisibility5);
+        $('input[name="stopform"]').on('change', updateVisibility5);
+
+        // 监听弹框 关闭计划原因
+        $('input[name="reason"]').on('change', updateVisibility6);
+        $('input[name="drugsStatus"]').on('change', updateVisibility6);//用药状态调整
+        $('input[name="drugsStop"]').on('change', updateVisibility6_1);//永久停药类型
+        $('input[name="flowNo"]').on('change', updateVisibility6);//随访不配合原因
+        $('input[name="closePlanScope"]').on('change', updateVisibility6_1);//关闭计划范围
+        $('input[name="closeType"]').on('change', updateVisibility6_2);//计划类型
+
+        // 监听治疗类型选择 是否复查 变化
+        $('input[name="isReview"]').on('change', updateVisibility7);//治疗类型
+        $('input[name="imagingInsuranceType"]').on('change', updateVisibility8);//治疗类型
+        $('input[name="clinicalInteraction"]').on('change', updateVisibility9);//计划类型
+        $('input[name="unnecessaryRepeatedMedication"]').on('change', updateVisibility10);//计划类型
+        $('input[name="medicationError"]').on('change', updateVisibility11);//计划类型
+        $('input[name="isConsultation"]').on('change', updateVisibility12);//计划类型
+        $('input[name="treatmentType"]').on('change', updateVisibility13);//治疗类型
+        $('input[name="tumorMarkerCheck"]').on('change', updateVisibility14);//肿瘤标记物检查
+
+        // 初始化时设置默认显示状态
+        updateVisibility1();
+        updateVisibility2();
+        updateVisibility3();
+        updateVisibility4();
+        updateVisibility4_2();
+        updateVisibility5();
+        updateVisibility7();
+        updateVisibility8();
+        updateVisibility9();
+        updateVisibility10();
+        updateVisibility11();
+        updateVisibility12();
+        updateVisibility13();
+        updateVisibility14();
+    });
+
+
+    // 初始化模版配置
+    function initializeTemplate() {
+        if (templateConfigId) {
+            loadTemplateConfig();
+        } else {
+            // 使用默认全量表单
+            loadDefaultTemplate();
+        }
+    }
+
+    // 加载模版配置
+    function loadTemplateConfig() {
+        $.ajax({
+            url: ctx + "gxhpz/followTemplateConfig/getTemplateConfig",
+            type: "POST",
+            data: { id: templateConfigId },
+            success: function(result) {
+                if (result.code == 0) {
+                    templateConfig = result.data;
+                    $('#templateIndicator').text('模版: ' + templateConfig.template.templateName);
+                    renderDynamicForm();
+                } else {
+                    console.error("加载模版配置失败:", result.msg);
+                    loadDefaultTemplate();
+                }
+            },
+            error: function() {
+                console.error("加载模版配置异常");
+                loadDefaultTemplate();
+            }
+        });
+    }
+
+    // 加载默认模版(全量表单)
+    function loadDefaultTemplate() {
+        $('#templateIndicator').text('模版: 全量表单 (默认)');
+        // 显示所有Tab和字段
+        $('.dynamic-tab').addClass('enabled');
+        $('.dynamic-field').addClass('enabled');
+
+        // 生成默认Tab导航
+        generateDefaultTabs();
+    }
+
+    // 生成默认Tab导航
+    function generateDefaultTabs() {
+        var defaultTabs = [
+            { code: 'tab-6', name: '用药依从性' },
+            { code: 'tab-7', name: '药物安全性' },
+            { code: 'tab-8', name: '药物有效性' },
+            { code: 'tab-9', name: '治疗方案' },
+            { code: 'tab-10', name: '适宜性评估' },
+            { code: 'tab-11', name: '用药记录' },
+            { code: 'tab-12', name: '量表测评' },
+            { code: 'tab-13', name: '患者咨询' },
+            { code: 'tab-14', name: '其他' }
+        ];
+
+        var tabHtml = '';
+        defaultTabs.forEach(function(tab) {
+            tabHtml += '<li><a data-toggle="tab" href="#' + tab.code + '">' + tab.name + '</a></li>';
+        });
+
+        $('#dynamicTabs').append(tabHtml);
+    }
+
+    // 渲染动态表单
+    function renderDynamicForm() {
+        if (!templateConfig) return;
+
+        // 渲染Tab导航
+        renderTabNavigation();
+
+        // 渲染字段
+        renderFields();
+
+        // 绑定字段事件
+        bindFieldEvents();
+    }
+
+    // 渲染Tab导航
+    function renderTabNavigation() {
+        var tabs = templateConfig.tabs;
+        if (!tabs || tabs.length === 0) return;
+
+        var tabHtml = '';
+        tabs.forEach(function(tab) {
+            if (tab.tabCode !== 'tab-4') { // 本次任务Tab已经存在
+                tabHtml += '<li><a data-toggle="tab" href="#' + tab.tabCode + '">' + tab.tabName + '</a></li>';
+                $('#' + tab.tabCode).addClass('enabled');
+            }
+        });
+
+        $('#dynamicTabs').append(tabHtml);
+    }
+
+    // 渲染字段
+    function renderFields() {
+        var fieldsByTab = templateConfig.fieldsByTab;
+        if (!fieldsByTab) return;
+
+        Object.keys(fieldsByTab).forEach(function(tabCode) {
+            var fields = fieldsByTab[tabCode];
+            var fieldsHtml = '';
+
+            // 按显示顺序排序
+            fields.sort(function(a, b) {
+                return (a.displayOrder || 0) - (b.displayOrder || 0);
+            });
+
+            fields.forEach(function(field) {
+                fieldsHtml += generateFieldHtml(field);
+            });
+
+            $('#' + tabCode + '-fields').html(fieldsHtml);
+        });
+    }
+
+    // 生成字段HTML
+    function generateFieldHtml(field) {
+        var fieldHtml = '';
+        var isRequired = field.isRequired == 1;
+        var requiredClass = isRequired ? 'is-required' : '';
+        var requiredText = isRequired ? ' <span style="color: red;">*</span>' : '';
+
+        switch (field.fieldType) {
+            case 'input':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <input name="${field.fieldCode}" id="${field.fieldCode}"
+                                   placeholder="${field.placeholder || ''}"
+                                   class="styled-input" type="text">
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'radio':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <div class="input-groups" id="${field.fieldCode}-options">
+                                <!-- 单选选项将通过JavaScript动态加载 -->
+                            </div>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'checkbox':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <div class="input-groups" id="${field.fieldCode}-options">
+                                <!-- 复选选项将通过JavaScript动态加载 -->
+                            </div>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'select':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <select name="${field.fieldCode}" id="${field.fieldCode}" class="styled-input">
+                                <option value="">请选择</option>
+                                <!-- 下拉选项将通过JavaScript动态加载 -->
+                            </select>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'textarea':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <textarea name="${field.fieldCode}" id="${field.fieldCode}"
+                                      placeholder="${field.placeholder || ''}"
+                                      class="styled-input edit_inputs textareas"
+                                      style="width: auto;height: 140px ;border: 1px solid;"
+                                      rows="1.9" cols="112"></textarea>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'datetime':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <input name="${field.fieldCode}" id="${field.fieldCode}"
+                                   placeholder="${field.placeholder || ''}"
+                                   class="time-input time-input2 styled-input" type="text">
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            case 'file':
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label class="${requiredClass}">${field.fieldName}:${requiredText}</label>
+                            <div class="fileinput fileinput-new" data-provides="fileinput">
+                                <div class="fileinput-preview thumbnail" data-trigger="fileinput" style="width: 200px; height: 150px;">
+                                    <div class="centered-content">
+                                        <span class="plus-sign">+</span>
+                                    </div>
+                                </div>
+                                <div>
+                                    <input style="display: none;" id="${field.fieldCode}" name="${field.fieldCode}" type="file">
+                                    <a href="javascript:;" class="btn btn-white" data-dismiss="fileinput">清除图片</a>
+                                </div>
+                            </div>
+                            <span class="status"></span>
+                        </div>`;
+                break;
+
+            default:
+                fieldHtml = `
+                        <div class="customize-form-group edit dynamic-field enabled">
+                            <label>${field.fieldName}:</label>
+                            <span>字段类型 ${field.fieldType} 暂不支持</span>
+                        </div>`;
+        }
+
+        return fieldHtml;
+    }
+
+    // 加载字段定义和选项
+    function loadFieldDefinitions() {
+        // 这里可以加载字段的选项数据,比如字典数据
+        // 示例:为单选和复选框字段加载选项
+        setTimeout(function() {
+            loadFieldOptions();
+        }, 1000);
+    }
+
+    // 加载字段选项
+    function loadFieldOptions() {
+        // 为动态生成的字段加载选项数据
+        // 这里应该根据实际的字典配置来加载
+
+        // 示例:回访方式选项
+        loadRadioOptions('returnMethod', [
+            { value: '电话', text: '电话' },
+            { value: '微信', text: '微信' },
+            { value: '面访', text: '面访' }
+        ]);
+
+        // 示例:是否配合选项
+        loadRadioOptions('iscoordinate', [
+            { value: '1', text: '是' },
+            { value: '2', text: '否' }
+        ]);
+
+        // 可以继续添加其他字段的选项加载
+    }
+
+    // 加载单选选项
+    function loadRadioOptions(fieldCode, options) {
+        var container = $('#' + fieldCode + '-options');
+        if (container.length === 0) return;
+
+        var html = '';
+        options.forEach(function(option) {
+            html += `<input type="radio" class="form-check-radio" name="${fieldCode}"
+                               value="${option.value}" id="${fieldCode}_${option.value}"> ${option.text}`;
+        });
+        container.html(html);
+    }
+
+    // 绑定字段事件
+    function bindFieldEvents() {
+        // 根据模版配置中的规则绑定字段联动事件
+        if (templateConfig.rules) {
+            templateConfig.rules.forEach(function(rule) {
+                bindFieldRule(rule);
+            });
+        }
+    }
+
+    // 绑定字段规则
+    function bindFieldRule(rule) {
+        var triggerField = $('input[name="' + rule.triggerFieldCode + '"], select[name="' + rule.triggerFieldCode + '"]');
+
+        triggerField.on('change', function() {
+            var currentValue = $(this).val();
+            var targetFields = rule.targetFieldCodes.split(',');
+
+            var shouldExecute = false;
+            switch (rule.ruleLogic) {
+                case 'equal':
+                    shouldExecute = currentValue === rule.triggerFieldValue;
+                    break;
+                case 'not_equal':
+                    shouldExecute = currentValue !== rule.triggerFieldValue;
+                    break;
+                case 'contains':
+                    shouldExecute = currentValue.indexOf(rule.triggerFieldValue) !== -1;
+                    break;
+                case 'in':
+                    var values = rule.triggerFieldValue.split(',');
+                    shouldExecute = values.indexOf(currentValue) !== -1;
+                    break;
+            }
+
+            targetFields.forEach(function(targetFieldCode) {
+                var targetElement = $('[name="' + targetFieldCode.trim() + '"]').closest('.customize-form-group');
+
+                if (shouldExecute) {
+                    if (rule.actionType === 'show') {
+                        targetElement.removeClass('hidden').addClass('shown');
+                    } else if (rule.actionType === 'hide') {
+                        targetElement.removeClass('shown').addClass('hidden');
+                    } else if (rule.actionType === 'required') {
+                        targetElement.find('label').addClass('is-required');
+                        targetElement.find('input, select, textarea').attr('required', true);
+                    } else if (rule.actionType === 'optional') {
+                        targetElement.find('label').removeClass('is-required');
+                        targetElement.find('input, select, textarea').removeAttr('required');
+                    }
+                } else {
+                    // 反向操作
+                    if (rule.actionType === 'show') {
+                        targetElement.removeClass('shown').addClass('hidden');
+                    } else if (rule.actionType === 'hide') {
+                        targetElement.removeClass('hidden').addClass('shown');
+                    }
+                }
+            });
+        });
+    }
+
+
+    function refreshData(response) {
+        // 解析 JSON 字符串
+        const parsedResponse = JSON.parse(response);
+        const data = parsedResponse.data;
+        // 清空原有的内容
+        $('#drug-info-container').empty();
+        // 遍历 data 数组并为每个对象生成 HTML 内容
+        data.forEach(function(item, index) {
+            // 使用模板字符串生成 HTML 内容
+            const htmlContent = `
+            <div style="margin-bottom: 10px; border: 1px solid #ccc; padding: 10px;">
+                <span>
+                    <strong>药品: <code class="genericName">${item.genericName}</code></strong><br>
+                    <strong>用药状态: <code class="medicationStatus">${item.medication_status}</code></strong><br>
+                    <strong>剩余用药天数: <code class="sumTotal">${item.sum_total}天</code></strong><br>
+                </span>
+            </div>
+        `;
+
+            // 将生成的 HTML 内容添加到容器中
+            $('#drug-info-container').append(htmlContent);
+        });
+    }
+    function addRowsToTable(data,tbodyId) {
+        // 检查 data 是否为 null 或 undefined
+        if (!Array.isArray(data)) {
+            console.warn("提供的数据不是数组", data);
+            return;
+        }
+        if(data.length > 0){
+            var tbody = document.getElementById(tbodyId);
+            if(tbodyId === 'blfyTableBody'){
+                data.forEach(function(item, index) {
+                    var row = document.createElement('tr');
+                    // 序号
+                    var tdIndex = document.createElement('td');
+                    tdIndex.textContent = index + 1;
+                    row.appendChild(tdIndex);
+                    // 不良反应症状
+                    var tdPlan = document.createElement('td');
+                    tdPlan.textContent = item.byfyData;
+                    row.appendChild(tdPlan);
+                    // 操作(这里可以添加按钮或其他交互元素)
+                    var tdAction = document.createElement('td');
+                    // 示例: 添加一个删除按钮
+                    var deleteButton = document.createElement('button');
+                    deleteButton.textContent = '删除';
+                    deleteButton.onclick = function() { deleteRow(this); };
+                    tdAction.appendChild(deleteButton);
+                    row.appendChild(tdAction);
+
+                    tbody.appendChild(row);
+                });
+
+            }
+            if(tbodyId === 'preMedicationPlanTableBody' || tbodyId === 'currentTreatmentPlanTableBody' || tbodyId === 'postProgressionTreatmentPlanTableBody'){
+                if(tbodyId === 'preMedicationPlanTableBody'){
+                    data.forEach(function(item, index) {
+                        var row = document.createElement('tr');
+
+                        // 序号
+                        var tdIndex = document.createElement('td');
+                        tdIndex.textContent = item.id;
+                        row.appendChild(tdIndex);
+
+                        // 治疗方案
+                        var tdPlan = document.createElement('td');
+                        tdPlan.textContent = item.pre_medication_plan;
+                        row.appendChild(tdPlan);
+
+                        // 治疗时间
+                        var tdTime = document.createElement('td');
+                        tdTime.textContent = item.pre_medication_plan_time;
+                        row.appendChild(tdTime);
+
+                        // 操作(这里可以添加按钮或其他交互元素)
+                        var tdAction = document.createElement('td');
+                        // 示例: 添加一个删除按钮
+                        var deleteButton = document.createElement('button');
+                        deleteButton.textContent = '删除';
+                        deleteButton.onclick = function() { deleteRow(this); };
+                        tdAction.appendChild(deleteButton);
+                        row.appendChild(tdAction);
+
+                        tbody.appendChild(row);
+                        updateIndices(1);
+                    });
+                }
+                if(tbodyId === 'currentTreatmentPlanTableBody'){
+                    data.forEach(function(item, index) {
+                        var row = document.createElement('tr');
+
+                        // 序号
+                        var tdIndex = document.createElement('td');
+                        tdIndex.textContent = item.id;
+                        row.appendChild(tdIndex);
+
+                        // 治疗方案
+                        var tdPlan = document.createElement('td');
+                        tdPlan.textContent = item.current_treatment_plan;
+                        row.appendChild(tdPlan);
+
+                        // 治疗时间
+                        var tdTime = document.createElement('td');
+                        tdTime.textContent = item.current_treatment_plan_time;
+                        row.appendChild(tdTime);
+
+                        // 操作(这里可以添加按钮或其他交互元素)
+                        var tdAction = document.createElement('td');
+                        // 示例: 添加一个删除按钮
+                        var deleteButton = document.createElement('button');
+                        deleteButton.textContent = '删除';
+                        deleteButton.onclick = function() { deleteRow(this); };
+                        tdAction.appendChild(deleteButton);
+                        row.appendChild(tdAction);
+
+                        tbody.appendChild(row);
+                        updateIndices(2);
+                    });
+                }
+                if(tbodyId === 'postProgressionTreatmentPlanTableBody'){
+                    data.forEach(function(item, index) {
+                        var row = document.createElement('tr');
+
+                        // 序号
+                        var tdIndex = document.createElement('td');
+                        tdIndex.textContent = item.id;
+                        row.appendChild(tdIndex);
+
+                        // 治疗方案
+                        var tdPlan = document.createElement('td');
+                        tdPlan.textContent = item.post_progression_treatment_plan;
+                        row.appendChild(tdPlan);
+
+                        // 治疗时间
+                        var tdTime = document.createElement('td');
+                        tdTime.textContent = item.post_progression_treatment_plan_time;
+                        row.appendChild(tdTime);
+
+                        // 操作(这里可以添加按钮或其他交互元素)
+                        var tdAction = document.createElement('td');
+                        // 示例: 添加一个删除按钮
+                        var deleteButton = document.createElement('button');
+                        deleteButton.textContent = '删除';
+                        deleteButton.onclick = function() { deleteRow(this); };
+                        tdAction.appendChild(deleteButton);
+                        row.appendChild(tdAction);
+
+                        tbody.appendChild(row);
+                        updateIndices(3);
+                    });
+
+                }
+            }
+
+
+
+        }
+        if(tbodyId === 'medicationRecordTableBody' || tbodyId === 'combinedMedicationRecordTableBody'){
+            if(tbodyId === 'medicationRecordTableBody'){
+                data.forEach(function(item, index) {
+                    var row = document.createElement('tr');
+
+                    // 序号
+                    var tdIndex = document.createElement('td');
+                    tdIndex.textContent = item.id;
+                    row.appendChild(tdIndex);
+
+                    // 1
+                    var durgName = document.createElement('td');
+                    durgName.textContent = item.durgName;
+                    row.appendChild(durgName);
+
+                    // 2
+                    var jiliang = document.createElement('td');
+                    jiliang.textContent = item.jiliang;
+                    row.appendChild(jiliang);
+                    // 1
+                    var startyyTime = document.createElement('td');
+                    startyyTime.textContent = item.startyyTime;
+                    row.appendChild(startyyTime);
+
+                    // 2
+                    var tyTime = document.createElement('td');
+                    tyTime.textContent = item.tyTime;
+                    row.appendChild(tyTime);
+                    // 1
+                    var lastsyTime = document.createElement('td');
+                    lastsyTime.textContent = item.lastsyTime;
+                    row.appendChild(lastsyTime);
+
+                    // 2
+                    var shiypv = document.createElement('td');
+                    shiypv.textContent = item.shiypv;
+                    row.appendChild(shiypv);
+                    // 7
+                    var zhuyishix = document.createElement('td');
+                    zhuyishix.textContent = item.zhuyishix;
+                    row.appendChild(zhuyishix);
+                    // 操作(这里可以添加按钮或其他交互元素)
+                    var tdAction = document.createElement('td');
+                    // 示例: 添加一个删除按钮
+                    var deleteButton = document.createElement('button');
+                    deleteButton.textContent = '删除';
+                    deleteButton.onclick = function() { deleteRow(this); };
+                    tdAction.appendChild(deleteButton);
+                    row.appendChild(tdAction);
+
+                    tbody.appendChild(row);
+                    updateIndices(4);
+                });
+
+
+            }
+            if(tbodyId === 'combinedMedicationRecordTableBody'){
+                data.forEach(function(item, index) {
+                    var row = document.createElement('tr');
+                    // 序号
+                    var tdIndex = document.createElement('td');
+                    tdIndex.textContent = item.id;
+                    row.appendChild(tdIndex);
+                    // 1
+                    var durgName = document.createElement('td');
+                    durgName.textContent = item.hbdurgName;
+                    row.appendChild(durgName);
+
+                    // 2
+                    var jiliang = document.createElement('td');
+                    jiliang.textContent = item.hbjiliang;
+                    row.appendChild(jiliang);
+                    // 1
+                    var startyyTime = document.createElement('td');
+                    startyyTime.textContent = item.hbstartyyTime;
+                    row.appendChild(startyyTime);
+
+                    // 2
+                    var tyTime = document.createElement('td');
+                    tyTime.textContent = item.hbtyTime;
+                    row.appendChild(tyTime);
+                    // 1
+                    var lastsyTime = document.createElement('td');
+                    lastsyTime.textContent = item.hblastsyTime;
+                    row.appendChild(lastsyTime);
+
+                    // 2
+                    var shiypv = document.createElement('td');
+                    shiypv.textContent = item.shiypv;
+                    row.appendChild(shiypv);
+                    // 7
+                    var zhuyishix = document.createElement('td');
+                    zhuyishix.textContent = item.hbzhuyishix;
+                    row.appendChild(zhuyishix);
+
+                    // 操作(这里可以添加按钮或其他交互元素)
+                    var tdAction = document.createElement('td');
+                    // 示例: 添加一个删除按钮
+                    var deleteButton = document.createElement('button');
+                    deleteButton.textContent = '删除';
+                    deleteButton.onclick = function() { deleteRow(this); };
+                    tdAction.appendChild(deleteButton);
+                    row.appendChild(tdAction);
+
+                    tbody.appendChild(row);
+                    updateIndices(5);
+                });
+
+
+            }
+
+        }
+
+    }
+    function updateVisibility1() {
+        var weixinDiv = $('#weixin');
+        var mianfangDiv = $('#mianfang');
+
+        var selectedValue = $('input[name="returnMethod"]:checked').val();
+        if (selectedValue === '微信') {
+            weixinDiv.removeClass('hidden');
+            mianfangDiv.addClass('hidden');
+        } else if (selectedValue === '电话') {
+            weixinDiv.addClass('hidden');
+            mianfangDiv.addClass('hidden');
+        } else if (selectedValue === '面访') {
+            weixinDiv.addClass('hidden');
+            mianfangDiv.removeClass('hidden');
+        }
+    }
+
+    function updateVisibility2() {
+        var iscoordinate = $('input[name="iscoordinate"]:checked').val();
+        var stopForm = $('input[name="stopform"]:checked').val();
+        var iscoordinateDiv = $('#iscoordinateDiv');
+        var formAllArea = $('#tab-7-14')
+        var tab6 = $('#tab-6')
+        if (iscoordinate === '2') {
+            iscoordinateDiv.removeClass('hidden');
+        } else {
+            iscoordinateDiv.addClass('hidden');
+        }
+        if (iscoordinate === '2' && stopForm === '不填写完整表单') {
+            // 取消选中所有具有相同name属性的单选按钮
+            var radios2 = document.querySelectorAll('input[name="medicationStatus"]');
+            radios2.forEach(function (radio) {
+                radio.checked = false;
+            });
+            formAllArea.addClass('hidden');
+            tab6.addClass('hidden');
+        }else{
+            formAllArea.removeClass('hidden');
+            tab6.removeClass('hidden');
+        }
+
+    }
+
+    function updateVisibility3() {
+        //是否出现不良反应
+        var bulfydiv = $('#bulfydiv');
+        var hbyysfyiblfy = $('#hbyysfyiblfy');
+        var is_adverse_reaction = $('input[name="is_adverse_reaction"]:checked').val();
+        var combinedMedicationAdverseReaction = $('input[name="combinedMedicationAdverseReaction"]:checked').val();
+
+        if (is_adverse_reaction === '是') {
+            bulfydiv.removeClass('hidden');
+        }
+        if (is_adverse_reaction === '否') {
+            bulfydiv.addClass('hidden');
+        }
+
+        if (combinedMedicationAdverseReaction === '1') {
+            hbyysfyiblfy.removeClass('hidden');
+        }
+        if (combinedMedicationAdverseReaction === '2') {
+            hbyysfyiblfy.addClass('hidden');
+        }
+
+    }
+
+    function updateVisibility4() {
+        var csyzyy = $('#csyzyy');//慈善援助用药
+        var yjty = $('#yjty');//永久停药
+        var qtgyqgy = $('#qtgyqgy');//其他渠道购药
+        var ycgyycjy = $('#ycgyycjy');//延迟购药(医嘱建议)
+        var ycgyhzyybgf = $('#ycgyhzyybgf');//延迟购药(患者用药不规范
+        var formAllArea = $('#tab-7-14')
+        var medicationStatus = $('input[name="medicationStatus"]:checked').val();
+        var reasons_uncooperative = $('input[name="reasons_uncooperative"]:checked').val();
+        // if ((sensitiveValues.includes(reasons_uncooperative) || sensitiveValues.includes(medicationStatus))  && formCheck===true) {
+        //     // 设置标志位
+        //    TJFlag = true;
+        //    $('#TJ1').removeClass('hidden');
+        //    $('#TJ2').addClass('hidden');
+        // }else{
+        //     TJFlag = false;
+        //     $('#TJ1').addClass('hidden');
+        //     $('#TJ2').removeClass('hidden');
+        // }
+        if (medicationStatus === '持续购药') {
+            csyzyy.addClass('hidden');
+            yjty.addClass('hidden');
+            qtgyqgy.addClass('hidden');
+            ycgyycjy.addClass('hidden');
+            ycgyhzyybgf.addClass('hidden');
+            formAllArea.removeClass('hidden');
+        }
+        if (medicationStatus === '领取慈善赠药') {
+            csyzyy.removeClass('hidden');
+            yjty.addClass('hidden');
+            qtgyqgy.addClass('hidden');
+            ycgyycjy.addClass('hidden');
+            ycgyhzyybgf.addClass('hidden');
+            formAllArea.removeClass('hidden');
+        }
+        if (medicationStatus === '永久停药') {
+            yjty.removeClass('hidden');
+            csyzyy.addClass('hidden');
+            qtgyqgy.addClass('hidden');
+            ycgyycjy.addClass('hidden');
+            ycgyhzyybgf.addClass('hidden');
+        }
+        if (medicationStatus === '其他渠道购药') {
+            debugger;
+            qtgyqgy.removeClass('hidden');
+            yjty.addClass('hidden');
+            csyzyy.addClass('hidden');
+            ycgyycjy.addClass('hidden');
+            ycgyhzyybgf.addClass('hidden');
+            formAllArea.removeClass('hidden');
+        }
+        if (medicationStatus === '延迟用药(医嘱建议)') {
+            ycgyycjy.removeClass('hidden');
+            qtgyqgy.addClass('hidden');
+            yjty.addClass('hidden');
+            csyzyy.addClass('hidden');
+            ycgyhzyybgf.addClass('hidden');
+            formAllArea.removeClass('hidden');
+        }
+        if (medicationStatus === '延迟购药 (患者用药不规范)') {
+            ycgyhzyybgf.removeClass('hidden');
+            qtgyqgy.addClass('hidden');
+            yjty.addClass('hidden');
+            csyzyy.addClass('hidden');
+            ycgyycjy.addClass('hidden');
+            formAllArea.removeClass('hidden');
+        }
+
+        if (medicationStatus != '永久停药') {
+            $('input[name="stoped"]').prop('checked', false);
+        }
+    }
+    function updateVisibility4_1() {
+        var strategy_Div = $('#follow_up_planning_strategy_Div');//计划策略
+        var perpetual_stopdrug_cause = $('input[name="perpetual_stopdrug_cause"]:checked').val();
+        if (perpetual_stopdrug_cause === '离世') {
+            strategy_Div.removeClass('hidden');
+        }else{
+            strategy_Div.addClass('hidden');
+        }
+
+    }
+    function updateVisibility4_2() {
+        var strategy_fDiv = $('#follow_up_planning_strategy_form_Div');//计划策略
+        var perpetual_stopdrug_cause = $('input[name="perpetual_stopdrug_cause"]:checked').val();
+        if (perpetual_stopdrug_cause === '离世') {
+            strategy_fDiv.removeClass('hidden');
+        }else{
+            strategy_fDiv.addClass('hidden');
+        }
+
+    }
+    function updateVisibility5() {
+        //不填写完整表单
+        var formAllArea = $('#tab-7-14')
+        var tab6 = $('#tab-6')
+        var yjty = $('#yjty');//永久停药
+        var stoped = $('input[name="stoped"]:checked').val();
+        var stopForm = $('input[name="stopform"]:checked').val();
+
+        if (stoped === '不填写完整表单') {
+            formAllArea.addClass('hidden');
+        } else {
+            formAllArea.removeClass('hidden');
+        }
+        if (stoped === '不填写完整表单' || stopForm === '不填写完整表单') {
+            formAllArea.addClass('hidden');
+        } else {
+            formAllArea.removeClass('hidden');
+        }
+
+        if (stopForm === '不填写完整表单') {
+            // 取消选中所有具有相同name属性的单选按钮
+            var radios = document.querySelectorAll('input[name="medicationStatus"]');
+            radios.forEach(function (radio) {
+                radio.checked = false;
+            });
+            tab6.addClass('hidden');
+            yjty.addClass('hidden');
+            formAllArea.addClass('hidden');
+
+        }else{
+            tab6.removeClass('hidden');
+        }
+    }
+
+    function updateVisibility6() {
+        //原因
+        var drugsStatusDiv = $('#drugsStatusDiv');//用药状态调整
+        var flowNoDiv = $('#flowNoDiv');
+        var otherReasonDiv = $('#otherReasonDiv');
+        var drugsStopDiv = $('#drugsStopDiv');
+        var reason = $('input[name="reason"]:checked').val();//原因
+        var drugsStatus = $('input[name="drugsStatus"]:checked').val();//原因
+        if (reason === '用药状态调整') {
+            drugsStatusDiv.removeClass('hidden');
+        } else {
+            drugsStatusDiv.addClass('hidden');
+            drugsStopDiv.addClass('hidden');
+        }
+        if (reason === '随访不配合') {
+            flowNoDiv.removeClass('hidden');
+        } else {
+            flowNoDiv.addClass('hidden');
+        }
+        if (reason === '其他') {
+            otherReasonDiv.removeClass('hidden');
+        } else {
+            otherReasonDiv.addClass('hidden');
+        }
+
+        if (drugsStatus === '永久停药') {
+            drugsStopDiv.removeClass('hidden');
+        } else {
+            drugsStopDiv.addClass('hidden');
+        }
+        if (drugsStatus === '永久停药' && reason != '用药状态调整') {
+            drugsStopDiv.addClass('hidden');
+        }
+
+
+    }
+    function updateVisibility6_1() {
+        var drugsStop = $('input[name="drugsStop"]:checked').val();//永久关闭是否
+        var closeplan_isnoDiv = $('#closeplan_isnoDiv');
+        var closePlanScope = $('input[name="closePlanScope"]:checked').val();//范围 选中 仅关闭当前计划
+        if (drugsStop === '离世' && closePlanScope === '关闭患者当前的全部计划') {
+            closeplan_isnoDiv.removeClass('hidden');
+        }
+        if (closePlanScope === '关闭当前药品的全部计划') {
+            closeplan_isnoDiv.removeClass('hidden');
+        } else {
+            closeplan_isnoDiv.addClass('hidden');
+        }
+        if (closePlanScope === '关闭当前药品的全部计划') {
+            closeplan_isnoDiv.removeClass('hidden');
+        }else {
+            closeplan_isnoDiv.addClass('hidden');
+        }
+    }
+    function updateVisibility6_2() {
+        var specifiedTypeDiv = $('#specifiedTypeDiv');
+        var closeType = $('input[name="closeType"]:checked').val();//关闭类型 选中点击带过来的
+        debugger;
+        if (closeType === '指定类型') {
+            specifiedTypeDiv.removeClass('hidden');
+        }
+        if (closeType === '全部类型') {
+            specifiedTypeDiv.addClass('hidden');
+        }
+    }
+    function updateVisibility7() {
+        var isReview = $('input[name="isReview"]:checked').val();//
+        var isReviewDiv = $('#isReviewDiv');//
+        if (isReview === '1') {
+            isReviewDiv.removeClass('hidden');
+        } else {
+            isReviewDiv.addClass('hidden');
+        }
+    }
+
+    function updateVisibility8() {
+        var imagingInsuranceType = $('input[name="imagingInsuranceType"]:checked').map(function () {
+            return $(this).val();
+        }).get();
+        var ctradio = $('#ctradio');//
+        var bcradio = $('#bcradio');//
+        var hcradio = $('#hcradio');//
+        var qtradio = $('#qtradio');//
+        if (imagingInsuranceType.includes('CT')) {
+            ctradio.removeClass('hidden');
+        } else {
+            ctradio.addClass('hidden');
+        }
+        if (imagingInsuranceType.includes('B超')) {
+            bcradio.removeClass('hidden');
+        } else {
+            bcradio.addClass('hidden');
+        }
+        if (imagingInsuranceType.includes('核磁')) {
+            hcradio.removeClass('hidden');
+        } else {
+            hcradio.addClass('hidden');
+        }
+        if (imagingInsuranceType.includes('其他')) {
+            qtradio.removeClass('hidden');
+        } else {
+            qtradio.addClass('hidden');
+        }
+    }
+
+    function updateVisibility9() {
+        var clinicalInteraction = $('input[name="clinicalInteraction"]:checked').val();//
+        var clinicalInteractionDiv = $('#clinicalInteractionDiv');//
+        if (clinicalInteraction === '1') {
+            clinicalInteractionDiv.removeClass('hidden');
+        } else {
+            clinicalInteractionDiv.addClass('hidden');
+        }
+    }
+
+    function updateVisibility10() {
+        var unnecessaryRepeatedMedication = $('input[name="unnecessaryRepeatedMedication"]:checked').val();//
+        var unnecessaryRepeatedMedicationDiv = $('#unnecessaryRepeatedMedicationDiv');//
+        if (unnecessaryRepeatedMedication === '1') {
+            unnecessaryRepeatedMedicationDiv.removeClass('hidden');
+        } else {
+            unnecessaryRepeatedMedicationDiv.addClass('hidden');
+        }
+    }
+
+    function updateVisibility11() {
+        var medicationError = $('input[name="medicationError"]:checked').val();//
+        var medicationErrorDiv = $('#medicationErrorDiv');//
+        if (medicationError === '1') {
+            medicationErrorDiv.removeClass('hidden');
+        } else {
+            medicationErrorDiv.addClass('hidden');
+        }
+    }
+
+    function updateVisibility12() {
+        var isConsultation = $('input[name="isConsultation"]:checked').val();//
+        var isConsultationDiv = $('#isConsultationDiv');//
+        if (isConsultation === '1') {
+            isConsultationDiv.removeClass('hidden');
+        } else {
+            isConsultationDiv.addClass('hidden');
+        }
+    }
+
+    function updateVisibility13() {
+        var treatmentTypeDiv = $('#treatmentTypeDiv');//
+        var currentTreatmentPlanDiv = $('#currentTreatmentPlanDiv');//
+        var postProgressionTreatmentPlanDiv = $('#postProgressionTreatmentPlanDiv');//
+        // 获取所有选中的复选框的值 repeatedMedicationFirstUseDateDiv
+        var selectedValues = $('input[name="treatmentType"]:checked').map(function () {
+            return $(this).val();
+        }).get();
+        // 遍历所有可能的值并根据是否选中来显示或隐藏对应的 div
+        if (selectedValues.includes('用药前治疗方案')) {
+            treatmentTypeDiv.removeClass('hidden');
+        } else {
+            treatmentTypeDiv.addClass('hidden');
+        }
+        if (selectedValues.includes('目前治疗方案')) {
+            currentTreatmentPlanDiv.removeClass('hidden');
+        } else {
+            currentTreatmentPlanDiv.addClass('hidden');
+        }
+        if (selectedValues.includes('进展后治疗方案')) {
+            postProgressionTreatmentPlanDiv.removeClass('hidden');
+        } else {
+            postProgressionTreatmentPlanDiv.addClass('hidden');
+        }
+    }
+
+    function updateVisibility14() {
+        //全量表单控制
+        var tumorMarkerChecks = $('input[name="tumorMarkerCheck"]:checked').map(function () {
+            return $(this).val();
+        }).get();
+        var ceaDiv = $('#ceaDiv');
+        var afpDiv = $('#afpDiv');
+        var ca199Div = $('#ca199Div');
+        var ca125Div = $('#ca125Div');
+        var ca153Div = $('#ca153Div');
+        var hcgDiv = $('#hcgDiv');
+        var nseDiv = $('#nseDiv');
+        var cyfra211Div = $('#cyfra211Div');
+        var tgDiv = $('#tgDiv');
+        var psaDiv = $('#psaDiv');
+
+        // 遍历所有可能的值并根据是否选中来显示或隐藏对应的 div
+        if (tumorMarkerChecks.includes('CEA')) {
+            ceaDiv.removeClass('hidden');
+        } else {
+            ceaDiv.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('AFP')) {
+            afpDiv.removeClass('hidden');
+        } else {
+            afpDiv.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('CA-199')) {
+            ca199Div.removeClass('hidden');
+        } else {
+            ca199Div.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('CA125')) {
+            ca125Div.removeClass('hidden');
+        } else {
+            ca125Div.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('CA153')) {
+            ca153Div.removeClass('hidden');
+        } else {
+            ca153Div.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('HCG')) {
+            hcgDiv.removeClass('hidden');
+        } else {
+            hcgDiv.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('NSE')) {
+            nseDiv.removeClass('hidden');
+        } else {
+            nseDiv.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('CYFRA21-1')) {
+            cyfra211Div.removeClass('hidden');
+        } else {
+            cyfra211Div.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('TG')) {
+            tgDiv.removeClass('hidden');
+        } else {
+            tgDiv.addClass('hidden');
+        }
+        if (tumorMarkerChecks.includes('PSA')) {
+            psaDiv.removeClass('hidden');
+        } else {
+            psaDiv.addClass('hidden');
+        }
+
+    }
+    function handleCloseTypeChange(selectedRadio) {
+        const selectedValue = selectedRadio.value;
+
+        // 如果选择了“指定类型”,则展开指定类型部分
+        if (selectedValue === '指定类型') {
+            document.getElementById('specifiedTypeDiv').style.display = 'block';
+        } else {
+            document.getElementById('specifiedTypeDiv').style.display = 'none';
+        }
+
+        // 如果选择了“全部类型”,则勾选所有指定类型的复选框
+        if (selectedValue === '全部类型') {
+            specifiedTypeCheckboxes.forEach(checkbox => {
+                checkbox.checked = true;
+            });
+        } else {
+            specifiedTypeCheckboxes.forEach(checkbox => {
+                checkbox.checked = false;
+            });
+        }
+    }
+
+    function handleSpecifiedTypeChange() {
+        let anyChecked = false;
+        specifiedTypeCheckboxes.forEach(checkbox => {
+            if (checkbox.checked) {
+                anyChecked = true;
+            }
+        });
+
+        // 如果有任何一个指定类型的复选框被选中,则自动选中“指定类型”的单选按钮
+        if (anyChecked) {
+            closeTypeRadios.forEach(radio => {
+                if (radio.value === '指定类型') {
+                    radio.checked = true;
+                    document.getElementById('specifiedTypeDiv').style.display = 'block'; // 展开指定类型部分
+                }
+            });
+        }
+    }
+    function makeEditableIfLatest(cellValue, row) {
+        return (row.status != 1 || row.status != 7 || row.status != 8)? {
+            type: 'text',
+            title: '单次剂量',
+            validate: function (value) {
+                if ($.trim(value) === '') return '单次剂量不能为空';
+            }
+        } : false; // 如果不是最新的记录,则禁用编辑
+    }
+    function initializeTableForTab(tabId) {
+
+        var tableId = 'bootstrap-table-' + tabId.substring(4);
+        var tableElement = $('#' + tableId);
+
+        var data = {
+            "patientPhone": $('#phoneNumber').val(),
+            "patientName": $('#name').val(),
+            "id": $('#id').val(),
+            "flag": tabId.substring(4),
+        };
+        console.log("tabId=" + tabId.substring(4));
+        if (tabId === 'tab-2') {
+            //购药记录
+            var data2 = [];
+            data2 = recordsData;
+            var options = {
+                data: data2,
+                columns: [
+                    {field: 'id', title: 'ID', visible: false,align: 'center'},
+                    {field: 'mdmCode', title: '药品编码', visible: false,align: 'center'},
+                    {field: 'patientId', title: '患者ID', visible: false,align: 'center'},
+                    {field: 'storeId', title: '门店Id', visible: false,align: 'center'},
+                    {field: 'is_latest_registration', title: '标识',align: 'center'},
+                    {field: 'dvalueDays',title: 'D值用药天数', visible: false,align: 'center'},
+                    {field: 'salesOrderNumber', title: '销售单号',align: 'center'},
+                    {field: 'prescriptionNumber', title: '处方编号',align: 'center'},
+                    {field: 'prescriptionDate', title: '处方日期',align: 'center'},
+                    {field: 'hospital', title: '医院',align: 'center'},
+                    {field: 'prescribingDoctor', title: '处方医生',align: 'center'},
+                    {field: 'department', title: '科室', visible: false,align: 'center'},
+                    {field: 'attendingDoctor', title: '主管医生',align: 'center'},  // 注意这里使用的是 "attendingDoctor" 而不是 "attendingPhysician"
+                    {field: 'prescriptionDiagnosis', title: '处方诊断',align: 'center'},
+                    {field: 'genericName', title: '药品通用名',align: 'center'},
+                    // {field: 'productName', title: '商品名',align: 'center'},
+                    {field: 'specification', title: '规格',align: 'center'},
+                    {field: 'packageQuantity', title: '取药数量',align: 'center'},
+                    {
+                        field: 'singleDoseValue',align: 'center',
+                        title: '单次剂量', editable: function(cellValue, row) {
+                            if (row.status === 1 || row.status === 7 || row.status === 8 || row.type ===0) {
+                                return {disabled: true};
+                            } else {
+                                return {
+                                    validate: function (value) {
+                                        if ($.trim(value) === '') return '单次剂量不能为空';
+                                    }
+                                };
+                            }
+                        }
+
+                    },
+                    {
+                        field: 'singleDoseUnit',
+                        align: 'center',
+                        title: '单次剂量单位',
+                        editable: function(cellValue, row) {
+                            if (row.status === 1 || row.status === 7 || row.status === 8 || row.type ===0) {
+                                return {disabled: true};
+                            } else {
+                                return {
+                                    type: 'select',
+                                    source: [
+                                        "mg", "g", "μg", "L", "ml", "μL", "U", "IU", "T", "S",
+                                        "片", "丸", "粒", "支", "袋", "瓶", "盒", "板", "包", "小盒"
+                                    ],
+                                    title: '单次剂量单位',
+                                    validate: function (value) {
+                                        if ($.trim(value) === '') return '单次剂量单位不能为空';
+                                    }
+                                };
+                            }
+                        }
+                    },
+                    {
+                        field: 'dosageFrequency',
+                        title: '用药频次',
+                        align: 'center',
+                        editable: function(cellValue, row) {
+                            if (row.status === 1 || row.status === 7 || row.status === 8 || row.type ===0) {
+                                return {disabled: true};
+                            } else {
+                                return {
+                                    type: 'select',
+                                    source: dosageFrequencyOptions,
+                                    valueField: 'value',
+                                    textField: 'text',
+                                    validate: function (value) {
+                                        if ($.trim(value) === '') return '用药频次不能为空';
+                                    }
+                                };
+                            }
+                        }
+                    },
+                    {field: 'medicationRoute', title: '用药途径', visible: false,align: 'center'},
+                    {field: 'registrant', title: '登记人', visible: false,align: 'center'},
+                    {field: 'registrationDate', title: '登记日期', visible: false,align: 'center'},
+                    {field: 'saleDate', title: '销售日期', visible: false,align: 'center'},
+                    {mdmCode: 'mdmCode', title: '药品编码', visible: false,align: 'center'},
+                    {field: 'pharmacyName', title: '购药门店名称',align: 'center'},
+                    {
+                        field: 'actions',
+                        title: '操作',
+                        formatter: actionFormatter,
+                        events: window.actionEvents
+                    }
+                ]
+
+            };
+            if (Array.isArray(data2) && data2.length > 0) {
+                tableElement.bootstrapTable(options);
+            } else if (!Array.isArray(data2)) {
+                console.error('listTask1 is not a valid array:', data2);
+            } else {
+                console.log('No data available');
+            }
+
+        }
+        if (tabId === 'tab-3') {
+            // 目标容器 常规
+            var dataContainer = document.getElementById('cgsfnormal');
+            // 清空之前的旧数据
+            dataContainer.innerHTML = '';
+            // 目标容器 脱落
+            var tlzhback = document.getElementById('tlzhback');
+            // 清空之前的旧数据
+            tlzhback.innerHTML = '';
+            var listPlanCG = /*[[${planListCG}]]*/ [];
+            debugger;
+            // 确保 listPlanCG 是数组并且包含数据
+            if (Array.isArray(listPlanCG) && listPlanCG.length > 0) {
+                // 遍历每个计划
+                listPlanCG.forEach(function(plan, index) {
+                    // 创建一个新的div来放置每个计划的信息和任务表格
+                    var planDiv = $('<div class="plan-container"></div>');
+
+                    // 添加计划信息到planDiv中
+                    var planInfo = `<div class="plan-collapse-section">
+                        <!-- 折叠标题 -->
+                        <div class="plan-header"
+                             data-toggle="collapse"
+                             href="#collapsePlan${index}"
+                             role="button"
+                             aria-expanded="false"
+                             style="cursor: pointer; padding: 10px; background-color: #f5f5f5; border-bottom: 1px solid #ddd;">
+                            <i class="fa fa-chevron-right toggle-icon"></i>
+                            <span class="plan-title">
+                                ${plan.planName === undefined || plan.planName === null ? '未命名计划' : plan.planName}
+                            </span>
+                        </div>
+
+                        <!-- 折叠内容 -->
+                        <div class="collapse" id="collapsePlan${index}">
+                            <div class="row" style="padding-top: 10px;">
+                                <div class="ibox-content">
+                                    <div class="plan-info">
+                                        <div class="product-details">
+                                            <span class="product-name">
+                                                ${plan.planName === undefined || plan.planName === null ? '' : plan.planName}
+                                            </span>
+                                            <span class="specification">
+                                                ${plan.specification === undefined || plan.specification === null ? '' : plan.specification}
+                                            </span>
+                                        </div>
+                                        <div class="status-and-actions">
+                                            <span class="business-belonging">
+                                                <i class="glyphicon glyphicon-ice-lolly"></i> ${plan.businessBelonging}
+                                            </span>
+                                            <span class="status-tag status-${plan.status}">
+                                                ${plan.status === 0 ? '已关闭' : plan.status === 1 ? '进行中' : plan.status === 2 ? '已创建' : plan.status}
+                                            </span>
+                                            <!-- 根据状态决定是否显示关闭计划按钮 -->
+                                            <a href="#" class="btn-plan-action close-btn" data-toggle="modal" data-target="#myModalClosePlan" onclick="${plan.status !== 0 ? 'closePlan(' + (2, plan.id) + ')' : ''}">
+                                                ${plan.status === 1 ? '关闭计划' : plan.status === 2 ? '关闭计划' : ''}
+                                            </a>
+                                            <a href="#" class="btn-plan-action restart-btn" onclick="${plan.status === 0 ? 'RestartPlan(' + plan.id + ')' : ''}">
+                                                ${plan.status === 0 ? '重启计划' : ''}
+                                            </a>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="ibox-content">
+                                    <div class="creator-info">
+                                        <span class="label">创建人:</span>
+                                        <span class="value">${plan.createdBy === undefined || plan.createdBy === null ? '' : plan.createdBy}</span>
+
+                                        <span class="label">开始时间:</span>
+                                        <span class="value">${plan.createdTime === undefined || plan.createdTime === null ? '' : plan.createdTime}</span>
+
+                                        <span class="label">更新人:</span>
+                                        <span class="value">${plan.updatedBy === undefined || plan.updatedBy === null ? '' : plan.updatedBy}</span>
+
+                                        <span class="label">更新时间:</span>
+                                        <span class="value">${plan.updatedTime === undefined || plan.updatedTime === null ? '' : plan.updatedTime}</span>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="col-sm-12 select-table table-striped">
+                                    <table id="bootstrap-table-${index}" class="bootstrap-table-class"></table>
+                                </div>
+                            </div>
+                        </div>
+                    </div>`;
+                    planDiv.html(planInfo);
+
+                    // 将新创建的planDiv添加到cgsfnormal div中
+                    $('#cgsfnormal').append(planDiv);
+
+                    // 初始化任务表格
+                    var tableElement = $(`#bootstrap-table-${index}`);
+                    var data = plan.tasks; // 获取当前计划的任务列表
+
+                    var options = {
+                        data: data,
+                        fitColumns: true,
+                        striped: true,
+                        autoRowHeight: true,
+                        rowNumbers: true,
+                        showFooter: true,
+                        clickToSelect: true,
+                        singleSelect: false,
+                        //  fixedColumns: true,
+                        //  fixedRightNumber: 1,
+                        columns: [
+                            {field: 'id', title: '序号', align: 'center'},
+                            {field: 'taskName', title: '任务名称', align: 'center'},
+                            {field: 'taskTheme', title: '任务类型', align: 'center'},
+                            {field: 'appointmentDate', title: '预约时间', align: 'center'},
+                            {field: 'completionTime', title: '完成时间', align: 'center'},
+                            {field: 'taskFollower', title: '任务跟进人', align: 'center'},
+                            {field: 'taskStatus', title: '任务状态', align: 'center'},
+                            {
+                                title: '操作',
+                                align: 'center',
+                                width: '180px',
+                                formatter: function(value, row, index) {
+                                    if (row.id && !['已取消', '已完成','已过期','未下发'].includes(row.taskStatus)) {
+                                        return `<a class="btn-xs" href="javascript:void(0)" onclick="edit('${row.id}')">查看</a> ` +
+                                            `<a class="btn-xs" href="javascript:void(0)" onclick="closeTask('${row.id}')">关闭任务</a>`;
+                                    } else if (row.id && ['已取消', '已完成','已过期'].includes(row.taskStatus)) {
+                                        return `<a class="btn-xs" href="javascript:void(0)" onclick="edit('${row.id}')">查看</a>`;
+                                    } else {
+                                        return "";
+                                    }
+                                }
+                            }
+                        ]
+                    };
+
+                    tableElement.bootstrapTable(options);
+                });
+
+                $('#cgsfnormal').show();
+            }else {
+                $('#cgsfnormal').hide();
+            }
+            //88888
+
+            //66666
+            var listPlanTL = /*[[${planListTL}]]*/ [];
+
+            // 确保 listPlanCG 是数组并且包含数据
+            if (Array.isArray(listPlanTL) && listPlanTL.length > 0) {
+                // 遍历每个计划
+                listPlanTL.forEach(function(plan, index) {
+                    // 创建一个新的div来放置每个计划的信息和任务表格
+                    var planDiv = $('<div class="plan-container"></div>');
+
+                    // 添加计划信息到planDiv中
+                    var planInfo = `<div class="plan-collapse-section">
+                        <!-- 折叠标题 -->
+                        <div class="plan-header"
+                             data-toggle="collapse"
+                             href="#collapsePlan${index}"
+                             role="button"
+                             aria-expanded="false"
+                             style="cursor: pointer; padding: 10px; background-color: #f5f5f5; border-bottom: 1px solid #ddd;">
+                            <i class="fa fa-chevron-right toggle-icon"></i>
+                            <span class="plan-title">
+                                ${plan.planName === undefined || plan.planName === null ? '未命名计划' : plan.planName}
+                            </span>
+                        </div>
+
+                        <!-- 折叠内容 -->
+                        <div class="panel-body collapse" id="collapsePlan${index}">
+                            <div class="row" style="padding-top: 10px;">
+                                <div class="ibox-content">
+                                    <div class="plan-info">
+                                        <div class="product-details">
+                                            <span class="product-name">
+                                                ${plan.planName === undefined || plan.planName === null ? '' : plan.planName}
+                                            </span>
+                                            <span class="specification">
+                                                ${plan.specification === undefined || plan.specification === null ? '' : plan.specification}
+                                            </span>
+                                        </div>
+                                        <div class="status-and-actions">
+                                            <span class="business-belonging">
+                                                <i class="glyphicon glyphicon-ice-lolly"></i> ${plan.businessBelonging}
+                                            </span>
+                                            <span class="status-tag status-${plan.status}">
+                                                ${plan.status === 0 ? '已关闭' : plan.status === 1 ? '进行中' : plan.status === 2 ? '已创建' : plan.status}
+                                            </span>
+                                            <!-- 根据状态决定是否显示关闭计划按钮 -->
+                                            <a href="#" class="btn-plan-action close-btn" data-toggle="modal" data-target="#myModalClosePlan" onclick="${plan.status !== 0 ? 'closePlan(' + (2, plan.id) + ')' : ''}">
+                                                ${plan.status === 1 ? '关闭计划' : plan.status === 2 ? '关闭计划' : ''}
+                                            </a>
+                                            <a href="#" class="btn-plan-action restart-btn" onclick="${plan.status === 0 ? 'RestartPlan(' + plan.id + ')' : ''}">
+                                                ${plan.status === 0 ? '重启计划' : ''}
+                                            </a>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="ibox-content">
+                                    <div class="creator-info">
+                                        <span class="label">创建人:</span>
+                                        <span class="value">${plan.createdBy === undefined || plan.createdBy === null ? '' : plan.createdBy}</span>
+
+                                        <span class="label">开始时间:</span>
+                                        <span class="value">${plan.createdTime === undefined || plan.createdTime === null ? '' : plan.createdTime}</span>
+
+                                        <span class="label">更新人:</span>
+                                        <span class="value">${plan.updatedBy === undefined || plan.updatedBy === null ? '' : plan.updatedBy}</span>
+
+                                        <span class="label">更新时间:</span>
+                                        <span class="value">${plan.updatedTime === undefined || plan.updatedTime === null ? '' : plan.updatedTime}</span>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="col-sm-12 select-table table-striped">
+                                    <table id="bootstrap-table-${index}" class="bootstrap-table-class"></table>
+                                </div>
+                            </div>
+                        </div>
+                    </div>`;
+                    planDiv.html(planInfo);
+
+                    // 将新创建的planDiv添加到cgsfnormal div中
+                    $('#tlzhback').append(planDiv);
+
+                    // 初始化任务表格
+                    var tableElement = $(`#bootstrap-table-${index}`);
+                    var data = plan.tasks; // 获取当前计划的任务列表
+
+                    var options = {
+                        data: data,
+                        fitColumns: true,
+                        striped: true,
+                        autoRowHeight: true,
+                        rowNumbers: true,
+                        showFooter: true,
+                        clickToSelect: true,
+                        singleSelect: false,
+                        //  fixedColumns: true,
+                        // fixedRightNumber: 1,
+                        columns: [
+                            {field: 'id', title: '序号', align: 'center'},
+                            {field: 'taskName', title: '任务名称', align: 'center'},
+                            {field: 'taskTheme', title: '任务类型', align: 'center'},
+                            {field: 'appointmentDate', title: '预约时间', align: 'center'},
+                            {field: 'completionTime', title: '完成时间', align: 'center'},
+                            {field: 'taskFollower', title: '任务跟进人', align: 'center'},
+                            {field: 'taskStatus', title: '任务状态', align: 'center'},
+                            {
+                                title: '操作',
+                                align: 'center',
+                                width: '180px',
+                                formatter: function(value, row, index) {
+                                    if (row.id && !['已取消', '已完成','已过期','未下发'].includes(row.taskStatus)) {
+                                        return `<a class="btn-xs" href="javascript:void(0)" onclick="edit('${row.id}')">查看</a> ` +
+                                            `<a class="btn-xs" href="javascript:void(0)" onclick="closeTask('${row.id}')">关闭任务</a>`;
+                                    } else if (row.id && ['已取消', '已完成','已过期'].includes(row.taskStatus)) {
+                                        return `<a class="btn-xs" href="javascript:void(0)" onclick="edit('${row.id}')">查看</a>`;
+                                    } else {
+                                        return "";
+                                    }
+                                }
+                            }
+                        ]
+                    };
+
+                    tableElement.bootstrapTable(options);
+                });
+
+                $('#tlzhback').show();
+            }else {
+                $('#tlzhback').hide();
+            }
+
+
+        }
+    }
+
+    // 定义操作列的事件处理
+    window.actionEvents = {
+        'click .save': function (e, value, row, index) {
+            saveDrug(row, index);
+        }
+    };
+
+    // 定义操作列的格式化函数
+    function actionFormatter(value, row, index) {
+        // 检查 dvalueDays 是否小于 0
+        if (row.dvalueDays !== undefined && parseFloat(row.dvalueDays) < 0) {
+            return '<span class="expired-label">已过期</span>';
+        }
+        if (row.status === 1 || row.status === 7 || row.status === 8 || row.type === 0) {
+            return '';
+        } else {
+            return '<button class="save ml10 btn btn-success btn-xs" type="button">保存</button>';
+        }
+        // // 如果 dvalueDays >= 0,则返回保存按钮
+        // return [
+        //     '<button class="save ml10 btn btn-success btn-xs" type="button">保存</button>'
+        // ].join('');
+    }
+
+    // 定义保存药品记录的方法
+    function saveDrug(row, index) {
+        // 查找对应的 dictLabel 和 dictValue 并添加到 row 对象中
+        var option = dosageFrequencyLookup[row.dosageFrequency];
+        if (option) {
+            row.dosageFrequencyLabel = option.label; // 添加 dictLabel 到 row 对象中
+            row.dosageFrequencyValue = option.value; // 添加 dictValue 到 row 对象中
+        } else {
+            row.dosageFrequencyLabel = ''; // 或者设置为默认值
+            row.dosageFrequencyValue = ''; // 或者设置为默认值
+        }
+
+        // 发送 AJAX 请求更新数据
+        $.ajax({
+            cache: true,
+            type: "POST",
+            url: ctx + "dtp/pmService/updateDrugPurchaseRecord",
+            data: row,
+            async: false,
+            success: function (data) {
+                $.modal.msg("保存成功");
+                // 刷新页面数据
+                refreshData(data.data);
+            },
+            error: function (error) {
+                $.modal.msg("更新失败");
+            }
+        });
+    };
+
+    function editArchives() {
+        var id = $("#patientId").val();
+        // table.set();
+        var prefix = ctx + "dtp/pmService/archivesEdit/{id}";
+        $.modal.openTab("修改档案", prefix.replace("{id}", id));
+    }
+
+    // 关闭计划  提交关闭原因
+    function submitClosePlan() {
+        var reason = $('input[name="reason"]:checked').val(); // 原因
+        if (reason==='' || reason===null) {
+            $.modal.alert("请选择关闭原因");
+            return;
+        }
+        var closePlanScope = $('input[name="closePlanScope"]:checked').val(); // 原因
+        if (closePlanScope==='' || closePlanScope===null) {
+            $.modal.alert("请选择关闭关闭范围");
+            return;
+        }
+        var closeType = $('input[name="closeType"]:checked').val(); // 原因
+        if (closeType==='' || closeType===null || closeType===undefined) {
+            $.modal.alert("请选择关闭类型");
+            return;
+        }
+
+        var drugsStatus = $('input[name="drugsStatus"]:checked').val(); // 用药状态调整为
+        // 检查是否需要显示确认弹框
+        var needsConfirmation = (reason === '电话号码错误' || drugsStatus === '领取慈善赠药');
+        if (needsConfirmation) {
+            $.modal.confirm("确认要关闭计划吗? 若关闭计划,同时关闭此任务", function () {
+                executeClosePlan();
+            });
+        } else {
+            executeClosePlan();
+        }
+    }
+
+    function executeClosePlan() {
+        // 获取指定类型的选中值 常规随访 脱落召回
+        var specifiedType = [];
+        $('input[name="specifiedType"]:checked').each(function () {
+            specifiedType.push($(this).val());
+        });
+        var taskId, planId_cg, planId_tl, patientId, mdmCode_cg, mdmCode_tl;
+        // 根据选中的指定类型设置相应的planId
+        specifiedType.forEach(function (type) {
+            if (type === '常规随访') {
+                planId_cg = planId_close;
+                mdmCode_cg = $("#mdmCode_cg").val();
+            } else if (type === '脱落召回') {
+                planId_tl = planId_close;
+                mdmCode_tl = $("#mdmCode_tl").val();
+            }
+        });
+        patientId = $("#patientId").val();
+        taskId = $("#id").val();
+
+        // 收集所有非隐藏的表单项
+        var formData = new FormData();
+        $('#ClosePlanForm').find(':not(.hidden)').find('input, select, radio,checkbox,textarea').each(function() {
+            var $this = $(this);
+            if ($this.is(':radio')) {
+                if ($this.is(':checked')) {
+                    formData.append($this.attr('name'), $this.val());
+                }
+            } else if ($this.is(':checkbox')) {
+                if ($this.is(':checked')) {
+                    formData.append($this.attr('name'), $this.val());
+                }
+            } else if ($this.attr('type') !== 'submit' && $this.attr('type') !== 'button') {
+                formData.append($this.attr('name'), $this.val());
+            }
+        });
+
+        // 添加额外的参数
+        formData.append('taskId', taskId);
+        formData.append('planId_cg', planId_close || '');
+        formData.append('planId_cg', planId_close || '');
+        formData.append('planId', planId_close || '');
+        formData.append('mdmCode_tl', mdmCode_tl || '');
+        formData.append('mdmCode_cg', mdmCode_cg || '');
+        formData.append('mdmCode', mdmCode || '');
+        formData.append('patientId', patientId);
+
+        // 如果有指定类型被选中,添加到formData
+        if (specifiedType.length > 0) {
+            formData.append('specifiedType', specifiedType.join(','));
+        }
+
+        console.log(formData);
+
+        $.ajax({
+            url: prefix_task + "/closePlan",
+            data: formData,
+            method: 'POST',
+            processData: false, // 防止 jQuery 自动转换数据
+            contentType: false, // 不设置内容类型
+            dataType: 'json',
+            error: function (data) {
+                $.modal.alertError("关闭计划失败");
+                flag = true;
+            },
+            success: function(data) {
+                if(data.code==0){
+                    flagStatus = true;
+                    if(flagStatus && flagStatus2 != 1){
+                        console.log("flagStatus="+flagStatus);
+                        submitHandler()
+                    }
+                    window.location.reload();
+                    $.modal.alertSuccess("关闭计划成功");
+                    updateTabState('#tab-3');
+                    flag=false;
+                }else{
+                    $.modal.alertError("关闭计划失败");
+                    flag=true;
+                }
+
+            }
+        });
+
+        if (flag == false) {
+            $('#myModalClosePlan').hide();
+        } else {
+            $('#myModalClosePlan').show();
+        }
+    }
+
+    /* 去关联 */
+    function correlation(id) {
+        //弹框做操作
+        // $.modal.confirm("确认要启用用户吗?", function() {
+        //     $.operate.post(prefix + "/toCorrelation", { "id": id, "status": 1 });
+        // })
+        onclick = "$.operate.edit(\'' + row.id + '\')"
+        var options = {
+            title: '添加复购品',
+            url: prefix + "/toCorrelation" + id,
+            callBack: doSubmit2
+        };
+        $.modal.openOptions(options);
+    }
+
+    // 关闭计划
+    function closePlan(planFlag, planId) {
+        closePlanFlag = planFlag;
+        flagStatus2 = 1;
+        var taskId;
+
+        if (planFlag === 1) {
+            taskId = $("#id").val();
+            planId_close = planId;
+            mdmCode = $("#mdmCode_cg").val();
+            // 设置默认选中的选项
+            $('input[name="closeType"][value="指定类型"]').prop('checked', true);
+            $('input[name="specifiedType"][value="常规随访"]').prop('checked', true);
+        } else if (planFlag === 2) {
+            $('input[name="closeType"][value="指定类型"]').prop('checked', true);
+            $('input[name="specifiedType"][value="脱落召回"]').prop('checked', true);
+            taskId = $("#id").val();
+            planId_close = planId;
+            mdmCode = $("#mdmCode_tl").val();
+        }
+        // updateVisibility4_1();
+        $('#myModalClosePlan').show();
+        $('input[name="closePlanScope"][value="仅关闭当前计划"]').prop('checked', true);
+        // 更新界面元素的可见性
+        updateVisibility6_1();
+        updateVisibility6_2();
+        updateVisibility6();
+
+    }
+    //重启计划
+    function RestartPlan(planFlagStart){
+
+        debugger;
+
+        if (planFlag === 1) {
+            taskId = $("#id").val();
+            planId = $("#planId_cg").val();
+            mdmCode = $("#mdmCode_cg").val();
+            // 设置默认选中的选项
+            $('input[name="closeType"][value="指定类型"]').prop('checked', true);
+            $('input[name="specifiedType"][value="常规随访"]').prop('checked', true);
+        } else if (planFlag === 2) {
+            $('input[name="closeType"][value="指定类型"]').prop('checked', true);
+            $('input[name="specifiedType"][value="脱落召回"]').prop('checked', true);
+            taskId = $("#id").val();
+            planId = $("#planId_tl").val();
+            mdmCode = $("#mdmCode_tl").val();
+        }
+        patientId = $("#patientId").val();
+        var formData = new FormData();
+        formData.append('taskId', taskId);
+        formData.append('planId', planId);
+        formData.append('mdmCode', mdmCode);
+        formData.append('patientId', patientId);
+        formData.append('planFlag', planFlag);
+        $.modal.confirm("确认要关闭任务吗? 关闭任务后将停止该任务的随访操作", function () {
+            $.ajax({
+                url: prefix_task + "/RestartPlan",
+                data: formData,
+                method: 'POST',
+                processData: false, // 防止 jQuery 自动转换数据
+                contentType: false, // 不设置内容类型
+                success: function (data) {
+                    $.modal.alertSuccess("重启计划成功");
+                    window.location.reload();
+                },
+                error: function (xhr, status, error) {
+                    $.modal.alertError("重启计划失败");
+                }
+            });
+        });
+    }
+    // 关闭任务
+    function closeTask(id) {
+        $.modal.confirm("确认要关闭任务吗? 关闭任务后将停止该任务的随访操作", function () {
+            var formData = new FormData();
+            formData.append('id', id);
+
+            $.ajax({
+                url: prefix_task + "/closeTask",
+                data: formData,
+                method: 'POST',
+                processData: false, // 防止 jQuery 自动转换数据
+                contentType: false, // 不设置内容类型
+                success: function (data) {
+                    $.modal.alertSuccess("关闭任务成功");
+                    // $.modal.reload();
+                    window.location.reload();
+                },
+                error: function (xhr, status, error) {
+                    $.modal.alertError("关闭任务失败");
+                }
+            });
+        });
+    }
+
+    // 辅助函数:用于更新选项卡状态
+    function updateTabState(tabId) {
+        // 移除所有 li 的 active 类
+        $('#myUlTabs .nav-item').removeClass('active');
+        // 设置指定 tab 的 li 为 active
+        $(tabId).closest('.nav-tabs').find('a[href="' + tabId + '"]').parent().addClass('active');
+
+        // 更新 a 标签的 aria-expanded 属性
+        $('#myUlTabs a').attr('aria-expanded', 'false');
+        $(tabId).closest('.nav-tabs').find('a[href="' + tabId + '"]').attr('aria-expanded', 'true');
+
+        // 移除所有 tab-pane 的 active 和 in 类
+        $('.tab-pane').removeClass('active in show'); // 注意这里使用了 'show' 类,取决于你使用的 Bootstrap 版本
+        // 为指定 tab-pane 添加 active 和 in 类
+        $(tabId).addClass('active in show'); // 同上,确保与你的 Bootstrap 版本匹配
+    }
+
+    function editSFGenJinRen() {
+        //随访计划跟进人
+        var followUpPersonId = /*[[${followUpPersonId}]]*/ '';
+        var followUpPersonName = /*[[${followUpPersonName}]]*/ '';
+        // $.operate.addSetwht('分配跟进人','dtp/pmService/followUpAssignAdd',800,800)
+        //var followUpPersonId=$('#followUpPersonId').val()
+        //alert("编辑随访跟进人"+followUpPersonId);
+        var options = {
+            title: '分配跟进人',
+            width: 800,
+            height: 600,
+            url: prefix + '/followUpAssignAdd',
+            callBack: doSubmit2
+        };
+        $.modal.openOptions(options);
+    }
+    function createPlan() {
+        //随访计划跟进人
+        var followUpPersonId = /*[[${followUpPersonId}]]*/ '';
+        var followUpPersonName = /*[[${followUpPersonName}]]*/ '';
+        // $.operate.addSetwht('分配跟进人','dtp/pmService/followUpAssignAdd',800,800)
+        //var followUpPersonId=$('#followUpPersonId').val()
+        //alert("编辑随访跟进人"+followUpPersonId);
+        var options = {
+            title: '创建计划',
+            width: 1000,
+            height: 600,
+            url: prefix_task + '/createPlanPage',//createPlan
+            callBack: doSubmitPlan
+        };
+        $.modal.openOptions(options);
+    }
+    function doSubmitPlan(index, layero) {
+        var hzparam;
+        var rows = layero.find("iframe")[0].contentWindow.selectTableObject();
+        if (rows.length == 0) {
+            $.modal.alertWarning("请至少选择一条记录");
+            return;
+        }
+        rows.forEach(function (item) {
+            // 动态选择所有列并映射到更具描述性的名称
+            hzparam = {
+                id: item.id,
+                templateId: item.templateId,
+                templateName: item.templateName,
+                businessBelonging: item.businessBelonging,
+                drug: item.drug,
+                nodeId: item.nodeId,
+                model: item.model,
+                storeId: item.storeId,
+                patientId:  $("#patientId").val(),
+                patientName:  $("#name").val(),
+                gender:  $("#genderv").val(),
+                age:  $("#age").val(),
+            };
+
+        });
+        $.ajax({
+            cache: true,
+            type: "POST",
+            url: prefix_task + '/createPlanAdd', // 创建计划
+            data: hzparam,
+            async: false,
+            success: function (data) {
+                $.modal.alertSuccess(data.msg);
+            },
+            error: function (error) {
+                $.modal.alertError("失败");
+            }
+        });
+        $.modal.close(index);
+    }
+    // callBack获取父窗口方法(方式二)
+    function doSubmit2(index, layero) {
+        var hzparam;
+        var rows = layero.find("iframe")[0].contentWindow.selectTableObject();
+        if (rows.length == 0) {
+            $.modal.alertWarning("请至少选择一条记录");
+            return;
+        }
+        var followUpPersonId = $('#followUpPersonId').val();//s_dtp_ysfw_follow_up_assign
+        rows.forEach(function (item) {
+            // 动态选择所有列并映射到更具描述性的名称
+            hzparam = {
+                id: item.id,
+                pharmacistName: item.pharmacistName,
+                position: item.position,
+                storeName: item.storeName,
+                phone: item.phone,
+                storeId: item.storeId,
+                followUpPersonId: followUpPersonId
+            };
+
+        });
+        $.ajax({
+            cache: true,
+            type: "POST",
+            url: prefix + '/editFollowUpAssign', // 替换为实际的搜索 URL
+            data: hzparam,
+            async: false,
+            success: function (data) {
+                $.modal.msg("操作成功");
+                // 更新 <code> 标签的内容
+                var followUpPersonName = hzparam.pharmacistName; // 假设需要第一个对象的 pharmacistName
+                $('#followUpPersonNameCode').text(followUpPersonName);
+                $('#followUpPersonName').val(followUpPersonName); // 更新输入框的值
+
+            },
+            error: function (error) {
+                $.modal.alertError("失败");
+            }
+        });
+        $.modal.close(index);
+    }
+
+    function editTaskGenJinRen() {
+        //任务跟进人
+
+        var options = {
+            title: '分配跟进人',
+            width: 800,
+            height: 600,
+            url: prefix + '/followUpAssignAdd',
+            callBack: doSubmit1
+        };
+        $.modal.openOptions(options);
+    }
+
+    function doSubmit1(index, layero) {
+        var bc_id = $('#bc_id').val()
+        var hzparam;
+        var rows = layero.find("iframe")[0].contentWindow.selectTableObject();
+        if (rows.length == 0) {
+            $.modal.alertWarning("请至少选择一条记录");
+            return;
+        }
+        rows.forEach(function (item) {
+            // 动态选择所有列并映射到更具描述性的名称
+            hzparam = {
+                id: item.id,
+                pharmacistName: item.pharmacistName,
+                position: item.position,
+                storeName: item.storeName,
+                phone: item.phone,
+                storeId: item.storeId,
+                taskId: bc_id
+            };
+
+        });
+        $.ajax({
+            cache: true,
+            type: "POST",
+            url: prefix + '/editFollowTaskAssignById', // 替换为实际的搜索 URL
+            data: hzparam,
+            async: false,
+            success: function (data) {
+                $.modal.msg("操作成功");
+                // 更新 <code> 标签的内容
+                var followUpPersonName = hzparam.pharmacistName; // 假设需要第一个对象的 pharmacistName
+                $('#bc_taskFollowerCode').text(followUpPersonName);
+                $('#bc_taskFollower').val(followUpPersonName); // 更新输入框的值
+
+            },
+            error: function (error) {
+                $.modal.alertError("失败");
+            }
+        });
+        $.modal.close(index);
+    }
+
+
+    function updateInterval(nextFollowTimeStr) {
+        // 获取当前时间
+        const now = new Date();
+        if (nextFollowTimeStr) {
+            // 将字符串转换为日期对象
+            const nextFollowTime = new Date(nextFollowTimeStr);
+
+            // 计算间隔天数
+            const intervalDays = Math.floor((nextFollowTime - now) / (1000 * 60 * 60 * 24));
+
+            // 显示间隔天数
+            const intervalThisTimeSpan = $('#interval_this_time');
+            if (intervalDays < 0) {
+                intervalThisTimeSpan.css('color', 'red').text(intervalDays);
+            } else {
+                intervalThisTimeSpan.css('color', '#1a7bb9').text(intervalDays);
+            }
+        } else {
+            // 如果没有选择下次随访时间,清除间隔天数显示
+            const intervalThisTimeSpan = $('#interval_this_time');
+            intervalThisTimeSpan.text('');
+        }
+    }
+
+    function onselectsf() {
+        // 初始化时检查是否有预设的下次随访时间
+        const initialNextFollowTime = $('#next_follow_time').val();
+        if (initialNextFollowTime) {
+            $('#next_follow_time').val(initialNextFollowTime);
+            updateInterval(initialNextFollowTime);
+        }
+    }
+</script>

+ 78 - 0
health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/add.html

@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <th:block th:include="include :: header('新增随访模版')" />
+</head>
+<body class="white-bg">
+<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+    <form class="form-horizontal m" id="form-template-add">
+        <div class="form-group">
+            <label class="col-sm-3 control-label is-required">模版名称:</label>
+            <div class="col-sm-8">
+                <input name="templateName" class="form-control" type="text" maxlength="100" required>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">模版描述:</label>
+            <div class="col-sm-8">
+                <textarea name="templateDesc" class="form-control" rows="3" maxlength="500"></textarea>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label is-required">模版类型:</label>
+            <div class="col-sm-8">
+                <select name="templateType" class="form-control" required>
+                    <option value="">请选择模版类型</option>
+                    <option value="custom">自定义</option>
+                    <option value="default">系统默认</option>
+                </select>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">状态:</label>
+            <div class="col-sm-8">
+                <div class="radio-box">
+                    <input type="radio" id="status1" name="status" value="1" checked>
+                    <label for="status1">启用</label>
+                </div>
+                <div class="radio-box">
+                    <input type="radio" id="status0" name="status" value="0">
+                    <label for="status0">禁用</label>
+                </div>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">适用业务:</label>
+            <div class="col-sm-8">
+                <select name="businessType" class="form-control">
+                    <option value="">请选择适用业务</option>
+                    <option value="常规随访">常规随访</option>
+                    <option value="脱落召回">脱落召回</option>
+                    <option value="不良反应">不良反应</option>
+                    <option value="用药指导">用药指导</option>
+                </select>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">备注:</label>
+            <div class="col-sm-8">
+                <textarea name="remark" class="form-control" rows="2" maxlength="200"></textarea>
+            </div>
+        </div>
+    </form>
+</div>
+<th:block th:include="include :: footer" />
+<script type="text/javascript">
+    var prefix = ctx + "gxhpz/followTemplateConfig/add";
+    $("#form-template-add").validate({
+        focusCleanup: true
+    });
+
+    function submitHandler() {
+        if ($.validate.form()) {
+            $.operate.save(prefix, $('#form-template-add').serialize());
+        }
+    }
+</script>
+</body>
+</html>

+ 219 - 0
health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/addField.html

@@ -0,0 +1,219 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <th:block th:include="include :: header('添加字段')" />
+    <th:block th:include="include :: select2-css" />
+</head>
+<body class="white-bg">
+<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+    <form class="form-horizontal m" id="form-field-add">
+        <input type="hidden" name="templateId" th:value="${templateId}">
+
+        <div class="form-group">
+            <label class="col-sm-3 control-label is-required">选择字段:</label>
+            <div class="col-sm-8">
+                <select name="fieldCode" class="form-control select2" required>
+                    <option value="">请选择字段</option>
+                    <optgroup th:each="entry : ${fieldsByTab}" th:label="${entry.key}">
+                        <option th:each="field : ${entry.value}"
+                                th:value="${field.fieldCode}"
+                                th:data-field-name="${field.fieldName}"
+                                th:data-field-type="${field.fieldType}"
+                                th:data-tab-code="${field.tabCode}"
+                                th:data-tab-name="${field.tabName}">
+                            [[${field.fieldName}]] ([[${field.fieldType}]])
+                        </option>
+                    </optgroup>
+                </select>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label class="col-sm-3 control-label">字段名称:</label>
+            <div class="col-sm-8">
+                <input name="fieldName" class="form-control" type="text" readonly>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label class="col-sm-3 control-label">字段类型:</label>
+            <div class="col-sm-8">
+                <input name="fieldType" class="form-control" type="text" readonly>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label class="col-sm-3 control-label">所属Tab:</label>
+            <div class="col-sm-8">
+                <input name="tabName" class="form-control" type="text" readonly>
+                <input name="tabCode" type="hidden">
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label class="col-sm-3 control-label">是否必填:</label>
+            <div class="col-sm-8">
+                <div class="radio-box">
+                    <input type="radio" id="isRequired1" name="isRequired" value="1">
+                    <label for="isRequired1">是</label>
+                </div>
+                <div class="radio-box">
+                    <input type="radio" id="isRequired0" name="isRequired" value="0" checked>
+                    <label for="isRequired0">否</label>
+                </div>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label class="col-sm-3 control-label">显示顺序:</label>
+            <div class="col-sm-8">
+                <input name="displayOrder" class="form-control" type="number" value="1" min="1" required>
+            </div>
+        </div>
+
+        <div class="form-group">
+            <label class="col-sm-3 control-label">占位符:</label>
+            <div class="col-sm-8">
+                <input name="placeholder" class="form-control" type="text" placeholder="请输入占位符文本">
+            </div>
+        </div>
+
+        <div class="form-group" id="fieldOptionsGroup" style="display: none;">
+            <label class="col-sm-3 control-label">字段选项:</label>
+            <div class="col-sm-8">
+                <div id="fieldOptions">
+                    <!-- 动态生成选项 -->
+                </div>
+                <button type="button" class="btn btn-sm btn-primary" onclick="addOption()">
+                    <i class="fa fa-plus"></i> 添加选项
+                </button>
+            </div>
+        </div>
+    </form>
+</div>
+
+<th:block th:include="include :: footer" />
+<th:block th:include="include :: select2-js" />
+<script th:inline="javascript">
+    var availableFields = [[${availableFields}]];
+    var fieldsByTab = {};
+
+    $(function() {
+        // 初始化select2
+        $('.select2').select2();
+
+        // 处理字段数据
+        availableFields.forEach(function(field) {
+            if (!fieldsByTab[field.tabName]) {
+                fieldsByTab[field.tabName] = [];
+            }
+            fieldsByTab[field.tabName].push(field);
+        });
+
+        // 字段选择变化事件
+        $('select[name="fieldCode"]').change(function() {
+            var selectedOption = $(this).find('option:selected');
+            var fieldName = selectedOption.data('field-name');
+            var fieldType = selectedOption.data('field-type');
+            var tabCode = selectedOption.data('tab-code');
+            var tabName = selectedOption.data('tab-name');
+
+            $('input[name="fieldName"]').val(fieldName);
+            $('input[name="fieldType"]').val(fieldType);
+            $('input[name="tabCode"]').val(tabCode);
+            $('input[name="tabName"]').val(tabName);
+
+            // 根据字段类型显示/隐藏选项配置
+            if (fieldType === 'radio' || fieldType === 'checkbox' || fieldType === 'select') {
+                $('#fieldOptionsGroup').show();
+                loadDefaultOptions(fieldType);
+            } else {
+                $('#fieldOptionsGroup').hide();
+            }
+
+            // 设置默认占位符
+            var defaultPlaceholder = '';
+            if (fieldType === 'input' || fieldType === 'textarea') {
+                defaultPlaceholder = '请输入' + fieldName;
+            } else if (fieldType === 'select') {
+                defaultPlaceholder = '请选择' + fieldName;
+            } else if (fieldType === 'datetime') {
+                defaultPlaceholder = '请选择日期时间';
+            }
+            $('input[name="placeholder"]').val(defaultPlaceholder);
+        });
+
+        $("#form-field-add").validate({
+            focusCleanup: true
+        });
+    });
+
+    // 加载默认选项
+    function loadDefaultOptions(fieldType) {
+        var html = '';
+        var defaultOptions = ['选项1', '选项2', '选项3'];
+
+        defaultOptions.forEach(function(option, index) {
+            html += '<div class="option-item" style="margin-bottom: 5px;">';
+            html += '  <input type="text" class="form-control input-sm" style="width: 200px; display: inline-block;" ';
+            html += '         name="fieldOption" value="' + option + '" placeholder="选项文本">';
+            html += '  <button type="button" class="btn btn-sm btn-danger" onclick="removeOption(this)" style="margin-left: 5px;">';
+            html += '    <i class="fa fa-minus"></i>';
+            html += '  </button>';
+            html += '</div>';
+        });
+
+        $('#fieldOptions').html(html);
+    }
+
+    // 添加选项
+    function addOption() {
+        var html = '<div class="option-item" style="margin-bottom: 5px;">';
+        html += '  <input type="text" class="form-control input-sm" style="width: 200px; display: inline-block;" ';
+        html += '         name="fieldOption" placeholder="选项文本">';
+        html += '  <button type="button" class="btn btn-sm btn-danger" onclick="removeOption(this)" style="margin-left: 5px;">';
+        html += '    <i class="fa fa-minus"></i>';
+        html += '  </button>';
+        html += '</div>';
+
+        $('#fieldOptions').append(html);
+    }
+
+    // 删除选项
+    function removeOption(btn) {
+        $(btn).closest('.option-item').remove();
+    }
+
+    function submitHandler() {
+        if ($.validate.form()) {
+            var formData = $('#form-field-add').serializeArray();
+            var data = {};
+
+            // 处理表单数据
+            formData.forEach(function(item) {
+                if (item.name === 'fieldOption') {
+                    if (!data.fieldOptions) {
+                        data.fieldOptions = [];
+                    }
+                    if (item.value) {
+                        data.fieldOptions.push(item.value);
+                    }
+                } else {
+                    data[item.name] = item.value;
+                }
+            });
+
+            // 将选项数组转换为JSON字符串
+            if (data.fieldOptions && data.fieldOptions.length > 0) {
+                data.fieldOptions = JSON.stringify(data.fieldOptions);
+            }
+
+            // 设置默认值
+            data.isEnabled = 1;
+
+            $.operate.save(ctx + "gxhpz/followTemplateConfig/saveField", data);
+        }
+    }
+</script>
+</body>
+</html>

+ 97 - 0
health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/edit.html

@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <th:block th:include="include :: header('修改随访模版')" />
+</head>
+<body class="white-bg">
+<div class="wrapper wrapper-content animated fadeInRight ibox-content">
+    <form class="form-horizontal m" id="form-template-edit" th:object="${template}">
+        <input name="id" th:value="${id}" type="hidden">
+        <div class="form-group">
+            <label class="col-sm-3 control-label is-required">模版名称:</label>
+            <div class="col-sm-8">
+                <input name="templateName" th:value="${templateName}" class="form-control" type="text" maxlength="100" required>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">模版描述:</label>
+            <div class="col-sm-8">
+                <textarea name="templateDesc" th:text="${templateDesc}" class="form-control" rows="3" maxlength="500"></textarea>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label is-required">模版类型:</label>
+            <div class="col-sm-8">
+                <select name="templateType" class="form-control" required>
+                    <option value="">请选择模版类型</option>
+                    <option value="custom" th:selected="${templateType} == 'custom'">自定义</option>
+                    <option value="default" th:selected="${templateType} == 'default'">系统默认</option>
+                </select>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">状态:</label>
+            <div class="col-sm-8">
+                <div class="radio-box">
+                    <input type="radio" id="status1" name="status" value="1" th:checked="${status} == 1">
+                    <label for="status1">启用</label>
+                </div>
+                <div class="radio-box">
+                    <input type="radio" id="status0" name="status" value="0" th:checked="${status} == 0">
+                    <label for="status0">禁用</label>
+                </div>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">适用业务:</label>
+            <div class="col-sm-8">
+                <select name="businessType" class="form-control">
+                    <option value="">请选择适用业务</option>
+                    <option value="常规随访" th:selected="${businessType} eq '常规随访'">常规随访</option>
+                    <option value="脱落召回" th:selected="${businessType} eq '脱落召回'">脱落召回</option>
+                    <option value="不良反应" th:selected="${businessType} eq '不良反应'">不良反应</option>
+                    <option value="用药指导" th:selected="${businessType} eq '用药指导'">用药指导</option>
+                </select>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">备注:</label>
+            <div class="col-sm-8">
+                <textarea name="remark" th:text="${remark}" class="form-control" rows="2" maxlength="200"></textarea>
+            </div>
+        </div>
+        <div class="form-group">
+            <label class="col-sm-3 control-label">创建信息:</label>
+            <div class="col-sm-8">
+                <div class="form-control-static">
+                    创建人:<span th:text="${createdBy}"></span> |
+                    创建时间:<span th:text="${createdTime}"></span>
+                </div>
+            </div>
+        </div>
+        <div class="form-group" th:if="${updatedBy}">
+            <label class="col-sm-3 control-label">更新信息:</label>
+            <div class="col-sm-8">
+                <div class="form-control-static">
+                    更新人:<span th:text="${updatedBy}"></span> |
+                    更新时间:<span th:text="${updatedTime}"></span>
+                </div>
+            </div>
+        </div>
+    </form>
+</div>
+<th:block th:include="include :: footer" />
+<script type="text/javascript">
+    var prefix = ctx + "gxhpz/followTemplateConfig/edit";
+    $("#form-template-edit").validate({
+        focusCleanup: true
+    });
+
+    function submitHandler() {
+        if ($.validate.form()) {
+            $.operate.save(prefix, $('#form-template-edit').serialize());
+        }
+    }
+</script>
+</body>
+</html>

+ 632 - 0
health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/fields.html

@@ -0,0 +1,632 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('字段配置')" />
+    <style>
+        .field-config-container {
+            display: flex;
+            height: 600px;
+        }
+
+        .available-fields {
+            width: 45%;
+            border: 1px solid #ddd;
+            padding: 10px;
+            margin-right: 10px;
+        }
+
+        .selected-fields {
+            width: 45%;
+            border: 1px solid #ddd;
+            padding: 10px;
+            margin-left: 10px;
+        }
+
+        .field-transfer-buttons {
+            width: 10%;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+        }
+
+        .field-item {
+            padding: 8px;
+            margin: 2px 0;
+            border: 1px solid #e7eaec;
+            background-color: #fff;
+            cursor: pointer;
+            user-select: none;
+        }
+
+        .field-item:hover {
+            background-color: #f1f1f1;
+        }
+
+        .field-item.selected {
+            background-color: #1ab394;
+            color: white;
+        }
+
+        .field-item .field-name {
+            font-weight: bold;
+        }
+
+        .field-item .field-info {
+            font-size: 12px;
+            color: #666;
+        }
+
+        .tab-fields {
+            margin-bottom: 20px;
+        }
+
+        .tab-header {
+            background-color: #f5f5f5;
+            padding: 10px;
+            border-left: 3px solid #1ab394;
+            margin-bottom: 10px;
+            font-weight: bold;
+        }
+
+        .field-list {
+            max-height: 150px;
+            overflow-y: auto;
+        }
+
+        .btn-transfer {
+            margin: 5px;
+            width: 60px;
+        }
+
+        .field-config-form {
+            margin-top: 20px;
+            padding: 15px;
+            border: 1px solid #ddd;
+            background-color: #f9f9f9;
+        }
+
+        .config-tabs {
+            margin-bottom: 20px;
+        }
+
+        .tab-checkbox {
+            margin-right: 10px;
+        }
+    </style>
+</head>
+<body class="gray-bg">
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-sm-12">
+            <div class="ibox">
+                <div class="ibox-title">
+                    <h5>模版字段配置 - <span th:text="${template.templateName}"></span></h5>
+                    <div class="ibox-tools">
+                        <button class="btn btn-primary btn-sm" onclick="saveConfig()">
+                            <i class="fa fa-save"></i> 保存配置
+                        </button>
+                        <button class="btn btn-default btn-sm" onclick="resetConfig()">
+                            <i class="fa fa-refresh"></i> 重置
+                        </button>
+                    </div>
+                </div>
+
+                <div class="ibox-content">
+                    <!-- Tab配置区域 -->
+                    <div class="config-tabs">
+                        <h4>Tab页配置</h4>
+                        <div class="row">
+                            <div class="col-sm-12">
+                                <div class="checkbox-group">
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-4" checked disabled> 本次任务 (必选)
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-6" name="enabledTabs"> 用药依从性
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-7" name="enabledTabs"> 药物安全性
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-8" name="enabledTabs"> 药物有效性
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-9" name="enabledTabs"> 治疗方案
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-10" name="enabledTabs"> 适宜性评估
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-11" name="enabledTabs"> 用药记录
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-12" name="enabledTabs"> 量表测评
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-13" name="enabledTabs"> 患者咨询
+                                    </label>
+                                    <label class="tab-checkbox">
+                                        <input type="checkbox" value="tab-14" name="enabledTabs"> 其他
+                                    </label>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <hr>
+
+                    <!-- 字段配置区域 -->
+                    <div class="field-config-container">
+                        <div class="available-fields">
+                            <h4>可用字段</h4>
+                            <div id="availableFieldsList"></div>
+                        </div>
+
+                        <div class="field-transfer-buttons">
+                            <button class="btn btn-primary btn-transfer" onclick="addFields()">
+                                <i class="fa fa-angle-right"></i>
+                            </button>
+                            <button class="btn btn-primary btn-transfer" onclick="addAllFields()">
+                                <i class="fa fa-angle-double-right"></i>
+                            </button>
+                            <button class="btn btn-default btn-transfer" onclick="removeFields()">
+                                <i class="fa fa-angle-left"></i>
+                            </button>
+                            <button class="btn btn-default btn-transfer" onclick="removeAllFields()">
+                                <i class="fa fa-angle-double-left"></i>
+                            </button>
+                        </div>
+
+                        <div class="selected-fields">
+                            <h4>已选字段</h4>
+                            <div id="selectedFieldsList"></div>
+                        </div>
+                    </div>
+
+                    <!-- 字段属性配置 -->
+                    <div class="field-config-form" id="fieldConfigForm" style="display: none;">
+                        <h4>字段属性配置</h4>
+                        <form id="fieldPropertyForm">
+                            <div class="row">
+                                <div class="col-sm-6">
+                                    <div class="form-group">
+                                        <label>字段名称:</label>
+                                        <input type="text" class="form-control" name="fieldName" readonly>
+                                    </div>
+                                </div>
+                                <div class="col-sm-6">
+                                    <div class="form-group">
+                                        <label>字段编码:</label>
+                                        <input type="text" class="form-control" name="fieldCode" readonly>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="col-sm-6">
+                                    <div class="form-group">
+                                        <label>是否必填:</label>
+                                        <select class="form-control" name="isRequired">
+                                            <option value="0">否</option>
+                                            <option value="1">是</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="col-sm-6">
+                                    <div class="form-group">
+                                        <label>显示顺序:</label>
+                                        <input type="number" class="form-control" name="displayOrder" min="1">
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="col-sm-12">
+                                    <div class="form-group">
+                                        <label>占位符:</label>
+                                        <input type="text" class="form-control" name="placeholder">
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="row">
+                                <div class="col-sm-12">
+                                    <button type="button" class="btn btn-primary" onclick="updateFieldProperty()">
+                                        更新字段属性
+                                    </button>
+                                </div>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<th:block th:include="include :: footer" />
+<script th:inline="javascript">
+    var templateId = [[${templateId}]];
+    var availableFields = [];
+    var selectedFields = [];
+    var currentField = null;
+
+    $(function() {
+        loadAvailableFields();
+        loadSelectedFields();
+        bindEvents();
+    });
+
+    // 加载可用字段
+    function loadAvailableFields() {
+        $.ajax({
+            url: ctx + "gxhpz/followTemplateConfig/getAvailableFields",
+            type: "GET",
+            success: function(result) {
+                if (result.code == 0) {
+                    availableFields = result.data;
+                    renderAvailableFields();
+                }
+            }
+        });
+    }
+
+    // 加载已选字段
+    function loadSelectedFields() {
+        $.ajax({
+            url: ctx + "gxhpz/followTemplateConfig/fieldList",
+            type: "POST",
+            data: { templateId: templateId },
+            success: function(result) {
+                if (result.code == 0) {
+                    selectedFields = result.data;
+                    renderSelectedFields();
+                    loadTabConfig();
+                }
+            }
+        });
+    }
+
+    // 加载Tab配置
+    function loadTabConfig() {
+        var enabledTabs = new Set();
+        selectedFields.forEach(function(field) {
+            enabledTabs.add(field.tabCode);
+        });
+
+        $('input[name="enabledTabs"]').each(function() {
+            if (enabledTabs.has($(this).val())) {
+                $(this).prop('checked', true);
+            }
+        });
+    }
+
+    // 渲染可用字段
+    function renderAvailableFields() {
+        var html = '';
+        var fieldsByTab = {};
+
+        // 按Tab分组
+        availableFields.forEach(function(field) {
+            if (!fieldsByTab[field.tabCode]) {
+                fieldsByTab[field.tabCode] = [];
+            }
+            fieldsByTab[field.tabCode].push(field);
+        });
+
+        // 渲染每个Tab的字段
+        Object.keys(fieldsByTab).forEach(function(tabCode) {
+            var tabName = fieldsByTab[tabCode][0].tabName;
+            html += '<div class="tab-fields">';
+            html += '<div class="tab-header">' + tabName + '</div>';
+            html += '<div class="field-list">';
+
+            fieldsByTab[tabCode].forEach(function(field) {
+                // 检查是否已选中
+                var isSelected = selectedFields.some(function(selected) {
+                    return selected.fieldCode === field.fieldCode;
+                });
+
+                if (!isSelected) {
+                    html += '<div class="field-item" data-field-code="' + field.fieldCode + '">';
+                    html += '<div class="field-name">' + field.fieldName + '</div>';
+                    html += '<div class="field-info">' + field.fieldType + ' | ' + field.tabName + '</div>';
+                    html += '</div>';
+                }
+            });
+
+            html += '</div></div>';
+        });
+
+        $('#availableFieldsList').html(html);
+    }
+
+    // 渲染已选字段
+    function renderSelectedFields() {
+        var html = '';
+        var fieldsByTab = {};
+
+        // 按Tab分组
+        selectedFields.forEach(function(field) {
+            if (!fieldsByTab[field.tabCode]) {
+                fieldsByTab[field.tabCode] = [];
+            }
+            fieldsByTab[field.tabCode].push(field);
+        });
+
+        // 渲染每个Tab的字段
+        Object.keys(fieldsByTab).forEach(function(tabCode) {
+            var tabName = fieldsByTab[tabCode][0].tabName;
+            html += '<div class="tab-fields">';
+            html += '<div class="tab-header">' + tabName + '</div>';
+            html += '<div class="field-list">';
+
+            fieldsByTab[tabCode].sort(function(a, b) {
+                return a.displayOrder - b.displayOrder;
+            }).forEach(function(field) {
+                html += '<div class="field-item selected-field" data-field-code="' + field.fieldCode + '">';
+                html += '<div class="field-name">' + field.fieldName;
+                if (field.isRequired == 1) {
+                    html += ' <span style="color: red;">*</span>';
+                }
+                html += '</div>';
+                html += '<div class="field-info">' + field.fieldType + ' | 顺序: ' + field.displayOrder + '</div>';
+                html += '</div>';
+            });
+
+            html += '</div></div>';
+        });
+
+        $('#selectedFieldsList').html(html);
+    }
+
+    // 绑定事件
+    function bindEvents() {
+        // 字段选择事件
+        $(document).on('click', '.field-item', function() {
+            $('.field-item').removeClass('selected');
+            $(this).addClass('selected');
+
+            var fieldCode = $(this).data('field-code');
+
+            // 如果是已选字段,显示配置表单
+            if ($(this).hasClass('selected-field')) {
+                showFieldConfig(fieldCode);
+            }
+        });
+
+        // Tab配置变化事件
+        $('input[name="enabledTabs"]').change(function() {
+            var tabCode = $(this).val();
+            var isEnabled = $(this).is(':checked');
+
+            if (!isEnabled) {
+                // 移除该Tab下的所有字段
+                selectedFields = selectedFields.filter(function(field) {
+                    return field.tabCode !== tabCode;
+                });
+                renderSelectedFields();
+                renderAvailableFields();
+            }
+        });
+    }
+
+    // 添加字段
+    function addFields() {
+        var selectedItems = $('.available-fields .field-item.selected');
+        if (selectedItems.length === 0) {
+            $.modal.alertWarning("请选择要添加的字段");
+            return;
+        }
+
+        selectedItems.each(function() {
+            var fieldCode = $(this).data('field-code');
+            var field = availableFields.find(function(f) {
+                return f.fieldCode === fieldCode;
+            });
+
+            if (field) {
+                field.templateId = templateId;
+                field.displayOrder = selectedFields.filter(function(f) {
+                    return f.tabCode === field.tabCode;
+                }).length + 1;
+                selectedFields.push(field);
+            }
+        });
+
+        renderSelectedFields();
+        renderAvailableFields();
+    }
+
+    // 添加所有字段
+    function addAllFields() {
+        var enabledTabs = getEnabledTabs();
+
+        availableFields.forEach(function(field) {
+            if (enabledTabs.includes(field.tabCode)) {
+                var isAlreadySelected = selectedFields.some(function(selected) {
+                    return selected.fieldCode === field.fieldCode;
+                });
+
+                if (!isAlreadySelected) {
+                    field.templateId = templateId;
+                    field.displayOrder = selectedFields.filter(function(f) {
+                        return f.tabCode === field.tabCode;
+                    }).length + 1;
+                    selectedFields.push(field);
+                }
+            }
+        });
+
+        renderSelectedFields();
+        renderAvailableFields();
+    }
+
+    // 移除字段
+    function removeFields() {
+        var selectedItems = $('.selected-fields .field-item.selected');
+        if (selectedItems.length === 0) {
+            $.modal.alertWarning("请选择要移除的字段");
+            return;
+        }
+
+        selectedItems.each(function() {
+            var fieldCode = $(this).data('field-code');
+            selectedFields = selectedFields.filter(function(field) {
+                return field.fieldCode !== fieldCode;
+            });
+        });
+
+        renderSelectedFields();
+        renderAvailableFields();
+        $('#fieldConfigForm').hide();
+    }
+
+    // 移除所有字段
+    function removeAllFields() {
+        selectedFields = selectedFields.filter(function(field) {
+            return field.tabCode === 'tab-4'; // 保留本次任务的必选字段
+        });
+
+        renderSelectedFields();
+        renderAvailableFields();
+        $('#fieldConfigForm').hide();
+    }
+
+    // 获取启用的Tab
+    function getEnabledTabs() {
+        var tabs = ['tab-4']; // 本次任务是必选的
+        $('input[name="enabledTabs"]:checked').each(function() {
+            tabs.push($(this).val());
+        });
+        return tabs;
+    }
+
+    // 显示字段配置
+    function showFieldConfig(fieldCode) {
+        var field = selectedFields.find(function(f) {
+            return f.fieldCode === fieldCode;
+        });
+
+        if (field) {
+            currentField = field;
+            $('input[name="fieldName"]').val(field.fieldName);
+            $('input[name="fieldCode"]').val(field.fieldCode);
+            $('select[name="isRequired"]').val(field.isRequired || 0);
+            $('input[name="displayOrder"]').val(field.displayOrder || 1);
+            $('input[name="placeholder"]').val(field.placeholder || '');
+
+            $('#fieldConfigForm').show();
+        }
+    }
+
+    // 更新字段属性
+    function updateFieldProperty() {
+        if (!currentField) return;
+
+        currentField.isRequired = $('select[name="isRequired"]').val();
+        currentField.displayOrder = parseInt($('input[name="displayOrder"]').val()) || 1;
+        currentField.placeholder = $('input[name="placeholder"]').val();
+
+        renderSelectedFields();
+        $.modal.alertSuccess("字段属性更新成功");
+    }
+
+    // 保存配置
+    // 保存配置
+    function saveConfig() {
+        // 验证Tab配置
+        var enabledTabs = getEnabledTabs();
+        if (enabledTabs.length === 0) {
+            $.modal.alertWarning("至少要启用一个Tab页");
+            return;
+        }
+
+        // 验证是否有选中的字段
+        if (selectedFields.length === 0) {
+            $.modal.alertWarning("请至少选择一个字段");
+            return;
+        }
+
+        // 保存Tab配置
+        var tabConfig = enabledTabs.map(function(tabCode, index) {
+            var tabName = '';
+            switch(tabCode) {
+                case 'tab-4': tabName = '本次任务'; break;
+                case 'tab-6': tabName = '用药依从性'; break;
+                case 'tab-7': tabName = '药物安全性'; break;
+                case 'tab-8': tabName = '药物有效性'; break;
+                case 'tab-9': tabName = '治疗方案'; break;
+                case 'tab-10': tabName = '适宜性评估'; break;
+                case 'tab-11': tabName = '用药记录'; break;
+                case 'tab-12': tabName = '量表测评'; break;
+                case 'tab-13': tabName = '患者咨询'; break;
+                case 'tab-14': tabName = '其他'; break;
+            }
+            return {
+                tabCode: tabCode,
+                tabName: tabName,
+                displayOrder: index + 1,
+                isEnabled: 1
+            };
+        });
+
+        // 过滤出启用Tab下的字段
+        var fieldsToSave = selectedFields.filter(function(field) {
+            return enabledTabs.includes(field.tabCode);
+        });
+
+        // 重新整理字段的displayOrder
+        var fieldsByTab = {};
+        fieldsToSave.forEach(function(field) {
+            if (!fieldsByTab[field.tabCode]) {
+                fieldsByTab[field.tabCode] = [];
+            }
+            fieldsByTab[field.tabCode].push(field);
+        });
+
+        // 为每个Tab的字段重新排序
+        Object.keys(fieldsByTab).forEach(function(tabCode) {
+            fieldsByTab[tabCode].sort(function(a, b) {
+                return (a.displayOrder || 0) - (b.displayOrder || 0);
+            });
+            fieldsByTab[tabCode].forEach(function(field, index) {
+                field.displayOrder = index + 1;
+            });
+        });
+
+        var data = {
+            templateId: templateId,
+            tabConfig: JSON.stringify(tabConfig),
+            fieldConfig: JSON.stringify(fieldsToSave)
+        };
+
+        $.modal.loading("正在保存,请稍候...");
+        $.ajax({
+            url: ctx + "gxhpz/followTemplateConfig/saveConfig",
+            type: "POST",
+            data: data,
+            success: function(result) {
+                $.modal.closeLoading();
+                if (result.code == 0) {
+                    $.modal.alertSuccess("保存成功");
+                    // 重新加载配置
+                    loadSelectedFields();
+                } else {
+                    $.modal.alertError(result.msg);
+                }
+            },
+            error: function() {
+                $.modal.closeLoading();
+                $.modal.alertError("保存失败,请重试");
+            }
+        });
+    }
+
+    // 重置配置
+    function resetConfig() {
+        $.modal.confirm("确认要重置配置吗?", function() {
+            location.reload();
+        });
+    }
+</script>
+</body>
+</html>

+ 288 - 0
health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/followTemplateConfig.html

@@ -0,0 +1,288 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('随访模版配置')" />
+    <th:block th:include="include :: bootstrap-select-css" />
+    <th:block th:include="include :: bootstrap-select-js" />
+    <th:block th:include="include :: bootstrap-fileinput-css" />
+    <th:block th:include="include :: bootstrap-fileinput-js" />
+    <th:block th:include="include :: select2-css" />
+    <th:block th:include="include :: bootstrap-fileinput-css" />
+</head>
+<body class="gray-bg">
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-sm-12 search-collapse">
+            <form id="formId">
+                <div class="select-list">
+                    <ul>
+                        <li>
+                            模版名称:<input type="text" name="templateName"/>
+                        </li>
+                        <li>
+                            状态:
+                            <select name="status" th:with="type=${@dict.getType('sys_normal_disable')}">
+                                <option value="">所有</option>
+                                <option th:each="dict : ${type}" th:text="${dict.dictLabel}" th:value="${dict.dictValue}"></option>
+                            </select>
+                        </li>
+                        <li>
+                            <a class="btn btn-primary btn-rounded btn-sm" onclick="$.table.search()">
+                                <i class="fa fa-search"></i>&nbsp;搜索
+                            </a>
+                            <a class="btn btn-warning btn-rounded btn-sm" onclick="$.form.reset()">
+                                <i class="fa fa-refresh"></i>&nbsp;重置
+                            </a>
+                        </li>
+                    </ul>
+                </div>
+            </form>
+        </div>
+
+        <div class="btn-group-sm" id="toolbar" role="group">
+            <a class="btn btn-success" onclick="$.operate.add()" shiro:hasPermission="gxhpz:followTemplate:add">
+                <i class="fa fa-plus"></i> 添加
+            </a>
+            <a class="btn btn-primary single disabled" onclick="$.operate.edit()" shiro:hasPermission="gxhpz:followTemplate:edit">
+                <i class="fa fa-edit"></i> 修改
+            </a>
+            <a class="btn btn-danger multiple disabled" onclick="$.operate.removeAll()" shiro:hasPermission="gxhpz:followTemplate:remove">
+                <i class="fa fa-remove"></i> 删除
+            </a>
+            <a class="btn btn-info single disabled" onclick="configFields()" shiro:hasPermission="gxhpz:followTemplate:field">
+                <i class="fa fa-cog"></i> 字段配置
+            </a>
+            <a class="btn btn-warning single disabled" onclick="configRules()" shiro:hasPermission="gxhpz:followTemplate:rule">
+                <i class="fa fa-gear"></i> 规则配置
+            </a>
+            <a class="btn btn-success single disabled" onclick="copyTemplate()" shiro:hasPermission="gxhpz:followTemplate:add">
+                <i class="fa fa-copy"></i> 复制模版
+            </a>
+        </div>
+
+        <div class="col-sm-12 select-table table-striped">
+            <table id="bootstrap-table"></table>
+        </div>
+    </div>
+</div>
+
+<!-- 复制模版弹窗 -->
+<div class="modal fade" id="copyTemplateModal" tabindex="-1" role="dialog">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+                <h4 class="modal-title">复制模版</h4>
+            </div>
+            <div class="modal-body">
+                <form id="copyTemplateForm">
+                    <div class="form-group">
+                        <label>新模版名称:</label>
+                        <input type="text" class="form-control" name="templateName" required>
+                        <input type="hidden" name="sourceTemplateId">
+                    </div>
+                    <div class="form-group">
+                        <label>状态:</label>
+                        <select class="form-control" name="status">
+                            <option value="1">启用</option>
+                            <option value="0">禁用</option>
+                        </select>
+                    </div>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-primary" onclick="submitCopyTemplate()">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<th:block th:include="include :: footer" />
+
+<script th:inline="javascript">
+    var prefix = ctx + "gxhpz/followTemplateConfig";
+    var editFlag = [[${@permission.hasPermi('gxhpz:followTemplate:edit')}]];
+    var removeFlag = [[${@permission.hasPermi('gxhpz:followTemplate:remove')}]];
+    var fieldFlag = [[${@permission.hasPermi('gxhpz:followTemplate:field')}]];
+    var ruleFlag = [[${@permission.hasPermi('gxhpz:followTemplate:rule')}]];
+
+    $(function() {
+        var options = {
+            url: prefix + "/list",
+            createUrl: prefix + "/add",
+            viewUrl: prefix + "/preview/{id}",
+            updateUrl: prefix + "/edit/{id}",
+            removeUrl: prefix + "/remove",
+            exportUrl: prefix + "/export",
+            modalName: "随访模版配置",
+            columns: [{
+                checkbox: true
+            },
+                {
+                    field: 'id',
+                    title: '模版ID',
+                    visible: false
+                },
+                {
+                    field: 'templateName',
+                    title: '模版名称'
+                },
+                {
+                    field: 'templateDesc',
+                    title: '模版描述'
+                },
+                {
+                    field: 'templateType',
+                    title: '模版类型',
+                    formatter: function(value, row, index) {
+                        if (value == 'default') {
+                            return '<span class="label label-primary">系统默认</span>';
+                        } else {
+                            return '<span class="label label-info">自定义</span>';
+                        }
+                    }
+                },
+                {
+                    field: 'status',
+                    title: '状态',
+                    formatter: function(value, row, index) {
+                        // 自定义字典转换函数
+                        const dictMap = {
+                            '0': '禁用',
+                            '1': '启用'
+                        };
+                        return dictMap[value] || value; // 匹配失败返回原值
+                    }
+                },
+                {
+                    field: 'createdBy',
+                    title: '创建人'
+                },
+                {
+                    field: 'createdTime',
+                    title: '创建时间'
+                },
+                {
+                    title: '操作',
+                    align: 'center',
+                    formatter: function(value, row, index) {
+                        var actions = [];
+
+                        actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="$.operate.view(' + row.id + ')"><i class="fa fa-eye"></i> 预览</a>');
+
+                        if (editFlag) {
+                            actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="$.operate.edit(\'' + row.id + '\')"><i class="fa fa-edit"></i> 编辑</a>');
+                        }
+
+                        if (fieldFlag) {
+                            actions.push('<a class="btn btn-info btn-xs" href="javascript:void(0)" onclick="configFields(' + row.id + ')"><i class="fa fa-cog"></i> 字段配置</a>');
+                        }
+
+                        if (ruleFlag) {
+                            actions.push('<a class="btn btn-warning btn-xs" href="javascript:void(0)" onclick="configRules(' + row.id + ')"><i class="fa fa-gear"></i> 规则配置</a>');
+                        }
+
+                        if (row.status == '1') {
+                            actions.push('<a class="btn btn-danger btn-xs" href="javascript:void(0)" onclick="changeStatus(' + row.id + ', 0)"><i class="fa fa-ban"></i> 禁用</a>');
+                        } else {
+                            actions.push('<a class="btn btn-success btn-xs" href="javascript:void(0)" onclick="changeStatus(' + row.id + ', 1)"><i class="fa fa-check"></i> 启用</a>');
+                        }
+
+                        return actions.join(' ');
+                    }
+                }]
+        };
+        $.table.init(options);
+    });
+
+    // 字段配置
+    function configFields(id) {
+        if (typeof id === 'undefined') {
+            var rows = $.table.selectFirstColumns();
+            if (rows.length == 0) {
+                $.modal.alertWarning("请选择一条记录");
+                return;
+            }
+            id = rows[0];
+        }
+        var url = ctx + 'gxhpz/followTemplateConfig/fields/' + id;
+        $.modal.openTab("字段配置", url);
+    }
+
+    // 规则配置
+    function configRules(id) {
+        if (typeof id === 'undefined') {
+            var rows = $.table.selectFirstColumns();
+            if (rows.length == 0) {
+                $.modal.alertWarning("请选择一条记录");
+                return;
+            }
+            id = rows[0];
+        }
+        var url = ctx + 'gxhpz/followTemplateConfig/rules/' + id;
+        $.modal.openTab("规则配置", url);
+    }
+
+    // 复制模版
+    function copyTemplate() {
+        var rows = $.table.selectFirstColumns();
+        if (rows.length == 0) {
+            $.modal.alertWarning("请选择一条记录");
+            return;
+        }
+
+        $("input[name='sourceTemplateId']").val(rows[0]);
+        $("#copyTemplateModal").modal('show');
+    }
+
+    // 提交复制模版
+    function submitCopyTemplate() {
+        var data = $("#copyTemplateForm").serialize();
+        $.ajax({
+            url: prefix + "/copy",
+            type: "post",
+            data: data,
+            success: function(result) {
+                if (result.code == 0) {
+                    $.modal.alertSuccess("复制成功");
+                    $("#copyTemplateModal").modal('hide');
+                    $.table.refresh();
+                } else {
+                    $.modal.alertError(result.msg);
+                }
+            }
+        });
+    }
+
+    // 更改状态
+    function changeStatus(id, status) {
+        var statusText = status == 1 ? "启用" : "禁用";
+        $.modal.confirm("确认要" + statusText + "该模版吗?", function() {
+            $.ajax({
+                url: prefix + "/changeStatus",
+                type: "post",
+                data: {
+                    id: id,
+                    status: status
+                },
+                success: function(result) {
+                    if (result.code == 0) {
+                        $.modal.alertSuccess(statusText + "成功");
+                        $.table.refresh();
+                    } else {
+                        $.modal.alertError(result.msg);
+                    }
+                }
+            });
+        });
+    }
+
+    // 预览模版
+    function preview(id) {
+        var url = ctx + 'gxhpz/followTemplateConfig/preview/' + id;
+        $.modal.openTab("模版预览", url);
+    }
+</script>
+</body>
+</html>

+ 406 - 0
health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/preview.html

@@ -0,0 +1,406 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <th:block th:include="include :: header('模版预览')" />
+    <th:block th:include="include :: layout-latest-css" />
+    <th:block th:include="include :: select2-css" />
+    <style type="text/css">
+        .preview-container {
+            background-color: #f5f5f5;
+            padding: 20px;
+            margin: 10px 0;
+            border: 2px dashed #1ab394;
+            border-radius: 5px;
+        }
+
+        .preview-header {
+            background-color: #1ab394;
+            color: white;
+            padding: 10px 15px;
+            margin: -20px -20px 20px -20px;
+            font-size: 16px;
+            font-weight: bold;
+        }
+
+        .template-info {
+            background-color: #fff;
+            padding: 15px;
+            margin-bottom: 20px;
+            border-radius: 5px;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+        }
+
+        .customize-form-group {
+            margin-bottom: 15px;
+            display: flex;
+            align-items: center;
+        }
+
+        .customize-form-group label {
+            width: 200px;
+            text-align: right;
+            margin-right: 10px;
+            font-weight: bold;
+        }
+
+        .customize-form-group.is-required label::after {
+            content: " *";
+            color: red;
+        }
+
+        .styled-input {
+            flex: 1;
+            max-width: 300px;
+            padding: 8px 12px;
+            border: 1px solid #ddd;
+            border-radius: 4px;
+            background-color: #f9f9f9;
+        }
+
+        .input-groups {
+            flex: 1;
+            display: flex;
+            flex-wrap: wrap;
+            gap: 15px;
+        }
+
+        .form-check-radio {
+            margin-right: 5px;
+        }
+
+        .preview-tabs {
+            margin-top: 20px;
+        }
+
+        .nav-tabs {
+            border-bottom: 2px solid #1ab394;
+        }
+
+        .nav-tabs > li.active > a {
+            background-color: #1ab394;
+            color: white;
+            border-color: #1ab394;
+        }
+
+        .tab-content {
+            padding: 20px;
+            background-color: white;
+            border: 1px solid #ddd;
+            border-top: none;
+        }
+
+        .dynamic-field.enabled {
+            display: block;
+        }
+
+        .dynamic-field:not(.enabled) {
+            display: none;
+        }
+
+        .preview-note {
+            background-color: #fff3cd;
+            border: 1px solid #ffeaa7;
+            color: #856404;
+            padding: 10px;
+            border-radius: 4px;
+            margin-bottom: 20px;
+        }
+    </style>
+</head>
+<body class="gray-bg">
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-sm-12">
+            <div class="ibox">
+                <div class="ibox-title">
+                    <h5>模版预览 - <span th:text="${template.templateName}"></span></h5>
+                    <div class="ibox-tools">
+                        <button class="btn btn-default btn-sm" onclick="window.close()">
+                            <i class="fa fa-times"></i> 关闭
+                        </button>
+                    </div>
+                </div>
+
+                <div class="ibox-content">
+                    <div class="preview-note">
+                        <i class="fa fa-info-circle"></i>
+                        这是模版预览页面,所有表单元素均为演示效果,不能进行实际操作。
+                    </div>
+
+                    <!-- 模版基本信息 -->
+                    <div class="template-info">
+                        <h4><i class="fa fa-info-circle"></i> 模版信息</h4>
+                        <div class="row">
+                            <div class="col-sm-6">
+                                <p><strong>模版名称:</strong><span th:text="${template.templateName}"></span></p>
+                                <p><strong>模版类型:</strong>
+                                    <span th:if="${template.templateType} =='custom' ">自定义</span>
+                                    <span th:if="${template.templateType} =='default'">系统默认</span></p>
+                                <p><strong>适用业务:</strong><span th:text="${template.businessType}"></span></p>
+                            </div>
+                            <div class="col-sm-6">
+                                <p><strong>状态:</strong>
+                                    <span th:if="${template.status == 1}" class="label label-success">启用</span>
+                                    <span th:if="${template.status == 0}" class="label label-danger">禁用</span>
+                                </p>
+                                <p><strong>创建人:</strong><span th:text="${template.createdBy}"></span></p>
+                                <p><strong>创建时间:</strong><span th:text="${template.createdTime}"></span></p>
+                            </div>
+                        </div>
+                        <div class="row" th:if="${template.templateDesc}">
+                            <div class="col-sm-12">
+                                <p><strong>模版描述:</strong><span th:text="${template.templateDesc}"></span></p>
+                            </div>
+                        </div>
+                    </div>
+
+                    <!-- 预览内容容器 -->
+                    <div class="preview-container">
+                        <div class="preview-header">
+                            <i class="fa fa-eye"></i> 表单预览效果
+                        </div>
+
+                        <!-- 动态生成的Tab导航 -->
+                        <ul class="nav nav-tabs preview-tabs" id="previewTabs">
+                            <li class="active">
+                                <a data-toggle="tab" href="#preview-tab-4">本次任务</a>
+                            </li>
+                            <!-- 其他Tab将通过JavaScript动态生成 -->
+                        </ul>
+
+                        <div class="tab-content" id="previewTabContent">
+                            <!-- 本次任务Tab - 必选 -->
+                            <div id="preview-tab-4" class="tab-pane active dynamic-tab enabled">
+                                <h4 style="color: #1E9FFF;">| 本次任务</h4>
+                                <div id="preview-tab-4-fields">
+                                    <!-- 字段将通过JavaScript动态生成 -->
+                                </div>
+                            </div>
+
+                            <!-- 其他Tab内容将通过JavaScript动态生成 -->
+                            <div id="preview-tab-6" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 用药依从性</h4>
+                                <div id="preview-tab-6-fields"></div>
+                            </div>
+
+                            <div id="preview-tab-7" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 药物安全性</h4>
+                                <div id="preview-tab-7-fields"></div>
+                            </div>
+
+                            <div id="preview-tab-8" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 药物有效性</h4>
+                                <div id="preview-tab-8-fields"></div>
+                            </div>
+
+                            <div id="preview-tab-9" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 治疗方案</h4>
+                                <div id="preview-tab-9-fields"></div>
+                            </div>
+
+                            <div id="preview-tab-10" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 适宜性评估</h4>
+                                <div id="preview-tab-10-fields"></div>
+                            </div>
+
+                            <div id="preview-tab-11" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 用药记录</h4>
+                                <div id="preview-tab-11-fields"></div>
+                            </div>
+
+                            <div id="preview-tab-12" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 量表测评</h4>
+                                <div id="preview-tab-12-fields"></div>
+                            </div>
+
+                            <div id="preview-tab-13" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 患者咨询</h4>
+                                <div id="preview-tab-13-fields"></div>
+                            </div>
+
+                            <div id="preview-tab-14" class="tab-pane dynamic-tab">
+                                <h4 style="color: #1E9FFF;">| 其他</h4>
+                                <div id="preview-tab-14-fields"></div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<th:block th:include="include :: footer" />
+<th:block th:include="include :: bootstrap-table-js" />
+<script th:inline="javascript">
+    var templateId = [[${templateId}]];
+    var templateConfig = null;
+
+    $(function() {
+        loadTemplateConfig();
+    });
+
+    // 加载模版配置
+    function loadTemplateConfig() {
+        $.ajax({
+            url: ctx + "gxhpz/followTemplateConfig/getTemplateConfig",
+            type: "POST",
+            data: { id: templateId },
+            success: function(result) {
+                if (result.code == 0) {
+                    templateConfig = result.data;
+                    renderPreview();
+                } else {
+                    console.error("加载模版配置失败:", result.msg);
+                }
+            },
+            error: function() {
+                console.error("加载模版配置异常");
+            }
+        });
+    }
+
+    // 渲染预览内容
+    function renderPreview() {
+        if (!templateConfig) return;
+
+        // 渲染Tab导航
+        renderTabNavigation();
+
+        // 渲染字段
+        renderPreviewFields();
+    }
+
+    // 渲染Tab导航
+    function renderTabNavigation() {
+        var tabs = templateConfig.tabs;
+        if (!tabs || tabs.length === 0) return;
+
+        var tabHtml = '';
+        tabs.forEach(function(tab) {
+            if (tab.tabCode !== 'tab-4') { // 本次任务Tab已经存在
+                tabHtml += '<li><a data-toggle="tab" href="#preview-' + tab.tabCode + '">' + tab.tabName + '</a></li>';
+                $('#preview-' + tab.tabCode).addClass('enabled');
+            }
+        });
+
+        $('#previewTabs').append(tabHtml);
+    }
+
+    // 渲染预览字段
+    function renderPreviewFields() {
+        var fieldsByTab = templateConfig.fieldsByTab;
+        if (!fieldsByTab) return;
+
+        Object.keys(fieldsByTab).forEach(function(tabCode) {
+            var fields = fieldsByTab[tabCode];
+            var fieldsHtml = '';
+
+            // 按显示顺序排序
+            fields.sort(function(a, b) {
+                return (a.displayOrder || 0) - (b.displayOrder || 0);
+            });
+
+            fields.forEach(function(field) {
+                fieldsHtml += generatePreviewFieldHtml(field);
+            });
+
+            $('#preview-' + tabCode + '-fields').html(fieldsHtml);
+        });
+    }
+
+    // 生成预览字段HTML
+    function generatePreviewFieldHtml(field) {
+        var fieldHtml = '';
+        var isRequired = field.isRequired == 1;
+        var requiredClass = isRequired ? 'is-required' : '';
+
+        switch (field.fieldType) {
+            case 'input':
+                fieldHtml = `
+                    <div class="customize-form-group ${requiredClass}">
+                        <label>${field.fieldName}:</label>
+                        <input placeholder="${field.placeholder || '请输入' + field.fieldName}"
+                               class="styled-input" type="text" disabled>
+                    </div>`;
+                break;
+
+            case 'radio':
+                fieldHtml = `
+                    <div class="customize-form-group ${requiredClass}">
+                        <label>${field.fieldName}:</label>
+                        <div class="input-groups">
+                            <input type="radio" class="form-check-radio" disabled> 选项1
+                            <input type="radio" class="form-check-radio" disabled> 选项2
+                            <input type="radio" class="form-check-radio" disabled> 选项3
+                        </div>
+                    </div>`;
+                break;
+
+            case 'checkbox':
+                fieldHtml = `
+                    <div class="customize-form-group ${requiredClass}">
+                        <label>${field.fieldName}:</label>
+                        <div class="input-groups">
+                            <input type="checkbox" class="form-check-radio" disabled> 选项1
+                            <input type="checkbox" class="form-check-radio" disabled> 选项2
+                            <input type="checkbox" class="form-check-radio" disabled> 选项3
+                        </div>
+                    </div>`;
+                break;
+
+            case 'select':
+                fieldHtml = `
+                    <div class="customize-form-group ${requiredClass}">
+                        <label>${field.fieldName}:</label>
+                        <select class="styled-input" disabled>
+                            <option value="">请选择${field.fieldName}</option>
+                            <option>选项1</option>
+                            <option>选项2</option>
+                            <option>选项3</option>
+                        </select>
+                    </div>`;
+                break;
+
+            case 'textarea':
+                fieldHtml = `
+                    <div class="customize-form-group ${requiredClass}">
+                        <label>${field.fieldName}:</label>
+                        <textarea placeholder="${field.placeholder || '请输入' + field.fieldName}"
+                                  class="styled-input" style="height: 80px;" disabled></textarea>
+                    </div>`;
+                break;
+
+            case 'datetime':
+                fieldHtml = `
+                    <div class="customize-form-group ${requiredClass}">
+                        <label>${field.fieldName}:</label>
+                        <input placeholder="${field.placeholder || '请选择' + field.fieldName}"
+                               class="styled-input" type="text" disabled>
+                    </div>`;
+                break;
+
+            case 'file':
+                fieldHtml = `
+                    <div class="customize-form-group ${requiredClass}">
+                        <label>${field.fieldName}:</label>
+                        <div style="border: 2px dashed #ddd; padding: 20px; text-align: center; color: #999;">
+                            <i class="fa fa-upload"></i><br>
+                            文件上传区域(预览)
+                        </div>
+                    </div>`;
+                break;
+
+            default:
+                fieldHtml = `
+                    <div class="customize-form-group">
+                        <label>${field.fieldName}:</label>
+                        <span style="color: #999;">字段类型 ${field.fieldType} (预览)</span>
+                    </div>`;
+        }
+
+        return fieldHtml;
+    }
+</script>
+</body>
+</html>

+ 640 - 0
health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/rules.html

@@ -0,0 +1,640 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
+<head>
+    <th:block th:include="include :: header('规则配置')" />
+    <style>
+        .rule-form-container {
+            background-color: #f5f5f5;
+            padding: 15px;
+            margin-bottom: 20px;
+            border-radius: 5px;
+        }
+
+        .rule-item {
+            background-color: white;
+            padding: 15px;
+            margin-bottom: 10px;
+            border: 1px solid #ddd;
+            border-radius: 5px;
+        }
+
+        .rule-header {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            margin-bottom: 10px;
+        }
+
+        .rule-title {
+            font-weight: bold;
+            color: #333;
+        }
+
+        .rule-status {
+            margin-left: 10px;
+        }
+
+        .rule-content {
+            color: #666;
+            font-size: 14px;
+        }
+
+        .rule-actions {
+            margin-top: 10px;
+        }
+
+        .condition-group {
+            background-color: #f9f9f9;
+            padding: 10px;
+            margin: 10px 0;
+            border-left: 3px solid #1ab394;
+        }
+
+        .action-group {
+            background-color: #f0f8ff;
+            padding: 10px;
+            margin: 10px 0;
+            border-left: 3px solid #5bc0de;
+        }
+    </style>
+</head>
+<body class="gray-bg">
+<div class="container-fluid">
+    <div class="row">
+        <div class="col-sm-12">
+            <div class="ibox">
+                <div class="ibox-title">
+                    <h5>字段显示规则配置 - <span th:text="${template.templateName}"></span></h5>
+                    <div class="ibox-tools">
+                        <button class="btn btn-primary btn-sm" onclick="addRule()">
+                            <i class="fa fa-plus"></i> 新增规则
+                        </button>
+                        <button class="btn btn-default btn-sm" onclick="backToList()">
+                            <i class="fa fa-arrow-left"></i> 返回
+                        </button>
+                    </div>
+                </div>
+
+                <div class="ibox-content">
+                    <!-- 规则列表 -->
+                    <div id="ruleList">
+                        <!-- 规则项将通过JavaScript动态生成 -->
+                    </div>
+
+                    <!-- 暂无规则提示 -->
+                    <div id="emptyTip" class="text-center" style="display: none; padding: 50px;">
+                        <i class="fa fa-info-circle fa-3x text-muted"></i>
+                        <p class="text-muted" style="margin-top: 10px;">暂无配置规则,点击"新增规则"按钮添加</p>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 新增/编辑规则弹窗 -->
+<div class="modal fade" id="ruleModal" tabindex="-1" role="dialog">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+                <h4 class="modal-title" id="ruleModalTitle">新增规则</h4>
+            </div>
+            <div class="modal-body">
+                <form id="ruleForm" class="form-horizontal">
+                    <input type="hidden" name="id" id="ruleId">
+                    <input type="hidden" name="templateId" th:value="${templateId}">
+
+                    <div class="form-group">
+                        <label class="col-sm-3 control-label is-required">规则名称:</label>
+                        <div class="col-sm-8">
+                            <input name="ruleName" class="form-control" type="text" placeholder="请输入规则名称" required>
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label class="col-sm-3 control-label is-required">触发条件:</label>
+                        <div class="col-sm-8">
+                            <div class="condition-group">
+                                <div class="row">
+                                    <div class="col-sm-5">
+                                        <select name="triggerFieldCode" class="form-control" required onchange="loadFieldValues(this.value)">
+                                            <option value="">选择字段</option>
+                                        </select>
+                                    </div>
+                                    <div class="col-sm-2 text-center">
+                                        <span style="line-height: 34px;">等于</span>
+                                    </div>
+                                    <div class="col-sm-5">
+                                        <select name="triggerFieldValue" class="form-control" required>
+                                            <option value="">选择值</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="help-block">当选择的字段值满足条件时,触发相应动作</div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label class="col-sm-3 control-label is-required">触发动作:</label>
+                        <div class="col-sm-8">
+                            <div class="action-group">
+                                <div class="row">
+                                    <div class="col-sm-4">
+                                        <select name="actionType" class="form-control" required onchange="updateActionFields()">
+                                            <option value="">选择动作</option>
+                                            <option value="show">显示字段</option>
+                                            <option value="hide">隐藏字段</option>
+                                            <option value="required">设为必填</option>
+                                            <option value="optional">设为选填</option>
+                                            <option value="enable">启用字段</option>
+                                            <option value="disable">禁用字段</option>
+                                        </select>
+                                    </div>
+                                    <div class="col-sm-8">
+                                        <select name="targetFieldCodes" class="form-control select2" multiple="multiple" required>
+                                            <option value="">选择目标字段</option>
+                                        </select>
+                                    </div>
+                                </div>
+                                <div class="help-block">选择要执行的动作和目标字段</div>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label class="col-sm-3 control-label">规则逻辑:</label>
+                        <div class="col-sm-8">
+                            <textarea name="ruleLogic" class="form-control" rows="3" placeholder="可选:输入自定义规则逻辑(JavaScript表达式)"></textarea>
+                            <div class="help-block">高级功能:自定义JavaScript逻辑,留空使用默认逻辑</div>
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label class="col-sm-3 control-label">状态:</label>
+                        <div class="col-sm-8">
+                            <div class="radio-box">
+                                <input type="radio" id="isEnabled1" name="isEnabled" value="1" checked>
+                                <label for="isEnabled1">启用</label>
+                            </div>
+                            <div class="radio-box">
+                                <input type="radio" id="isEnabled0" name="isEnabled" value="0">
+                                <label for="isEnabled0">禁用</label>
+                            </div>
+                        </div>
+                    </div>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-primary" onclick="saveRule()">保存</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 规则测试弹窗 -->
+<div class="modal fade" id="testRuleModal" tabindex="-1" role="dialog">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal">&times;</button>
+                <h4 class="modal-title">规则测试</h4>
+            </div>
+            <div class="modal-body">
+                <div id="testRuleContent">
+                    <!-- 测试内容将动态生成 -->
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<th:block th:include="include :: footer" />
+<th:block th:include="include :: select2-js" />
+<script th:inline="javascript">
+    var templateId = [[${templateId}]];
+    var prefix = ctx + "gxhpz/followTemplateConfig";
+    var rules = [];
+    var fields = [];
+    var currentRule = null;
+
+    $(function() {
+        // 初始化select2
+        $('.select2').select2({
+            placeholder: "请选择目标字段",
+            allowClear: true,
+            language: 'zh-CN'
+        });
+
+        loadRules();
+        loadFields();
+    });
+
+    // 加载规则列表
+    function loadRules() {
+        $.ajax({
+            url: prefix + "/ruleList",
+            type: "POST",
+            data: { templateId: templateId },
+            success: function(result) {
+                if (result.code == 0) {
+                    rules = result.rows;
+                    renderRules();
+                }
+            }
+        });
+    }
+
+    // 加载字段列表
+    function loadFields() {
+        $.ajax({
+            url: prefix + "/getTemplateFields",
+            type: "POST",
+            data: { templateId: templateId },
+            success: function(result) {
+                if (result.code == 0) {
+                    fields = result.data;
+                    updateFieldSelects();
+                }
+            }
+        });
+    }
+
+    // 渲染规则列表
+    function renderRules() {
+        var html = '';
+        if (rules.length === 0) {
+            $('#ruleList').hide();
+            $('#emptyTip').show();
+            return;
+        }
+
+        $('#emptyTip').hide();
+        $('#ruleList').show();
+
+        rules.forEach(function(rule) {
+            var statusHtml = rule.isEnabled == 1
+                ? '<span class="label label-success">启用</span>'
+                : '<span class="label label-default">禁用</span>';
+
+            var actionText = getActionText(rule.actionType);
+            var targetFields = rule.targetFieldCodes ? rule.targetFieldCodes.split(',') : [];
+            var targetFieldNames = targetFields.map(function(code) {
+                var field = fields.find(f => f.fieldCode === code);
+                return field ? field.fieldName : code;
+            }).join(', ');
+
+            html += '<div class="rule-item">';
+            html += '  <div class="rule-header">';
+            html += '    <div>';
+            html += '      <span class="rule-title">' + rule.ruleName + '</span>';
+            html += '      <span class="rule-status">' + statusHtml + '</span>';
+            html += '    </div>';
+            html += '    <div class="rule-actions">';
+            html += '      <button class="btn btn-xs btn-primary" onclick="editRule(' + rule.id + ')"><i class="fa fa-edit"></i> 编辑</button>';
+            html += '      <button class="btn btn-xs btn-info" onclick="testRule(' + rule.id + ')"><i class="fa fa-flask"></i> 测试</button>';
+            if (rule.isEnabled == 1) {
+                html += '      <button class="btn btn-xs btn-warning" onclick="toggleRuleStatus(' + rule.id + ', 0)"><i class="fa fa-ban"></i> 禁用</button>';
+            } else {
+                html += '      <button class="btn btn-xs btn-success" onclick="toggleRuleStatus(' + rule.id + ', 1)"><i class="fa fa-check"></i> 启用</button>';
+            }
+            html += '      <button class="btn btn-xs btn-danger" onclick="deleteRule(' + rule.id + ')"><i class="fa fa-trash"></i> 删除</button>';
+            html += '    </div>';
+            html += '  </div>';
+            html += '  <div class="rule-content">';
+            html += '    <p><strong>触发条件:</strong>当 <span class="text-primary">' + getFieldName(rule.triggerFieldCode) + '</span> = <span class="text-info">' + rule.triggerFieldValue + '</span> 时</p>';
+            html += '    <p><strong>执行动作:</strong>' + actionText + ' <span class="text-success">' + targetFieldNames + '</span></p>';
+            if (rule.ruleLogic) {
+                html += '    <p><strong>自定义逻辑:</strong><code>' + rule.ruleLogic + '</code></p>';
+            }
+            html += '  </div>';
+            html += '</div>';
+        });
+
+        $('#ruleList').html(html);
+    }
+
+    // 获取字段名称
+    function getFieldName(fieldCode) {
+        var field = fields.find(f => f.fieldCode === fieldCode);
+        return field ? field.fieldName : fieldCode;
+    }
+
+    // 获取动作文本
+    function getActionText(actionType) {
+        var actionMap = {
+            'show': '显示字段',
+            'hide': '隐藏字段',
+            'required': '设为必填',
+            'optional': '设为选填',
+            'enable': '启用字段',
+            'disable': '禁用字段'
+        };
+        return actionMap[actionType] || actionType;
+    }
+
+    // 更新字段选择框
+    function updateFieldSelects() {
+        // 更新触发字段选择框
+        var triggerOptions = '<option value="">选择字段</option>';
+        fields.forEach(function(field) {
+            triggerOptions += '<option value="' + field.fieldCode + '">' + field.fieldName + '</option>';
+        });
+        $('select[name="triggerFieldCode"]').html(triggerOptions);
+
+        // 更新目标字段选择框
+        var targetOptions = '';
+        fields.forEach(function(field) {
+            targetOptions += '<option value="' + field.fieldCode + '">' + field.fieldName + '</option>';
+        });
+        $('select[name="targetFieldCodes"]').html(targetOptions);
+        $('select[name="targetFieldCodes"]').select2('destroy').select2({
+            placeholder: "请选择目标字段",
+            allowClear: true,
+            language: 'zh-CN'
+        });
+    }
+
+    // 加载字段值选项
+    function loadFieldValues(fieldCode) {
+        if (!fieldCode) {
+            $('select[name="triggerFieldValue"]').html('<option value="">选择值</option>');
+            return;
+        }
+
+        var field = fields.find(f => f.fieldCode === fieldCode);
+        if (!field) return;
+
+        var valueOptions = '<option value="">选择值</option>';
+
+        // 根据字段类型设置选项
+        if (field.fieldType === 'radio' || field.fieldType === 'select') {
+            // 这里应该从字段配置中获取选项,暂时使用默认值
+            if (fieldCode === 'iscoordinate' || fieldCode === 'medicationStatus') {
+                valueOptions += '<option value="是">是</option>';
+                valueOptions += '<option value="否">否</option>';
+            } else if (fieldCode === 'returnMethod') {
+                valueOptions += '<option value="电话">电话</option>';
+                valueOptions += '<option value="微信">微信</option>';
+                valueOptions += '<option value="面访">面访</option>';
+            } else {
+                // 默认选项
+                valueOptions += '<option value="选项1">选项1</option>';
+                valueOptions += '<option value="选项2">选项2</option>';
+                valueOptions += '<option value="选项3">选项3</option>';
+            }
+        } else if (field.fieldType === 'checkbox') {
+            valueOptions += '<option value="包含">包含特定选项</option>';
+            valueOptions += '<option value="不包含">不包含特定选项</option>';
+        } else {
+            valueOptions += '<option value="非空">非空</option>';
+            valueOptions += '<option value="为空">为空</option>';
+        }
+
+        $('select[name="triggerFieldValue"]').html(valueOptions);
+    }
+
+    // 更新动作字段
+    function updateActionFields() {
+        var actionType = $('select[name="actionType"]').val();
+        // 可以根据不同的动作类型过滤可选字段
+    }
+
+    // 新增规则
+    function addRule() {
+        currentRule = null;
+        $('#ruleModalTitle').text('新增规则');
+        $('#ruleForm')[0].reset();
+        $('#ruleId').val('');
+        $('select[name="targetFieldCodes"]').val(null).trigger('change');
+        $('#ruleModal').modal('show');
+    }
+
+    // 编辑规则
+    function editRule(id) {
+        currentRule = rules.find(r => r.id === id);
+        if (!currentRule) return;
+
+        $('#ruleModalTitle').text('编辑规则');
+        $('#ruleId').val(currentRule.id);
+        $('input[name="ruleName"]').val(currentRule.ruleName);
+        $('select[name="triggerFieldCode"]').val(currentRule.triggerFieldCode);
+
+        // 加载字段值选项后设置值
+        loadFieldValues(currentRule.triggerFieldCode);
+        setTimeout(function() {
+            $('select[name="triggerFieldValue"]').val(currentRule.triggerFieldValue);
+        }, 100);
+
+        $('select[name="actionType"]').val(currentRule.actionType);
+
+        // 设置目标字段
+        var targetFields = currentRule.targetFieldCodes ? currentRule.targetFieldCodes.split(',') : [];
+        $('select[name="targetFieldCodes"]').val(targetFields).trigger('change');
+
+        $('textarea[name="ruleLogic"]').val(currentRule.ruleLogic || '');
+        $('input[name="isEnabled"][value="' + currentRule.isEnabled + '"]').prop('checked', true);
+
+        $('#ruleModal').modal('show');
+    }
+
+    // 保存规则
+    function saveRule() {
+        if (!$('#ruleForm').valid()) {
+            return;
+        }
+
+        var formData = $('#ruleForm').serializeArray();
+        var data = {};
+        formData.forEach(function(item) {
+            if (item.name === 'targetFieldCodes') {
+                if (!data[item.name]) {
+                    data[item.name] = [];
+                }
+                data[item.name].push(item.value);
+            } else {
+                data[item.name] = item.value;
+            }
+        });
+
+        // 将目标字段数组转换为逗号分隔的字符串
+        if (data.targetFieldCodes && Array.isArray(data.targetFieldCodes)) {
+            data.targetFieldCodes = data.targetFieldCodes.join(',');
+        }
+
+        var url = currentRule ? prefix + "/updateRule" : prefix + "/saveRule";
+
+        $.ajax({
+            url: url,
+            type: "POST",
+            data: data,
+            success: function(result) {
+                if (result.code == 0) {
+                    $.modal.alertSuccess("保存成功");
+                    $('#ruleModal').modal('hide');
+                    loadRules();
+                } else {
+                    $.modal.alertError(result.msg);
+                }
+            }
+        });
+    }
+
+    // 测试规则
+    function testRule(id) {
+        var rule = rules.find(r => r.id === id);
+        if (!rule) return;
+
+        var html = '<div class="form-horizontal">';
+        html += '<div class="form-group">';
+        html += '  <label class="col-sm-4 control-label">规则名称:</label>';
+        html += '  <div class="col-sm-8"><p class="form-control-static">' + rule.ruleName + '</p></div>';
+        html += '</div>';
+        html += '<div class="form-group">';
+        html += '  <label class="col-sm-4 control-label">触发条件:</label>';
+        html += '  <div class="col-sm-8">';
+        html += '    <select class="form-control" id="testTriggerValue">';
+        html += '      <option value="">请选择' + getFieldName(rule.triggerFieldCode) + '的值</option>';
+
+        // 添加测试选项
+        $('select[name="triggerFieldValue"] option').each(function() {
+            if ($(this).val()) {
+                html += '<option value="' + $(this).val() + '">' + $(this).text() + '</option>';
+            }
+        });
+
+        html += '    </select>';
+        html += '  </div>';
+        html += '</div>';
+        html += '<div class="form-group">';
+        html += '  <label class="col-sm-4 control-label">测试结果:</label>';
+        html += '  <div class="col-sm-8">';
+        html += '    <div id="testResult" class="alert alert-info" style="display: none;"></div>';
+        html += '  </div>';
+        html += '</div>';
+        html += '</div>';
+
+        $('#testRuleContent').html(html);
+
+        // 绑定测试事件
+        $('#testTriggerValue').change(function() {
+            var value = $(this).val();
+            var resultHtml = '';
+
+            if (value === rule.triggerFieldValue) {
+                resultHtml = '<i class="fa fa-check-circle text-success"></i> 规则触发!<br>';
+                resultHtml += '执行动作:' + getActionText(rule.actionType) + ' ';
+
+                var targetFields = rule.targetFieldCodes ? rule.targetFieldCodes.split(',') : [];
+                var targetFieldNames = targetFields.map(function(code) {
+                    return getFieldName(code);
+                }).join(', ');
+
+                resultHtml += '<strong>' + targetFieldNames + '</strong>';
+                $('#testResult').removeClass('alert-warning').addClass('alert-success');
+            } else {
+                resultHtml = '<i class="fa fa-times-circle text-warning"></i> 规则未触发';
+                $('#testResult').removeClass('alert-success').addClass('alert-warning');
+            }
+
+            $('#testResult').html(resultHtml).show();
+        });
+
+        $('#testRuleModal').modal('show');
+    }
+
+    // 切换规则状态
+    function toggleRuleStatus(id, status) {
+        var statusText = status == 1 ? "启用" : "禁用";
+        $.modal.confirm("确认要" + statusText + "该规则吗?", function() {
+            $.ajax({
+                url: prefix + "/updateRuleStatus",
+                type: "POST",
+                data: {
+                    id: id,
+                    isEnabled: status
+                },
+                success: function(result) {
+                    if (result.code == 0) {
+                        $.modal.alertSuccess(statusText + "成功");
+                        loadRules();
+                    } else {
+                        $.modal.alertError(result.msg);
+                    }
+                }
+            });
+        });
+    }
+
+    // 删除规则
+    function deleteRule(id) {
+        $.modal.confirm("确认要删除该规则吗?", function() {
+            $.ajax({
+                url: prefix + "/deleteRule",
+                type: "POST",
+                data: { id: id },
+                success: function(result) {
+                    if (result.code == 0) {
+                        $.modal.alertSuccess("删除成功");
+                        loadRules();
+                    } else {
+                        $.modal.alertError(result.msg);
+                    }
+                }
+            });
+        });
+    }
+
+    // 返回列表
+    function backToList() {
+        var url = ctx + 'gxhpz/followTemplateConfig';
+        $.modal.openTab("随访模版配置", url);
+    }
+
+    // 表单验证
+    $("#ruleForm").validate({
+        rules: {
+            ruleName: {
+                required: true,
+                maxlength: 100
+            },
+            triggerFieldCode: {
+                required: true
+            },
+            triggerFieldValue: {
+                required: true
+            },
+            actionType: {
+                required: true
+            },
+            targetFieldCodes: {
+                required: true
+            }
+        },
+        messages: {
+            ruleName: {
+                required: "请输入规则名称",
+                maxlength: "规则名称不能超过100个字符"
+            },
+            triggerFieldCode: {
+                required: "请选择触发字段"
+            },
+            triggerFieldValue: {
+                required: "请选择触发值"
+            },
+            actionType: {
+                required: "请选择动作类型"
+            },
+            targetFieldCodes: {
+                required: "请选择目标字段"
+            }
+        }
+    });
+</script>
+</body>
+</html>

+ 302 - 0
health-admin/src/main/resources/templates/gxhpz/followTemplateConfig/testRule.html

@@ -0,0 +1,302 @@
+<!DOCTYPE html>
+<html lang="zh" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <th:block th:include="include :: header('测试规则')" />
+    <style>
+        .test-container {
+            padding: 20px;
+        }
+        .test-form {
+            background-color: #f5f5f5;
+            padding: 15px;
+            border-radius: 5px;
+            margin-bottom: 20px;
+        }
+        .test-result {
+            background-color: #fff;
+            padding: 15px;
+            border-radius: 5px;
+            border: 1px solid #ddd;
+        }
+        .result-item {
+            padding: 10px;
+            margin: 5px 0;
+            border-left: 3px solid #1ab394;
+            background-color: #f9f9f9;
+        }
+        .field-status {
+            display: inline-block;
+            padding: 2px 8px;
+            border-radius: 3px;
+            font-size: 12px;
+            margin-left: 10px;
+        }
+        .field-visible {
+            background-color: #1ab394;
+            color: white;
+        }
+        .field-hidden {
+            background-color: #ed5565;
+            color: white;
+        }
+        .field-required {
+            background-color: #f8ac59;
+            color: white;
+        }
+        .field-disabled {
+            background-color: #999;
+            color: white;
+        }
+    </style>
+</head>
+<body class="white-bg">
+<div class="wrapper wrapper-content animated fadeInRight">
+    <div class="ibox">
+        <div class="ibox-title">
+            <h5>规则测试 - <span th:text="${rule.ruleName}"></span></h5>
+            <div class="ibox-tools">
+                <button class="btn btn-default btn-sm" onclick="window.close()">
+                    <i class="fa fa-times"></i> 关闭
+                </button>
+            </div>
+        </div>
+        <div class="ibox-content">
+            <div class="test-container">
+                <!-- 规则信息 -->
+                <div class="panel panel-primary">
+                    <div class="panel-heading">
+                        <h3 class="panel-title">规则信息</h3>
+                    </div>
+                    <div class="panel-body">
+                        <p><strong>规则名称:</strong><span th:text="${rule.ruleName}"></span></p>
+                        <p><strong>触发条件:</strong>当 <span class="text-primary" id="triggerFieldName"></span> = <span class="text-info" th:text="${rule.triggerFieldValue}"></span></p>
+                        <p><strong>执行动作:</strong><span id="actionText"></span> <span class="text-success" id="targetFieldNames"></span></p>
+                        <p th:if="${rule.ruleLogic}"><strong>自定义逻辑:</strong><code th:text="${rule.ruleLogic}"></code></p>
+                    </div>
+                </div>
+
+                <!-- 测试表单 -->
+                <div class="panel panel-default">
+                    <div class="panel-heading">
+                        <h3 class="panel-title">测试输入</h3>
+                    </div>
+                    <div class="panel-body">
+                        <div class="test-form">
+                            <form id="testForm" class="form-horizontal">
+                                <div class="form-group">
+                                    <label class="col-sm-3 control-label">触发字段值:</label>
+                                    <div class="col-sm-6">
+                                        <select id="triggerValue" class="form-control">
+                                            <option value="">请选择值</option>
+                                        </select>
+                                    </div>
+                                    <div class="col-sm-3">
+                                        <button type="button" class="btn btn-primary" onclick="executeTest()">
+                                            <i class="fa fa-play"></i> 执行测试
+                                        </button>
+                                    </div>
+                                </div>
+                            </form>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 测试结果 -->
+                <div class="panel panel-info">
+                    <div class="panel-heading">
+                        <h3 class="panel-title">测试结果</h3>
+                    </div>
+                    <div class="panel-body">
+                        <div id="testResult" class="test-result">
+                            <p class="text-muted text-center">请选择触发字段值并执行测试</p>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 字段状态预览 -->
+                <div class="panel panel-success" id="fieldPreview" style="display: none;">
+                    <div class="panel-heading">
+                        <h3 class="panel-title">字段状态预览</h3>
+                    </div>
+                    <div class="panel-body">
+                        <div id="fieldStatusList">
+                            <!-- 动态生成字段状态 -->
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<th:block th:include="include :: footer" />
+<script th:inline="javascript">
+    var rule = [[${rule}]];
+    var templateId = rule.templateId;
+    var fields = [];
+
+    $(function() {
+        loadFields();
+        initTestOptions();
+    });
+
+    // 加载字段信息
+    function loadFields() {
+        $.ajax({
+            url: ctx + "gxhpz/followTemplateConfig/getTemplateFields",
+            type: "POST",
+            data: { templateId: templateId },
+            async: false,
+            success: function(result) {
+                if (result.code == 0) {
+                    fields = result.data;
+                    displayRuleInfo();
+                }
+            }
+        });
+    }
+
+    // 显示规则信息
+    function displayRuleInfo() {
+        // 显示触发字段名称
+        var triggerField = fields.find(f => f.fieldCode === rule.triggerFieldCode);
+        $('#triggerFieldName').text(triggerField ? triggerField.fieldName : rule.triggerFieldCode);
+
+        // 显示动作文本
+        var actionMap = {
+            'show': '显示字段',
+            'hide': '隐藏字段',
+            'required': '设为必填',
+            'optional': '设为选填',
+            'enable': '启用字段',
+            'disable': '禁用字段'
+        };
+        $('#actionText').text(actionMap[rule.actionType] || rule.actionType);
+
+        // 显示目标字段名称
+        var targetCodes = rule.targetFieldCodes ? rule.targetFieldCodes.split(',') : [];
+        var targetNames = targetCodes.map(function(code) {
+            var field = fields.find(f => f.fieldCode === code);
+            return field ? field.fieldName : code;
+        }).join(', ');
+        $('#targetFieldNames').text(targetNames);
+    }
+
+    // 初始化测试选项
+    function initTestOptions() {
+        var triggerField = fields.find(f => f.fieldCode === rule.triggerFieldCode);
+        if (!triggerField) return;
+
+        var options = '<option value="">请选择值</option>';
+
+        // 根据字段类型生成选项
+        if (triggerField.fieldType === 'radio' || triggerField.fieldType === 'select') {
+            // 使用预定义的选项
+            if (rule.triggerFieldCode === 'iscoordinate' || rule.triggerFieldCode === 'medicationStatus') {
+                options += '<option value="是">是</option>';
+                options += '<option value="否">否</option>';
+            } else if (rule.triggerFieldCode === 'returnMethod') {
+                options += '<option value="电话">电话</option>';
+                options += '<option value="微信">微信</option>';
+                options += '<option value="面访">面访</option>';
+            } else {
+                // 默认选项
+                options += '<option value="选项1">选项1</option>';
+                options += '<option value="选项2">选项2</option>';
+                options += '<option value="选项3">选项3</option>';
+            }
+        } else {
+            options += '<option value="非空">非空</option>';
+            options += '<option value="为空">为空</option>';
+        }
+
+        // 确保包含规则的触发值
+        if (rule.triggerFieldValue && !options.includes(rule.triggerFieldValue)) {
+            options += '<option value="' + rule.triggerFieldValue + '">' + rule.triggerFieldValue + '</option>';
+        }
+
+        $('#triggerValue').html(options);
+    }
+
+    // 执行测试
+    function executeTest() {
+        var triggerValue = $('#triggerValue').val();
+        if (!triggerValue) {
+            $.modal.alertWarning("请选择触发字段值");
+            return;
+        }
+
+        var resultHtml = '';
+        var isTriggered = (triggerValue === rule.triggerFieldValue);
+
+        if (isTriggered) {
+            resultHtml = '<div class="alert alert-success">';
+            resultHtml += '<i class="fa fa-check-circle fa-2x"></i> <strong>规则已触发!</strong><br>';
+            resultHtml += '<p style="margin-top: 10px;">执行动作:' + $('#actionText').text() + '</p>';
+            resultHtml += '<p>影响字段:' + $('#targetFieldNames').text() + '</p>';
+            resultHtml += '</div>';
+
+            // 显示字段状态预览
+            showFieldPreview(true);
+        } else {
+            resultHtml = '<div class="alert alert-warning">';
+            resultHtml += '<i class="fa fa-times-circle fa-2x"></i> <strong>规则未触发</strong><br>';
+            resultHtml += '<p style="margin-top: 10px;">当前值:' + triggerValue + '</p>';
+            resultHtml += '<p>期望值:' + rule.triggerFieldValue + '</p>';
+            resultHtml += '</div>';
+
+            // 显示字段状态预览
+            showFieldPreview(false);
+        }
+
+        $('#testResult').html(resultHtml);
+    }
+
+    // 显示字段状态预览
+    function showFieldPreview(isTriggered) {
+        var targetCodes = rule.targetFieldCodes ? rule.targetFieldCodes.split(',') : [];
+        var html = '';
+
+        // 显示所有相关字段的状态
+        fields.forEach(function(field) {
+            if (targetCodes.includes(field.fieldCode)) {
+                html += '<div class="result-item">';
+                html += '<strong>' + field.fieldName + '</strong> (' + field.fieldCode + ')';
+
+                if (isTriggered) {
+                    // 根据动作类型显示不同状态
+                    switch(rule.actionType) {
+                        case 'show':
+                            html += '<span class="field-status field-visible">显示</span>';
+                            break;
+                        case 'hide':
+                            html += '<span class="field-status field-hidden">隐藏</span>';
+                            break;
+                        case 'required':
+                            html += '<span class="field-status field-required">必填</span>';
+                            break;
+                        case 'optional':
+                            html += '<span class="field-status field-visible">选填</span>';
+                            break;
+                        case 'enable':
+                            html += '<span class="field-status field-visible">启用</span>';
+                            break;
+                        case 'disable':
+                            html += '<span class="field-status field-disabled">禁用</span>';
+                            break;
+                    }
+                } else {
+                    // 显示默认状态
+                    html += '<span class="field-status field-visible">默认状态</span>';
+                }
+
+                html += '</div>';
+            }
+        });
+
+        $('#fieldStatusList').html(html);
+        $('#fieldPreview').show();
+    }
+</script>
+</body>
+</html>

+ 4 - 4
health-admin/src/main/resources/templates/gxhpz/template.html

@@ -81,19 +81,19 @@
                     visible: false
                 },
                 {
-                    field: 'templateCode',
+                    field: 'template_code',
                     title: '模板编码'
                 },
                 {
-                    field: 'templateName',
+                    field: 'template_name',
                     title: '模板名称'
                 },
                 {
-                    field: 'templateType',
+                    field: 'template_type',
                     title: '模板类型'
                 },
                 {
-                    field: 'businessBelonging',
+                    field: 'business_belonging',
                     title: '业务归属'
                 },
                 {

+ 2 - 2
health-admin/src/main/resources/templates/index-topnav.html

@@ -28,8 +28,8 @@
         </div>
         <a th:href="@{/index}">
             <li class="logo hidden-xs">
-				<!--log.png-->
-				<img th:src="@{/imglog.png}" class="logo-lg" width="100%" height="100%" style="padding-left:0px;">
+				<!--xlogmk.jpg-->
+				<img th:src="@{/imgxlogmk.jpg}" class="logo-lg" width="100%" height="100%" style="padding-left:0px;">
                 <!--<span class="logo-lg">Aa</span>-->
             </li>
          </a>

+ 2 - 2
health-admin/src/main/resources/templates/index.html

@@ -27,8 +27,8 @@
         </div>
         <a th:href="@{/index}">
             <li class="logo hidden-xs">
-				<!--log.png-->
-				<img th:src="@{/img/log.png}" class="logo-lg" width="100%" height="100%" style="padding-left:0px;">
+				<!--xlogmk.jpg-->
+				<img th:src="@{/img/xlogmk.jpg}" class="logo-lg" width="100%" height="100%" style="padding-left:0px;">
                 <!--&lt;!&ndash;<span class="logo-lg">英招在康</span>&ndash;&gt;-->
             </li>
          </a>

+ 2 - 2
health-admin/src/main/resources/templates/login.html

@@ -28,8 +28,8 @@
             <div class="col-sm-7">
                 <div class="signin-info">
                     <div class="logopanel m-b">
-                        <!--logo1.png-->
-                        <h1><img alt="[ 健康管理 ]" src="../static/img/logo1.png" th:src="@{/img/logo1.png}" width="90%" height="30%"></h1>
+                        <!--meikeindex.png-->
+                        <h1><img alt="[ 健康管理 ]" src="../static/img/meikeindex.png" th:src="@{/img/meikeindex.png}" width="90%" height="30%"></h1>
                     </div>
                     <div class="m-b"></div>
                     <ul class="m-b">

+ 2 - 2
health-admin/src/main/resources/templates/register.html

@@ -24,8 +24,8 @@
             <div class="col-sm-7">
                 <div class="signin-info">
                     <div class="logopanel m-b">
-                        <!--logo1.png-->
-                        <h1><img alt="[ 健康管理 ]" src="../static/img/logo1.png" th:src="@{/img/logo1.png}" width="90%" height="30%"></h1>
+                        <!--meikeindex.png-->
+                        <h1><img alt="[ 健康管理 ]" src="../static/img/meikeindex.png" th:src="@{/img/meikeindex.png}" width="90%" height="30%"></h1>
                     </div>
                     <div class="m-b"></div>
                     <ul class="m-b">

+ 499 - 0
health-system/src/main/java/com/bzd/system/service/gxhpz/FollowTemplateConfigService.java

@@ -0,0 +1,499 @@
+package com.bzd.system.service.gxhpz;
+
+import com.bzd.common.config.dao.DaoSupport;
+import com.bzd.common.config.dao.PageData;
+import com.bzd.common.utils.StringUtils;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * 随访模版配置服务
+ * @author system
+ */
+@Service
+public class FollowTemplateConfigService {
+
+    @Resource(name = "daoSupport")
+    private DaoSupport daoSupport;
+
+    /**
+     * 查询模版配置列表
+     */
+    public List<PageData> selectTemplateList(PageData pd) throws Exception {
+        return (List<PageData>) daoSupport.findForList("followTemplateConfigMapper.selectTemplateList", pd);
+    }
+
+    /**
+     * 根据ID查询模版配置
+     */
+    public PageData selectTemplateById(PageData pd) throws Exception {
+        return (PageData) daoSupport.findForObject("followTemplateConfigMapper.selectTemplateById", pd);
+    }
+
+    /**
+     * 新增模版配置
+     */
+    public Integer insertTemplate(PageData pd) throws Exception {
+        return daoSupport.save("followTemplateConfigMapper.insertTemplate", pd);
+    }
+
+    /**
+     * 修改模版配置
+     */
+    public Integer updateTemplate(PageData pd) throws Exception {
+        return daoSupport.update("followTemplateConfigMapper.updateTemplate", pd);
+    }
+
+    /**
+     * 删除模版配置
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Integer deleteTemplateByIds(String[] ids) throws Exception {
+        int result = 0;
+        for (String id : ids) {
+            PageData pd = new PageData();
+            pd.put("templateId", id);
+            
+            // 删除相关的字段配置
+            daoSupport.delete("followTemplateConfigMapper.deleteFieldsByTemplateId", pd);
+            // 删除相关的规则配置
+            daoSupport.delete("followTemplateConfigMapper.deleteRulesByTemplateId", pd);
+            // 删除相关的Tab配置
+            daoSupport.delete("followTemplateConfigMapper.deleteTabsByTemplateId", pd);
+            // 删除模版
+            pd.put("id", id);
+            result += daoSupport.delete("followTemplateConfigMapper.deleteTemplate", pd);
+        }
+        return result;
+    }
+
+    /**
+     * 查询字段配置列表
+     */
+    public List<PageData> selectFieldList(PageData pd) throws Exception {
+        return (List<PageData>) daoSupport.findForList("followTemplateConfigMapper.selectFieldList", pd);
+    }
+
+    /**
+     * 新增字段配置
+     */
+    public Integer insertField(PageData pd) throws Exception {
+        return daoSupport.save("followTemplateConfigMapper.insertField", pd);
+    }
+
+    /**
+     * 删除字段配置
+     */
+    public Integer deleteFieldByIds(String[] ids) throws Exception {
+        return daoSupport.delete("followTemplateConfigMapper.deleteFieldByIds", Arrays.asList(ids));
+    }
+
+    /**
+     * 查询规则配置列表
+     */
+    public List<PageData> selectRuleList(PageData pd) throws Exception {
+        return (List<PageData>) daoSupport.findForList("followTemplateConfigMapper.selectRuleList", pd);
+    }
+
+
+
+    /**
+     * 获取可用字段列表
+     */
+    public List<PageData> getAvailableFields() throws Exception {
+        List<PageData> fields = new ArrayList<>();
+        
+        // 本次任务 tab-4
+        fields.add(createField("returnMethod", "回访方式", "radio", "tab-4", "本次任务", 1, true));
+        fields.add(createField("returnImgUrl", "回访图片", "file", "tab-4", "本次任务", 2, false));
+        fields.add(createField("InterviewRecord", "面访记录", "input", "tab-4", "本次任务", 3, false));
+        fields.add(createField("returnObject", "回访对象", "select", "tab-4", "本次任务", 4, false));
+        fields.add(createField("iscoordinate", "是否配合", "radio", "tab-4", "本次任务", 5, true));
+        fields.add(createField("reasons_uncooperative", "随访不配合原因", "radio", "tab-4", "本次任务", 6, false));
+        
+        // 用药依从性 tab-6
+        fields.add(createField("medicationStatus", "是否持续用药", "radio", "tab-6", "用药依从性", 1, false));
+        fields.add(createField("charitable", "慈善援助用药", "radio", "tab-6", "用药依从性", 2, false));
+        fields.add(createField("permanentStopTime", "永久停药时间", "datetime", "tab-6", "用药依从性", 3, false));
+        fields.add(createField("perpetual_stopdrug_cause", "永久停药原因", "radio", "tab-6", "用药依从性", 4, false));
+        fields.add(createField("other_channels", "其他渠道购药", "radio", "tab-6", "用药依从性", 5, false));
+        
+        // 药物安全性 tab-7
+        fields.add(createField("is_adverse_reaction", "是否出现不良反应", "radio", "tab-7", "药物安全性", 1, true));
+        fields.add(createField("adverse_reaction_time", "不良反应时间", "datetime", "tab-7", "药物安全性", 2, false));
+        fields.add(createField("tar", "不良反应处理方式", "textarea", "tab-7", "药物安全性", 3, false));
+        fields.add(createField("combinedMedicationAdverseReaction", "合并用药是否引起不良反应", "radio", "tab-7", "药物安全性", 4, false));
+        
+        // 药物有效性 tab-8
+        fields.add(createField("isReview", "是否复查", "radio", "tab-8", "药物有效性", 1, true));
+        fields.add(createField("imagingInsuranceType", "影像学检查", "checkbox", "tab-8", "药物有效性", 2, false));
+        fields.add(createField("ctCheck", "CT", "radio", "tab-8", "药物有效性", 3, false));
+        fields.add(createField("ultrasoundCheck", "B超", "radio", "tab-8", "药物有效性", 4, false));
+        fields.add(createField("mriCheck", "核磁", "radio", "tab-8", "药物有效性", 5, false));
+        fields.add(createField("tumorMarkerCheck", "肿瘤标记物检查", "checkbox", "tab-8", "药物有效性", 6, false));
+        fields.add(createField("labTestIndicators", "实验室检查指标", "textarea", "tab-8", "药物有效性", 7, false));
+        
+        // 治疗方案 tab-9
+        fields.add(createField("treatmentType", "治疗类型", "checkbox", "tab-9", "治疗方案", 1, true));
+        
+        // 适宜性评估 tab-10
+        fields.add(createField("hasMedicationIndications", "有无药品适应症", "radio", "tab-10", "适宜性评估", 1, true));
+        fields.add(createField("drugEffectiveness", "药物对该疾病是否有效", "radio", "tab-10", "适宜性评估", 2, false));
+        fields.add(createField("clinicalInteraction", "药物间是否存在临床相互作用", "radio", "tab-10", "适宜性评估", 3, true));
+        fields.add(createField("unnecessaryRepeatedMedication", "是否有不必要重复用药", "radio", "tab-10", "适宜性评估", 4, false));
+        fields.add(createField("medicationError", "是否出现用药错误", "radio", "tab-10", "适宜性评估", 5, false));
+        
+        // 用药记录 tab-11
+        fields.add(createField("medicationRecord", "用药记录", "table", "tab-11", "用药记录", 1, false));
+        fields.add(createField("combinedMedicationRecord", "合并用药记录", "table", "tab-11", "用药记录", 2, false));
+        
+        // 量表测评 tab-12
+        fields.add(createField("painNrsScore", "疼痛标准评分NRS", "radio", "tab-12", "量表测评", 1, false));
+        fields.add(createField("physicalConditionScore", "体力状况评分", "radio", "tab-12", "量表测评", 2, false));
+        
+        // 患者咨询 tab-13
+        fields.add(createField("isConsultation", "本次回访是否咨询", "radio", "tab-13", "患者咨询", 1, false));
+        fields.add(createField("consultationType", "咨询问题类型", "select", "tab-13", "患者咨询", 2, false));
+        fields.add(createField("specificQuestion", "具体问题", "textarea", "tab-13", "患者咨询", 3, false));
+        fields.add(createField("pharmacistResponse", "药师解答", "textarea", "tab-13", "患者咨询", 4, false));
+        
+        // 其他 tab-14
+        fields.add(createField("patientConditionAssessment", "患者病情评估", "select", "tab-14", "其他", 1, false));
+        fields.add(createField("projectDescription", "共建项目描述", "textarea", "tab-14", "其他", 2, false));
+        
+        return fields;
+    }
+
+    /**
+     * 创建字段配置
+     */
+    private PageData createField(String fieldCode, String fieldName, String fieldType, 
+                                String tabCode, String tabName, int displayOrder, boolean isRequired) {
+        PageData field = new PageData();
+        field.put("fieldCode", fieldCode);
+        field.put("fieldName", fieldName);
+        field.put("fieldType", fieldType);
+        field.put("tabCode", tabCode);
+        field.put("tabName", tabName);
+        field.put("displayOrder", displayOrder);
+        field.put("isRequired", isRequired ? 1 : 0);
+        field.put("isEnabled", 1);
+        return field;
+    }
+
+    /**
+     * 获取模版配置详情(用于表单渲染)
+     */
+    public Map<String, Object> getTemplateConfig(PageData pd) throws Exception {
+        Map<String, Object> result = new HashMap<>();
+        
+        // 获取模版基本信息
+        PageData template = selectTemplateById(pd);
+        result.put("template", template);
+        
+        // 获取启用的Tab配置
+        List<PageData> tabs = (List<PageData>) daoSupport.findForList("followTemplateConfigMapper.selectTabList", pd);
+        result.put("tabs", tabs);
+        
+        // 获取字段配置,按Tab分组
+        List<PageData> fields = selectFieldList(pd);
+        Map<String, List<PageData>> fieldsByTab = new HashMap<>();
+        for (PageData field : fields) {
+            String tabCode = (String) field.get("tabCode");
+            fieldsByTab.computeIfAbsent(tabCode, k -> new ArrayList<>()).add(field);
+        }
+        result.put("fieldsByTab", fieldsByTab);
+        
+        // 获取字段规则配置
+        List<PageData> rules = selectRuleList(pd);
+        result.put("rules", rules);
+        
+        return result;
+    }
+
+    /**
+     * 复制模版
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Integer copyTemplate(PageData pd) throws Exception {
+        String sourceTemplateId = (String) pd.get("sourceTemplateId");
+        String newTemplateName = (String) pd.get("templateName");
+        
+        // 获取源模版信息
+        PageData sourceTemplate = new PageData();
+        sourceTemplate.put("id", sourceTemplateId);
+        sourceTemplate = selectTemplateById(sourceTemplate);
+        
+        // 创建新模版
+        PageData newTemplate = new PageData();
+        newTemplate.put("templateName", newTemplateName);
+        newTemplate.put("templateDesc", sourceTemplate.get("templateDesc"));
+        newTemplate.put("templateType", "custom");
+        newTemplate.put("status", pd.get("status"));
+        newTemplate.put("storeId", pd.get("storeId"));
+        newTemplate.put("createdBy", pd.get("createdBy"));
+        newTemplate.put("createdTime", pd.get("createdTime"));
+        
+        Integer templateId = daoSupport.save("followTemplateConfigMapper.insertTemplate", newTemplate);
+        
+        // 复制Tab配置
+        PageData tabQuery = new PageData();
+        tabQuery.put("templateId", sourceTemplateId);
+        List<PageData> tabs = (List<PageData>) daoSupport.findForList("followTemplateConfigMapper.selectTabList", tabQuery);
+        for (PageData tab : tabs) {
+            tab.put("templateId", templateId);
+            tab.remove("id");
+            daoSupport.save("followTemplateConfigMapper.insertTab", tab);
+        }
+        
+        // 复制字段配置
+        List<PageData> fields = selectFieldList(tabQuery);
+        for (PageData field : fields) {
+            field.put("templateId", templateId);
+            field.remove("id");
+            daoSupport.save("followTemplateConfigMapper.insertField", field);
+        }
+        
+        // 复制规则配置
+        List<PageData> rules = selectRuleList(tabQuery);
+        for (PageData rule : rules) {
+            rule.put("templateId", templateId);
+            rule.remove("id");
+            daoSupport.save("followTemplateConfigMapper.insertRule", rule);
+        }
+        
+        return templateId;
+    }
+
+    /**
+     * 更新模版状态
+     */
+    public Integer updateTemplateStatus(PageData pd) throws Exception {
+        return daoSupport.update("followTemplateConfigMapper.updateTemplateStatus", pd);
+    }
+
+    /**
+     * 查询Tab配置列表
+     */
+    public List<PageData> selectTabList(PageData pd) throws Exception {
+        return (List<PageData>) daoSupport.findForList("followTemplateConfigMapper.selectTabList", pd);
+    }
+
+    /**
+     * 批量保存Tab配置
+     */
+    @Transactional(rollbackFor = Exception.class)
+    public Integer saveTabConfig(PageData pd) throws Exception {
+        String templateId = (String) pd.get("templateId");
+        String tabConfigJson = (String) pd.get("tabConfig");
+        
+        // 删除原有Tab配置
+        PageData deleteParam = new PageData();
+        deleteParam.put("templateId", templateId);
+        daoSupport.delete("followTemplateConfigMapper.deleteTabsByTemplateId", deleteParam);
+        
+        // 解析新的Tab配置
+        ObjectMapper mapper = new ObjectMapper();
+        List<Map<String, Object>> tabConfigs = mapper.readValue(tabConfigJson, new TypeReference<List<Map<String, Object>>>(){});
+        
+        int result = 0;
+        for (Map<String, Object> tabConfig : tabConfigs) {
+            PageData tabData = new PageData();
+            tabData.put("templateId", templateId);
+            tabData.put("tabCode", tabConfig.get("tabCode"));
+            tabData.put("tabName", tabConfig.get("tabName"));
+            tabData.put("displayOrder", tabConfig.get("displayOrder"));
+            tabData.put("isEnabled", tabConfig.get("isEnabled"));
+            tabData.put("iconClass", tabConfig.get("iconClass"));
+            tabData.put("createdTime", pd.get("createdTime"));
+            
+            result += daoSupport.save("followTemplateConfigMapper.insertTab", tabData);
+        }
+        
+        return result;
+    }
+
+    /**
+     * 获取可用字段列表 以下是需要改进的代码,换个写法
+     * @return 字段列表
+     * @throws Exception
+     */
+    private ObjectMapper objectMapper = new ObjectMapper();
+
+
+    @Transactional
+    public Integer saveTemplateConfig(PageData pd) throws Exception {
+        String templateId = pd.getString("templateId");
+        String tabConfigData = pd.getString("tabConfigData");
+        String fieldConfigData = pd.getString("fieldConfigData");
+
+        // 保存Tab配置
+        if (StringUtils.isNotEmpty(tabConfigData)) {
+            // 先删除原有配置
+            PageData deleteTabPd = new PageData();
+            deleteTabPd.put("templateId", templateId);
+            daoSupport.delete("FollowTemplateConfigMapper.deleteTemplateTabsByTemplateId", deleteTabPd);
+
+            // 解析并保存新配置
+            List<Map<String, Object>> tabConfigs = objectMapper.readValue(tabConfigData,
+                    new TypeReference<List<Map<String, Object>>>() {});
+
+            for (Map<String, Object> tabConfig : tabConfigs) {
+                PageData tabPd = new PageData();
+                tabPd.put("templateId", templateId);
+                tabPd.put("tabCode", tabConfig.get("tabCode"));
+                tabPd.put("tabName", tabConfig.get("tabName"));
+                tabPd.put("displayOrder", tabConfig.get("displayOrder"));
+                tabPd.put("isEnabled", tabConfig.get("isEnabled"));
+                tabPd.put("createdTime", pd.get("updatedTime"));
+                daoSupport.save("FollowTemplateConfigMapper.insertTemplateTab", tabPd);
+            }
+        }
+
+        // 保存字段配置
+        if (StringUtils.isNotEmpty(fieldConfigData)) {
+            // 先删除原有配置
+            PageData deleteFieldPd = new PageData();
+            deleteFieldPd.put("templateId", templateId);
+            daoSupport.delete("FollowTemplateConfigMapper.deleteTemplateFieldsByTemplateId", deleteFieldPd);
+
+            // 解析并保存新配置
+            List<Map<String, Object>> fieldConfigs = objectMapper.readValue(fieldConfigData,
+                    new TypeReference<List<Map<String, Object>>>() {});
+
+            for (Map<String, Object> fieldConfig : fieldConfigs) {
+                PageData fieldPd = new PageData();
+                fieldPd.put("templateId", templateId);
+                fieldPd.put("tabCode", fieldConfig.get("tabCode"));
+                fieldPd.put("fieldCode", fieldConfig.get("fieldCode"));
+                fieldPd.put("fieldName", fieldConfig.get("fieldName"));
+                fieldPd.put("fieldType", fieldConfig.get("fieldType"));
+                fieldPd.put("isRequired", fieldConfig.get("isRequired"));
+                fieldPd.put("displayOrder", fieldConfig.get("displayOrder"));
+                fieldPd.put("placeholder", fieldConfig.get("placeholder"));
+                fieldPd.put("isEnabled", 1);
+                fieldPd.put("createdTime", pd.get("updatedTime"));
+                daoSupport.save("FollowTemplateConfigMapper.insertTemplateField", fieldPd);
+            }
+        }
+
+        return 1;
+    }
+
+
+
+
+
+
+
+    public List<PageData> getTemplateFields(PageData pd) throws Exception {
+        return (List<PageData>) daoSupport.findForList("FollowTemplateConfigMapper.selectTemplateFieldsByTemplateId", pd);
+    }
+
+    public Integer updateRuleStatus(PageData pd) throws Exception {
+        return (Integer) daoSupport.update("FollowTemplateConfigMapper.updateRuleStatus", pd);
+    }
+
+    public Integer deleteRuleById(String id) throws Exception {
+        PageData pd = new PageData();
+        pd.put("id", id);
+        return (Integer) daoSupport.delete("FollowTemplateConfigMapper.deleteRuleById", pd);
+    }
+
+    public PageData selectRuleById(PageData pd) throws Exception {
+        return (PageData) daoSupport.findForObject("FollowTemplateConfigMapper.selectRuleById", pd);
+    }
+
+    public List<PageData> getFieldOptions(String fieldCode) throws Exception {
+        PageData pd = new PageData();
+        pd.put("fieldCode", fieldCode);
+        return (List<PageData>) daoSupport.findForList("FollowTemplateConfigMapper.selectFieldOptions", pd);
+    }
+
+    public Integer saveFieldOptions(PageData pd) throws Exception {
+        // 实现字段选项保存逻辑
+        String fieldCode = pd.getString("fieldCode");
+        String templateId = pd.getString("templateId");
+
+        // 先删除原有选项
+        PageData deletePd = new PageData();
+        deletePd.put("fieldCode", fieldCode);
+        deletePd.put("templateId", templateId);
+        daoSupport.delete("FollowTemplateConfigMapper.deleteFieldOptions", deletePd);
+
+        // 插入新选项(需要解析选项数据)
+        // 具体实现根据前端传递的数据格式
+
+        return 1;
+    }
+
+    public Integer batchUpdateFields(PageData pd) throws Exception {
+        // 实现批量更新字段逻辑
+        return (Integer) daoSupport.update("FollowTemplateConfigMapper.batchUpdateFields", pd);
+    }
+
+    public Map<String, Object> exportTemplate(PageData pd) throws Exception {
+        // 实现模版导出逻辑
+        Map<String, Object> exportData = getTemplateConfig(pd);
+        return exportData;
+    }
+
+    public Integer importTemplate(PageData pd) throws Exception {
+        // 实现模版导入逻辑
+        String importData = pd.getString("importData");
+
+        // 解析导入数据并保存
+        Map<String, Object> templateData = objectMapper.readValue(importData,
+                new TypeReference<Map<String, Object>>() {});
+
+        // 保存模版基本信息
+        // 保存Tab配置
+        // 保存字段配置
+        // 保存规则配置
+
+        return 1;
+    }
+
+    public Map<String, Object> getTemplateStats(PageData pd) throws Exception {
+        // 实现模版使用统计逻辑
+        Map<String, Object> stats = new HashMap<>();
+
+        // 统计使用该模版的任务数量
+        PageData taskCountPd = new PageData();
+        taskCountPd.put("templateConfigId", pd.get("templateId"));
+        Long taskCount = (Long) daoSupport.findForObject("FollowTemplateConfigMapper.countTemplateUsage", taskCountPd);
+        stats.put("taskCount", taskCount);
+
+        // 其他统计信息...
+
+        return stats;
+    }
+
+    public Boolean checkTemplateNameExists(PageData pd) throws Exception {
+        Long count = (Long) daoSupport.findForObject("FollowTemplateConfigMapper.checkTemplateNameExists", pd);
+        return count > 0;
+    }
+
+
+    /**
+     * 新增规则配置
+     */
+    public Integer insertRule(PageData pd) throws Exception {
+        return daoSupport.save("followTemplateConfigMapper.insertRule", pd);
+    }
+
+    /**
+     * 更新规则配置
+     */
+    public Integer updateRule(PageData pd) throws Exception {
+        return daoSupport.update("followTemplateConfigMapper.updateRule", pd);
+    }
+
+
+
+}

+ 333 - 0
health-system/src/main/resources/mapper/gxhpz/followTemplateConfigMapper.xml

@@ -0,0 +1,333 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="followTemplateConfigMapper">
+
+    <!-- 模版配置结果映射 -->
+    <resultMap id="TemplateConfigResult" type="com.bzd.common.config.dao.PageData">
+        <result property="id" column="id"/>
+        <result property="templateName" column="template_name"/>
+        <result property="templateDesc" column="template_desc"/>
+        <result property="templateType" column="template_type"/>
+        <result property="businessType" column="business_type"/>
+        <result property="status" column="status"/>
+        <result property="storeId" column="store_id"/>
+        <result property="createdBy" column="created_by"/>
+        <result property="createdTime" column="created_time"/>
+        <result property="updatedBy" column="updated_by"/>
+        <result property="updatedTime" column="updated_time"/>
+        <result property="remark" column="remark"/>
+    </resultMap>
+
+    <!-- 字段配置结果映射 -->
+    <resultMap id="FieldConfigResult" type="com.bzd.common.config.dao.PageData">
+        <result property="id" column="id"/>
+        <result property="templateId" column="template_id"/>
+        <result property="fieldCode" column="field_code"/>
+        <result property="fieldName" column="field_name"/>
+        <result property="fieldType" column="field_type"/>
+        <result property="fieldOptions" column="field_options"/>
+        <result property="isRequired" column="is_required"/>
+        <result property="displayOrder" column="display_order"/>
+        <result property="tabCode" column="tab_code"/>
+        <result property="tabName" column="tab_name"/>
+        <result property="isEnabled" column="is_enabled"/>
+        <result property="placeholder" column="placeholder"/>
+        <result property="validationRules" column="validation_rules"/>
+        <result property="createdTime" column="created_time"/>
+    </resultMap>
+
+    <!-- 规则配置结果映射 -->
+    <resultMap id="RuleConfigResult" type="com.bzd.common.config.dao.PageData">
+        <result property="id" column="id"/>
+        <result property="templateId" column="template_id"/>
+        <result property="ruleName" column="rule_name"/>
+        <result property="triggerFieldCode" column="trigger_field_code"/>
+        <result property="triggerFieldValue" column="trigger_field_value"/>
+        <result property="targetFieldCodes" column="target_field_codes"/>
+        <result property="actionType" column="action_type"/>
+        <result property="ruleLogic" column="rule_logic"/>
+        <result property="isEnabled" column="is_enabled"/>
+        <result property="createdTime" column="created_time"/>
+    </resultMap>
+
+    <!-- Tab配置结果映射 -->
+    <resultMap id="TabConfigResult" type="com.bzd.common.config.dao.PageData">
+        <result property="id" column="id"/>
+        <result property="templateId" column="template_id"/>
+        <result property="tabCode" column="tab_code"/>
+        <result property="tabName" column="tab_name"/>
+        <result property="displayOrder" column="display_order"/>
+        <result property="isEnabled" column="is_enabled"/>
+        <result property="iconClass" column="icon_class"/>
+        <result property="createdTime" column="created_time"/>
+    </resultMap>
+
+    <!-- 查询模版配置列表 -->
+    <select id="selectTemplateList" parameterType="pd" resultMap="TemplateConfigResult">
+        SELECT
+        id, template_name, template_desc, template_type, status, store_id,
+        created_by, created_time, updated_by, updated_time, remark
+        FROM s_follow_template_config
+        WHERE 1=1
+        <if test="templateName != null and templateName != ''">
+            AND template_name LIKE CONCAT('%', #{templateName}, '%')
+        </if>
+        <if test="status != null and status != ''">
+            AND status = #{status}
+        </if>
+        <if test="storeId != null and storeId != ''">
+            AND (store_id = #{storeId} OR store_id IS NULL)
+        </if>
+        ORDER BY created_time DESC
+    </select>
+
+    <!-- 根据ID查询模版配置 -->
+    <select id="selectTemplateById" parameterType="pd" resultMap="TemplateConfigResult">
+        SELECT
+            id, template_name, template_desc, template_type, status, store_id,
+            created_by, created_time, updated_by, updated_time, remark,business_type
+        FROM s_follow_template_config
+        WHERE id = #{id}
+    </select>
+
+    <!-- 新增模版配置 -->
+    <insert id="insertTemplate" parameterType="pd" useGeneratedKeys="true" keyProperty="id">
+        INSERT INTO s_follow_template_config (
+            template_name, template_desc, template_type, status, store_id,
+            created_by, created_time, remark,business_type
+        ) VALUES (
+                     #{templateName}, #{templateDesc}, #{templateType}, #{status}, #{storeId},
+                     #{createdBy}, #{createdTime}, #{remark},#{businessType}
+                 )
+    </insert>
+
+    <!-- 修改模版配置 -->
+    <update id="updateTemplate" parameterType="pd">
+        UPDATE s_follow_template_config
+        SET template_name = #{templateName},
+            template_desc = #{templateDesc},
+            status = #{status},
+            updated_by = #{updatedBy},
+            updated_time = #{updatedTime},
+            remark = #{remark},
+            business_type = #{businessType},
+        WHERE id = #{id}
+    </update>
+
+    <!-- 删除模版配置 -->
+    <delete id="deleteTemplate" parameterType="pd">
+        DELETE FROM s_follow_template_config WHERE id = #{id}
+    </delete>
+
+    <!-- 更新模版状态 -->
+    <update id="updateTemplateStatus" parameterType="pd">
+        UPDATE s_follow_template_config
+        SET status = #{status},
+            updated_by = #{updatedBy},
+            updated_time = #{updatedTime}
+        WHERE id = #{id}
+    </update>
+
+    <!-- 查询字段配置列表 -->
+    <select id="selectFieldList" parameterType="pd" resultMap="FieldConfigResult">
+        SELECT
+        id, template_id, field_code, field_name, field_type, field_options,
+        is_required, display_order, tab_code, tab_name, is_enabled,
+        placeholder, validation_rules, created_time
+        FROM s_follow_template_fields
+        WHERE template_id = #{templateId}
+        <if test="isEnabled != null and isEnabled != ''">
+            AND is_enabled = #{isEnabled}
+        </if>
+        ORDER BY tab_code, display_order
+    </select>
+
+    <!-- 新增字段配置 -->
+    <insert id="insertField" parameterType="pd">
+        INSERT INTO s_follow_template_fields (
+            template_id, field_code, field_name, field_type, field_options,
+            is_required, display_order, tab_code, tab_name, is_enabled,
+            placeholder, validation_rules, created_time
+        ) VALUES (
+                     #{templateId}, #{fieldCode}, #{fieldName}, #{fieldType}, #{fieldOptions},
+                     #{isRequired}, #{displayOrder}, #{tabCode}, #{tabName}, #{isEnabled},
+                     #{placeholder}, #{validationRules}, #{createdTime}
+                 )
+    </insert>
+
+    <!-- 删除字段配置 -->
+    <delete id="deleteFieldByIds" parameterType="java.util.List">
+        DELETE FROM s_follow_template_fields WHERE id IN
+        <foreach collection="list" item="id" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+    </delete>
+
+    <!-- 根据模版ID删除字段配置 -->
+    <delete id="deleteFieldsByTemplateId" parameterType="pd">
+        DELETE FROM s_follow_template_fields WHERE template_id = #{templateId}
+    </delete>
+
+    <!-- 查询规则配置列表 -->
+    <select id="selectRuleList" parameterType="pd" resultMap="RuleConfigResult">
+        SELECT
+        id, template_id, rule_name, trigger_field_code, trigger_field_value,
+        target_field_codes, action_type, rule_logic, is_enabled, created_time
+        FROM s_follow_field_rules
+        WHERE template_id = #{templateId}
+        <if test="isEnabled != null and isEnabled != ''">
+            AND is_enabled = #{isEnabled}
+        </if>
+        ORDER BY created_time DESC
+    </select>
+
+    <!-- 新增规则配置 -->
+    <insert id="insertRule" parameterType="pd">
+        INSERT INTO s_follow_field_rules (
+            template_id, rule_name, trigger_field_code, trigger_field_value,
+            target_field_codes, action_type, rule_logic, is_enabled, created_time
+        ) VALUES (
+                     #{templateId}, #{ruleName}, #{triggerFieldCode}, #{triggerFieldValue},
+                     #{targetFieldCodes}, #{actionType}, #{ruleLogic}, #{isEnabled}, #{createdTime}
+                 )
+    </insert>
+
+
+
+    <!-- 查询Tab配置列表 -->
+    <select id="selectTabList" parameterType="pd" resultMap="TabConfigResult">
+        SELECT
+        id, template_id, tab_code, tab_name, display_order, is_enabled,
+        icon_class, created_time
+        FROM s_follow_template_tabs
+        WHERE template_id = #{templateId}
+        <if test="isEnabled != null and isEnabled != ''">
+            AND is_enabled = #{isEnabled}
+        </if>
+        ORDER BY display_order
+    </select>
+
+    <!-- 新增Tab配置 -->
+    <insert id="insertTab" parameterType="pd">
+        INSERT INTO s_follow_template_tabs (
+            template_id, tab_code, tab_name, display_order, is_enabled,
+            icon_class, created_time
+        ) VALUES (
+                     #{templateId}, #{tabCode}, #{tabName}, #{displayOrder}, #{isEnabled},
+                     #{iconClass}, #{createdTime}
+                 )
+    </insert>
+
+    <!-- 根据模版ID删除Tab配置 -->
+    <delete id="deleteTabsByTemplateId" parameterType="pd">
+        DELETE FROM s_follow_template_tabs WHERE template_id = #{templateId}
+    </delete>
+
+    <!-- 批量保存字段配置 -->
+    <insert id="batchInsertFields" parameterType="java.util.List">
+        INSERT INTO s_follow_template_fields (
+        template_id, field_code, field_name, field_type, field_options,
+        is_required, display_order, tab_code, tab_name, is_enabled,
+        placeholder, validation_rules, created_time
+        ) VALUES
+        <foreach collection="list" item="item" separator=",">
+            (
+            #{item.templateId}, #{item.fieldCode}, #{item.fieldName},
+            #{item.fieldType}, #{item.fieldOptions}, #{item.isRequired},
+            #{item.displayOrder}, #{item.tabCode}, #{item.tabName},
+            #{item.isEnabled}, #{item.placeholder}, #{item.validationRules},
+            #{item.createdTime}
+            )
+        </foreach>
+    </insert>
+
+    <!-- 批量保存Tab配置 -->
+    <insert id="batchInsertTabs" parameterType="java.util.List">
+        INSERT INTO s_follow_template_tabs (
+        template_id, tab_code, tab_name, display_order, is_enabled,
+        icon_class, created_time
+        ) VALUES
+        <foreach collection="list" item="item" separator=",">
+            (
+            #{item.templateId}, #{item.tabCode}, #{item.tabName},
+            #{item.displayOrder}, #{item.isEnabled}, #{item.iconClass},
+            #{item.createdTime}
+            )
+        </foreach>
+    </insert>
+
+    <!-- 批量保存规则配置 -->
+    <insert id="batchInsertRules" parameterType="java.util.List">
+        INSERT INTO s_follow_field_rules (
+        template_id, rule_name, trigger_field_code, trigger_field_value,
+        target_field_codes, action_type, rule_logic, is_enabled, created_time
+        ) VALUES
+        <foreach collection="list" item="item" separator=",">
+            (
+            #{item.templateId}, #{item.ruleName}, #{item.triggerFieldCode},
+            #{item.triggerFieldValue}, #{item.targetFieldCodes}, #{item.actionType},
+            #{item.ruleLogic}, #{item.isEnabled}, #{item.createdTime}
+            )
+        </foreach>
+    </insert>
+
+    <!-- 查询模版使用情况 -->
+    <select id="selectTemplateUsage" parameterType="pd" resultType="int">
+        SELECT COUNT(1)
+        FROM s_gxhpz_follow_up_task
+        WHERE template_config_id = #{templateId}
+    </select>
+
+    <!-- 获取字段的字典选项 -->
+    <select id="selectFieldOptions" parameterType="pd" resultType="com.bzd.common.config.dao.PageData">
+        SELECT dict_code as value, dict_label as text
+        FROM sys_dict_data
+        WHERE dict_type = #{dictType}
+          AND status = '0'
+        ORDER BY dict_sort
+    </select>
+
+
+
+
+    <!-- 删除规则配置 -->
+    <delete id="deleteRulesByTemplateId" parameterType="pd">
+        DELETE FROM s_follow_field_rules WHERE template_id = #{templateId}
+    </delete>
+
+    <!-- 更新规则配置 -->
+    <update id="updateRule" parameterType="pd">
+        UPDATE s_follow_field_rules
+        SET rule_name = #{ruleName},
+            trigger_field_code = #{triggerFieldCode},
+            trigger_field_value = #{triggerFieldValue},
+            target_field_codes = #{targetFieldCodes},
+            action_type = #{actionType},
+            rule_logic = #{ruleLogic},
+            is_enabled = #{isEnabled},
+            updated_time = #{updatedTime}
+        WHERE id = #{id}
+    </update>
+
+    <!-- 根据ID查询规则 -->
+    <select id="selectRuleById" parameterType="pd" resultMap="RuleConfigResult">
+        SELECT
+            id, template_id, rule_name, trigger_field_code, trigger_field_value,
+            target_field_codes, action_type, rule_logic, is_enabled, created_time
+        FROM s_follow_field_rules
+        WHERE id = #{id}
+    </select>
+
+    <!-- 更新规则状态 -->
+    <update id="updateRuleStatus" parameterType="pd">
+        UPDATE s_follow_field_rules
+        SET is_enabled = #{isEnabled},
+            updated_time = #{updatedTime}
+        WHERE id = #{id}
+    </update>
+
+    <!-- 删除单个规则 -->
+    <delete id="deleteRuleById" parameterType="pd">
+        DELETE FROM s_follow_field_rules WHERE id = #{id}
+    </delete>
+</mapper>