<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>用户管理</title>
    <link rel="stylesheet" href="{{ asset('CmsProUi/component/pear/css/pear.css') }}">
    <link rel="stylesheet" href="{{ asset('CmsProUi/font-awesome/4.7.0/css/font-awesome.min.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/admin.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/variables.css') }}">
    <link rel="stylesheet" href="{{ asset('Admin/css/reset.css') }}">
    <style>
    .layui-table img {
        max-width: 30px;
        padding: 6px;
        border-radius: 50%;
    }
    .user-info {
        display: flex;
        align-items: center;
        gap: 8px;
    }
    .user-info .user-detail {
        text-align: left;
        line-height: 1.4;
    }
    .user-info .user-detail .username {
        font-weight: 500;
    }
    .user-info .user-detail .nickname {
        font-size: 12px;
        color: #999;
    }
</style>
    @include('admin.partials.permission-script')
</head>
<body>
<div class="pear-container">
    <div class="layui-card">
        <div class="layui-card-body">
            <form class="layui-form" action="">
                <div class="layui-inline">
                    <div class="layui-input-inline">
                        <input type="text" name="keyword" placeholder="用户名/姓名/邮箱" class="layui-input">
                    </div>
                </div>
                <div class="layui-inline">
                    <div class="layui-input-inline">
                        <select name="role_id">
                            <option value="">全部角色</option>
                        </select>
                    </div>
                </div>
                <div class="layui-inline">
                    <div class="layui-input-inline">
                        <select name="status">
                            <option value="">全部状态</option>
                            <option value="1">正常</option>
                            <option value="0">禁用</option>
                        </select>
                    </div>
                </div>
                <div class="layui-inline">
                    <button class="layui-btn layui-btn-md" lay-submit lay-filter="user-query">
                        <i class="layui-icon layui-icon-search"></i> 查询
                    </button>
                    <button type="reset" class="layui-btn layui-btn-md layui-btn-primary">
                        <i class="layui-icon layui-icon-refresh"></i> 重置
                    </button>
                </div>
                <div class="layui-inline" style="float: right;">
                    <button type="button" class="layui-btn layui-btn-md layui-btn-normal" id="btn-ext-fields">
                        <i class="layui-icon layui-icon-app"></i> 扩展管理
                    </button>
                </div>
            </form>
        </div>
    </div>

    <div class="layui-card">
        <div class="layui-card-body">
            <table id="user-table" lay-filter="user-table"></table>
        </div>
    </div>

    <script type="text/html" id="user-toolbar">
        <button class="layui-btn layui-btn-sm" lay-event="add" data-permission="admin.user.store">
            <i class="layui-icon layui-icon-add-1"></i> 新增
        </button>
        <button class="layui-btn layui-btn-danger layui-btn-sm" lay-event="batchRemove" data-permission="admin.user.batch-delete">
            <i class="layui-icon layui-icon-delete"></i> 批量删除
        </button>
    </script>

    <script type="text/html" id="user-bar">
        <div class="layui-btn-container">
            <a class="layui-btn layui-btn-xs" lay-event="more">操作 <i class="layui-icon layui-icon-down"></i></a>
        </div>
    </script>

    @verbatim
    <script type="text/html" id="user-info-tpl">
        <div class="user-info">
            <img src="{{ d.avatar || '/Admin/images/avatar.png' }}" alt="">
            <div class="user-detail">
                <div class="username">{{ d.username }}</div>
                <div class="nickname">{{ d.name }}</div>
            </div>
        </div>
    </script>
    @endverbatim

    @verbatim
    <script type="text/html" id="user-status-tpl">
        <input type="checkbox" name="status" value="{{ d.id }}" lay-skin="switch" lay-text="正常|禁用" lay-filter="user-status" {{ d.status == 1 ? 'checked' : '' }} {{ d.can_manage === false ? 'disabled' : '' }} />
    </script>
    @endverbatim

    @verbatim
    <script type="text/html" id="user-last-login-tpl">
        <span>{{# if(d.last_login_at){ }}{{ d.last_login_at }}{{# } else { }}-{{# } }}</span>
    </script>
    @endverbatim

    <!-- 扩展管理弹窗模板 -->
    @verbatim
    <script type="text/html" id="ext-field-status-tpl">
        <input type="checkbox" name="status" value="{{ d.id }}" lay-skin="switch" lay-text="启用|禁用" lay-filter="ext-field-status" {{ d.status == 1 ? 'checked' : '' }} />
    </script>
    @endverbatim

    @verbatim
    <script type="text/html" id="ext-field-bar-tpl">
        <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
        <a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
    </script>
    @endverbatim
</div>
<script src="{{ asset('CmsProUi/component/layui/layui.js') }}"></script>
<script src="{{ asset('CmsProUi/component/pear/pear.js') }}"></script>
<script>
    layui.use(['table', 'form', 'jquery', 'common', 'dropdown'], function() {
        var table = layui.table;
        var form = layui.form;
        var $ = layui.jquery;
        var dropdown = layui.dropdown;

        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': '{{ csrf_token() }}'
            }
        });

        // 根据权限隐藏工具栏按钮
        $('#user-toolbar [data-permission]').each(function() {
            if (!window.hasPermission || !window.hasPermission($(this).data('permission'))) {
                $(this).hide();
            }
        });

        // 加载角色列表到筛选下拉框
        $.ajax({
            url: '/api/admin/roles/all',
            type: 'GET',
            dataType: 'json',
            success: function(res) {
                if (res.code === 0 && res.data) {
                    var list = Array.isArray(res.data) ? res.data : (res.data.items || []);
                    var $sel = $('select[name="role_id"]');
                    for (var i = 0; i < list.length; i++) {
                        $sel.append('<option value="' + list[i].id + '">' + list[i].name + '</option>');
                    }
                    form.render('select');
                }
            }
        });

        var cols = [[
            { type: 'checkbox', fixed: 'left' },
            { title: 'ID', field: 'id', align: 'center', width: 80, sort: true },
            { title: '用户信息', field: 'username', align: 'center', minWidth: 140, templet: '#user-info-tpl' },
            { title: '邮箱', field: 'email', align: 'center', minWidth: 160 },
            { title: '手机号', field: 'phone', align: 'center', width: 130 },
            { title: '角色', field: 'roles', align: 'center', width: 120, templet: function(d) {
                if (!d.roles || d.roles.length === 0) return '-';
                return d.roles.map(function(r) { return r.name; }).join(', ');
            }},
            { title: '状态', field: 'status', align: 'center', width: 110, templet: '#user-status-tpl' },
            { title: '登录次数', field: 'login_count', align: 'center', width: 100, sort: true },
            { title: '最后登录', field: 'last_login_at', align: 'center', width: 170, templet: '#user-last-login-tpl' },
            { title: '操作', toolbar: '#user-bar', align: 'center', width: 100, fixed: 'right' }
        ]];

        var inst = table.render({
            elem: '#user-table',
            url: '/api/admin/users',
            page: {
                layout: ['count', 'prev', 'page', 'next', 'limit'],
                groups: 5,
                limit: 20,
                limits: [10, 20, 50, 100]
            },
            cols: cols,
            skin: false,
            toolbar: '#user-toolbar',
            defaultToolbar: [{
                title: '刷新',
                layEvent: 'refresh',
                icon: 'layui-icon-refresh'
            }, 'filter', 'print', 'exports'],
            parseData: function(res) {
                return {
                    "code": res.code === 0 ? 0 : 1,
                    "msg": res.message || "",
                    "count": res.data && res.data.pagination ? res.data.pagination.total : 0,
                    "data": res.data ? res.data.items : []
                };
            }
        });

        form.on('submit(user-query)', function(data) {
            table.reload('user-table', { where: data.field, page: { curr: 1 } });
            return false;
        });

        form.on('switch(user-status)', function(obj) {
            if (!window.hasPermission || !window.hasPermission('admin.user.status')) {
                $(obj.elem).prop('checked', !obj.elem.checked);
                form.render();
                layer.msg('无操作权限', { icon: 2, time: 1000 });
                return;
            }
            var id = this.value;
            $.ajax({
                url: '/api/admin/users/' + id + '/status',
                type: 'POST',
                dataType: 'json',
                contentType: 'application/json',
                data: JSON.stringify({ status: obj.elem.checked ? 1 : 0 }),
                success: function(res) {
                    if (res.code === 0) {
                        layer.msg('状态更新成功', { icon: 1, time: 1000 });
                    } else {
                        layer.msg(res.message || '操作失败', { icon: 2, time: 1000 });
                        $(obj.elem).prop('checked', !obj.elem.checked);
                        form.render();
                    }
                },
                error: function() {
                    layer.msg('请求失败', { icon: 2, time: 1000 });
                    $(obj.elem).prop('checked', !obj.elem.checked);
                    form.render();
                }
            });
        });

        table.on('toolbar(user-table)', function(obj) {
            if (obj.event === 'add') {
                window.add();
            } else if (obj.event === 'refresh') {
                table.reload('user-table');
            } else if (obj.event === 'batchRemove') {
                window.batchRemove(obj);
            }
        });

        table.on('tool(' + inst.config.id + ')', function(obj) {
            if (obj.event === 'more') {
                // 无管辖权的账号不显示任何操作菜单
                if (obj.data.can_manage === false) {
                    layer.msg('无权操作该用户（超出管辖范围）', { icon: 2, time: 1500 });
                    return;
                }
                var menuData = [
                    { title: '编辑', id: 'edit', permission: 'admin.user.update' },
                    { title: '重置密码', id: 'resetPwd', permission: 'admin.user.reset-password' },
                    { title: '删除', id: 'del', permission: 'admin.user.destroy' }
                ];
                // 根据权限过滤菜单项
                if (window.hasPermission) {
                    menuData = menuData.filter(function(item) {
                        return window.hasPermission(item.permission);
                    });
                }
                if (menuData.length === 0) return;
                dropdown.render({
                    elem: this,
                    show: true,
                    align: 'right',
                    data: menuData,
                    click: function(menudata) {
                        if (menudata.id === 'edit') {
                            window.edit(obj);
                        } else if (menudata.id === 'resetPwd') {
                            window.resetPassword(obj);
                        } else if (menudata.id === 'del') {
                            window.remove(obj);
                        }
                    }
                });
            }
        });

        // 双击行查看用户详情
        table.on('rowDouble(' + inst.config.id + ')', function(obj) {
            window.viewDetail(obj.data.id);
        });

        // 查看用户详情弹窗
        window.viewDetail = function(id) {
            var loading = layer.load();
            // 并发拉取用户详情 + 扩展字段定义（用于显示扩展字段 label）
            var userReq = $.ajax({ url: '/api/admin/users/' + id, type: 'GET', dataType: 'json' });
            var extReq = $.ajax({ url: '/api/admin/admin-user-ext-fields', type: 'GET', dataType: 'json' });
            $.when(userReq, extReq).done(function(userRes, extRes) {
                layer.close(loading);
                userRes = userRes[0];
                extRes = extRes[0];
                if (userRes.code === 0 && userRes.data) {
                    var extDefs = (extRes.code === 0 && extRes.data) ? extRes.data : [];
                    showUserDetail(userRes.data, extDefs);
                } else {
                    layer.msg(userRes.message || '获取用户信息失败', { icon: 2 });
                }
            }).fail(function() {
                layer.close(loading);
                layer.msg('请求失败', { icon: 2 });
            });
        };

        function escapeHtml(str) {
            if (str === null || str === undefined) return '';
            return String(str).replace(/[&<>"']/g, function(s) {
                return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[s];
            });
        }

        function showUserDetail(d, extDefs) {
            // 构建扩展字段 label 映射 + 静态 select 选项 label 映射
            var extLabelMap = {};
            var extOptionMap = {};  // field_name => { value: label }
            for (var i = 0; i < extDefs.length; i++) {
                var f = extDefs[i];
                extLabelMap[f.field_name] = f.field_label;
                if (f.field_type === 'select' && Array.isArray(f.field_options)) {
                    var optMap = {};
                    for (var j = 0; j < f.field_options.length; j++) {
                        optMap[f.field_options[j].value] = f.field_options[j].label;
                    }
                    extOptionMap[f.field_name] = optMap;
                }
            }

            var html = '<div>';

            // 基本信息区
            html += '<fieldset class="layui-elem-field"><legend>基本信息</legend><div class="layui-field-box">';
            html += '<table class="layui-table" lay-size="sm" style="margin:0;">';
            html += '<colgroup><col width="120"><col></colgroup>';
            html += '<tr><td>用户名</td><td>' + escapeHtml(d.username) + '</td></tr>';
            html += '<tr><td>姓名</td><td>' + escapeHtml(d.name || '-') + '</td></tr>';
            html += '<tr><td>邮箱</td><td>' + escapeHtml(d.email || '-') + '</td></tr>';
            html += '<tr><td>手机号</td><td>' + escapeHtml(d.phone || '-') + '</td></tr>';
            html += '<tr><td>状态</td><td>' + (d.status == 1
                ? '<span class="layui-badge layui-bg-green">正常</span>'
                : '<span class="layui-badge layui-bg-gray">禁用</span>') + '</td></tr>';
            html += '<tr><td>登录次数</td><td>' + (d.login_count || 0) + '</td></tr>';
            html += '<tr><td>最后登录</td><td>' + escapeHtml(d.last_login_at || '从未登录') + '</td></tr>';
            html += '<tr><td>最后登录IP</td><td>' + escapeHtml(d.last_login_ip || '-') + '</td></tr>';
            html += '<tr><td>创建时间</td><td>' + escapeHtml(d.create_time || '-') + '</td></tr>';
            html += '<tr><td>更新时间</td><td>' + escapeHtml(d.update_time || '-') + '</td></tr>';
            html += '</table>';
            html += '</div></fieldset>';

            // 角色信息
            if (d.roles && d.roles.length > 0) {
                html += '<fieldset class="layui-elem-field"><legend>角色</legend><div class="layui-field-box">';
                for (var r = 0; r < d.roles.length; r++) {
                    html += '<span class="layui-badge layui-bg-blue" style="margin:2px;">' + escapeHtml(d.roles[r].name) + '</span>';
                }
                html += '</div></fieldset>';
            }

            // 扩展字段信息
            if (d.ext_fields && Object.keys(d.ext_fields).length > 0) {
                html += '<fieldset class="layui-elem-field"><legend>扩展信息</legend><div class="layui-field-box">';
                html += '<table class="layui-table" lay-size="sm" style="margin:0;">';
                html += '<colgroup><col width="120"><col></colgroup>';
                // 收集动态数据源字段，渲染后异步拉取并替换显示值
                var dynamicFields = [];
                for (var key in d.ext_fields) {
                    if (!d.ext_fields.hasOwnProperty(key)) continue;
                    var val = d.ext_fields[key];
                    var displayVal = val;
                    var extDef = null;
                    for (var i = 0; i < extDefs.length; i++) {
                        if (extDefs[i].field_name === key) { extDef = extDefs[i]; break; }
                    }
                    var isMultiple = extDef && extDef.field_options && extDef.field_options.multiple === true;
                    if (isMultiple && Array.isArray(val)) {
                        // 多选字段：逐个映射 label
                        var labels = [];
                        for (var vi = 0; vi < val.length; vi++) {
                            var v = val[vi];
                            if (extOptionMap[key] && extOptionMap[key][v]) {
                                labels.push(extOptionMap[key][v]);
                            } else {
                                labels.push(v);
                            }
                        }
                        displayVal = labels.join('、');
                    } else {
                        // 单选或非 select
                        if (extOptionMap[key] && val !== null && val !== '' && extOptionMap[key][val]) {
                            displayVal = extOptionMap[key][val];
                        }
                    }
                    if (displayVal === null || displayVal === '' || displayVal === undefined) {
                        displayVal = '-';
                    }
                    var cellId = '';
                    if (extDef && extDef.field_type === 'select'
                        && extDef.field_options && extDef.field_options.source) {
                        cellId = ' id="ext-detail-' + key + '"';
                        dynamicFields.push({
                            name: key,
                            value: val,
                            source: extDef.field_options.source
                        });
                    }
                    html += '<tr><td>' + escapeHtml(extLabelMap[key] || key) + '</td><td' + cellId + '>' + escapeHtml(displayVal) + '</td></tr>';
                }
                html += '</table>';
                html += '</div></fieldset>';

                // 异步拉取动态数据源，替换 ID 为 label
                dynamicFields.forEach(function(item) {
                    $.ajax({
                        url: item.source.url,
                        type: 'GET',
                        dataType: 'json',
                        success: function(res) {
                            if (res.code === 0 && res.data) {
                                var list = Array.isArray(res.data) ? res.data : (res.data.items || []);
                                var $cell = $('#ext-detail-' + item.name);
                                if (!$cell.length) return;
                                if (Array.isArray(item.value)) {
                                    // 多选：映射多个 label
                                    var labels = [];
                                    for (var idx = 0; idx < item.value.length; idx++) {
                                        for (var k = 0; k < list.length; k++) {
                                            if (String(list[k][item.source.value_key]) === String(item.value[idx])) {
                                                labels.push(list[k][item.source.label_key]);
                                                break;
                                            }
                                        }
                                    }
                                    $cell.text(labels.length ? labels.join('、') : '-');
                                } else {
                                    // 单选
                                    var label = null;
                                    for (var k = 0; k < list.length; k++) {
                                        if (String(list[k][item.source.value_key]) === String(item.value)) {
                                            label = list[k][item.source.label_key];
                                            break;
                                        }
                                    }
                                    if (label !== null && label !== undefined) {
                                        $cell.text(label);
                                    }
                                }
                            }
                        }
                    });
                });
            }

            html += '</div>';

            layer.open({
                type: 1,
                title: '用户详情：' + d.username,
                area: ['520px', '640px'],
                shadeClose: true,
                content: html
            });
        }

        window.add = function() {
            layer.open({
                type: 2,
                title: '新增用户',
                shade: 0.1,
                area: ['550px', '496px'],
                content: '/admin/user/form'
            });
        };

        window.edit = function(obj) {
            layer.open({
                type: 2,
                title: '编辑用户：' + obj.data.username,
                shade: 0.1,
                area: ['550px', '496px'],
                content: '/admin/user/form?id=' + obj.data.id
            });
        };

        window.resetPassword = function(obj) {
            layer.prompt({
                formType: 1,
                title: '重置用户【' + obj.data.username + '】的密码',
                value: '',
            }, function(value, index) {
                layer.close(index);
                var loading = layer.load();
                $.ajax({
                    url: '/api/admin/users/' + obj.data.id + '/reset-password',
                    type: 'PUT',
                    dataType: 'json',
                    contentType: 'application/json',
                    data: JSON.stringify({ password: value }),
                    success: function(res) {
                        layer.close(loading);
                        if (res.code === 0) {
                            layer.msg('重置成功', { icon: 1, time: 1000 });
                        } else {
                            layer.msg(res.message || '重置失败', { icon: 2, time: 1000 });
                        }
                    },
                    error: function() {
                        layer.close(loading);
                        layer.msg('请求失败', { icon: 2, time: 1000 });
                    }
                });
            });
        };

        window.remove = function(obj) {
            layer.confirm('确定要删除该用户？删除后无法恢复！', {
                icon: 3,
                title: '操作提示',
                btn: ['确定', '取消']
            }, function(index) {
                layer.close(index);
                var loading = layer.load();
                $.ajax({
                    url: '/api/admin/users/' + obj.data.id,
                    type: 'DELETE',
                    dataType: 'json',
                    success: function(res) {
                        layer.close(loading);
                        if (res.code === 0) {
                            layer.msg('删除成功', { icon: 1, time: 1000 }, function() {
                                table.reload('user-table');
                            });
                        } else {
                            layer.msg(res.message || '删除失败', { icon: 2, time: 1000 });
                        }
                    },
                    error: function() {
                        layer.close(loading);
                        layer.msg('请求失败', { icon: 2, time: 1000 });
                    }
                });
            });
        };

        window.batchRemove = function(obj) {
            var checkData = table.checkStatus('user-table').data;
            if (checkData.length === 0) {
                layer.msg('未选中数据', { icon: 3, time: 1000 });
                return false;
            }
            var ids = checkData.map(function(item) { return item.id; });
            layer.confirm('确定要删除选中的 ' + ids.length + ' 个用户？删除后无法恢复！', {
                icon: 3,
                title: '操作提示',
                btn: ['确定', '取消']
            }, function(index) {
                layer.close(index);
                var loading = layer.load();
                $.ajax({
                    url: '/api/admin/users/batch-delete',
                    type: 'DELETE',
                    dataType: 'json',
                    contentType: 'application/json',
                    data: JSON.stringify({ ids: ids }),
                    success: function(res) {
                        layer.close(loading);
                        if (res.code === 0) {
                            layer.msg('删除成功', { icon: 1, time: 1000 }, function() {
                                table.reload('user-table');
                            });
                        } else {
                            layer.msg(res.message || '删除失败', { icon: 2, time: 1000 });
                        }
                    },
                    error: function() {
                        layer.close(loading);
                        layer.msg('请求失败', { icon: 2, time: 1000 });
                    }
                });
            });
        };

        // ========== 扩展管理功能 ==========
        var extFieldApi = '/api/admin/admin-user-ext-fields';

        // 点击"扩展管理"按钮，打开列表弹窗
        $('#btn-ext-fields').on('click', function() {
            layer.open({
                type: 1,
                title: '扩展字段管理',
                area: ['800px', '520px'],
                shadeClose: false,
                content: '<div style="padding:10px 15px;"><table id="ext-field-table" lay-filter="ext-field-table"></table></div>',
                success: function(layero, index) {
                    renderExtFieldTable(index);
                }
            });
        });

        // 渲染扩展字段列表
        function renderExtFieldTable(layerIndex) {
            table.render({
                elem: '#ext-field-table',
                url: extFieldApi,
                where: { _t: Date.now() },
                page: false,
                cols: [[
                    { title: 'ID', field: 'id', align: 'center', sort: true },
                    { title: '字段标识', field: 'field_name', align: 'center' },
                    { title: '显示名称', field: 'field_label', align: 'center'},
                    { title: '字段类型', field: 'field_type', align: 'center'},
                    { title: '排序', field: 'sort', align: 'center', sort: true },
                    { title: '状态', field: 'status', align: 'center', templet: '#ext-field-status-tpl' },
                    { title: '操作', toolbar: '#ext-field-bar-tpl', align: 'center', width: 150, fixed: 'right' }
                ]],
                skin: false,
                toolbar: '<div class="layui-btn-container"><button class="layui-btn layui-btn-sm" lay-event="extAdd"><i class="layui-icon layui-icon-add-1"></i> 新增</button></div>',
                parseData: function(res) {
                    var list = [];
                    if (res.code === 0 && res.data) {
                        list = Array.isArray(res.data) ? res.data : (res.data.items || []);
                    }
                    return { code: 0, msg: '', count: list.length, data: list };
                },
                done: function() {
                    // 绑定工具栏事件需在渲染完成后重新注册
                }
            });

            // 扩展字段表格 - 工具栏事件
            table.on('toolbar(ext-field-table)', function(obj) {
                if (obj.event === 'extAdd') {
                    openExtFieldForm(layerIndex);
                }
            });

            // 扩展字段表格 - 行操作事件
            table.on('tool(ext-field-table)', function(obj) {
                if (obj.event === 'edit') {
                    openExtFieldForm(layerIndex, obj.data);
                } else if (obj.event === 'del') {
                    deleteExtField(obj.data, layerIndex);
                }
            });

            // 扩展字段状态切换
            form.on('switch(ext-field-status)', function(obj) {
                var id = this.value;
                $.ajax({
                    url: extFieldApi + '/' + id,
                    type: 'PUT',
                    dataType: 'json',
                    contentType: 'application/json',
                    data: JSON.stringify({ status: obj.elem.checked ? 1 : 0 }),
                    success: function(res) {
                        if (res.code === 0) {
                            layer.msg('状态更新成功', { icon: 1, time: 1000 });
                        } else {
                            layer.msg(res.message || '操作失败', { icon: 2, time: 1000 });
                            $(obj.elem).prop('checked', !obj.elem.checked);
                            form.render();
                        }
                    },
                    error: function() {
                        layer.msg('请求失败', { icon: 2, time: 1000 });
                        $(obj.elem).prop('checked', !obj.elem.checked);
                        form.render();
                    }
                });
            });
        }

        // 新增/编辑扩展字段弹窗
        function openExtFieldForm(parentIndex, data) {
            var isEdit = !!data;
            var fieldTypes = [
                { value: 'text', title: 'text' },
                { value: 'number', title: 'number' },
                { value: 'select', title: 'select' },
                { value: 'textarea', title: 'textarea' },
                { value: 'switch', title: 'switch' },
                { value: 'date', title: 'date' },
                { value: 'json', title: 'json' }
            ];
            var typeOptions = fieldTypes.map(function(t) {
                var sel = (isEdit && data.field_type === t.value) ? ' selected' : '';
                return '<option value="' + t.value + '"' + sel + '>' + t.title + '</option>';
            }).join('');

            var fieldNameVal = isEdit ? data.field_name : '';
            var fieldLabelVal = isEdit ? data.field_label : '';
            var sortVal = isEdit ? (data.sort || 0) : 0;
            var statusChecked = (!isEdit || data.status == 1) ? ' checked' : '';
            // 解析 field_options：可能是静态数组、动态数据源、或空
            var optionsJsonVal = '';
            var sourceUrlVal = '', sourceLabelKeyVal = 'name', sourceValueKeyVal = 'id';
            var optionsMode = 'static'; // static | source
            if (isEdit && data.field_options) {
                var opts = data.field_options;
                if (opts && typeof opts === 'object' && opts.source) {
                    optionsMode = 'source';
                    sourceUrlVal = opts.source.url || '';
                    sourceLabelKeyVal = opts.source.label_key || 'name';
                    sourceValueKeyVal = opts.source.value_key || 'id';
                } else if (Array.isArray(opts)) {
                    optionsJsonVal = JSON.stringify(opts, null, 2);
                } else if (opts && typeof opts === 'object' && opts.options) {
                    // 多选静态选项：{ multiple: true, options: [...] }
                    optionsJsonVal = JSON.stringify(opts.options, null, 2);
                }
            }
            var optionsDisplay = (isEdit && data.field_type === 'select') ? 'block' : 'none';
            var multipleChecked = (isEdit && data.field_options && data.field_options.multiple === true) ? ' checked' : '';

            var formHtml = [
                '<div style="padding:20px 30px 0;">',
                '  <form class="layui-form" id="ext-field-form" lay-filter="ext-field-form">',
                '    <div class="layui-form-item">',
                '      <label class="layui-form-label">字段标识</label>',
                '      <div class="layui-input-block">',
                '        <input type="text" name="field_name" value="' + fieldNameVal + '" lay-verify="required" placeholder="英文字母下划线，如 company_name" class="layui-input">',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item">',
                '      <label class="layui-form-label">显示名称</label>',
                '      <div class="layui-input-block">',
                '        <input type="text" name="field_label" value="' + fieldLabelVal + '" lay-verify="required" placeholder="如：公司名称" class="layui-input">',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item">',
                '      <label class="layui-form-label">字段类型</label>',
                '      <div class="layui-input-block">',
                '        <select name="field_type" lay-filter="ext-field-type">',
                '          <option value="">请选择类型</option>',
                '          ' + typeOptions,
                '        </select>',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item" id="ext-options-wrap" style="display:' + optionsDisplay + '">',
                '      <label class="layui-form-label">选项来源</label>',
                '      <div class="layui-input-block">',
                '        <select name="options_mode" lay-filter="ext-options-mode">',
                '          <option value="static"' + (optionsMode === 'static' ? ' selected' : '') + '>静态选项</option>',
                '          <option value="source"' + (optionsMode === 'source' ? ' selected' : '') + '>动态数据源</option>',
                '        </select>',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item" id="ext-options-json-wrap" style="' + (optionsDisplay === 'block' && optionsMode === 'static' ? '' : 'display:none;') + '">',
                '      <label class="layui-form-label">选项JSON</label>',
                '      <div class="layui-input-block">',
                '        <textarea name="options_json" placeholder=\'如：[{"label":"选项1","value":"1"},{"label":"选项2","value":"2"}]\' class="layui-textarea">' + optionsJsonVal + '</textarea>',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item" id="ext-options-source-wrap" style="' + (optionsDisplay === 'block' && optionsMode === 'source' ? '' : 'display:none;') + '">',
                '      <label class="layui-form-label">数据源URL</label>',
                '      <div class="layui-input-block">',
                '        <input type="text" name="source_url" value="' + sourceUrlVal + '" placeholder="如：/api/admin/cmspro/childrehab/hospitals" class="layui-input">',
                '      </div>',
                '      <div style="margin-top:10px;padding-left:110px;color:#999;font-size:12px;">URL 需返回 {code:0, data:[...]} 格式的 JSON，data 为数组</div>',
                '    </div>',
                '    <div class="layui-form-item" id="ext-options-keys-wrap" style="' + (optionsDisplay === 'block' && optionsMode === 'source' ? '' : 'display:none;') + '">',
                '      <label class="layui-form-label">字段映射</label>',
                '      <div class="layui-input-block layui-row layui-col-space10">',
                '        <div class="layui-col-md6"><input type="text" name="source_label_key" value="' + sourceLabelKeyVal + '" placeholder="显示字段，如 name" class="layui-input"></div>',
                '        <div class="layui-col-md6"><input type="text" name="source_value_key" value="' + sourceValueKeyVal + '" placeholder="值字段，如 id" class="layui-input"></div>',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item" id="ext-multiple-wrap" style="display:' + optionsDisplay + '">',
                '      <label class="layui-form-label">多选</label>',
                '      <div class="layui-input-block">',
                '        <input type="checkbox" name="ext_multiple" lay-skin="switch" lay-text="是|否"' + multipleChecked + '>',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item">',
                '      <label class="layui-form-label">排序</label>',
                '      <div class="layui-input-block">',
                '        <input type="number" name="sort" value="' + sortVal + '" class="layui-input">',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item">',
                '      <label class="layui-form-label">状态</label>',
                '      <div class="layui-input-block">',
                '        <input type="checkbox" name="status" lay-skin="switch" lay-text="启用|禁用"' + statusChecked + '>',
                '      </div>',
                '    </div>',
                '    <div class="layui-form-item" style="text-align:right;margin-top:20px;padding-right:10px;">',
                '      <button type="button" class="layui-btn" id="ext-field-submit" lay-submit lay-filter="ext-field-submit">提交</button>',
                '      <button type="button" class="layui-btn layui-btn-primary" id="ext-field-cancel">取消</button>',
                '    </div>',
                '  </form>',
                '</div>'
            ].join('');

            var formIndex = layer.open({
                type: 1,
                title: isEdit ? '编辑扩展字段' : '新增扩展字段',
                area: ['500px', '560px'],
                shadeClose: false,
                content: formHtml,
                success: function(layero) {
                    form.render(null, 'ext-field-form');

                    // 字段类型切换时控制选项区域显示/隐藏
                    form.on('select(ext-field-type)', function(obj) {
                        var wrap = layero.find('#ext-options-wrap');
                        var jsonWrap = layero.find('#ext-options-json-wrap');
                        var sourceWrap = layero.find('#ext-options-source-wrap');
                        var keysWrap = layero.find('#ext-options-keys-wrap');
                        var multipleWrap = layero.find('#ext-multiple-wrap');
                        if (obj.value === 'select') {
                            wrap.show();
                            multipleWrap.show();
                            // 根据当前选项来源模式显示对应子区域
                            var mode = layero.find('select[name="options_mode"]').val();
                            if (mode === 'source') {
                                sourceWrap.show(); keysWrap.show(); jsonWrap.hide();
                            } else {
                                jsonWrap.show(); sourceWrap.hide(); keysWrap.hide();
                            }
                        } else {
                            wrap.hide(); jsonWrap.hide(); sourceWrap.hide(); keysWrap.hide();
                            multipleWrap.hide();
                        }
                    });

                    // 选项来源切换
                    form.on('select(ext-options-mode)', function(obj) {
                        var jsonWrap = layero.find('#ext-options-json-wrap');
                        var sourceWrap = layero.find('#ext-options-source-wrap');
                        var keysWrap = layero.find('#ext-options-keys-wrap');
                        if (obj.value === 'source') {
                            sourceWrap.show(); keysWrap.show(); jsonWrap.hide();
                        } else {
                            jsonWrap.show(); sourceWrap.hide(); keysWrap.hide();
                        }
                    });

                    // 提交表单
                    form.on('submit(ext-field-submit)', function(formObj) {
                        var formData = formObj.field;
                        formData.sort = parseInt(formData.sort) || 0;
                        // switch 未勾选时不提交，需手动设为0
                        formData.status = layero.find('input[name="status"]').is(':checked') ? 1 : 0;

                        // 组装 field_options：根据选项来源模式构造数组或 source 对象
                        var fieldOptions = null;
                        if (formData.field_type === 'select') {
                            var mode = formData.options_mode;
                            if (mode === 'source') {
                                if (!formData.source_url) {
                                    layer.msg('请填写数据源URL', { icon: 2, time: 1500 });
                                    return false;
                                }
                                fieldOptions = {
                                    source: {
                                        url: formData.source_url,
                                        label_key: formData.source_label_key || 'name',
                                        value_key: formData.source_value_key || 'id'
                                    }
                                };
                            } else {
                                // 静态选项：解析 JSON
                                if (formData.options_json) {
                                    try {
                                        var parsed = JSON.parse(formData.options_json);
                                        if (!Array.isArray(parsed)) {
                                            layer.msg('选项JSON 必须是数组', { icon: 2, time: 1500 });
                                            return false;
                                        }
                                        fieldOptions = parsed;
                                    } catch(e) {
                                        layer.msg('选项JSON 格式错误：' + e.message, { icon: 2, time: 1500 });
                                        return false;
                                    }
                                }
                            }
                            // 多选标记
                            var isMultiple = layero.find('input[name="ext_multiple"]').is(':checked');
                            if (isMultiple) {
                                if (fieldOptions === null) {
                                    fieldOptions = {};
                                } else if (Array.isArray(fieldOptions)) {
                                    // 静态选项包装为对象
                                    fieldOptions = { options: fieldOptions };
                                }
                                fieldOptions.multiple = true;
                            }
                        }
                        delete formData.options_mode;
                        delete formData.options_json;
                        delete formData.source_url;
                        delete formData.source_label_key;
                        delete formData.source_value_key;
                        formData.field_options = fieldOptions;

                        var ajaxUrl = isEdit ? (extFieldApi + '/' + data.id) : extFieldApi;
                        var ajaxType = isEdit ? 'PUT' : 'POST';

                        $.ajax({
                            url: ajaxUrl,
                            type: ajaxType,
                            dataType: 'json',
                            contentType: 'application/json',
                            data: JSON.stringify(formData),
                            success: function(res) {
                                if (res.code === 0) {
                                    layer.msg(isEdit ? '更新成功' : '新增成功', { icon: 1, time: 1000 });
                                    layer.close(formIndex);
                                    table.reload('ext-field-table', { where: { _t: Date.now() } });
                                } else {
                                    layer.msg(res.message || '操作失败', { icon: 2, time: 1000 });
                                }
                            },
                            error: function() {
                                layer.msg('请求失败', { icon: 2, time: 1000 });
                            }
                        });
                        return false;
                    });

                    // 取消按钮
                    layero.find('#ext-field-cancel').on('click', function() {
                        layer.close(formIndex);
                    });
                }
            });
        }

        // 删除扩展字段
        function deleteExtField(rowData, parentIndex) {
            layer.confirm('确定要删除该扩展字段？', {
                icon: 3,
                title: '操作提示',
                btn: ['确定', '取消']
            }, function(index) {
                layer.close(index);
                var loading = layer.load();
                $.ajax({
                    url: extFieldApi + '/' + rowData.id,
                    type: 'DELETE',
                    dataType: 'json',
                    success: function(res) {
                        layer.close(loading);
                        if (res.code === 0) {
                            layer.msg('删除成功', { icon: 1, time: 1000 });
                            table.reload('ext-field-table', { where: { _t: Date.now() } });
                        } else {
                            layer.msg(res.message || '删除失败', { icon: 2, time: 1000 });
                        }
                    },
                    error: function() {
                        layer.close(loading);
                        layer.msg('请求失败', { icon: 2, time: 1000 });
                    }
                });
            });
        }
    });
</script>
</body>
</html>
