```html

<!DOCTYPE html>

<html lang="zh">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>快速简历包装器 · 实时生成</title>

    <style>

        * {

            margin: 0;

            padding: 0;

            box-sizing: border-box;

            font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;

        }

 

        body {

            background: #f1f5f9;

            min-height: 100vh;

            display: flex;

            justify-content: center;

            align-items: center;

            padding: 2rem 1rem;

        }

 

        .container {

            max-width: 1200px;

            width: 100%;

            display: grid;

            grid-template-columns: 1fr 1.2fr;

            gap: 2rem;

            background: white;

            border-radius: 2.5rem;

            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);

            padding: 2rem;

            transition: all 0.2s ease;

        }

 

        /* 输入区 */

        .input-panel {

            background: #fafcff;

            border-radius: 1.8rem;

            padding: 1.8rem 1.5rem;

            box-shadow: inset 0 2px 8px rgba(0,0,0,0.02), 0 4px 12px rgba(0,20,40,0.04);

        }

 

        .input-panel h2 {

            font-size: 1.6rem;

            font-weight: 600;

            letter-spacing: -0.02em;

            color: #0b1e33;

            display: flex;

            align-items: center;

            gap: 0.5rem;

            margin-bottom: 1.8rem;

            border-bottom: 2px solid #e9eef3;

            padding-bottom: 0.8rem;

        }

 

        .input-panel h2 span {

            background: #1e4a6b;

            color: white;

            font-size: 0.9rem;

            font-weight: 500;

            border-radius: 40px;

            padding: 0.1rem 0.9rem;

            margin-left: 0.25rem;

        }

 

        .form-group {

            margin-bottom: 1.25rem;

        }

 

        .form-group label {

            display: block;

            font-weight: 500;

            font-size: 0.85rem;

            text-transform: uppercase;

            letter-spacing: 0.03em;

            color: #2c3e58;

            margin-bottom: 0.35rem;

        }

 

        .form-group input,

        .form-group textarea {

            width: 100%;

            padding: 0.7rem 1rem;

            background: white;

            border: 1px solid #dce3ec;

            border-radius: 1.2rem;

            font-size: 0.95rem;

            transition: 0.2s;

            outline: none;

            color: #0b1e33;

        }

 

        .form-group input:focus,

        .form-group textarea:focus {

            border-color: #1e4a6b;

            box-shadow: 0 0 0 3px rgba(30, 74, 107, 0.15);

        }

 

        .form-group textarea {

            resize: vertical;

            min-height: 70px;

            line-height: 1.5;

        }

 

        .row-2col {

            display: grid;

            grid-template-columns: 1fr 1fr;

            gap: 0.8rem;

        }

 

        .btn-reset {

            background: transparent;

            border: 1px solid #d0dae8;

            color: #2f405b;

            padding: 0.6rem 1.8rem;

            border-radius: 3rem;

            font-weight: 500;

            font-size: 0.9rem;

            cursor: pointer;

            transition: 0.15s;

            margin-top: 0.3rem;

        }

 

        .btn-reset:hover {

            background: #eef3f9;

            border-color: #a7b9cf;

        }

 

        .btn-reset:active {

            transform: scale(0.96);

        }

 

        .hint {

            font-size: 0.8rem;

            color: #62748c;

            margin-top: 0.4rem;

            display: flex;

            gap: 0.2rem;

            align-items: center;

        }

 

        /* 简历预览区 — 包装效果 */

        .resume-panel {

            background: #ffffff;

            border-radius: 1.8rem;

            padding: 1.8rem 1.5rem;

            box-shadow: 0 8px 24px rgba(0, 20, 40, 0.06);

            border: 1px solid #eef2f7;

        }

 

        .resume-panel .header {

            display: flex;

            justify-content: space-between;

            align-items: baseline;

            margin-bottom: 1.2rem;

            border-bottom: 2px dashed #dce3ec;

            padding-bottom: 0.7rem;

        }

 

        .resume-panel .header h3 {

            font-weight: 600;

            font-size: 1.3rem;

            color: #0b1e33;

            letter-spacing: -0.02em;

        }

 

        .resume-panel .header .badge {

            background: #eef3f9;

            color: #1e4a6b;

            font-size: 0.75rem;

            font-weight: 600;

            padding: 0.2rem 1rem;

            border-radius: 40px;

        }

 

        /* 简历卡片 — 核心包装 */

        .resume-card {

            background: #f9fcff;

            border-radius: 1.6rem;

            padding: 1.8rem 1.8rem 1.6rem;

            box-shadow: 0 6px 14px rgba(0, 20, 40, 0.04);

            border: 1px solid #e6edf6;

            transition: 0.2s;

            min-height: 400px;

            display: flex;

            flex-direction: column;

        }

 

        .resume-card .name-title {

            margin-bottom: 1rem;

        }

 

        .resume-card .name-title h1 {

            font-size: 2.2rem;

            font-weight: 700;

            color: #0b1e33;

            letter-spacing: -0.02em;

            line-height: 1.1;

            word-break: break-word;

        }

 

        .resume-card .name-title .title {

            font-size: 1rem;

            font-weight: 500;

            color: #2a4b6e;

            background: #e4ecf5;

            display: inline-block;

            padding: 0.2rem 1.2rem;

            border-radius: 40px;

            margin-top: 0.3rem;

            letter-spacing: 0.02em;

        }

 

        .resume-divider {

            height: 2px;

            background: linear-gradient(90deg, #cbd9e9, #eef2f7);

            margin: 0.8rem 0 1rem;

        }

 

        .resume-contact {

            display: flex;

            flex-wrap: wrap;

            gap: 0.8rem 1.5rem;

            font-size: 0.9rem;

            color: #1e3b56;

            background: #f0f5fc;

            padding: 0.6rem 1.2rem;

            border-radius: 3rem;

            margin-bottom: 1.2rem;

        }

 

        .resume-contact span {

            display: flex;

            align-items: center;

            gap: 0.3rem;

        }

 

        .resume-contact .icon {

            opacity: 0.6;

            font-weight: 300;

        }

 

        .resume-section {

            margin-top: 0.5rem;

        }

 

        .resume-section h4 {

            font-weight: 600;

            font-size: 0.9rem;

            letter-spacing: 0.04em;

            color: #1e4a6b;

            text-transform: uppercase;

            border-bottom: 1px solid #dce5ef;

            padding-bottom: 0.3rem;

            margin-bottom: 0.6rem;

        }

 

        .resume-section p {

            font-size: 0.95rem;

            line-height: 1.6;

            color: #1b3147;

            white-space: pre-wrap;

            word-break: break-word;

        }

 

        .resume-section .skill-tags {

            display: flex;

            flex-wrap: wrap;

            gap: 0.4rem 0.6rem;

            margin-top: 0.2rem;

        }

 

        .resume-section .skill-tags span {

            background: #eaf0f8;

            padding: 0.2rem 1rem;

            border-radius: 40px;

            font-size: 0.8rem;

            font-weight: 500;

            color: #1e3f5c;

            letter-spacing: 0.01em;

        }

 

        .empty-state {

            color: #8b9fb2;

            font-size: 0.95rem;

            text-align: center;

            padding: 2.5rem 0.5rem;

            font-style: italic;

            background: #f6faff;

            border-radius: 1.8rem;

        }

 

        .empty-state p {

            margin-top: 0.5rem;

            font-size: 0.85rem;

        }

 

        /* 响应式 */

        @media (max-width: 800px) {

            .container {

                grid-template-columns: 1fr;

                gap: 1.8rem;

                padding: 1.5rem;

            }

            .resume-card .name-title h1 {

                font-size: 1.8rem;

            }

            .row-2col {

                grid-template-columns: 1fr;

            }

        }

 

        @media (max-width: 480px) {

            .container {

                padding: 0.8rem;

                border-radius: 1.8rem;

            }

            .input-panel, .resume-panel {

                padding: 1rem;

            }

        }

    </style>

</head>

<body>

<div class="container">

 

    <!-- 输入面板 -->

    <div class="input-panel">

        <h2>

            📄 简历包装器

            <span>实时</span>

        </h2>

 

        <div class="form-group">

            <label>👤 姓名</label>

            <input type="text" id="nameInput" placeholder="例如:陈思远" value="林语桐">

        </div>

 

        <div class="form-group">

            <label>💼 求职岗位 / 头衔</label>

            <input type="text" id="titleInput" placeholder="例如:全栈开发工程师" value="资深前端架构师">

        </div>

 

        <div class="row-2col">

            <div class="form-group">

                <label>📧 邮箱</label>

                <input type="text" id="emailInput" placeholder="name@work.com" value="yutong.lin@dev.io">

            </div>

            <div class="form-group">

                <label>📱 电话</label>

                <input type="text" id="phoneInput" placeholder="+86 138 0000 0000" value="+86 136 8192 3745">

            </div>

        </div>

 

        <div class="form-group">

            <label>📍 地址 / 城市</label>

            <input type="text" id="addressInput" placeholder="例如:上海 · 远程" value="上海 · 远程">

        </div>

 

        <div class="form-group">

            <label>📝 个人简介 / 亮点</label>

            <textarea id="summaryInput" rows="2" placeholder="简短突出你的核心优势…">7 年全栈经验,专注前端架构与性能优化,带领团队交付多个高并发项目。</textarea>

        </div>

 

        <div class="form-group">

            <label>🛠️ 技能标签(用逗号分隔)</label>

            <input type="text" id="skillsInput" placeholder="React, TypeScript, Node.js, Docker" value="React, TypeScript, Node.js, Docker, AWS, GraphQL">

        </div>

 

        <div style="display: flex; justify-content: flex-end; margin-top: 0.2rem;">

            <button class="btn-reset" id="resetBtn">↺ 恢复示例</button>

        </div>

        <div class="hint">

            <span>⚡ 输入即更新 · 简历自动包装</span>

        </div>

    </div>

 

    <!-- 预览面板:包装后的简历 -->

    <div class="resume-panel">

        <div class="header">

            <h3>✨ 简历预览</h3>

            <span class="badge">包装效果</span>

        </div>

        <div class="resume-card" id="resumeCard">

            <!-- 动态渲染通过 JS 完成 -->

            <div id="resumeContent"></div>

        </div>

    </div>

</div>

 

<script>

    (function() {

        // DOM 元素

        const nameInput = document.getElementById('nameInput');

        const titleInput = document.getElementById('titleInput');

        const emailInput = document.getElementById('emailInput');

        const phoneInput = document.getElementById('phoneInput');

        const addressInput = document.getElementById('addressInput');

        const summaryInput = document.getElementById('summaryInput');

        const skillsInput = document.getElementById('skillsInput');

        const resetBtn = document.getElementById('resetBtn');

        const resumeContent = document.getElementById('resumeContent');

 

        // 默认示例数据(用于重置)

        const defaultData = {

            name: '林语桐',

            title: '资深前端架构师',

            email: 'yutong.lin@dev.io',

            phone: '+86 136 8192 3745',

            address: '上海 · 远程',

            summary: '7 年全栈经验,专注前端架构与性能优化,带领团队交付多个高并发项目。',

            skills: 'React, TypeScript, Node.js, Docker, AWS, GraphQL'

        };

 

        // 渲染简历(包装)

        function renderResume() {

            const name = nameInput.value.trim() || '未填写';

            const title = titleInput.value.trim() || '岗位未设置';

            const email = emailInput.value.trim() || '—';

            const phone = phoneInput.value.trim() || '—';

            const address = addressInput.value.trim() || '—';

            const summary = summaryInput.value.trim() || '暂无简介,请添加个人亮点。';

            const skillsRaw = skillsInput.value.trim();

 

            // 技能数组:过滤空字符串

            let skillsArray = [];

            if (skillsRaw) {

                skillsArray = skillsRaw.split(',').map(s => s.trim()).filter(s => s.length > 0);

            }

 

            // 构建简历 HTML (包装后的结构)

            let html = '';

 

            // 1. 姓名 + 头衔

            html += `

                <div class="name-title">

                    <h1>${escapeHtml(name)}</h1>

                    <div class="title">${escapeHtml(title)}</div>

                </div>

            `;

 

            // 2. 联系信息 (包装)

            html += `

                <div class="resume-contact">

                    <span><span class="icon">📧</span> ${escapeHtml(email)}</span>

                    <span><span class="icon">📱</span> ${escapeHtml(phone)}</span>

                    <span><span class="icon">📍</span> ${escapeHtml(address)}</span>

                </div>

            `;

 

            // 3. 分隔线 + 简介

            html += `<div class="resume-divider"></div>`;

            html += `

                <div class="resume-section">

                    <h4>📌 个人亮点</h4>

                    <p>${escapeHtml(summary)}</p>

                </div>

            `;

 

            // 4. 技能标签 (包装)

            if (skillsArray.length > 0) {

                html += `

                    <div class="resume-section" style="margin-top: 1rem;">

                        <h4>🛠️ 技术栈</h4>

                        <div class="skill-tags">

                            ${skillsArray.map(skill => `<span>${escapeHtml(skill)}</span>`).join('')}

                        </div>

                    </div>

                `;

            } else {

                html += `

                    <div class="resume-section" style="margin-top: 1rem;">

                        <h4>🛠️ 技术栈</h4>

                        <p style="color:#7f96ae; font-size:0.9rem;">未添加技能标签</p>

                    </div>

                `;

            }

 

            // 如果内容极少,显示提示

            if (name === '未填写' && title === '岗位未设置' && email === '—' && phone === '—' && address === '—' && summary === '暂无简介,请添加个人亮点。' && skillsArray.length === 0) {

                html = `

                    <div class="empty-state">

                        <div style="font-size:2.8rem; margin-bottom:0.2rem;">📋</div>

                        <p>输入信息后,简历将自动包装</p>

                        <p style="font-size:0.8rem; opacity:0.7;">姓名 · 岗位 · 联系方式 · 简介 · 技能</p>

                    </div>

                `;

            }

 

            resumeContent.innerHTML = html;

        }

 

        // 简单的防 XSS 转义 (只转义 & < > " ')

        function escapeHtml(str) {

            if (!str) return '';

            return String(str)

                .replace(/&/g, '&amp;')

                .replace(/</g, '&lt;')

                .replace(/>/g, '&gt;')

                .replace(/"/g, '&quot;')

                .replace(/'/g, '&#039;');

        }

 

        // 更新所有输入事件

        function bindInputs() {

            const inputs = [nameInput, titleInput, emailInput, phoneInput, addressInput, summaryInput, skillsInput];

            inputs.forEach(input => {

                input.addEventListener('input', renderResume);

            });

        }

 

        // 重置示例数据

        function resetToDefault() {

            nameInput.value = defaultData.name;

            titleInput.value = defaultData.title;

            emailInput.value = defaultData.email;

            phoneInput.value = defaultData.phone;

            addressInput.value = defaultData.address;

            summaryInput.value = defaultData.summary;

            skillsInput.value = defaultData.skills;

            renderResume();

        }

 

        // 初始化

        function init() {

            // 用默认值填充 (但保留HTML中预设的value,如果不为空则使用预设,否则使用default)

            // 但为了统一,若输入框为空则设置默认,不过我们已经在HTML预设了内容,所以可以不覆盖

            // 但为了重置功能,以及保证示例数据一致性,初次加载时如果值为空则填充默认

            if (!nameInput.value) nameInput.value = defaultData.name;

            if (!titleInput.value) titleInput.value = defaultData.title;

            if (!emailInput.value) emailInput.value = defaultData.email;

            if (!phoneInput.value) phoneInput.value = defaultData.phone;

            if (!addressInput.value) addressInput.value = defaultData.address;

            if (!summaryInput.value) summaryInput.value = defaultData.summary;

            if (!skillsInput.value) skillsInput.value = defaultData.skills;

 

            bindInputs();

            renderResume();

 

            // 重置按钮

            resetBtn.addEventListener('click', resetToDefault);

        }

 

        init();

    })();

</script>

</body>

</html>

```

 

更多推荐