LIJIAN il y a 1 mois
Parent
commit
999d0a4186

+ 2 - 2
ema-admin/src/main/java/com/ema/admin/modules/system/controller/SysDictDataController.java

@@ -52,7 +52,7 @@ public class SysDictDataController {
      */
     @DeleteMapping("remove/{id}")
     @ApiOperation("根据主键系统字典值表")
-    public boolean remove(@PathVariable @ApiParam("系统字典值表主键") Long id) {
+    public boolean remove(@PathVariable @ApiParam("系统字典值表主键") String id) {
         return sysDictDataService.removeById(id);
     }
 
@@ -89,7 +89,7 @@ public class SysDictDataController {
      */
     @GetMapping("getInfo/{id}")
     @ApiOperation("根据主键获取系统字典值表")
-    public SysDictData getInfo(@PathVariable @ApiParam("系统字典值表主键") Long id) {
+    public SysDictData getInfo(@PathVariable @ApiParam("系统字典值表主键") String id) {
         return sysDictDataService.getById(id);
     }
 

+ 2 - 2
ema-admin/src/main/java/com/ema/admin/modules/system/controller/SysDictTypeController.java

@@ -46,7 +46,7 @@ public class SysDictTypeController {
      */
     @DeleteMapping("remove/{id}")
     @ApiOperation("根据主键系统字典类型表")
-    public boolean remove(@PathVariable @ApiParam("系统字典类型表主键") Long id) {
+    public boolean remove(@PathVariable @ApiParam("系统字典类型表主键") String id) {
         return sysDictTypeService.removeById(id);
     }
 
@@ -81,7 +81,7 @@ public class SysDictTypeController {
      */
     @GetMapping("getInfo/{id}")
     @ApiOperation("根据主键获取系统字典类型表")
-    public SysDictType getInfo(@PathVariable @ApiParam("系统字典类型表主键") Long id) {
+    public SysDictType getInfo(@PathVariable @ApiParam("系统字典类型表主键") String id) {
         return sysDictTypeService.getById(id);
     }
 

+ 5 - 5
ema-admin/src/main/resources/web/js/common.js

@@ -296,14 +296,15 @@ var TableRender = {
                 statusCode: 200,
                 msgName: 'msg',
                 dataName: 'data',
-                countName: 'total'
+                countName: 'count'
             },
             parseData: function(res) {
+                // 兼容多种分页返回格式:total/totalRow/totalRow/size
                 return {
                     code: res.code,
-                    msg: res.msg,
-                    count: res.data ? res.data.totalRow : 0,
-                    data: res.data ? res.data.records : []
+                    msg: res.message,
+                    count: res.data.totalRow || res.data.total || res.data.size || res.data.count || 0,
+                    data: res.data ? (res.data.records || res.data.list || []) : []
                 };
             },
             before: function(req) {
@@ -315,7 +316,6 @@ var TableRender = {
                 }
             }
         };
-
         return table.render($.extend(defaults, options));
     },
     

+ 3 - 1
ema-admin/src/main/resources/web/pages/dict/dict_data_form.html

@@ -87,7 +87,9 @@
                         Common.success(isEdit ? '修改成功' : '添加成功', function() {
                             var index = parent.layer.getFrameIndex(window.name);
                             parent.layer.close(index);
-                            parent.layui.table.reload('tableList');
+                            if (parent.refreshDataList) {
+                                parent.refreshDataList();
+                            }
                         });
                     }
                 });

+ 3 - 1
ema-admin/src/main/resources/web/pages/dict/dict_type_form.html

@@ -77,7 +77,9 @@
                         Common.success(isEdit ? '修改成功' : '添加成功', function() {
                             var index = parent.layer.getFrameIndex(window.name);
                             parent.layer.close(index);
-                            parent.layui.table.reload('tableList');
+                            if (parent.refreshTypeList) {
+                                parent.refreshTypeList();
+                            }
                         });
                     }
                 });

+ 480 - 53
ema-admin/src/main/resources/web/pages/dict/dict_type_list.html

@@ -3,49 +3,300 @@
 <head>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    <title>字典类型管理</title>
