<!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>
        .designer-layout { display: flex; gap: 16px; min-height: calc(100vh - 140px); }
        .designer-left { flex: 0 0 55%; display: flex; flex-direction: column; }
        .designer-right { flex: 1; display: flex; flex-direction: column; }
        .panel-section { border: 1px solid #e6e6e6; border-radius: 4px; overflow: hidden; display: flex; flex-direction: column; }
        .panel-header { display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; background: #f8f9fa; border-bottom: 1px solid #e6e6e6; flex-shrink: 0; }
        .panel-header span { font-weight: 600; font-size: 14px; color: #333; }
        .panel-body { flex: 1; overflow: hidden; display: flex; flex-direction: column; }
        .sort-row { display: flex; align-items: center; padding: 8px 12px; border-bottom: 1px solid #f0f0f0; transition: background 0.2s; cursor: move; }
        .sort-row:hover { background: #fafafa; }
        .sort-row.sort-dragging { opacity: 0.5; background: #e6f7ff; border: 1px dashed #1890ff; z-index: 10; position: relative; }
        .sort-row .row-type { width: 50px; text-align: center; margin-right: 8px; }
        .sort-row .row-type .layui-badge { font-size: 10px; padding: 0 5px; line-height: 18px; height: 18px; }
        .sort-row .row-name { width: 100px; font-weight: 500; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
        .sort-row .row-key { width: 110px; color: #999; font-size: 12px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
        .sort-row .row-actions { margin-left: auto; display: flex; gap: 4px; flex-shrink: 0; }
        .sort-row .row-actions .layui-btn-xs { padding: 0 6px; height: 24px; line-height: 22px; font-size: 12px; }
        .sort-row.row-hidden { opacity: 0.45; text-decoration: line-through; background: #fff9f0; }
        .sort-list { max-height: none; overflow-y: auto; flex: 1; }
        .field-table-wrap { flex: 1; overflow: auto; }
        .field-table-wrap .layui-table-view { margin: 0; }
    </style>
</head>
<body>
<div class="pear-container">
    <div class="layui-card">
        <div class="layui-card-header" style="display:flex;justify-content:space-between;align-items:center;">
            <span id="modelTitle">模型设计器</span>
            <div style="display:flex;gap:6px;">
                <button class="layui-btn layui-btn-sm layui-btn-primary" id="saveFieldConfigBtn"><i class="layui-icon layui-icon-ok"></i> 保存配置</button>
                <a class="layui-btn layui-btn-sm" href="/admin/content-model">
                    <i class="layui-icon layui-icon-return"></i> 返回列表
                </a>
            </div>
        </div>
        <div class="layui-card-body">
            <div class="designer-layout">
                <div class="designer-left">
                    <div class="panel-section" style="height:100%;">
                        <div class="panel-header">
                            <span><i class="fa fa-list-alt"></i> 扩展字段管理</span>
                            <div style="display:flex;gap:6px;">
                                <button class="layui-btn layui-btn-xs layui-btn-normal" id="addFieldBtn"><i class="layui-icon layui-icon-add-1"></i> 添加字段</button>
                                <button class="layui-btn layui-btn-xs" id="previewBtn" title="预览模型"><i class="layui-icon layui-icon-search"></i> 预览</button>
                            </div>
                        </div>
                        <div class="panel-body">
                            <div class="field-table-wrap">
                                <table id="field-table" lay-filter="field-table"></table>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="designer-right">
                    <div class="panel-section" style="height:100%;">
                        <div class="panel-header">
                            <span><i class="fa fa-arrows-v"></i> 字段排序（拖拽调整顺序）</span>
                            <div style="display:flex;gap:6px;">
                                <button class="layui-btn layui-btn-xs layui-btn-warm" id="showAllFieldsBtn" title="显示全部"><i class="fa fa-eye"></i></button>
                                <button class="layui-btn layui-btn-xs" id="hideSystemFieldsBtn" title="隐藏系统字段"><i class="fa fa-eye-slash"></i></button>
                            </div>
                        </div>
                        <div class="panel-body">
                            <div id="sortList" class="sort-list"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    @verbatim
    <script type="text/html" id="field-bar">
        <div class="layui-btn-container">
            <a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
            <a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
        </div>
    </script>

    <script type="text/html" id="field-status-tpl">
        <input type="checkbox" name="status" value="{{ d.id }}" lay-skin="switch" lay-text="正常|禁用" lay-filter="field-status" {{ d.status == 1 ? 'checked' : '' }} />
    </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'], function() {
        var table = layui.table;
        var form = layui.form;
        var $ = layui.jquery;

        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': '{{ csrf_token() }}'
            },
            statusCode: {
                401: function() {
                    layer.msg('登录已过期，请重新登录', {icon: 2, time: 1500}, function() {
                        window.location.href = '/admin/login?redirect=' + encodeURIComponent(window.location.pathname + window.location.search);
                    });
                }
            }
        });

        var modelId = window.location.pathname.split('/').pop();
        var fieldList = [];
        var modelData = null;

        var defaultMainFields = [
            { key: 'category_id', label: '分类', required: true, system: true, type: 'main' },
            { key: 'title', label: '标题', required: true, system: true, type: 'main' },
            { key: 'summary', label: '摘要', required: false, system: false, type: 'main' },
            { key: 'cover_image', label: '封面图', required: false, system: false, type: 'main' },
            { key: 'author', label: '作者', required: false, system: false, type: 'main' },
            { key: 'source', label: '来源', required: false, system: false, type: 'main' },
            { key: 'published_at', label: '发布时间', required: false, system: false, type: 'main' },
            { key: 'content', label: '正文', required: false, system: true, type: 'main' },
            { key: 'sort', label: '排序', required: false, system: true, type: 'main' },
            { key: 'status', label: '状态', required: false, system: true, type: 'main' }
        ];

        var allSortedFields = [];
        var savedConfig = null;

        $.ajax({
            url: '/api/admin/content-models/' + modelId,
            type: 'GET',
            dataType: 'json',
            async: false,
            success: function(res) {
                if (res.code === 0 && res.data) {
                    modelData = res.data;
                    $('#modelTitle').text('模型设计器 - ' + res.data.name);
                    savedConfig = res.data.field_config;
                }
            }
        });

        function loadSortedList(extensionFields) {
            if (savedConfig && savedConfig.fields) {
                allSortedFields = JSON.parse(JSON.stringify(savedConfig.fields));
                var existingKeys = {};
                for (var i = 0; i < allSortedFields.length; i++) {
                    existingKeys[allSortedFields[i].key] = true;
                }

                for (var j = 0; j < defaultMainFields.length; j++) {
                    if (!existingKeys[defaultMainFields[j].key]) {
                        allSortedFields.push({
                            key: defaultMainFields[j].key,
                            label: defaultMainFields[j].label,
                            type: 'main',
                            required: defaultMainFields[j].required,
                            system: defaultMainFields[j].system,
                            visible: true
                        });
                    }
                }

                for (var k = 0; k < (extensionFields || []).length; k++) {
                    var ef = extensionFields[k];
                    if (!existingKeys['ext_' + ef.id]) {
                        allSortedFields.push({
                            key: 'ext_' + ef.id,
                            fieldKey: ef.field,
                            label: ef.name,
                            type: 'extension',
                            extId: ef.id,
                            formType: ef.form_type,
                            visible: true
                        });
                    } else {
                        for (var m = 0; m < allSortedFields.length; m++) {
                            if (allSortedFields[m].key === 'ext_' + ef.id) {
                                allSortedFields[m].fieldKey = ef.field;
                                allSortedFields[m].label = ef.name;
                                allSortedFields[m].formType = ef.form_type;
                                break;
                            }
                        }
                    }
                }

                allSortedFields.sort(function(a, b) {
                    return (a.order || 999) - (b.order || 999);
                });

                var extIdMap = {};
                for (var ei = 0; ei < (extensionFields || []).length; ei++) {
                    extIdMap[extensionFields[ei].id] = true;
                }

                allSortedFields = allSortedFields.filter(function(field) {
                    if (field.type !== 'extension') return true;
                    return !!extIdMap[field.extId];
                });
            } else {
                allSortedFields = [];

                for (var n = 0; n < defaultMainFields.length; n++) {
                    allSortedFields.push({
                        key: defaultMainFields[n].key,
                        label: defaultMainFields[n].label,
                        type: 'main',
                        required: defaultMainFields[n].required,
                        system: defaultMainFields[n].system,
                        visible: true,
                        order: n
                    });
                }

                for (var p = 0; p < (extensionFields || []).length; p++) {
                    var efd = extensionFields[p];
                    allSortedFields.push({
                        key: 'ext_' + efd.id,
                        fieldKey: efd.field,
                        label: efd.name,
                        type: 'extension',
                        extId: efd.id,
                        formType: efd.form_type,
                        visible: true,
                        order: defaultMainFields.length + p
                    });
                }
            }
            renderSortList();
        }

        function renderSortList() {
            allSortedFields.sort(function(a, b) {
                return (a.order || 0) - (b.order || 0);
            });

            var html = '';
            for (var i = 0; i < allSortedFields.length; i++) {
                var f = allSortedFields[i];
                var hiddenClass = f.visible ? '' : ' row-hidden';
                var reqMark = f.required ? '<span style="color:#ff5722;margin-right:2px;">*</span>' : '';

                var typeBadge, typeClass;
                if (f.type === 'main') {
                    typeBadge = f.system ? '系统' : '公共';
                    typeClass = f.system ? 'layui-bg-gray' : 'layui-bg-blue';
                } else {
                    typeBadge = '扩展';
                    typeClass = 'layui-bg-green';
                }

                var eyeIcon = f.visible ? 'fa-eye' : 'fa-eye-slash';
                var eyeTitle = f.visible ? '隐藏' : '显示';

                var isFirst = (i === 0);
                var isLast = (i === allSortedFields.length - 1);

                html += '<div class="sort-row' + hiddenClass + '" data-idx="' + i + '" data-key="' + f.key + '" draggable="true">'
                    + '<div class="row-type"><span class="layui-badge ' + typeClass + '">' + typeBadge + '</span></div>'
                    + '<div class="row-name">' + reqMark + escapeHtml(f.label) + '</div>'
                    + '<div class="row-key"><code>' + escapeHtml(f.type === 'main' ? f.key : (f.fieldKey || '-')) + '</code></div>'
                    + '<div class="row-actions">'
                    + '<button class="layui-btn layui-btn-xs layui-btn-primary move-up" data-idx="' + i + '" title="上移"' + (isFirst ? ' disabled style="opacity:0.3"' : '') + '><i class="fa fa-arrow-up"></i></button>'
                    + '<button class="layui-btn layui-btn-xs layui-btn-primary move-down" data-idx="' + i + '" title="下移"' + (isLast ? ' disabled style="opacity:0.3"' : '') + '><i class="fa fa-arrow-down"></i></button>'
                    + '<button class="layui-btn layui-btn-xs toggle-visible" data-idx="' + i + '" title="' + eyeTitle + '"><i class="fa ' + eyeIcon + '"></i></button>';
                if (f.type === 'extension') {
                    html += '<a class="layui-btn layui-btn-xs layui-btn-normal edit-ext-field" data-ext-id="' + (f.extId || '') + '" title="编辑"><i class="fa fa-edit"></i></a>';
                }
                html += '</div></div>';
            }
            $('#sortList').html(html);
            bindDragEvents();
        }

        function bindDragEvents() {
            var $list = $('#sortList');
            var $dragItem = null;

            $list.off('dragstart').on('dragstart', '.sort-row', function(e) {
                $dragItem = $(this);
                $(this).addClass('sort-dragging');
                e.originalEvent.dataTransfer.effectAllowed = 'move';
                e.originalEvent.dataTransfer.setData('text/plain', $(this).data('idx'));
            });

            $list.off('dragover').on('dragover', '.sort-row', function(e) {
                e.preventDefault();
                e.originalEvent.dataTransfer.dropEffect = 'move';

                if ($dragItem && $(this)[0] !== $dragItem[0]) {
                    var thisTop = $(this).offset().top;
                    var thisHeight = $(this).outerHeight();
                    var y = e.pageY;

                    if (y < thisTop + thisHeight / 2) {
                        $(this).before($dragItem);
                    } else {
                        $(this).after($dragItem);
                    }
                }
            });

            $list.off('dragend').on('dragend', '.sort-row', function(e) {
                $(this).removeClass('sort-dragging');
                updateOrderFromDOM();
                $dragItem = null;
            });
        }

        function updateOrderFromDOM() {
            $('#sortList .sort-row').each(function(idx) {
                var key = $(this).data('key');
                for (var i = 0; i < allSortedFields.length; i++) {
                    if (allSortedFields[i].key === key) {
                        allSortedFields[i].order = idx;
                        break;
                    }
                }
            });
        }

        $(document).on('click', '.move-up', function(e) {
            e.stopPropagation();
            var idx = parseInt($(this).data('idx'));
            if (idx <= 0) return;
            swapFields(idx, idx - 1);
        });

        $(document).on('click', '.move-down', function(e) {
            e.stopPropagation();
            var idx = parseInt($(this).data('idx'));
            if (idx >= allSortedFields.length - 1) return;
            swapFields(idx, idx + 1);
        });

        function swapFields(fromIdx, toIdx) {
            var tmp = allSortedFields[fromIdx];
            allSortedFields[fromIdx] = allSortedFields[toIdx];
            allSortedFields[toIdx] = tmp;
            renderSortList();
        }

        $(document).on('click', '.toggle-visible', function(e) {
            e.stopPropagation();
            var idx = parseInt($(this).data('idx'));
            allSortedFields[idx].visible = !allSortedFields[idx].visible;
            renderSortList();
        });

        $(document).on('click', '.edit-ext-field', function(e) {
            e.stopPropagation();
            var extId = $(this).data('ext-id');
            for (var i = 0; i < fieldList.length; i++) {
                if (fieldList[i].id == extId) {
                    openFieldForm(fieldList[i]);
                    break;
                }
            }
        });

        $('#showAllFieldsBtn').on('click', function() {
            for (var i = 0; i < allSortedFields.length; i++) {
                allSortedFields[i].visible = true;
            }
            renderSortList();
        });

        $('#hideSystemFieldsBtn').on('click', function() {
            for (var i = 0; i < allSortedFields.length; i++) {
                if (allSortedFields[i].type === 'main' && allSortedFields[i].system) {
                    allSortedFields[i].visible = false;
                }
            }
            renderSortList();
        });

        $('#saveFieldConfigBtn').on('click', function() {
            updateOrderFromDOM();

            allSortedFields.sort(function(a, b) {
                return (a.order || 0) - (b.order || 0);
            });

            var config = { fields: [] };
            for (var i = 0; i < allSortedFields.length; i++) {
                config.fields.push({
                    key: allSortedFields[i].key,
                    label: allSortedFields[i].label,
                    type: allSortedFields[i].type,
                    visible: allSortedFields[i].visible,
                    order: i
                });
            }

            var loading = layer.load(2);
            $.ajax({
                url: '/api/admin/content-models/' + modelId,
                type: 'PUT',
                dataType: 'json',
                contentType: 'application/json',
                data: JSON.stringify({ field_config: config }),
                success: function(res) {
                    layer.close(loading);
                    if (res.code === 0) {
                        layer.msg('字段配置保存成功', { icon: 1, time: 1200 });
                        savedConfig = config;
                    } else {
                        layer.msg(res.message || '保存失败', { icon: 2 });
                    }
                },
                error: function() {
                    layer.close(loading);
                    layer.msg('请求失败', { icon: 2 });
                }
            });
        });

        var dbTypeMap = {
            varchar: 'VARCHAR',
            text: 'TEXT',
            longtext: 'LONGTEXT',
            int: 'INT',
            decimal: 'DECIMAL',
            date: 'DATE',
            datetime: 'DATETIME',
            json: 'JSON'
        };

        var formTypeMap = {
            text: '单行文本',
            textarea: '多行文本',
            tinymce: '富文本',
            select: '下拉选择',
            radio: '单选框',
            checkbox: '复选框',
            switch: '开关',
            date: '日期',
            datetime: '日期时间',
            image: '图片',
            file: '文件',
            number: '数字',
            color: '颜色',
            tags: '标签'
        };

        var cols = [[
            { title: 'ID', field: 'id', align: 'center', width: 70, sort: true },
            { title: '字段名称', field: 'name', align: 'center', minWidth: 120 },
            { title: '字段标识', field: 'field', align: 'center', width: 120 },
            { title: '数据库类型', field: 'type', align: 'center', width: 110, templet: function(d) {
                return dbTypeMap[d.type] || d.type;
            }},
            { title: '长度', field: 'length', align: 'center', width: 70 },
            { title: '表单类型', field: 'form_type', align: 'center', width: 100, templet: function(d) {
                return formTypeMap[d.form_type] || d.form_type;
            }},
            { title: '排序', field: 'sort', align: 'center', width: 70 },
            { title: '状态', field: 'status', align: 'center', width: 100, templet: '#field-status-tpl' },
            { title: '操作', toolbar: '#field-bar', align: 'center', width: 140, fixed: 'right' }
        ]];

        var inst = table.render({
            elem: '#field-table',
            url: '/api/admin/content-models/' + modelId + '/fields',
            page: false,
            cols: cols,
            skin: false,
            defaultToolbar: [{
                title: '刷新',
                layEvent: 'refresh',
                icon: 'layui-icon-refresh'
            }],
            parseData: function(res) {
                fieldList = res.data || [];
                loadSortedList(fieldList);
                return {
                    "code": res.code === 0 ? 0 : 1,
                    "msg": res.message || "",
                    "count": fieldList.length,
                    "data": fieldList
                };
            }
        });

        $('#addFieldBtn').on('click', function() {
            openFieldForm(null);
        });
        $('#previewBtn').on('click', function() {
            openModelPreview();
        });

        form.on('switch(field-status)', function(obj) {
            var id = this.value;
            $.ajax({
                url: '/api/admin/content-model-fields/' + 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();
                }
            });
        });

        table.on('toolbar(field-table)', function(obj) {
            if (obj.event === 'refresh') {
                table.reload('field-table');
            }
        });

        table.on('tool(' + inst.config.id + ')', function(obj) {
            if (obj.event === 'edit') {
                openFieldForm(obj.data);
            } else if (obj.event === 'del') {
                removeField(obj);
            }
        });

        function removeField(obj) {
            layer.confirm('确定要删除该字段？删除后无法恢复！', {
                icon: 3,
                title: '操作提示',
                btn: ['确定', '取消']
            }, function(index) {
                layer.close(index);
                var loading = layer.load();
                $.ajax({
                    url: '/api/admin/content-model-fields/' + 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('field-table');
                            });
                        } else {
                            layer.msg(res.message || '删除失败', { icon: 2, time: 1500 });
                        }
                    },
                    error: function() {
                        layer.close(loading);
                        layer.msg('请求失败', { icon: 2, time: 1500 });
                    }
                });
            });
        }

        function openFieldForm(data) {
            var isEdit = !!data;
            var dbTypeOptions = ['varchar', 'text', 'longtext', 'int', 'decimal', 'date', 'datetime', 'json'];
            var formTypeOptions = ['text', 'textarea', 'tinymce', 'select', 'radio', 'checkbox', 'switch', 'date', 'datetime', 'image', 'file', 'number', 'color', 'tags'];

            var dbTypeSelectHtml = '';
            for (var i = 0; i < dbTypeOptions.length; i++) {
                var sel = (data && data.type === dbTypeOptions[i]) ? ' selected' : (!data && dbTypeOptions[i] === 'varchar' ? ' selected' : '');
                dbTypeSelectHtml += '<option value="' + dbTypeOptions[i] + '"' + sel + '>' + dbTypeOptions[i].toUpperCase() + '</option>';
            }

            var formTypeSelectHtml = '';
            for (var j = 0; j < formTypeOptions.length; j++) {
                var fSel = (data && data.form_type === formTypeOptions[j]) ? ' selected' : (!data && formTypeOptions[j] === 'text' ? ' selected' : '');
                formTypeSelectHtml += '<option value="' + formTypeOptions[j] + '"' + fSel + '>' + (formTypeMap[formTypeOptions[j]] || formTypeOptions[j]) + '</option>';
            }

            var formConfigVal = '';
            if (data && data.form_config) {
                formConfigVal = typeof data.form_config === 'string' ? data.form_config : JSON.stringify(data.form_config);
            }

            var content = '<form class="layui-form" style="padding:20px;" lay-filter="fieldForm">'
                + '<div class="layui-form-item"><label class="layui-form-label">字段名称</label>'
                + '<div class="layui-input-block"><input type="text" name="name" value="' + (data ? (data.name || '') : '') + '" class="layui-input" placeholder="字段显示名称" lay-verify="required"></div></div>'
                + '<div class="layui-form-item"><label class="layui-form-label">字段标识</label>'
                + '<div class="layui-input-block"><input type="text" name="field" value="' + (data ? (data.field || '') : '') + '" class="layui-input" placeholder="数据库字段名（英文）" lay-verify="required"' + (isEdit ? ' disabled' : '') + '></div></div>'
                + '<div class="layui-form-item"><label class="layui-form-label">数据库类型</label>'
                + '<div class="layui-input-block"><select name="type" id="fieldDbType">' + dbTypeSelectHtml + '</select></div></div>'
                + '<div class="layui-form-item" id="fieldLengthItem"><label class="layui-form-label">长度</label>'
                + '<div class="layui-input-block"><input type="number" name="length" value="' + (data ? (data.length || '') : '255') + '" class="layui-input" placeholder="字段长度"></div></div>'
                + '<div class="layui-form-item" id="fieldDecimalItem" style="display:none;"><label class="layui-form-label">小数位数</label>'
                + '<div class="layui-input-block"><input type="number" name="decimal_precision" value="' + (data ? (data.decimal_precision || 2) : '2') + '" class="layui-input" placeholder="小数位数"></div></div>'
                + '<div class="layui-form-item"><label class="layui-form-label">默认值</label>'
                + '<div class="layui-input-block"><input type="text" name="default_value" value="' + (data ? (data.default_value || '') : '') + '" class="layui-input" placeholder="默认值（可选）"></div></div>'
                + '<div class="layui-form-item"><label class="layui-form-label">表单类型</label>'
                + '<div class="layui-input-block"><select name="form_type" id="fieldFormType">' + formTypeSelectHtml + '</select></div></div>'
                + '<div class="layui-form-item" id="fieldFormConfigItem" style="display:none;"><label class="layui-form-label">表单配置</label>'
                + '<div class="layui-input-block"><textarea name="form_config" class="layui-textarea" style="min-height:80px;" placeholder=\'选项配置JSON，如：[{"label":"选项1","value":"1"}]\'>' + formConfigVal + '</textarea></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="正常|禁用"' + (!data || data.status == 1 ? ' checked' : '') + '></div></div>'
                + '<div class="layui-form-item"><label class="layui-form-label">排序</label>'
                + '<div class="layui-input-block"><input type="number" name="sort" value="' + (data ? (data.sort || 0) : 0) + '" class="layui-input"></div></div>'
                + '<div class="layui-form-item" style="text-align:right;margin-top:16px;">'
                + '<button type="button" class="layui-btn layui-btn-primary" id="fieldCancelBtn">取消</button> '
                + '<button type="button" class="layui-btn" id="fieldSubmitBtn">确定</button></div></form>';

            layer.open({
                type: 1,
                title: isEdit ? '编辑字段' : '添加字段',
                area: ['550px', '580px'],
                content: content,
                success: function(layero) {
                    form.render(null, 'fieldForm');
                    toggleFieldVisibility(layero);

                    layero.find('#fieldDbType').on('change', function() {
                        toggleFieldVisibility(layero);
                    });
                    layero.find('#fieldFormType').on('change', function() {
                        toggleFieldVisibility(layero);
                    });

                    layero.find('#fieldCancelBtn').on('click', function() {
                        layer.closeAll();
                    });

                    layero.find('#fieldSubmitBtn').on('click', function() {
                        var formData = {
                            name: layero.find('input[name=name]').val().trim(),
                            field: layero.find('input[name=field]').val().trim(),
                            type: layero.find('select[name=type]').val(),
                            length: layero.find('input[name=length]').val() || null,
                            decimal_precision: layero.find('input[name=decimal_precision]').val() || null,
                            default_value: layero.find('input[name=default_value]').val(),
                            form_type: layero.find('select[name=form_type]').val(),
                            status: layero.find('input[name=status]').prop('checked') ? 1 : 0,
                            sort: parseInt(layero.find('input[name=sort]').val()) || 0
                        };

                        var formConfigStr = layero.find('textarea[name=form_config]').val().trim();
                        if (formConfigStr) {
                            try {
                                formData.form_config = JSON.parse(formConfigStr);
                            } catch(e) {
                                formData.form_config = formConfigStr;
                            }
                        }

                        if (!formData.name || !formData.field) {
                            layer.msg('字段名称和字段标识不能为空', { icon: 5 });
                            return;
                        }

                        var url, method;
                        if (isEdit) {
                            url = '/api/admin/content-model-fields/' + data.id;
                            method = 'PUT';
                        } else {
                            url = '/api/admin/content-models/' + modelId + '/fields';
                            method = 'POST';
                        }

                        $.ajax({
                            url: url,
                            type: method,
                            dataType: 'json',
                            contentType: 'application/json',
                            data: JSON.stringify(formData),
                            success: function(res) {
                                if (res.code === 0) {
                                    layer.msg(isEdit ? '更新成功' : '添加成功', { icon: 1, time: 1000 });
                                    layer.closeAll();
                                    table.reload('field-table');
                                } else {
                                    layer.msg(res.message || '操作失败', { icon: 2, time: 1500 });
                                }
                            },
                            error: function() {
                                layer.msg('请求失败', { icon: 2, time: 1500 });
                            }
                        });
                    });
                }
            });
        }

        function openModelPreview() {
            updateOrderFromDOM();
            var previewConfig = buildSaveConfig();

            var loading = layer.load(2);
            $.ajax({
                url: '/api/admin/content-models/' + modelId,
                type: 'GET',
                dataType: 'json',
                success: function(modelRes) {
                    if (modelRes.code !== 0 || !modelRes.data) {
                        layer.close(loading);
                        layer.msg('模型数据加载失败', { icon: 2 });
                        return;
                    }
                    var model = modelRes.data;

                    $.ajax({
                        url: '/api/admin/content-models/' + modelId + '/fields',
                        type: 'GET',
                        dataType: 'json',
                        success: function(fieldRes) {
                            layer.close(loading);
                            var fields = (fieldRes.code === 0 && fieldRes.data) ? fieldRes.data : [];

                            var formHtml = '<form class="layui-form" style="margin:0;padding:0;">';
                            formHtml += renderUnifiedPreview(previewConfig, fields);
                            formHtml += '</form>';

                            layer.open({
                                type: 1,
                                title: escapeHtml(model.name) + ' - 表单预览',
                                area: ['700px', '85vh'],
                                content: formHtml,
                                maxmin: true,
                                success: function(layero) {
                                    form.render(null, 'previewForm');
                                }
                            });
                        },
                        error: function() {
                            layer.close(loading);
                            layer.msg('字段数据加载失败', { icon: 2 });
                        }
                    });
                },
                error: function() {
                    layer.close(loading);
                    layer.msg('请求失败', { icon: 2 });
                }
            });
        }

        function buildSaveConfig() {
            var sorted = allSortedFields.slice().sort(function(a, b) {
                return (a.order || 0) - (b.order || 0);
            });

            var config = { fields: [] };
            for (var i = 0; i < sorted.length; i++) {
                config.fields.push({
                    key: sorted[i].key,
                    label: sorted[i].label,
                    type: sorted[i].type,
                    visible: sorted[i].visible,
                    order: i
                });
            }
            return config;
        }

        function getMainFieldTemplate(key) {
            switch (key) {
                case 'category_id': return '<select disabled><option value="">请选择分类</option></select>';
                case 'title': return '<input type="text" class="layui-input" disabled placeholder="请输入标题" style="background:#f5f5f5;">';
                case 'summary': return '<textarea class="layui-textarea" disabled placeholder="内容摘要（可选）" style="min-height:60px;background:#f5f5f5;"></textarea>';
                case 'cover_image': return '<button type="button" class="layui-btn layui-btn-sm layui-btn-disabled" disabled><i class="layui-icon layui-icon-upload"></i> 选择图片</button> <span style="color:#aaa;">未选择图片</span>';
                case 'author': return '<input type="text" class="layui-input" disabled placeholder="作者（可选）" style="background:#f5f5f5;">';
                case 'source': return '<input type="text" class="layui-input" disabled placeholder="来源（可选）" style="background:#f5f5f5;">';
                case 'published_at': return '<input type="text" class="layui-input" disabled placeholder="选择发布时间" style="background:#f5f5f5;">';
                case 'content': return '<textarea class="layui-textarea" disabled placeholder="富文本编辑器区域" style="min-height:150px;background:#f5f5f5;"></textarea>';
                case 'sort': return '<input type="number" class="layui-input" disabled placeholder="数字越小越靠前" value="0" style="background:#f5f5f5;">';
                case 'status': return '<input type="radio" name="prev_status" title="草稿" checked disabled> <input type="radio" name="prev_status" title="已发布" disabled> <input type="radio" name="prev_status" title="已下架" disabled>';
                default: return '<input type="text" class="layui-input" disabled style="background:#f5f5f5;">';
            }
        }

        function getExtFieldTemplate(formType, fieldName) {
            switch (formType) {
                case 'text': return '<input type="text" class="layui-input" disabled placeholder="请输入' + escapeHtml(fieldName) + '" style="background:#f5f5f5;">';
                case 'textarea':
                case 'tinymce': return '<textarea class="layui-textarea" disabled placeholder="' + escapeHtml(fieldName) + '" style="min-height:80px;background:#f5f5f5;"></textarea>';
                case 'select': return '<select disabled><option value="">请选择' + escapeHtml(fieldName) + '</option><option>选项示例1</option></select>';
                case 'radio': return '<input type="radio" name="prev_ext_' + Math.random().toString(36).substr(2, 5) + '" title="选项A" disabled checked> <input type="radio" name="prev_ext_b" title="选项B" disabled>';
                case 'checkbox': return '<input type="checkbox" title="复选项A" disabled> <input type="checkbox" title="复选项B" disabled>';
                case 'switch': return '<input type="checkbox" lay-skin="switch" lay-text="是|否" disabled>';
                case 'date':
                case 'datetime': return '<input type="text" class="layui-input" disabled placeholder="选择' + (formType === 'date' ? '日期' : '时间') + '" style="background:#f5f5f5;">';
                case 'image': return '<button type="button" class="layui-btn layui-btn-sm layui-btn-disabled" disabled><i class="layui-icon layui-icon-upload"></i> 选择图片</button> <span style="color:#aaa;">未选择</span>';
                case 'file': return '<button type="button" class="layui-btn layui-btn-sm layui-btn-disabled" disabled><i class="layui-icon layui-icon-upload"></i> 选择文件</button> <span style="color:#aaa;">未选择</span>';
                case 'number': return '<input type="number" class="layui-input" disabled placeholder="请输入数字" style="background:#f5f5f5;">';
                case 'color': return '<input type="color" value="#16b777" disabled style="width:50px;height:38px;padding:2px;">';
                case 'tags': return '<input type="text" class="layui-input" disabled placeholder="多个标签用逗号分隔" style="background:#f5f5f5;">';
                default: return '<input type="text" class="layui-input" disabled style="background:#f5f5f5;">';
            }
        }

        function renderUnifiedPreview(config, extensionFields) {
            var orderedFields = config.fields || [];

            var extMap = {};
            for (var i = 0; i < (extensionFields || []).length; i++) {
                extMap['ext_' + extensionFields[i].id] = extensionFields[i];
            }

            var mainReqMap = {};
            for (var j = 0; j < defaultMainFields.length; j++) {
                mainReqMap[defaultMainFields[j].key] = defaultMainFields[j].required;
            }

            var visibleCount = 0;
            for (var k = 0; k < orderedFields.length; k++) {
                if (orderedFields[k].visible) visibleCount++;
            }

            if (visibleCount === 0) {
                return '<div style="padding:20px;text-align:center;color:#999;">所有字段已隐藏</div>';
            }

            var html = '<div style="padding:12px 15px;background:#f8f9fa;border-bottom:1px solid #eee;font-size:13px;color:#666;margin-bottom:5px;">'
                + '表单预览（共 ' + visibleCount + ' 个可见字段，按设计器中的统一顺序排列）'
                + '</div>';

            for (var m = 0; m < orderedFields.length; m++) {
                var f = orderedFields[m];
                if (!f.visible) continue;

                var reqMark = isRequired(f.key) ? '<span style="color:#ff5722;">*</span> ' : '';

                var controlHtml;
                if (f.type === 'main') {
                    controlHtml = getMainFieldTemplate(f.key);
                } else {
                    var extData = extMap[f.key] || {};
                    controlHtml = getExtFieldTemplate(extData.form_type || 'text', f.label);
                }

                html += '<div class="layui-form-item">'
                    + '<label class="layui-form-label">' + reqMark + escapeHtml(f.label) + '</label>'
                    + '<div class="layui-input-block">' + controlHtml + '</div></div>';
            }
            return html;
        }

        function isRequired(key) {
            for (var i = 0; i < defaultMainFields.length; i++) {
                if (defaultMainFields[i].key === key) return defaultMainFields[i].required;
            }
            return false;
        }

        function escapeHtml(str) {
            if (!str) return '';
            return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
        }

        function toggleFieldVisibility(layero) {
            var dbType = layero.find('#fieldDbType').val();
            var formType = layero.find('#fieldFormType').val();

            if (dbType === 'varchar' || dbType === 'int' || dbType === 'decimal') {
                layero.find('#fieldLengthItem').show();
            } else {
                layero.find('#fieldLengthItem').hide();
            }

            if (dbType === 'decimal') {
                layero.find('#fieldDecimalItem').show();
            } else {
                layero.find('#fieldDecimalItem').hide();
            }

            if (formType === 'select' || formType === 'radio' || formType === 'checkbox') {
                layero.find('#fieldFormConfigItem').show();
            } else {
                layero.find('#fieldFormConfigItem').hide();
            }
        }
    });
</script>
</body>
</html>
