Просмотр исходного кода

知识库,文章分类调整

徐滕 2 недель назад
Родитель
Сommit
ea1bd1604b

+ 6 - 0
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/dao/WorkKnowledgeBaseShareInfoDao.java

@@ -50,4 +50,10 @@ public interface WorkKnowledgeBaseShareInfoDao extends CrudDao<WorkKnowledgeBase
      */
      */
     List<Map<String, Object>> findDuplicateFilePaths(@org.apache.ibatis.annotations.Param("name") String name,
     List<Map<String, Object>> findDuplicateFilePaths(@org.apache.ibatis.annotations.Param("name") String name,
                                                       @org.apache.ibatis.annotations.Param("excludeId") String excludeId);
                                                       @org.apache.ibatis.annotations.Param("excludeId") String excludeId);
+
+    /**
+     * 分类调整:仅更新 tree_node_id
+     * @param entity 包含 id、treeNodeId、updateBy、updateDate
+     */
+    int updateCategory(WorkKnowledgeBaseShareInfo entity);
 }
 }

+ 43 - 0
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/service/WorkKnowledgeBaseShareService.java

@@ -497,6 +497,49 @@ public class WorkKnowledgeBaseShareService extends CrudService<WorkKnowledgeBase
     }
     }
 
 
     /**
     /**
+     * 分类调整:更新文件的归属分类节点 + 替换动态字段值
+     * @param fileId 文件ID
+     * @param newTreeNodeId 新的树节点ID
+     * @param newDynamicValues 新的动态字段值列表(可为null)
+     */
+    @Transactional(readOnly = false)
+    public void changeCategory(String fileId, String newTreeNodeId, List<WorkKnowledgeBaseDynamicValueInfo> newDynamicValues) {
+        WorkKnowledgeBaseShareInfo entity = dao.get(fileId);
+        if (entity == null) {
+            throw new RuntimeException("文件记录不存在");
+        }
+        // 校验新节点是否存在
+        WorkKnowledgeBaseTreeInfo newTreeInfo = getTreeInfoById(newTreeNodeId);
+        if (newTreeInfo == null) {
+            throw new RuntimeException("目标分类节点不存在");
+        }
+        // 1. 更新 tree_node_id
+        entity.setTreeNodeId(newTreeNodeId);
+        entity.setRootId(newTreeInfo.getRootId());
+        entity.preUpdate();
+        dao.updateCategory(entity);
+
+        // 2. 逻辑删除旧的动态字段值
+        WorkKnowledgeBaseDynamicValueInfo delEntity = new WorkKnowledgeBaseDynamicValueInfo();
+        delEntity.setFileId(fileId);
+        delEntity.preUpdate();
+        dynamicValueInfoDao.deleteByFileId(delEntity);
+
+        // 3. 插入新的动态字段值
+        if (newDynamicValues != null) {
+            for (WorkKnowledgeBaseDynamicValueInfo valueInfo : newDynamicValues) {
+                if (StringUtils.isBlank(valueInfo.getDynamicFieldId())) {
+                    continue;
+                }
+                valueInfo.setId(IdGen.uuid());
+                valueInfo.setFileId(fileId);
+                valueInfo.preInsert();
+                dynamicValueInfoDao.insert(valueInfo);
+            }
+        }
+    }
+
+    /**
      * 判断附件列表中是否存在有效(未删除的)附件
      * 判断附件列表中是否存在有效(未删除的)附件
      */
      */
     private boolean hasValidAttachment(List<Workattachment> attachments) {
     private boolean hasValidAttachment(List<Workattachment> attachments) {

+ 173 - 0
src/main/java/com/jeeplus/modules/WorkKnowledgeBase/web/WorkKnowledgeBaseShareController.java

@@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
 import java.util.Set;
 import java.util.Set;
@@ -958,6 +959,178 @@ public class WorkKnowledgeBaseShareController extends BaseController {
     }
     }
 
 
     /**
     /**
+     * 分类调整页面:显示原数据 + 新分类选择
+     */
+    @RequiresPermissions("workKnowledgeBase:share:adjustCategory")
+    @RequestMapping(value = "changeCategoryForm")
+    public String changeCategoryForm(@RequestParam String id, Model model) {
+        WorkKnowledgeBaseShareInfo entity = shareService.get(id);
+        if (entity == null) {
+            addMessage(model, "记录不存在!");
+            return "error";
+        }
+
+        // 加载原分类信息
+        String treeNodeId = entity.getTreeNodeId();
+        WorkKnowledgeBaseTreeInfo currentTreeInfo = shareService.getTreeInfoById(treeNodeId);
+        String currentRootId = shareService.getRootIdByNodeId(treeNodeId);
+
+        // 加载原动态字段配置及已有值
+        List<WorkKnowledgeBaseDynamicInfo> originalDynamicFields = new ArrayList<>();
+        if (StringUtils.isNotBlank(currentRootId)) {
+            originalDynamicFields = shareService.findDynamicFields(currentRootId);
+        }
+        Map<String, String> originalDynValues = new HashMap<>();
+        List<WorkKnowledgeBaseDynamicValueInfo> existValues = shareService.findDynamicValuesByFileId(id);
+        if (existValues != null) {
+            for (WorkKnowledgeBaseDynamicValueInfo val : existValues) {
+                originalDynValues.put(val.getDynamicFieldId(), val.getFieldValue());
+            }
+        }
+
+        // 查询创建人名称(get查询SQL只映射了createBy.id,未join sys_user表)
+        String createByName = "";
+        if (entity.getCreateBy() != null && StringUtils.isNotBlank(entity.getCreateBy().getId())) {
+            com.jeeplus.modules.sys.entity.User createUser = UserUtils.get(entity.getCreateBy().getId());
+            if (createUser != null) {
+                createByName = createUser.getName();
+            }
+        }
+
+        // 构建当前分类的完整路径(从根节点到当前节点,用-连接)
+        String currentCategoryPath = "";
+        if (currentTreeInfo != null) {
+            List<String> pathNames = new ArrayList<>();
+            String parentIds = currentTreeInfo.getParentIds();
+            if (StringUtils.isNotBlank(parentIds)) {
+                String[] ids = parentIds.split(",");
+                for (String pid : ids) {
+                    String trimmed = pid.trim();
+                    if (StringUtils.isNotBlank(trimmed) && !"0".equals(trimmed)) {
+                        WorkKnowledgeBaseTreeInfo ancestor = shareService.getTreeInfoById(trimmed);
+                        if (ancestor != null) {
+                            pathNames.add(ancestor.getTreeName());
+                        }
+                    }
+                }
+            }
+            pathNames.add(currentTreeInfo.getTreeName());
+            currentCategoryPath = StringUtils.join(pathNames, "—");
+        }
+
+        model.addAttribute("entity", entity);
+        model.addAttribute("currentTreeInfo", currentTreeInfo);
+        model.addAttribute("currentRootId", currentRootId);
+        model.addAttribute("currentCategoryPath", currentCategoryPath);
+        model.addAttribute("originalDynamicFields", originalDynamicFields);
+        model.addAttribute("originalDynValues", originalDynValues);
+        model.addAttribute("createByName", createByName);
+        return "modules/WorkKnowledgeBase/workKnowledgeBaseShareChangeCategory";
+    }
+
+    /**
+     * 分类调整提交:更新归属分类 + 替换动态字段值
+     */
+    @RequiresPermissions("workKnowledgeBase:share:adjustCategory")
+    @RequestMapping(value = "changeCategorySave")
+    @ResponseBody
+    public Map<String, Object> changeCategorySave(@RequestParam String id,
+                                                   @RequestParam String newTreeNodeId,
+                                                   @RequestParam(required = false) String newDynamicValuesJson) {
+        Map<String, Object> result = new HashMap<>();
+        try {
+            if (StringUtils.isBlank(newTreeNodeId)) {
+                result.put("success", false);
+                result.put("message", "请选择目标分类");
+                return result;
+            }
+            // 解析新的动态字段值
+            List<WorkKnowledgeBaseDynamicValueInfo> newDynamicValues = null;
+            if (StringUtils.isNotBlank(newDynamicValuesJson)) {
+                newDynamicValuesJson = newDynamicValuesJson.replace("&quot;", "\"");
+                newDynamicValues = JSON.parseArray(newDynamicValuesJson, WorkKnowledgeBaseDynamicValueInfo.class);
+            }
+            shareService.changeCategory(id, newTreeNodeId, newDynamicValues);
+            result.put("success", true);
+            result.put("message", "分类调整成功");
+        } catch (Exception e) {
+            result.put("success", false);
+            result.put("message", "分类调整失败:" + e.getMessage());
+        }
+        return result;
+    }
+
+    /**
+     * 根据根节点ID查询所有子孙节点(Ajax,用于分类调整页面的树节点下拉)
+     */
+    @RequiresPermissions("workKnowledgeBase:share:adjustCategory")
+    @RequestMapping(value = "getTreeNodesByRootId")
+    @ResponseBody
+    public List<Map<String, String>> getTreeNodesByRootId(@RequestParam String rootId) {
+        List<Map<String, String>> nodeList = new ArrayList<>();
+        List<WorkKnowledgeBaseTreeInfo> descendants = shareService.findAllDescendantsByRootId(rootId);
+        if (descendants != null) {
+            for (WorkKnowledgeBaseTreeInfo node : descendants) {
+                Map<String, String> item = new HashMap<>();
+                item.put("id", node.getId());
+                item.put("treeName", node.getTreeName());
+                item.put("parentIds", node.getParentIds());
+                item.put("rootId", rootId);
+                nodeList.add(item);
+            }
+        }
+        return nodeList;
+    }
+
+    /**
+     * 查询所有树节点(含根节点,返回树形嵌套结构,用于layui.dropdown渲染)
+     */
+    @RequiresPermissions("workKnowledgeBase:share:adjustCategory")
+    @RequestMapping(value = "getAllTreeNodes")
+    @ResponseBody
+    public List<Map<String, Object>> getAllTreeNodes() {
+        List<Map<String, Object>> treeList = new ArrayList<>();
+        List<WorkKnowledgeBaseTreeInfo> rootNodes = shareService.findRootNodes();
+        if (rootNodes != null) {
+            for (WorkKnowledgeBaseTreeInfo root : rootNodes) {
+                Map<String, Object> nodeMap = buildTreeNodeMap(root);
+                treeList.add(nodeMap);
+            }
+        }
+        return treeList;
+    }
+
+    /**
+     * 递归构建树节点Map(含child子节点数组),用于layui.dropdown树形菜单
+     */
+    private Map<String, Object> buildTreeNodeMap(WorkKnowledgeBaseTreeInfo node) {
+        Map<String, Object> map = new LinkedHashMap<>();
+        map.put("id", node.getId());
+        map.put("title", node.getTreeName());
+        List<WorkKnowledgeBaseTreeInfo> children = shareService.findDirectChildrenByParentId(node.getId());
+        if (children != null && !children.isEmpty()) {
+            map.put("type", "group");
+            map.put("isSpreadItem", false);
+            List<Map<String, Object>> childList = new ArrayList<>();
+            for (WorkKnowledgeBaseTreeInfo child : children) {
+                childList.add(buildTreeNodeMap(child));
+            }
+            map.put("child", childList);
+        }
+        return map;
+    }
+
+    /**
+     * 根据根节点ID查询动态字段配置(Ajax,用于分类调整页面动态加载新分类的灵活字段)
+     */
+    @RequiresPermissions("workKnowledgeBase:share:adjustCategory")
+    @RequestMapping(value = "getDynamicFieldsByRootId")
+    @ResponseBody
+    public List<WorkKnowledgeBaseDynamicInfo> getDynamicFieldsByRootId(@RequestParam String rootId) {
+        return shareService.findDynamicFields(rootId);
+    }
+
+    /**
      * 判断给定的treeNodeId是否属于"公司内部发文"根节点(parent_id=0)
      * 判断给定的treeNodeId是否属于"公司内部发文"根节点(parent_id=0)
      */
      */
     private boolean isInternalDocByTreeNodeId(String treeNodeId) {
     private boolean isInternalDocByTreeNodeId(String treeNodeId) {

+ 9 - 0
src/main/resources/mappings/modules/WorkKnowledgeBase/WorkKnowledgeBaseShareInfoDao.xml

@@ -318,6 +318,15 @@
         WHERE id = #{id} AND del_flag = '0'
         WHERE id = #{id} AND del_flag = '0'
     </update>
     </update>
 
 
+    <!-- 分类调整:更新 tree_node_id 和 root_id -->
+    <update id="updateCategory">
+        UPDATE work_knowledge_base_share_info SET
+            tree_node_id  = #{treeNodeId},
+            update_by     = #{updateBy.id},
+            update_date   = #{updateDate}
+        WHERE id = #{id}
+    </update>
+
     <!-- 根据文件名称查询重名文件的树节点信息(排除问答答疑分类) -->
     <!-- 根据文件名称查询重名文件的树节点信息(排除问答答疑分类) -->
     <select id="findDuplicateFilePaths" resultType="java.util.HashMap">
     <select id="findDuplicateFilePaths" resultType="java.util.HashMap">
         SELECT DISTINCT
         SELECT DISTINCT

+ 319 - 0
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBaseShareChangeCategory.jsp

@@ -0,0 +1,319 @@
+<%@ page contentType="text/html;charset=UTF-8" %>
+<%@ include file="/webpage/include/taglib.jsp"%>
+<html>
+<head>
+    <title>分类调整</title>
+    <meta name="decorator" content="default"/>
+    <script type="text/javascript" src="${ctxStatic}/layui/layui.js"></script>
+    <link rel='stylesheet' type="text/css" href="${ctxStatic}/layui/css/layui.css"/>
+    <script src="${ctxStatic}/common/html/js/script.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/helloweba_editable-select/jquery.editable-select.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/iCheck/icheck.min.js"></script>
+    <script type="text/javascript" src="${ctxStatic}/layui/layuidown.js"></script>
+    <link rel='stylesheet' type="text/css" href="${ctxStatic}/layui/layuidown.css"/>
+    <link rel='stylesheet' type="text/css" href="${ctxStatic}/helloweba_editable-select/jquery.editable-select.min.css"/>
+    <style>
+        .tree-dropdown-panel {
+            display: none;
+            position: absolute;
+            z-index: 9999;
+            background: #fff;
+            border: 1px solid #e6e6e6;
+            border-radius: 2px;
+            box-shadow: 0 2px 4px rgba(0,0,0,.12);
+        }
+        .tree-results {
+            max-height: 280px;
+            overflow-y: auto;
+            padding: 5px 0;
+        }
+        .tree-node-item {
+            padding: 6px 15px;
+            cursor: pointer;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            font-size: 14px;
+        }
+        .tree-node-item:hover {
+            background-color: #f2f2f2;
+        }
+        .tree-group-toggle {
+            cursor: pointer;
+            display: inline-block;
+            width: 16px;
+            text-align: center;
+            color: #999;
+            font-size: 12px;
+        }
+        .tree-leaf-spacer {
+            display: inline-block;
+            width: 16px;
+        }
+    </style>
+    <script type="text/javascript">
+        function doSubmit(i) {
+            var newTreeNodeId = $('#newTreeNodeId').val();
+            if (!newTreeNodeId) {
+                top.layer.msg('请选择目标分类节点', {icon: 0});
+                return false;
+            }
+            // 收集新的动态字段值
+            collectNewDynamicValues();
+            // 提交
+            var formData = {
+                id: '${entity.id}',
+                newTreeNodeId: newTreeNodeId,
+                newDynamicValuesJson: $('#newDynamicValuesJson').val()
+            };
+            $.ajax({
+                type: 'POST',
+                url: '${ctx}/workKnowledgeBase/share/changeCategorySave',
+                data: formData,
+                dataType: 'json',
+                success: function(res) {
+                    if (res.success) {
+                        top.layer.msg('分类调整成功', {icon: 1});
+                        // 刷新父页面列表
+                        setTimeout(function() {
+                            var parentWin = top.layer.getFrameIndex(window.name);
+                            top.layer.close(parentWin);
+                            if (window.parent && window.parent.search) {
+                                window.parent.search();
+                            }
+                        }, 800);
+                    } else {
+                        top.layer.msg(res.message || '操作失败', {icon: 0});
+                    }
+                },
+                error: function() {
+                    top.layer.msg('请求失败', {icon: 2});
+                }
+            });
+            return false;
+        }
+
+        function collectNewDynamicValues() {
+            var values = [];
+            $('.new-dynamic-field-input').each(function() {
+                var fieldId = $(this).data('field-id');
+                var fieldKey = $(this).data('field-key');
+                var val = $(this).val();
+                values.push({dynamicFieldId: fieldId, fieldKey: fieldKey, fieldValue: val || ''});
+            });
+            $('#newDynamicValuesJson').val(JSON.stringify(values));
+        }
+
+        $(document).ready(function() {
+            var treeData = [];
+            var nodeToRootMap = {};
+            var expandedNodes = {};
+
+            // 获取树形数据
+            $.ajax({
+                type: 'GET',
+                url: '${ctx}/workKnowledgeBase/share/getAllTreeNodes',
+                success: function(data) {
+                    treeData = data;
+                    buildNodeRootMap(treeData, null);
+                    renderTree();
+                }
+            });
+
+            // 构建 nodeId → rootId 映射
+            function buildNodeRootMap(nodes, currentRootId) {
+                for (var i = 0; i < nodes.length; i++) {
+                    var n = nodes[i];
+                    var rid = currentRootId || n.id;
+                    nodeToRootMap[n.id] = rid;
+                    if (n.child && n.child.length > 0) {
+                        buildNodeRootMap(n.child, rid);
+                    }
+                }
+            }
+
+            // 按钮点击切换面板
+            $('#treeNodeDropdownBtn').on('click', function(e) {
+                e.stopPropagation();
+                $('#treeDropdownPanel').toggle();
+            });
+            // 点击面板内部不关闭
+            $('#treeDropdownPanel').on('click', function(e) {
+                e.stopPropagation();
+            });
+            // 点击外部关闭面板
+            $(document).on('click', function() {
+                $('#treeDropdownPanel').hide();
+            });
+
+            // 渲染可折叠树
+            function renderTree() {
+                $('#treeResults').html(buildTreeHtml(treeData, 0));
+            }
+
+            // 构建可折叠树HTML
+            function buildTreeHtml(nodes, level) {
+                var html = '';
+                for (var i = 0; i < nodes.length; i++) {
+                    var n = nodes[i];
+                    var hasChild = n.child && n.child.length > 0;
+                    var indent = level * 20;
+                    if (hasChild) {
+                        var isExpanded = expandedNodes[n.id];
+                        var arrow = isExpanded ? '&#9660;' : '&#9654;';
+                        html += '<div class="tree-node-item" style="padding-left:' + (15 + indent) + 'px" data-node-id="' + n.id + '" data-toggle="true">';
+                        html += '<span class="tree-group-toggle">' + arrow + '</span> ' + n.title;
+                        html += '</div>';
+                        if (isExpanded) {
+                            html += buildTreeHtml(n.child, level + 1);
+                        }
+                    } else {
+                        html += '<div class="tree-node-item" style="padding-left:' + (15 + indent + 16) + 'px" data-id="' + n.id + '" data-title="' + n.title + '">';
+                        html += '<span class="tree-leaf-spacer"></span>' + n.title;
+                        html += '</div>';
+                    }
+                }
+                return html;
+            }
+
+            // 点击树节点(展开/收起 或 选择)
+            $('#treeResults').on('click', '.tree-node-item', function() {
+                if ($(this).data('toggle')) {
+                    var nodeId = $(this).data('node-id');
+                    expandedNodes[nodeId] = !expandedNodes[nodeId];
+                    renderTree();
+                } else if ($(this).data('id')) {
+                    var id = $(this).data('id');
+                    var title = $(this).data('title');
+                    selectNode(id, title);
+                }
+            });
+
+            // 选中节点
+            function selectNode(id, title) {
+                $('#treeNodeDropdownBtn span').text(title);
+                $('#newTreeNodeId').val(id);
+                var rootId = nodeToRootMap[id];
+                $('#newRootIdHidden').val(rootId);
+                $('#treeDropdownPanel').hide();
+                loadDynamicFields(rootId);
+            }
+
+            // 加载灵活字段
+            function loadDynamicFields(rootId) {
+                $.ajax({
+                    type: 'GET',
+                    url: '${ctx}/workKnowledgeBase/share/getDynamicFieldsByRootId?rootId=' + rootId,
+                    success: function(fields) {
+                        var html = '';
+                        if (fields && fields.length > 0) {
+                            for (var i = 0; i < fields.length; i++) {
+                                var f = fields[i];
+                                var labelClass = f.fieldLabel.length > 5 ? 'layui-form-label double-line' : 'layui-form-label';
+                                html += '<div class="layui-item layui-col-sm6 lw6">';
+                                html += '<label class="' + labelClass + '">' + f.fieldLabel + ':</label>';
+                                html += '<div class="layui-input-block">';
+                                html += '<input type="text" class="form-control layui-input new-dynamic-field-input" ';
+                                html += 'data-field-id="' + f.id + '" data-field-key="' + f.fieldKey + '" ';
+                                html += 'placeholder="请输入' + f.fieldLabel + '">';
+                                html += '</div></div>';
+                            }
+                        } else {
+                            html = '<div class="layui-item layui-col-sm12"><div style="color:#999;padding:10px 0;">该分类暂无灵活字段配置</div></div>';
+                        }
+                        $('#newDynamicFieldsContainer').html(html);
+                    }
+                });
+            }
+        });
+    </script>
+</head>
+<body>
+<div class="single-form">
+    <div class="container">
+        <input type="hidden" id="newDynamicValuesJson" name="newDynamicValuesJson"/>
+        <input type="hidden" id="newRootIdHidden" name="newRootIdHidden"/>
+
+        <%-- ========== 原数据信息 ========== --%>
+        <div class="form-group layui-row">
+            <div class="form-group-label"><h2>原数据信息</h2></div>
+
+            <div class="layui-item layui-col-sm6 lw6">
+                <label class="layui-form-label">文件名称:</label>
+                <div class="layui-input-block">
+                    <input type="text" class="form-control layui-input" value="<c:out value='${entity.name}'/>" readonly style="background-color:#fff;"/>
+                </div>
+            </div>
+
+            <div class="layui-item layui-col-sm6 lw6">
+                <label class="layui-form-label">当前分类:</label>
+                <div class="layui-input-block">
+                    <input type="text" class="form-control layui-input" value="<c:out value='${currentTreeInfo.treeName}'/>" readonly style="background-color:#fff;color:#1E9FFF;font-weight:bold;"/>
+                    <div style="color:#FF5722;font-size:12px;line-height:20px;padding-top:2px;"><c:out value="${currentCategoryPath}"/></div>
+                </div>
+            </div>
+
+            <div class="layui-item layui-col-sm6 lw6">
+                <label class="layui-form-label">内容属性:</label>
+                <div class="layui-input-block">
+                    <input type="text" class="form-control layui-input" value="<c:choose><c:when test='${entity.contentAttribute == "0"}'>原创</c:when><c:when test='${entity.contentAttribute == "1"}'>转载</c:when><c:otherwise>-</c:otherwise></c:choose>" readonly style="background-color:#fff;"/>
+                </div>
+            </div>
+
+            <div class="layui-item layui-col-sm6 lw6">
+                <label class="layui-form-label">创建人:</label>
+                <div class="layui-input-block">
+                    <input type="text" class="form-control layui-input" value="<c:out value='${createByName}'/>" readonly style="background-color:#fff;"/>
+                </div>
+            </div>
+        </div>
+
+        <%-- 原灵活字段值 --%>
+        <c:if test="${not empty originalDynamicFields}">
+            <div class="form-group layui-row">
+                <div class="form-group-label"><h2>原信息值</h2></div>
+                <c:forEach items="${originalDynamicFields}" var="field">
+                    <div class="layui-item layui-col-sm6 lw6">
+                        <c:choose>
+                            <c:when test="${fn:length(field.fieldLabel) > 5}">
+                                <label class="layui-form-label double-line"><c:out value="${field.fieldLabel}"/>:</label>
+                            </c:when>
+                            <c:otherwise>
+                                <label class="layui-form-label"><c:out value="${field.fieldLabel}"/>:</label>
+                            </c:otherwise>
+                        </c:choose>
+                        <div class="layui-input-block">
+                            <input type="text" class="form-control layui-input" value="<c:out value='${originalDynValues[field.id]}' default='-'/>" readonly style="background-color:#fff;"/>
+                        </div>
+                    </div>
+                </c:forEach>
+            </div>
+        </c:if>
+
+        <%-- ========== 调整为新分类 ========== --%>
+        <div class="form-group layui-row">
+            <div class="form-group-label"><h2>调整为新分类</h2></div>
+
+            <div class="layui-item layui-col-sm6 lw6">
+                <label class="layui-form-label"><span class="require-item">*</span>目标分类:</label>
+                <div class="layui-input-block" style="position:relative;">
+                    <button type="button" class="layui-btn layui-btn-primary" style="width: 100%;text-align: left" id="treeNodeDropdownBtn">
+                        <span>-- 请选择目标分类 --</span>
+                        <i class="layui-icon layui-icon-down layui-font-12" style="float: right"></i>
+                    </button>
+                    <input type="hidden" id="newTreeNodeId" value=""/>
+                    <div id="treeDropdownPanel" class="tree-dropdown-panel" style="width:100%;">
+                        <div id="treeResults" class="tree-results"></div>
+                    </div>
+                </div>
+            </div>
+
+            <%-- 新分类的灵活字段动态加载区域 --%>
+            <div id="newDynamicFieldsContainer" style="width:100%;clear:both;"></div>
+        </div>
+
+        <div class="form-group layui-row page-end"></div>
+    </div>
+</div>
+</body>
+</html>

+ 27 - 0
src/main/webapp/webpage/modules/WorkKnowledgeBase/workKnowledgeBaseShareList.jsp

@@ -283,6 +283,27 @@
             });
             });
         }
         }
 
 