+    <title>字典管理</title>
     <link rel="stylesheet" href="../../lib/layui/css/layui.css">
     <style>
-        body { padding: 15px; }
-        .search-form { margin-bottom: 15px; padding: 15px; background: #fff; border-radius: 4px; }
+        body { padding: 10px; overflow: hidden; }
+        .dict-container {
+            display: flex;
+            height: calc(100vh - 60px);
+            gap: 10px;
+        }
+        .dict-left {
+            width: 320px;
+            background: #fff;
+            border-radius: 4px;
+            display: flex;
+            flex-direction: column;
+            overflow: hidden;
+        }
+        .dict-left .panel-header {
+            padding: 12px 15px;
+            border-bottom: 1px solid #eee;
+            background: #fafafa;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+        }
+        .dict-left .panel-header .title {
+            font-size: 14px;
+            font-weight: 600;
+            color: #333;
+        }
+        .dict-left .search-box {
+            padding: 10px;
+            border-bottom: 1px solid #eee;
+            background: #fafafa;
+        }
+        .dict-left .search-box .layui-form-item {
+            margin-bottom: 0;
+        }
+        .dict-left .search-box .layui-input-inline {
+            width: calc(100% - 36px);
+            position: relative;
+        }
+        .dict-left .search-box .layui-input {
+            height: 28px;
+            font-size: 12px;
+            padding-right: 24px;
+        }
+        .dict-left .search-box .input-clear {
+            position: absolute;
+            right: 38px;
+            top: 50%;
+            transform: translateY(-50%);
+            cursor: pointer;
+            color: #999;
+            display: none;
+            font-size: 14px;
+        }
+        .dict-left .search-box .input-clear:hover {
+            color: #666;
+        }
+        .dict-left .search-box .search-btn {
+            margin-left: 6px;
+        }
+        .dict-left .panel-body {
+            flex: 1;
+            overflow: hidden;
+            padding: 0;
+        }
+        .dict-right {
+            flex: 1;
+            background: #fff;
+            border-radius: 4px;
+            display: flex;
+            flex-direction: column;
+            overflow: auto;
+        }
+        .dict-right .panel-header {
+            padding: 12px 15px;
+            border-bottom: 1px solid #eee;
+            background: #fafafa;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+        }
+        .dict-right .panel-header .title {
+            font-size: 14px;
+            font-weight: 600;
+            color: #333;
+        }
+        .dict-right .search-form {
+            padding: 12px 15px;
+            border-bottom: 1px solid #f0f0f0;
+        }
+        .dict-right .panel-body {
+            height: 350px;
+            padding: 0;
+        }
+        .dict-right .table-toolbar {
+            padding: 10px 15px;
+            border-bottom: 1px solid #f0f0f0;
+        }
+        .empty-tip {
+            text-align: center;
+            padding: 60px 20px;
+            color: #999;
+        }
+        .empty-tip i {
+            font-size: 48px;
+            margin-bottom: 15px;
+            color: #ddd;
+        }
+        .type-info-card {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            color: #fff;
+            padding: 20px;
+            border-radius: 4px;
+            margin: 10px;
+            display: flex;
+            justify-content: space-between;
+            align-items: flex-start;
+        }
+        .type-info-card .type-info {
+            flex: 1;
+            min-width: 0;
+        }
+        .type-info-card .type-name {
+            font-size: 20px;
+            font-weight: 600;
+            margin-bottom: 8px;
+        }
+        .type-info-card .type-code {
+            font-size: 13px;
+            opacity: 0.9;
+            display: flex;
+            align-items: center;
+            gap: 8px;
+        }
+        .type-info-card .type-code::before {
+            content: '';
+            display: inline-block;
+            width: 8px;
+            height: 8px;
+            background: rgba(255,255,255,0.6);
+            border-radius: 50%;
+        }
+        .type-info-card .type-actions {
+            display: flex;
+            gap: 8px;
+            flex-shrink: 0;
+        }
+        .type-info-card .type-actions .layui-btn {
+            background: rgba(255,255,255,0.2);
+            border: none;
+            color: #fff;
+        }
+        .type-info-card .type-actions .layui-btn:hover {
+            background: rgba(255,255,255,0.35);
+        }
+        .type-info-card .type-actions .layui-btn-danger {
+            background: rgba(255,59,48,0.6);
+        }
+        .type-info-card .type-actions .layui-btn-danger:hover {
+            background: rgba(255,59,48,0.8);
+        }
+        .type-detail-card {
+            background: #fff;
+            margin: 0 10px 10px 10px;
+            border-radius: 4px;
+            padding: 12px 15px;
+            display: flex;
+            align-items: flex-start;
+            gap: 20px;
+        }
+        .type-detail-card .detail-group {
+            flex: 1;
+            min-width: 0;
+        }
+        .type-detail-card .detail-label {
+            color: #999;
+            font-size: 12px;
+        }
+        .type-detail-card .detail-value {
+            color: #333;
+            font-size: 13px;
+            white-space: nowrap;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            cursor: pointer;
+        }
     </style>
 </head>
 <body>
-    <div class="search-form">
-        <form class="layui-form layui-form-pane" lay-filter="searchForm">
-            <div class="layui-form-item">
-                <div class="layui-inline">
-                    <label class="layui-form-label">字典名称</label>
-                    <div class="layui-input-inline">
-                        <input type="text" name="name" placeholder="请输入字典名称" class="layui-input">
+    <div class="dict-container">
+        <!-- 左侧:字典类型列表 -->
+        <div class="dict-left">
+            <div class="panel-header">
+                <span class="title"><i class="layui-icon layui-icon-app"></i> 字典类型</span>
+                <button class="layui-btn layui-btn-xs layui-btn-normal" id="btnAddType"><i class="layui-icon layui-icon-add-1"></i></button>
+            </div>
+            <div class="search-box">
+                <form class="layui-form" lay-filter="typeSearchForm">
+                    <div class="layui-form-item" style="margin-bottom: 0;">
+                        <div class="layui-inline" style="width: 100%; display: flex;">
+                            <div class="layui-input-inline" style="position: relative;">
+                                <input type="text" name="code" placeholder="类型编码" class="layui-input" id="typeCodeSearch">
+                                <i class="layui-icon layui-icon-close input-clear" id="inputClear">&#x1006;</i>
+                            </div>
+                            <button type="button" class="layui-btn layui-btn-sm search-btn" id="btnSearchType"><i class="layui-icon layui-icon-search"></i></button>
+                        </div>
+                    </div>
+                </form>
+            </div>
+            <div class="panel-body" id="typeListBody">
+                <table id="typeList" lay-filter="typeList"></table>
+            </div>
+        </div>
+        
+        <!-- 右侧:字典数据列表 -->
+        <div class="dict-right">
+            <div class="type-info-card-container">
+                <!-- 字典类型详情卡片 -->
+                <div class="type-info-card" id="typeInfoCard" style="display:none;">
+                    <div class="type-info">
+                        <div class="type-name" id="typeInfoName">-</div>
+                        <div class="type-code" id="typeInfoCode">-</div>
+                    </div>
+                    <div class="type-actions">
+                        <button class="layui-btn layui-btn-xs" id="btnEditType"><i class="layui-icon layui-icon-edit"></i></button>
+                        <button class="layui-btn layui-btn-xs layui-btn-danger" id="btnDelType"><i class="layui-icon layui-icon-delete"></i></button>
                     </div>
                 </div>
-                <div class="layui-inline">
-                    <label class="layui-form-label">字典类型</label>
-                    <div class="layui-input-inline">
-                        <input type="text" name="code" placeholder="请输入字典类型" class="layui-input">
+                <div class="type-detail-card" id="typeDetailCard" style="display:none;">
+                    <div class="detail-group">
+                        <div class="detail-label">备注</div>
+                        <div class="detail-value" id="typeInfoRemark" title="">-</div>
+                    </div>
+                    <div class="detail-group" style="flex-shrink: 0;">
+                        <div class="detail-label">创建时间</div>
+                        <div class="detail-value" id="typeInfoCreateTime">-</div>
                     </div>
                 </div>
-                <div class="layui-inline">
-                    <button type="button" class="layui-btn" id="btnSearch"><i class="layui-icon layui-icon-search"></i> 搜索</button>
-                    <button type="reset" class="layui-btn layui-btn-primary">重置</button>
+
+                <div class="panel-header">
+                    <span class="title"><i class="layui-icon layui-icon-table"></i> <span id="currentTypeName">字典数据</span></span>
+                </div>
+                <div class="search-form">
+                    <form class="layui-form layui-form-pane" lay-filter="searchForm">
+                        <div class="layui-form-item" style="margin-bottom: 0;">
+                            <div class="layui-inline">
+                                <label class="layui-form-label">数据编码</label>
+                                <div class="layui-input-inline">
+                                    <input type="text" name="code" placeholder="编码" class="layui-input">
+                                </div>
+                            </div>
+                            <div class="layui-inline">
+                                <label class="layui-form-label">数据值</label>
+                                <div class="layui-input-inline">
+                                    <input type="text" name="value" placeholder="数据值" class="layui-input">
+                                </div>
+                            </div>
+                            <div class="layui-inline">
+                                <button type="button" class="layui-btn layui-btn-sm" id="btnSearch"><i class="layui-icon layui-icon-search"></i></button>
+                                <button type="reset" class="layui-btn layui-btn-sm layui-btn-primary">重置</button>
+                            </div>
+                        </div>
+                    </form>
+                </div>
+                <div class="table-toolbar">
+                    <button class="layui-btn layui-btn-sm" id="btnAddData"><i class="layui-icon layui-icon-add-1"></i> 添加数据</button>
+                </div>
+                <div class="panel-body">
+                    <div id="emptyTip" class="empty-tip" style="display:none;">
+                        <i class="layui-icon layui-icon-tree"></i>
+                        <p>请从左侧选择一个字典类型</p>
+                    </div>
+                    <table id="tableList" lay-filter="tableList"></table>
                 </div>
             </div>
-        </form>
-    </div>
-    
-    <div class="table-toolbar">
-        <button class="layui-btn layui-btn-sm" id="btnAdd"><i class="layui-icon layui-icon-add-1"></i> 添加</button>
+        </div>
     </div>
     
-    <table id="tableList" lay-filter="tableList"></table>
-    
     <script type="text/html" id="toolbar">
-        <a class="layui-btn layui-btn-xs" lay-event="data"><i class="layui-icon layui-icon-survey"></i> 字典数据</a>
         <a class="layui-btn layui-btn-xs" lay-event="edit"><i class="layui-icon layui-icon-edit"></i> 编辑</a>
         <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del"><i class="layui-icon layui-icon-delete"></i> 删除</a>
     </script>
     
+    <script type="text/html" id="statusTpl">
+        {{# if(d.status === 1) { }}
+            <span class="layui-badge green">正常</span>
+        {{# } else { }}
+            <span class="layui-badge layui-bg-gray">停用</span>
+        {{# } }}
+    </script>
+    
     <script src="../../lib/jquery.min.js"></script>
     <script src="../../lib/layui/layui.js"></script>
     <script src="../../js/config.js"></script>
@@ -56,28 +307,161 @@
             var layer = layui.layer;
             var form = layui.form;
             
-            var tableIns = TableRender.init({
-                elem: '#tableList',
-                url: Config.api.dictType.page,
-                cols: [[
-                    { type: 'checkbox', fixed: 'left' },
-                    { field: 'name', title: '字典名称', width: 180 },
-                    { field: 'code', title: '字典类型'},
-                    { field: 'sort', title: '排序', width: 80 },
-                    { field: 'createTime', title: '创建时间', width: 170, templet: function(d) { return Common.formatDate(d.createTime); } },
-                    { field: 'remark', title: '备注', width: 180},
-                    { fixed: 'right', title: '操作', width: 300, align: 'center', toolbar: '#toolbar' }
-                ]]
+            var currentType = null;
+            var tableIns = null;
+            var typeTableIns = null;
+            var currentTypeId = null;
+            
+            // 加载字典类型详情
+            function loadTypeInfo(typeId) {
+                Common.get(Config.api.dictType.getInfo + '/' + typeId, function(res) {
+                    if (res.code === 200 && res.data) {
+                        var info = res.data;
+                        $('#typeInfoCard').show();
+                        $('#typeDetailCard').show();
+                        $('#typeInfoName').text(info.name || '-');
+                        $('#typeInfoCode').text(info.code || '-');
+                        var remark = info.remark || '-';
+                        $('#typeInfoRemark').text(remark);
+                        $('#typeInfoRemark').attr('title', remark);
+                        $('#typeInfoCreateTime').text(info.createTime ? Common.formatDate(info.createTime) : '-');
+                    }
+                });
+            }
+            
+            // 初始化字典类型表格(带分页和搜索)
+            function initTypeTable() {
+                typeTableIns = TableRender.init({
+                    elem: '#typeList',
+                    url: Config.api.dictType.page,
+                    page: true,
+                    limit: 10,
+                    limits: [10, 20, 30],
+                    height: 'full-180',
+                    where: {},
+                    cols: [[
+                        { field: 'name', title: '类型名称', width: 120 },
+                        { field: 'code', title: '类型编码' }
+                    ]],
+                    done: function(res, curr, count) {
+                        // 默认选中第一行
+                        if (count > 0 && !currentTypeId) {
+                            var firstRow = res.data[0];
+                            if (firstRow) {
+                                selectType(firstRow.id, firstRow);
+                            }
+                        }
+                    }
+                });
+            }
+            
+            // 选中字典类型
+            function selectType(typeId, rowData) {
+                currentTypeId = typeId;
+                currentType = rowData;
+                loadTypeInfo(typeId);
+                if (currentType && currentType.code) {
+                    loadDataList(currentType.code);
+                }
+            }
+            
+            // 搜索字典类型
+            function searchTypeList() {
+                var code = $('#typeCodeSearch').val();
+                table.reload('typeList', {
+                    where: { code: code },
+                    page: { curr: 1 }
+                });
+            }
+            
+            // 加载字典数据列表
+            function loadDataList(typeCode) {
+                if (!typeCode) {
+                    $('#emptyTip').show();
+                    return;
+                }
+                $('#emptyTip').hide();
+                
+                if (tableIns) {
+                    table.reload('tableList', {
+                        where: { typeCode: typeCode },
+                        page: { curr: 1 }
+                    });
+                } else {
+                    tableIns = TableRender.init({
+                        elem: '#tableList',
+                        url: Config.api.dictData.page,
+                        where: { typeCode: typeCode },
+                        page: true,
+                        limits: [10, 20, 50, 100],
+                        miniHeight: '500',
+                        cols: [[
+                            { type: 'checkbox', fixed: 'left' },
+                            { field: 'code', title: '数据编码', width: 200 },
+                            { field: 'value', title: '数据值' },
+                            { field: 'sort', title: '排序', width: 70 },
+                            { field: 'status', title: '状态', width: 80, templet: '#statusTpl' },
+                            { field: 'remark', title: '备注', width: 200 },
+                            { fixed: 'right', title: '操作', width: 160, align: 'center', toolbar: '#toolbar' }
+                        ]]
+                    });
+                }
+            }
+            
+            // 初始化字典类型表格
+            initTypeTable();
+            
+            // 搜索字典类型
+            $('#btnSearchType').click(function() {
+                searchTypeList();
+            });
+            
+            // 输入时显示/隐藏清除按钮
+            $('#typeCodeSearch').on('input', function() {
+                var val = $(this).val();
+                if (val) {
+                    $('#inputClear').show();
+                } else {
+                    $('#inputClear').hide();
+                }
+            });
+            
+            // 点击清除按钮
+            $('#inputClear').click(function() {
+                $('#typeCodeSearch').val('');
+                $(this).hide();
+                searchTypeList();
+            });
+            
+            // 回车搜索
+            $('#typeCodeSearch').keypress(function(e) {
+                if (e.which === 13) {
+                    searchTypeList();
+                    return false;
+                }
+            });
+            
+            // 字典类型行点击
+            table.on('row(typeList)', function(obj) {
+                selectType(obj.data.id, obj.data);
             });
             
+            // 搜索
             $('#btnSearch').click(function() {
+                if (!currentType) {
+                    layer.msg('请先选择字典类型', { icon: 0 });
+                    return;
+                }
+                var data = form.val('searchForm');
+                data.typeCode = currentType.code;
                 table.reload('tableList', {
-                    where: form.val('searchForm'),
+                    where: data,
                     page: { curr: 1 }
                 });
             });
             
-            $('#btnAdd').click(function() {
+            // 添加字典类型
+            $('#btnAddType').click(function() {
                 Common.open({
                     title: '添加字典类型',
                     area: ['500px', '380px'],
@@ -85,31 +469,62 @@
                 });
             });
             
-            $('#btnData').click(function() {
-                var checkStatus = table.checkStatus('tableList');
-                if (checkStatus.data.length !== 1) {
-                    layer.msg('请选择一条字典类型', { icon: 0 });
+            // 添加字典数据
+            $('#btnAddData').click(function() {
+                if (!currentType) {
+                    layer.msg('请先选择字典类型', { icon: 0 });
+                    return;
+                }
+                Common.open({
+                    title: '添加字典数据',
+                    area: ['500px', '400px'],
+                    content: 'dict_data_form.html?typeCode=' + currentType.code
+                });
+            });
+            
+            // 编辑字典类型
+            $('#btnEditType').click(function() {
+                if (!currentType) {
+                    layer.msg('请先选择字典类型', { icon: 0 });
+                    return;
+                }
+                Common.open({
+                    title: '编辑字典类型',
+                    area: ['500px', '380px'],
+                    content: 'dict_type_form.html?id=' + currentType.id
+                });
+            });
+            
+            // 删除字典类型
+            $('#btnDelType').click(function() {
+                if (!currentType) {
+                    layer.msg('请先选择字典类型', { icon: 0 });
                     return;
                 }
-                var dictType = checkStatus.data[0];
-                parent.openTab('dict/dict_data_list.html?typeCode=' + dictType.code, '字典数据-' + dictType.name, 'dict_data_' + dictType.code);
+                Common.confirm('确定要删除字典类型 【' + currentType.name + '】 吗?', function() {
+                    Common.del(Config.api.dictType.remove + '/' + currentType.id, function(res) {
+                        Common.success('删除成功', function() {
+                            currentType = null; // 重置当前选中
+                            loadTypeList(false); // 不保持选中
+                        });
+                    });
+                });
             });
             
+            // 表格行操作
             table.on('tool(tableList)', function(obj) {
                 var data = obj.data;
                 var event = obj.event;
                 
-                if (event === 'data') {
-                    parent.openTab('dict/dict_data_list.html?typeCode=' + data.code, '字典数据-' + data.name, 'dict_data_' + data.code);
-                } else if (event === 'edit') {
+                if (event === 'edit') {
                     Common.open({
-                        title: '编辑字典类型',
-                        area: ['500px', '380px'],
-                        content: 'dict_type_form.html?id=' + data.id
+                        title: '编辑字典数据',
+                        area: ['500px', '400px'],
+                        content: 'dict_data_form.html?typeCode=' + currentType.code + '&id=' + data.id
                     });
                 } else if (event === 'del') {
-                    Common.confirm('确定要删除字典类型 【' + data.name + '】 吗?', function() {
-                        Common.del(Config.api.dictType.remove + '/' + data.id, function(res) {
+                    Common.confirm('确定要删除字典数据 【' + data.value + '】 吗?', function() {
+                        Common.del(Config.api.dictData.remove + '/' + data.id, function(res) {
                             Common.success('删除成功', function() {
                                 obj.del();
                             });
@@ -117,6 +532,18 @@
                     });
                 }
             });
+            
+            // 监听弹窗关闭,刷新类型列表
+            window.refreshTypeList = function() {
+                table.reload('typeList');
+            };
+            
+            // 监听弹窗关闭,刷新数据列表
+            window.refreshDataList = function() {
+                if (currentType) {
+                    loadDataList(currentType.code);
+                }
+            };
         });
     </script>
 </body>