+        /** 调整分类弹窗 */
+        function openChangeCategoryDialog(id) {
+            top.layer.open({
+                type: 2,
+                area: ['80%', '80%'],
+                title: '调整分类',
+                maxmin: true,
+                content: '${ctx}/workKnowledgeBase/share/changeCategoryForm?id=' + id,
+                skin: 'three-btns',
+                btn: ['保存', '关闭'],
+                btn1: function(index, layero) {
+                    var body = top.layer.getChildFrame('body', index);
+                    var iframeWin = layero.find('iframe')[0];
+                    if (iframeWin.contentWindow.doSubmit(1)) {
+                        // doSubmit 内部已处理关闭和刷新
+                    }
+                },
+                btn2: function(index) { top.layer.close(index); }
+            });
+        }
+
         /** 发起审核 */
         /** 发起审核 */
         function submitAudit(id) {
         function submitAudit(id) {
             layer.open({
             layer.open({
@@ -905,6 +926,11 @@
                         xml += '<a href="javascript:void(0)" onclick="likeFile(\'' + d.id + '\')" class="layui-btn layui-btn-xs layui-bg-red"><i class="fa fa-heart-o"></i> 点赞</a>';
                         xml += '<a href="javascript:void(0)" onclick="likeFile(\'' + d.id + '\')" class="layui-btn layui-btn-xs layui-bg-red"><i class="fa fa-heart-o"></i> 点赞</a>';
                     }
                     }
                 }
                 }
+
+                // 拥有adjustCategory权限的人可以对文档的归属分类进行调整
+                if (d.canAdjustCategory === '1') {
+                    xml += '<a href="javascript:void(0)" onclick="openChangeCategoryDialog(\'' + d.id + '\')" class="layui-btn layui-btn-xs layui-bg-cyan"> 调整分类</a>';
+                }
             
             
                 xml += '</div>';
                 xml += '</div>';
                 return xml;
                 return xml;
@@ -956,6 +982,7 @@
                     </c:if>
                     </c:if>
                     </c:forEach>
                     </c:forEach>
                     ,"currentUserAudited": ${row.currentUserAudited == true}
                     ,"currentUserAudited": ${row.currentUserAudited == true}
+                    <shiro:hasPermission name="workKnowledgeBase:share:adjustCategory">,"canAdjustCategory":"1"</shiro:hasPermission>
                 }
                 }
                 </c:forEach>
                 </c:forEach>
                 </c:when>
                 </c:when>