Selaa lähdekoodia

增加Mock数据工具

zxlie 3 kuukautta sitten
vanhempi
sitoutus
591803b143

+ 33 - 0
README.md

@@ -167,3 +167,36 @@ FeHelper在开发者社区中广受好评,以下是一些使用推荐和案例
 - 卸载工具后,该工具会自动从排序列表中移除
 - 重置排序将恢复到默认的安装时间顺序
 
+## 最新优化:弹窗显示优化
+
+### 问题描述
+修复了当启用工具数量较少时弹窗显示不协调的问题,优化了不同工具数量下的视觉体验。
+
+### 优化内容
+1. **动态布局调整**: 
+   - 根据已安装工具数量自动调整弹窗最小高度
+   - 1个工具时使用紧凑布局(110px最小高度)
+   - 2-3个工具时使用适中布局(140px最小高度)
+   - 4个及以上工具使用标准布局(120px最小高度)
+
+2. **间距优化**:
+   - 工具数量少时增加工具项的高度和间距
+   - 优化图标位置,确保视觉平衡
+   - 改进工具列表的内边距设置
+
+3. **布局增强**:
+   - 使用Flexbox布局,确保反馈区域始终在底部
+   - 添加平滑过渡动画,提升用户体验
+   - 优化工具列表滚动行为,支持大量工具时的滚动显示
+
+4. **响应式设计**:
+   - 设置合理的最大高度,避免弹窗过高
+   - 确保在不同屏幕DPI下都有良好的显示效果
+   - 优化空状态和加载状态的显示
+
+### 技术实现
+- 使用Vue.js计算属性动态判断工具数量
+- CSS类名动态绑定实现不同状态下的样式
+- 添加调试日志便于开发时查看布局状态
+- 平滑过渡动画提升用户体验
+

+ 8 - 0
apps/background/tools.js

@@ -193,6 +193,14 @@ let toolMap = {
             text: '网页截屏工具'
         }]
     },
+    'mock-data': {
+        name: 'Mock数据生成',
+        tips: '快速生成各种测试数据,支持个人信息、商业数据、技术数据等多种类型,可自定义字段和输出格式',
+        menuConfig: [{
+            icon: '⟡',
+            text: 'Mock数据生成'
+        }]
+    },
     'color-picker': {
         name: '页面取色工具',
         tips: '可直接在网页上针对任意元素进行色值采集,将光标移动到需要取色的位置,单击确定即可',

+ 404 - 0
apps/mock-data/fake-data-lib.js

@@ -0,0 +1,404 @@
+/**
+ * 假数据生成器核心库
+ * 提供各种类型的假数据生成功能
+ */
+
+class FakeDataGenerator {
+    constructor() {
+        this.init();
+    }
+
+    init() {
+        // 中文姓氏
+        this.surnames = [
+            '王', '李', '张', '刘', '陈', '杨', '赵', '黄', '周', '吴',
+            '徐', '孙', '胡', '朱', '高', '林', '何', '郭', '马', '罗',
+            '梁', '宋', '郑', '谢', '韩', '唐', '冯', '于', '董', '萧'
+        ];
+
+        // 中文名字
+        this.givenNames = [
+            '伟', '芳', '娜', '秀英', '敏', '静', '丽', '强', '磊', '军',
+            '洋', '勇', '艳', '杰', '娟', '涛', '明', '超', '秀兰', '霞',
+            '平', '刚', '桂英', '永', '健', '鑫', '帅', '莉', '凯', '浩',
+            '宇', '琳', '雅', '欣', '晨', '阳', '雪', '晴', '萌', '悦'
+        ];
+
+        // 公司名称后缀
+        this.companySuffixes = [
+            '有限公司', '股份有限公司', '科技有限公司', '贸易有限公司',
+            '实业有限公司', '投资有限公司', '集团有限公司', '控股有限公司',
+            '发展有限公司', '建设有限公司', '咨询有限公司', '服务有限公司'
+        ];
+
+        // 公司名称前缀
+        this.companyPrefixes = [
+            '阿里巴巴', '腾讯', '百度', '京东', '美团', '字节跳动', '滴滴',
+            '小米', '华为', '网易', '新浪', '搜狐', '爱奇艺', '快手',
+            '拼多多', '携程', '途牛', '去哪儿', '58同城', '赶集网',
+            '优酷', '土豆', '乐视', '暴风', '金山', '猎豹', '360',
+            '蚂蚁金服', '陆金所', '恒生电子', '同花顺', '东方财富'
+        ];
+
+        // 部门名称
+        this.departments = [
+            '技术部', '产品部', '运营部', '市场部', '销售部', '人事部',
+            '财务部', '行政部', '法务部', '客服部', '设计部', '测试部',
+            '运维部', '数据部', '商务部', '品牌部', '公关部', '投资部'
+        ];
+
+        // 职位名称
+        this.positions = [
+            '前端工程师', '后端工程师', '全栈工程师', '移动端工程师', 'DevOps工程师',
+            '产品经理', '项目经理', '技术经理', '运营专员', '市场专员',
+            'UI设计师', 'UX设计师', '测试工程师', '数据分析师', '算法工程师',
+            '架构师', 'CTO', 'CEO', 'COO', 'CFO', '总监', '主管', '专员'
+        ];
+
+        // 省份
+        this.provinces = [
+            '北京市', '上海市', '天津市', '重庆市', '河北省', '山西省',
+            '辽宁省', '吉林省', '黑龙江省', '江苏省', '浙江省', '安徽省',
+            '福建省', '江西省', '山东省', '河南省', '湖北省', '湖南省',
+            '广东省', '海南省', '四川省', '贵州省', '云南省', '陕西省',
+            '甘肃省', '青海省', '台湾省', '内蒙古自治区', '广西壮族自治区',
+            '西藏自治区', '宁夏回族自治区', '新疆维吾尔自治区', '香港特别行政区', '澳门特别行政区'
+        ];
+
+        // 城市
+        this.cities = [
+            '北京', '上海', '广州', '深圳', '杭州', '南京', '武汉', '成都',
+            '西安', '郑州', '青岛', '大连', '宁波', '厦门', '福州', '长沙',
+            '济南', '重庆', '天津', '苏州', '无锡', '石家庄', '太原', '沈阳',
+            '长春', '哈尔滨', '合肥', '南昌', '昆明', '贵阳', '兰州', '银川'
+        ];
+
+        // User Agent 列表
+        this.userAgents = [
+            'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
+            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
+            'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
+            'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0',
+            'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15'
+        ];
+
+        // MIME 类型
+        this.mimeTypes = [
+            'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/svg+xml',
+            'text/html', 'text/css', 'text/javascript', 'text/plain', 'text/csv',
+            'application/json', 'application/xml', 'application/pdf', 'application/zip',
+            'video/mp4', 'video/webm', 'audio/mp3', 'audio/wav', 'audio/ogg'
+        ];
+
+        // 文件扩展名
+        this.fileExtensions = [
+            'jpg', 'png', 'gif', 'pdf', 'doc', 'docx', 'xls', 'xlsx',
+            'ppt', 'pptx', 'txt', 'csv', 'json', 'xml', 'zip', 'rar',
+            'mp4', 'avi', 'mov', 'mp3', 'wav', 'html', 'css', 'js'
+        ];
+
+        // 域名后缀
+        this.domainSuffixes = [
+            'com', 'cn', 'net', 'org', 'edu', 'gov', 'mil', 'int',
+            'com.cn', 'net.cn', 'org.cn', 'edu.cn', 'gov.cn'
+        ];
+
+        // 邮箱域名
+        this.emailDomains = [
+            'gmail.com', 'yahoo.com', 'hotmail.com', 'outlook.com', '163.com',
+            '126.com', 'qq.com', 'sina.com', 'sohu.com', 'foxmail.com',
+            'aliyun.com', 'yeah.net', 'vip.sina.com', 'vip.163.com'
+        ];
+    }
+
+    // 生成随机整数
+    randomInt(min, max) {
+        return Math.floor(Math.random() * (max - min + 1)) + min;
+    }
+
+    // 生成随机浮点数
+    randomFloat(min, max, precision = 2) {
+        const num = Math.random() * (max - min) + min;
+        return parseFloat(num.toFixed(precision));
+    }
+
+    // 从数组中随机选择一个元素
+    randomChoice(array) {
+        return array[Math.floor(Math.random() * array.length)];
+    }
+
+    // 生成随机字符串
+    randomString(length = 10, charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') {
+        let result = '';
+        for (let i = 0; i < length; i++) {
+            result += charset.charAt(Math.floor(Math.random() * charset.length));
+        }
+        return result;
+    }
+
+    // 生成中文姓名
+    generateName() {
+        const surname = this.randomChoice(this.surnames);
+        const givenNameLength = Math.random() > 0.7 ? 2 : 1; // 70%概率生成双字名
+        let givenName = '';
+        for (let i = 0; i < givenNameLength; i++) {
+            givenName += this.randomChoice(this.givenNames);
+        }
+        return surname + givenName;
+    }
+
+    // 生成邮箱
+    generateEmail() {
+        const username = this.randomString(this.randomInt(6, 12));
+        const domain = this.randomChoice(this.emailDomains);
+        return `${username}@${domain}`;
+    }
+
+    // 生成手机号
+    generatePhone() {
+        const prefixes = ['130', '131', '132', '133', '134', '135', '136', '137', '138', '139',
+                         '150', '151', '152', '153', '155', '156', '157', '158', '159',
+                         '180', '181', '182', '183', '184', '185', '186', '187', '188', '189'];
+        const prefix = this.randomChoice(prefixes);
+        const suffix = this.randomString(8, '0123456789');
+        return prefix + suffix;
+    }
+
+    // 生成身份证号
+    generateIdCard() {
+        // 地区码(简化)
+        const areaCodes = ['110000', '120000', '130000', '140000', '150000', '210000', '220000', '230000'];
+        const areaCode = this.randomChoice(areaCodes);
+        
+        // 生日(1970-2000年)
+        const year = this.randomInt(1970, 2000);
+        const month = this.randomInt(1, 12).toString().padStart(2, '0');
+        const day = this.randomInt(1, 28).toString().padStart(2, '0');
+        const birthday = `${year}${month}${day}`;
+        
+        // 顺序码
+        const sequence = this.randomInt(100, 999).toString();
+        
+        // 校验码(简化为随机)
+        const checkCode = this.randomChoice(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'X']);
+        
+        return areaCode.substring(0, 6) + birthday + sequence + checkCode;
+    }
+
+    // 生成性别
+    generateGender() {
+        return Math.random() > 0.5 ? '男' : '女';
+    }
+
+    // 生成年龄
+    generateAge() {
+        return this.randomInt(18, 65);
+    }
+
+    // 生成生日
+    generateBirthday() {
+        const year = this.randomInt(1960, 2005);
+        const month = this.randomInt(1, 12);
+        const day = this.randomInt(1, 28);
+        return `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
+    }
+
+    // 生成地址
+    generateAddress() {
+        const province = this.randomChoice(this.provinces);
+        const city = this.randomChoice(this.cities);
+        const district = this.randomChoice(['朝阳区', '海淀区', '西城区', '东城区', '丰台区', '石景山区']);
+        const street = this.randomString(2, '一二三四五六七八九十') + '街道';
+        const number = this.randomInt(1, 999) + '号';
+        return `${province}${city}${district}${street}${number}`;
+    }
+
+    // 生成公司名称
+    generateCompany() {
+        const prefix = this.randomChoice(this.companyPrefixes);
+        const suffix = this.randomChoice(this.companySuffixes);
+        return prefix + suffix;
+    }
+
+    // 生成部门
+    generateDepartment() {
+        return this.randomChoice(this.departments);
+    }
+
+    // 生成职位
+    generatePosition() {
+        return this.randomChoice(this.positions);
+    }
+
+    // 生成薪资
+    generateSalary() {
+        return this.randomInt(5000, 50000);
+    }
+
+    // 生成银行卡号
+    generateBankCard() {
+        const prefixes = ['6225', '6222', '6228', '6229', '6227', '6223', '6226'];
+        const prefix = this.randomChoice(prefixes);
+        const suffix = this.randomString(12, '0123456789');
+        return prefix + suffix;
+    }
+
+    // 生成信用卡号
+    generateCreditCard() {
+        const prefixes = ['4', '5', '6'];
+        const prefix = this.randomChoice(prefixes);
+        const suffix = this.randomString(15, '0123456789');
+        return prefix + suffix;
+    }
+
+    // 生成价格
+    generatePrice() {
+        return this.randomFloat(0.01, 9999.99);
+    }
+
+    // 生成货币
+    generateCurrency() {
+        const currencies = ['CNY', 'USD', 'EUR', 'JPY', 'GBP', 'AUD', 'CAD', 'CHF', 'HKD', 'SGD'];
+        return this.randomChoice(currencies);
+    }
+
+    // 生成UUID
+    generateUUID() {
+        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+            const r = Math.random() * 16 | 0;
+            const v = c === 'x' ? r : (r & 0x3 | 0x8);
+            return v.toString(16);
+        });
+    }
+
+    // 生成IP地址
+    generateIP() {
+        return `${this.randomInt(1, 255)}.${this.randomInt(0, 255)}.${this.randomInt(0, 255)}.${this.randomInt(1, 255)}`;
+    }
+
+    // 生成MAC地址
+    generateMAC() {
+        const chars = '0123456789ABCDEF';
+        let mac = '';
+        for (let i = 0; i < 6; i++) {
+            if (i > 0) mac += ':';
+            mac += this.randomString(2, chars);
+        }
+        return mac;
+    }
+
+    // 生成User Agent
+    generateUserAgent() {
+        return this.randomChoice(this.userAgents);
+    }
+
+    // 生成URL
+    generateURL() {
+        const protocols = ['http', 'https'];
+        const domains = ['example.com', 'test.com', 'demo.com', 'sample.org', 'mock.net'];
+        const paths = ['/', '/home', '/about', '/contact', '/products', '/services', '/blog'];
+        
+        const protocol = this.randomChoice(protocols);
+        const domain = this.randomChoice(domains);
+        const path = this.randomChoice(paths);
+        
+        return `${protocol}://${domain}${path}`;
+    }
+
+    // 生成域名
+    generateDomain() {
+        const name = this.randomString(this.randomInt(5, 15));
+        const suffix = this.randomChoice(this.domainSuffixes);
+        return `${name}.${suffix}`;
+    }
+
+    // 生成密码
+    generatePassword() {
+        const length = this.randomInt(8, 16);
+        const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
+        return this.randomString(length, chars);
+    }
+
+    // 生成Token
+    generateToken() {
+        return this.randomString(32, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
+    }
+
+    // 生成颜色值
+    generateColor() {
+        return '#' + this.randomString(6, '0123456789ABCDEF');
+    }
+
+    // 生成时间戳
+    generateTimestamp() {
+        const now = Date.now();
+        const offset = this.randomInt(-365 * 24 * 60 * 60 * 1000, 365 * 24 * 60 * 60 * 1000);
+        return now + offset;
+    }
+
+    // 生成文件名
+    generateFilename() {
+        const name = this.randomString(this.randomInt(5, 15));
+        const ext = this.randomChoice(this.fileExtensions);
+        return `${name}.${ext}`;
+    }
+
+    // 生成MIME类型
+    generateMimeType() {
+        return this.randomChoice(this.mimeTypes);
+    }
+
+    // 生成布尔值
+    generateBoolean() {
+        return Math.random() > 0.5;
+    }
+
+    // 生成日期
+    generateDate() {
+        const start = new Date(2020, 0, 1);
+        const end = new Date();
+        const timestamp = start.getTime() + Math.random() * (end.getTime() - start.getTime());
+        return new Date(timestamp).toISOString().split('T')[0];
+    }
+
+    // 根据字段类型生成数据
+    generateByType(type) {
+        const generators = {
+            name: () => this.generateName(),
+            email: () => this.generateEmail(),
+            phone: () => this.generatePhone(),
+            idCard: () => this.generateIdCard(),
+            gender: () => this.generateGender(),
+            age: () => this.generateAge(),
+            birthday: () => this.generateBirthday(),
+            address: () => this.generateAddress(),
+            company: () => this.generateCompany(),
+            department: () => this.generateDepartment(),
+            position: () => this.generatePosition(),
+            salary: () => this.generateSalary(),
+            bankCard: () => this.generateBankCard(),
+            creditCard: () => this.generateCreditCard(),
+            price: () => this.generatePrice(),
+            currency: () => this.generateCurrency(),
+            uuid: () => this.generateUUID(),
+            ip: () => this.generateIP(),
+            mac: () => this.generateMAC(),
+            userAgent: () => this.generateUserAgent(),
+            url: () => this.generateURL(),
+            domain: () => this.generateDomain(),
+            password: () => this.generatePassword(),
+            token: () => this.generateToken(),
+            color: () => this.generateColor(),
+            timestamp: () => this.generateTimestamp(),
+            filename: () => this.generateFilename(),
+            mimeType: () => this.generateMimeType(),
+            boolean: () => this.generateBoolean(),
+            date: () => this.generateDate()
+        };
+
+        return generators[type] ? generators[type]() : null;
+    }
+}
+
+// 导出为全局变量
+window.FakeDataGenerator = FakeDataGenerator; 

+ 787 - 0
apps/mock-data/index.css

@@ -0,0 +1,787 @@
+
+body {
+    margin: 0;
+    padding: 0;
+    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
+    background-color: #f5f7fa;
+}
+
+.wrapper {
+    padding-top: 10px;
+}
+
+/* 现代化导航栏样式 */
+.main-navbar {
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    color: white;
+    padding: 12px 20px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+    position: sticky;
+    top: 0;
+    z-index: 1000;
+    margin-bottom: 0;
+}
+
+.navbar-brand {
+    display: flex;
+    align-items: center;
+}
+
+.brand-link {
+    color: white;
+    text-decoration: none;
+    display: flex;
+    align-items: center;
+    transition: all 0.3s ease;
+}
+
+.brand-link:hover {
+    color: rgba(255, 255, 255, 0.9);
+    transform: translateY(-1px);
+}
+
+.brand-link img {
+    margin-right: 8px;
+    border-radius: 2px;
+}
+
+.brand-text {
+    font-size: 18px;
+    font-weight: 600;
+    margin-right: 8px;
+}
+
+.brand-subtitle {
+    font-size: 14px;
+    opacity: 0.9;
+    position: relative;
+    padding-left: 8px;
+}
+
+.brand-subtitle::before {
+    content: "·";
+    position: absolute;
+    left: 0;
+    top: 50%;
+    transform: translateY(-50%);
+    font-weight: bold;
+    opacity: 0.7;
+}
+
+.navbar-actions {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+}
+
+.nav-item {
+    color: rgba(255, 255, 255, 0.9);
+    text-decoration: none;
+    padding: 8px 16px;
+    border-radius: 6px;
+    font-size: 14px;
+    font-weight: 500;
+    display: flex;
+    align-items: center;
+    gap: 6px;
+    transition: all 0.3s ease;
+    position: relative;
+    overflow: hidden;
+    cursor: pointer;
+}
+
+.nav-item:hover {
+    background: rgba(255, 255, 255, 0.1);
+    color: white;
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
+}
+
+.nav-item:active {
+    transform: translateY(0);
+}
+
+.nav-icon {
+    font-style: normal;
+    font-size: 16px;
+    transition: transform 0.3s ease;
+}
+
+.nav-item:hover .nav-icon {
+    transform: scale(1.1);
+}
+
+.nav-item::after {
+    content: '';
+    position: absolute;
+    top: 0;
+    left: -100%;
+    width: 100%;
+    height: 100%;
+    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
+    transition: left 0.5s;
+}
+
+.nav-item:hover::after {
+    left: 100%;
+}
+
+.navbar-actions .donate-link {
+    background: rgba(255, 107, 107, 0.2);
+    border: 1px solid rgba(255, 107, 107, 0.3);
+}
+
+.navbar-actions .donate-link:hover {
+    background: rgba(255, 107, 107, 0.3);
+    border-color: rgba(255, 107, 107, 0.5);
+    box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
+}
+
+.navbar-actions .donate-link .nav-icon {
+    color: #ff6b6b;
+    animation: heartbeat 2s ease-in-out infinite;
+}
+
+.navbar-actions .donate-link:hover .nav-icon {
+    color: #ff5252;
+    animation: heartbeat 1s ease-in-out infinite;
+}
+
+.navbar-actions .other-tools-link {
+    background: rgba(255, 255, 255, 0.1);
+    border: 1px solid rgba(255, 255, 255, 0.2);
+}
+
+.navbar-actions .other-tools-link:hover {
+    background: rgba(255, 255, 255, 0.2);
+    border-color: rgba(255, 255, 255, 0.3);
+}
+
+.navbar-actions .other-tools-link .nav-icon {
+    color: #4ecdc4;
+    font-weight: bold;
+}
+
+.navbar-actions .other-tools-link:hover .nav-icon {
+    color: #26d0ce;
+    animation: rotate 0.6s ease-in-out;
+}
+
+@keyframes heartbeat {
+    0%, 14%, 28%, 42%, 70% {
+        transform: scale(1);
+    }
+    7%, 21%, 35% {
+        transform: scale(1.1);
+    }
+}
+
+@keyframes rotate {
+    0% {
+        transform: rotate(0deg);
+    }
+    100% {
+        transform: rotate(360deg);
+    }
+}
+
+.tool-market-badge {
+    background: rgba(255, 255, 255, 0.2);
+    padding: 2px 8px;
+    border-radius: 10px;
+    font-size: 11px;
+    font-weight: 500;
+    margin-left: 4px;
+    border: 1px solid rgba(255, 255, 255, 0.3);
+}
+
+/* 响应式导航栏 */
+@media (max-width: 768px) {
+    .main-navbar {
+        padding: 10px 15px;
+        flex-direction: column;
+        gap: 10px;
+    }
+    
+    .navbar-actions {
+        width: 100%;
+        justify-content: center;
+        flex-wrap: wrap;
+    }
+    
+    .nav-item {
+        font-size: 13px;
+        padding: 6px 12px;
+    }
+    
+    .brand-subtitle {
+        display: none;
+    }
+}
+
+@media (max-width: 600px) {
+    .nav-item span {
+        display: none;
+    }
+    
+    .nav-icon {
+        font-size: 18px;
+    }
+    
+    .tool-market-badge {
+        display: none;
+    }
+}
+
+.panel {
+    background: white;
+    border-radius: 8px;
+    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
+    overflow: hidden;
+    margin-top: 0;
+}
+
+.panel-heading {
+    display: none; /* 隐藏旧的导航栏 */
+}
+
+.panel-title {
+    display: none; /* 隐藏旧的标题样式 */
+}
+
+/* 移除旧的导航栏样式 */
+.x-a-high,
+.x-other-tools,
+.x-donate-link,
+.icon-plus-circle {
+    display: none;
+}
+
+.panel-body {
+    padding: 20px;
+}
+
+/* 数据类型选择区域 */
+.data-type-section {
+    margin-bottom: 25px;
+}
+
+.data-type-section h4 {
+    margin: 0 0 15px 0;
+    color: #333;
+    font-size: 16px;
+    font-weight: 600;
+}
+
+.data-type-tabs {
+    display: flex;
+    gap: 2px;
+    background: #f1f3f4;
+    border-radius: 6px;
+    padding: 4px;
+}
+
+.data-tab {
+    flex: 1;
+    padding: 10px 16px;
+    border: none;
+    background: transparent;
+    color: #666;
+    border-radius: 4px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    font-size: 14px;
+    font-weight: 500;
+}
+
+.data-tab:hover {
+    background: rgba(102, 126, 234, 0.1);
+    color: #667eea;
+}
+
+.data-tab.active {
+    background: #667eea;
+    color: white;
+    box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
+}
+
+/* 数据内容区域 */
+.data-content {
+    margin-bottom: 25px;
+}
+
+.field-group h5 {
+    margin: 0 0 15px 0;
+    color: #444;
+    font-size: 14px;
+    font-weight: 600;
+    border-bottom: 2px solid #e9ecef;
+    padding-bottom: 8px;
+}
+
+.field-row {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+    margin-bottom: 15px;
+}
+
+.field-row label {
+    display: flex;
+    align-items: center;
+    cursor: pointer;
+    font-size: 14px;
+    color: #555;
+    min-width: 120px;
+    transition: color 0.3s ease;
+}
+
+.field-row label:hover {
+    color: #667eea;
+}
+
+.field-row input[type="checkbox"] {
+    margin-right: 8px;
+    width: 16px;
+    height: 16px;
+    cursor: pointer;
+}
+
+/* 自定义数据区域 */
+.custom-input {
+    display: flex;
+    align-items: center;
+    margin-bottom: 15px;
+    gap: 10px;
+}
+
+.custom-input label {
+    min-width: 100px;
+    font-size: 14px;
+    color: #555;
+    font-weight: 500;
+}
+
+.custom-input input,
+.custom-input select {
+    flex: 1;
+    padding: 8px 12px;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    font-size: 14px;
+    transition: border-color 0.3s ease;
+}
+
+.custom-input input:focus,
+.custom-input select:focus {
+    outline: none;
+    border-color: #667eea;
+    box-shadow: 0 0 0 2px rgba(102, 126, 234, 0.1);
+}
+
+.custom-fields-list {
+    margin-top: 20px;
+    padding: 15px;
+    background: #f8f9fa;
+    border-radius: 6px;
+}
+
+.custom-field-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 8px 0;
+    border-bottom: 1px solid #e9ecef;
+}
+
+.custom-field-item:last-child {
+    border-bottom: none;
+}
+
+.btn-remove {
+    background: #dc3545;
+    color: white;
+    border: none;
+    padding: 4px 8px;
+    border-radius: 3px;
+    font-size: 12px;
+    cursor: pointer;
+    transition: background 0.3s ease;
+}
+
+.btn-remove:hover {
+    background: #c82333;
+}
+
+/* 生成配置 */
+.generate-config {
+    margin-bottom: 25px;
+    padding: 15px;
+    background: #f8f9fa;
+    border-radius: 6px;
+    border-left: 4px solid #667eea;
+}
+
+.config-row {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+    flex-wrap: wrap;
+}
+
+.config-row label {
+    font-size: 14px;
+    color: #555;
+    font-weight: 500;
+}
+
+.config-row input,
+.config-row select {
+    padding: 6px 10px;
+    border: 1px solid #ddd;
+    border-radius: 4px;
+    font-size: 14px;
+}
+
+/* 按钮样式 */
+.action-buttons {
+    display: flex;
+    gap: 10px;
+    margin-bottom: 25px;
+    flex-wrap: wrap;
+}
+
+.btn {
+    padding: 10px 20px;
+    border: none;
+    border-radius: 5px;
+    cursor: pointer;
+    font-size: 14px;
+    font-weight: 500;
+    transition: all 0.3s ease;
+    text-decoration: none;
+    display: inline-flex;
+    align-items: center;
+    justify-content: center;
+}
+
+.btn:disabled {
+    opacity: 0.6;
+    cursor: not-allowed;
+}
+
+.btn-success {
+    background: #28a745;
+    color: white;
+}
+
+.btn-success:hover:not(:disabled) {
+    background: #218838;
+    transform: translateY(-1px);
+    box-shadow: 0 4px 12px rgba(40, 167, 69, 0.3);
+}
+
+.btn-info {
+    background: #17a2b8;
+    color: white;
+}
+
+.btn-info:hover:not(:disabled) {
+    background: #138496;
+    transform: translateY(-1px);
+    box-shadow: 0 4px 12px rgba(23, 162, 184, 0.3);
+}
+
+.btn-warning {
+    background: #ffc107;
+    color: #212529;
+}
+
+.btn-warning:hover:not(:disabled) {
+    background: #e0a800;
+    transform: translateY(-1px);
+    box-shadow: 0 4px 12px rgba(255, 193, 7, 0.3);
+}
+
+.btn-primary {
+    background: #667eea;
+    color: white;
+}
+
+.btn-primary:hover:not(:disabled) {
+    background: #5a6fd8;
+    transform: translateY(-1px);
+    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+}
+
+.btn-secondary {
+    background: #6c757d;
+    color: white;
+}
+
+.btn-secondary:hover:not(:disabled) {
+    background: #5a6268;
+    transform: translateY(-1px);
+    box-shadow: 0 4px 12px rgba(108, 117, 125, 0.3);
+}
+
+.btn-template {
+    background: #e9ecef;
+    color: #495057;
+    border: 1px solid #ced4da;
+}
+
+.btn-template:hover {
+    background: #667eea;
+    color: white;
+    border-color: #667eea;
+    transform: translateY(-1px);
+}
+
+/* 结果显示区域 */
+.result-section {
+    margin-top: 25px;
+    border: 1px solid #e9ecef;
+    border-radius: 6px;
+    overflow: hidden;
+}
+
+.result-header {
+    background: #f8f9fa;
+    padding: 12px 16px;
+    border-bottom: 1px solid #e9ecef;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.result-header h4 {
+    margin: 0;
+    color: #333;
+    font-size: 16px;
+}
+
+.data-size {
+    color: #666;
+    font-size: 12px;
+    background: #e9ecef;
+    padding: 4px 8px;
+    border-radius: 12px;
+}
+
+.result-content {
+    max-height: 400px;
+    overflow: auto;
+    background: #f8f9fa;
+}
+
+.result-content pre {
+    margin: 0;
+    padding: 16px;
+    background: #282c34;
+    color: #abb2bf;
+    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
+    font-size: 13px;
+    line-height: 1.5;
+    overflow-x: auto;
+    white-space: pre-wrap;
+    word-wrap: break-word;
+}
+
+/* 模板区域 */
+.template-section {
+    margin-top: 30px;
+    padding-top: 20px;
+    border-top: 2px solid #e9ecef;
+}
+
+.template-section h4 {
+    margin: 0 0 15px 0;
+    color: #333;
+    font-size: 16px;
+    font-weight: 600;
+}
+
+.template-buttons {
+    display: flex;
+    gap: 10px;
+    flex-wrap: wrap;
+}
+
+/* 响应式设计 */
+@media (max-width: 768px) {
+    .wrapper {
+        padding: 10px;
+    }
+    
+    .panel-body {
+        padding: 15px;
+    }
+    
+    .data-type-tabs {
+        flex-direction: column;
+    }
+    
+    .field-row {
+        flex-direction: column;
+        gap: 10px;
+    }
+    
+    .action-buttons {
+        flex-direction: column;
+    }
+    
+    .btn {
+        width: 100%;
+    }
+    
+    .config-row {
+        flex-direction: column;
+        align-items: flex-start;
+    }
+}
+
+/* Vue.js 过渡效果 */
+[v-cloak] {
+    display: none;
+}
+
+/* 加载动画 */
+.loading {
+    display: inline-block;
+    width: 20px;
+    height: 20px;
+    border: 3px solid rgba(255, 255, 255, 0.3);
+    border-radius: 50%;
+    border-top-color: #fff;
+    animation: spin 1s ease-in-out infinite;
+}
+
+@keyframes spin {
+    to {
+        transform: rotate(360deg);
+    }
+}
+
+/* 成功提示 */
+.success-message {
+    background: #d4edda;
+    color: #155724;
+    padding: 10px 15px;
+    border-radius: 4px;
+    margin-bottom: 15px;
+    border: 1px solid #c3e6cb;
+}
+
+/* 错误提示 */
+.error-message {
+    background: #f8d7da;
+    color: #721c24;
+    padding: 10px 15px;
+    border-radius: 4px;
+    margin-bottom: 15px;
+    border: 1px solid #f5c6cb;
+}
+
+/* 暗色模式支持 */
+@media (prefers-color-scheme: dark) {
+    body {
+        background-color: #1a1a1a;
+        color: #e0e0e0;
+    }
+    
+    .main-navbar {
+        background: linear-gradient(135deg, #434190 0%, #5a4b9d 100%);
+        box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
+    }
+    
+    .panel {
+        background: #2d2d2d;
+        box-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
+    }
+    
+    .panel-body {
+        background: #2d2d2d;
+    }
+    
+    .field-row label {
+        color: #ccc;
+    }
+    
+    .custom-input input,
+    .custom-input select,
+    .config-row input,
+    .config-row select {
+        background: #3d3d3d;
+        border-color: #555;
+        color: #e0e0e0;
+    }
+    
+    .generate-config,
+    .custom-fields-list {
+        background: #3d3d3d;
+    }
+    
+    .result-content pre {
+        background: #1e1e1e;
+        color: #d4d4d4;
+    }
+    
+    .data-type-tabs {
+        background: #3d3d3d;
+    }
+    
+    .data-tab {
+        color: #ccc;
+    }
+    
+    .data-tab:hover {
+        background: rgba(102, 126, 234, 0.3);
+        color: #667eea;
+    }
+    
+    .data-tab.active {
+        background: #667eea;
+        color: white;
+    }
+    
+    .field-group h5 {
+        color: #e0e0e0;
+        border-bottom-color: #555;
+    }
+    
+    .data-type-section h4,
+    .template-section h4 {
+        color: #e0e0e0;
+    }
+    
+    .result-header {
+        background: #3d3d3d;
+        border-bottom-color: #555;
+        color: #e0e0e0;
+    }
+    
+    .result-header h4 {
+        color: #e0e0e0;
+    }
+    
+    .custom-field-item {
+        border-bottom-color: #555;
+        color: #ccc;
+    }
+    
+    .btn-template {
+        background: #3d3d3d;
+        color: #ccc;
+        border-color: #555;
+    }
+    
+    .btn-template:hover {
+        background: #667eea;
+        color: white;
+        border-color: #667eea;
+    }
+} 

+ 216 - 0
apps/mock-data/index.html

@@ -0,0 +1,216 @@
+<!DOCTYPE HTML>
+<html lang="zh-CN">
+<head>
+    <meta charset="utf-8"/>
+    <title>Mock数据生成器</title>
+    <link rel="stylesheet" href="index.css"/>
+    <script type="text/javascript" src="../static/vendor/evalCore.min.js"></script>
+    <script type="text/javascript" src="../static/vendor/vue/vue.js"></script>
+</head>
+
+<body>
+    <div class="wrapper" id="pageContainer">
+        <!-- 现代化顶部导航栏 -->
+        <div class="main-navbar">
+            <div class="navbar-brand">
+                <a href="https://www.baidufe.com/fehelper/index/index.html" target="_blank" class="brand-link">
+                    <img src="../static/img/fe-16.png" alt="fehelper"/> 
+                    <span class="brand-text">FeHelper</span>
+                    <span class="brand-subtitle">Mock数据生成器</span>
+                </a>
+            </div>
+            <div class="navbar-actions">
+                <a href="#" @click="openOptionsPage($event)" class="nav-item other-tools-link">
+                    <i class="nav-icon">⊕</i>
+                    <span>探索更多实用工具</span>
+                    <span class="tool-market-badge">工具市场</span>
+                </a>
+                <a href="#" @click="openDonateModal($event)" class="nav-item donate-link">
+                    <i class="nav-icon">❤</i>
+                    <span>打赏鼓励</span>
+                </a>
+            </div>
+        </div>
+
+        <div class="panel panel-default">
+            <!-- 主要内容 -->
+            <div class="panel-body" v-cloak>
+                <!-- 数据类型选择区域 -->
+                <div class="data-type-section">
+                    <h4>选择数据类型</h4>
+                    <div class="data-type-tabs">
+                        <button class="data-tab" 
+                                :class="{ active: activeTab === 'personal' }"
+                                @click="activeTab = 'personal'">
+                            个人信息
+                        </button>
+                        <button class="data-tab" 
+                                :class="{ active: activeTab === 'business' }"
+                                @click="activeTab = 'business'">
+                            商业数据
+                        </button>
+                        <button class="data-tab" 
+                                :class="{ active: activeTab === 'technical' }"
+                                @click="activeTab = 'technical'">
+                            技术数据
+                        </button>
+                        <button class="data-tab" 
+                                :class="{ active: activeTab === 'custom' }"
+                                @click="activeTab = 'custom'">
+                            自定义数据
+                        </button>
+                    </div>
+                </div>
+
+                <!-- 个人信息数据 -->
+                <div v-show="activeTab === 'personal'" class="data-content">
+                    <div class="field-group">
+                        <h5>基本信息</h5>
+                        <div class="field-row">
+                            <label><input type="checkbox" v-model="selectedFields.name"> 姓名</label>
+                            <label><input type="checkbox" v-model="selectedFields.email"> 邮箱</label>
+                            <label><input type="checkbox" v-model="selectedFields.phone"> 手机号</label>
+                            <label><input type="checkbox" v-model="selectedFields.idCard"> 身份证号</label>
+                        </div>
+                        <div class="field-row">
+                            <label><input type="checkbox" v-model="selectedFields.gender"> 性别</label>
+                            <label><input type="checkbox" v-model="selectedFields.age"> 年龄</label>
+                            <label><input type="checkbox" v-model="selectedFields.birthday"> 生日</label>
+                            <label><input type="checkbox" v-model="selectedFields.address"> 地址</label>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 商业数据 -->
+                <div v-show="activeTab === 'business'" class="data-content">
+                    <div class="field-group">
+                        <h5>商业信息</h5>
+                        <div class="field-row">
+                            <label><input type="checkbox" v-model="selectedFields.company"> 公司名称</label>
+                            <label><input type="checkbox" v-model="selectedFields.department"> 部门</label>
+                            <label><input type="checkbox" v-model="selectedFields.position"> 职位</label>
+                            <label><input type="checkbox" v-model="selectedFields.salary"> 薪资</label>
+                        </div>
+                        <div class="field-row">
+                            <label><input type="checkbox" v-model="selectedFields.bankCard"> 银行卡号</label>
+                            <label><input type="checkbox" v-model="selectedFields.creditCard"> 信用卡号</label>
+                            <label><input type="checkbox" v-model="selectedFields.price"> 价格</label>
+                            <label><input type="checkbox" v-model="selectedFields.currency"> 货币</label>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 技术数据 -->
+                <div v-show="activeTab === 'technical'" class="data-content">
+                    <div class="field-group">
+                        <h5>技术信息</h5>
+                        <div class="field-row">
+                            <label><input type="checkbox" v-model="selectedFields.uuid"> UUID</label>
+                            <label><input type="checkbox" v-model="selectedFields.ip"> IP地址</label>
+                            <label><input type="checkbox" v-model="selectedFields.mac"> MAC地址</label>
+                            <label><input type="checkbox" v-model="selectedFields.userAgent"> User Agent</label>
+                        </div>
+                        <div class="field-row">
+                            <label><input type="checkbox" v-model="selectedFields.url"> URL</label>
+                            <label><input type="checkbox" v-model="selectedFields.domain"> 域名</label>
+                            <label><input type="checkbox" v-model="selectedFields.password"> 密码</label>
+                            <label><input type="checkbox" v-model="selectedFields.token"> Token</label>
+                        </div>
+                        <div class="field-row">
+                            <label><input type="checkbox" v-model="selectedFields.color"> 颜色值</label>
+                            <label><input type="checkbox" v-model="selectedFields.timestamp"> 时间戳</label>
+                            <label><input type="checkbox" v-model="selectedFields.filename"> 文件名</label>
+                            <label><input type="checkbox" v-model="selectedFields.mimeType"> MIME类型</label>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 自定义数据 -->
+                <div v-show="activeTab === 'custom'" class="data-content">
+                    <div class="field-group">
+                        <h5>自定义规则</h5>
+                        <div class="custom-input">
+                            <label>字段名称:</label>
+                            <input type="text" v-model="customField.name" placeholder="请输入字段名">
+                        </div>
+                        <div class="custom-input">
+                            <label>数据类型:</label>
+                            <select v-model="customField.type">
+                                <option value="string">字符串</option>
+                                <option value="number">数字</option>
+                                <option value="boolean">布尔值</option>
+                                <option value="date">日期</option>
+                                <option value="array">数组</option>
+                            </select>
+                        </div>
+                        <div class="custom-input">
+                            <label>生成规则:</label>
+                            <input type="text" v-model="customField.rule" placeholder="如:长度10-20的随机字符串">
+                        </div>
+                        <button @click="addCustomField" class="btn btn-primary">添加字段</button>
+                    </div>
+                    
+                    <div v-if="customFields.length > 0" class="custom-fields-list">
+                        <h5>已添加字段</h5>
+                        <div v-for="(field, index) in customFields" :key="index" class="custom-field-item">
+                            <span>{{ field.name }} ({{ field.type }})</span>
+                            <button @click="removeCustomField(index)" class="btn-remove">删除</button>
+                        </div>
+                    </div>
+                </div>
+
+                <!-- 生成配置 -->
+                <div class="generate-config">
+                    <div class="config-row">
+                        <label>生成数量:</label>
+                        <input type="number" v-model="generateCount" min="1" max="1000" value="10">
+                        
+                        <label style="margin-left: 20px;">输出格式:</label>
+                        <select v-model="outputFormat">
+                            <option value="json">JSON</option>
+                            <option value="csv">CSV</option>
+                            <option value="sql">SQL INSERT</option>
+                            <option value="xml">XML</option>
+                        </select>
+                    </div>
+                </div>
+
+                <!-- 操作按钮 -->
+                <div class="action-buttons">
+                    <button @click="generateData" class="btn btn-success">生成数据</button>
+                    <button @click="selectAll" class="btn btn-info">全选</button>
+                    <button @click="clearAll" class="btn btn-warning">清空</button>
+                    <button @click="copyResult" class="btn btn-primary" :disabled="!generatedData">复制结果</button>
+                    <button @click="downloadData" class="btn btn-secondary" :disabled="!generatedData">下载文件</button>
+                </div>
+
+                <!-- 结果显示区域 -->
+                <div v-if="generatedData" class="result-section">
+                    <div class="result-header">
+                        <h4>生成结果 ({{ generateCount }} 条)</h4>
+                        <span class="data-size">数据大小: {{ dataSize }}</span>
+                    </div>
+                    <div class="result-content">
+                        <pre>{{ generatedData }}</pre>
+                    </div>
+                </div>
+
+                <!-- 预设模板 -->
+                <div class="template-section">
+                    <h4>快速模板</h4>
+                    <div class="template-buttons">
+                        <button @click="loadTemplate('user')" class="btn btn-template">用户信息</button>
+                        <button @click="loadTemplate('employee')" class="btn btn-template">员工信息</button>
+                        <button @click="loadTemplate('product')" class="btn btn-template">商品信息</button>
+                        <button @click="loadTemplate('order')" class="btn btn-template">订单信息</button>
+                        <button @click="loadTemplate('api')" class="btn btn-template">API测试数据</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <script type="text/javascript" src="fake-data-lib.js"></script>
+    <script type="text/javascript" src="index.js"></script>
+</body>
+</html> 

+ 541 - 0
apps/mock-data/index.js

@@ -0,0 +1,541 @@
+/**
+ * 假数据生成器主逻辑
+ * 使用Vue.js构建交互式界面
+ */
+
+new Vue({
+    el: '#pageContainer',
+    data: {
+        // 当前激活的标签页
+        activeTab: 'personal',
+        
+        // 选中的字段
+        selectedFields: {
+            // 个人信息
+            name: false,
+            email: false,
+            phone: false,
+            idCard: false,
+            gender: false,
+            age: false,
+            birthday: false,
+            address: false,
+            
+            // 商业数据
+            company: false,
+            department: false,
+            position: false,
+            salary: false,
+            bankCard: false,
+            creditCard: false,
+            price: false,
+            currency: false,
+            
+            // 技术数据
+            uuid: false,
+            ip: false,
+            mac: false,
+            userAgent: false,
+            url: false,
+            domain: false,
+            password: false,
+            token: false,
+            color: false,
+            timestamp: false,
+            filename: false,
+            mimeType: false
+        },
+        
+        // 自定义字段
+        customField: {
+            name: '',
+            type: 'string',
+            rule: ''
+        },
+        customFields: [],
+        
+        // 生成配置
+        generateCount: 10,
+        outputFormat: 'json',
+        
+        // 生成的数据
+        generatedData: '',
+        dataSize: '0 B',
+        
+        // 数据生成器实例
+        generator: null,
+        
+        // 预设模板
+        templates: {
+            user: {
+                name: '用户信息模板',
+                fields: ['name', 'email', 'phone', 'gender', 'age', 'address']
+            },
+            employee: {
+                name: '员工信息模板',
+                fields: ['name', 'email', 'phone', 'company', 'department', 'position', 'salary']
+            },
+            product: {
+                name: '商品信息模板',
+                fields: ['name', 'price', 'currency', 'uuid', 'timestamp']
+            },
+            order: {
+                name: '订单信息模板',
+                fields: ['uuid', 'name', 'email', 'phone', 'address', 'price', 'timestamp']
+            },
+            api: {
+                name: 'API测试数据模板',
+                fields: ['uuid', 'token', 'ip', 'userAgent', 'timestamp', 'boolean']
+            }
+        }
+    },
+    
+    mounted() {
+        // 初始化数据生成器
+        this.generator = new FakeDataGenerator();
+        
+        // 检查URL参数,如果有模板参数则自动加载
+        const urlParams = new URLSearchParams(window.location.search);
+        const template = urlParams.get('template');
+        if (template && this.templates[template]) {
+            this.loadTemplate(template);
+        }
+    },
+    
+    methods: {
+        /**
+         * 添加自定义字段
+         */
+        addCustomField() {
+            if (!this.customField.name.trim()) {
+                alert('请输入字段名称');
+                return;
+            }
+            
+            // 检查字段名是否已存在
+            const exists = this.customFields.some(field => field.name === this.customField.name);
+            if (exists) {
+                alert('字段名已存在');
+                return;
+            }
+            
+            this.customFields.push({
+                name: this.customField.name,
+                type: this.customField.type,
+                rule: this.customField.rule
+            });
+            
+            // 重置输入框
+            this.customField = {
+                name: '',
+                type: 'string',
+                rule: ''
+            };
+        },
+        
+        /**
+         * 删除自定义字段
+         */
+        removeCustomField(index) {
+            this.customFields.splice(index, 1);
+        },
+        
+        /**
+         * 全选当前标签页的字段
+         */
+        selectAll() {
+            const fieldGroups = {
+                personal: ['name', 'email', 'phone', 'idCard', 'gender', 'age', 'birthday', 'address'],
+                business: ['company', 'department', 'position', 'salary', 'bankCard', 'creditCard', 'price', 'currency'],
+                technical: ['uuid', 'ip', 'mac', 'userAgent', 'url', 'domain', 'password', 'token', 'color', 'timestamp', 'filename', 'mimeType']
+            };
+            
+            const fields = fieldGroups[this.activeTab] || [];
+            fields.forEach(field => {
+                this.selectedFields[field] = true;
+            });
+        },
+        
+        /**
+         * 清空所有选择
+         */
+        clearAll() {
+            Object.keys(this.selectedFields).forEach(key => {
+                this.selectedFields[key] = false;
+            });
+            this.customFields = [];
+            this.generatedData = '';
+            this.dataSize = '0 B';
+        },
+        
+        /**
+         * 生成假数据
+         */
+        generateData() {
+            const selectedFieldKeys = Object.keys(this.selectedFields).filter(key => this.selectedFields[key]);
+            
+            // 检查是否选择了字段
+            if (selectedFieldKeys.length === 0 && this.customFields.length === 0) {
+                alert('请至少选择一个字段');
+                return;
+            }
+            
+            // 生成数据
+            const data = [];
+            for (let i = 0; i < this.generateCount; i++) {
+                const item = {};
+                
+                // 生成预定义字段
+                selectedFieldKeys.forEach(field => {
+                    item[field] = this.generator.generateByType(field);
+                });
+                
+                // 生成自定义字段
+                this.customFields.forEach(field => {
+                    item[field.name] = this.generateCustomFieldData(field);
+                });
+                
+                data.push(item);
+            }
+            
+            // 格式化输出
+            this.formatOutput(data);
+        },
+        
+        /**
+         * 生成自定义字段数据
+         */
+        generateCustomFieldData(field) {
+            switch (field.type) {
+                case 'string':
+                    return this.generator.randomString(this.generator.randomInt(5, 20));
+                case 'number':
+                    return this.generator.randomInt(1, 1000);
+                case 'boolean':
+                    return this.generator.generateBoolean();
+                case 'date':
+                    return this.generator.generateDate();
+                case 'array':
+                    const arrayLength = this.generator.randomInt(1, 5);
+                    const array = [];
+                    for (let i = 0; i < arrayLength; i++) {
+                        array.push(this.generator.randomString(5));
+                    }
+                    return array;
+                default:
+                    return this.generator.randomString(10);
+            }
+        },
+        
+        /**
+         * 格式化输出数据
+         */
+        formatOutput(data) {
+            switch (this.outputFormat) {
+                case 'json':
+                    this.generatedData = JSON.stringify(data, null, 2);
+                    break;
+                case 'csv':
+                    this.generatedData = this.convertToCSV(data);
+                    break;
+                case 'sql':
+                    this.generatedData = this.convertToSQL(data);
+                    break;
+                case 'xml':
+                    this.generatedData = this.convertToXML(data);
+                    break;
+                default:
+                    this.generatedData = JSON.stringify(data, null, 2);
+            }
+            
+            // 计算数据大小
+            this.dataSize = this.calculateSize(this.generatedData);
+        },
+        
+        /**
+         * 转换为CSV格式
+         */
+        convertToCSV(data) {
+            if (data.length === 0) return '';
+            
+            const headers = Object.keys(data[0]);
+            const csvContent = [
+                headers.join(','),
+                ...data.map(row => 
+                    headers.map(header => {
+                        const value = row[header];
+                        // 处理包含逗号或引号的值
+                        if (typeof value === 'string' && (value.includes(',') || value.includes('"'))) {
+                            return `"${value.replace(/"/g, '""')}"`;
+                        }
+                        return value;
+                    }).join(',')
+                )
+            ].join('\n');
+            
+            return csvContent;
+        },
+        
+        /**
+         * 转换为SQL INSERT语句
+         */
+        convertToSQL(data) {
+            if (data.length === 0) return '';
+            
+            const tableName = 'fake_data';
+            const headers = Object.keys(data[0]);
+            
+            let sql = `-- 表结构\nCREATE TABLE ${tableName} (\n`;
+            sql += headers.map(header => `  ${header} VARCHAR(255)`).join(',\n');
+            sql += '\n);\n\n-- 数据插入\n';
+            
+            data.forEach(row => {
+                const values = headers.map(header => {
+                    const value = row[header];
+                    if (typeof value === 'string') {
+                        return `'${value.replace(/'/g, "''")}'`;
+                    }
+                    return value;
+                }).join(', ');
+                
+                sql += `INSERT INTO ${tableName} (${headers.join(', ')}) VALUES (${values});\n`;
+            });
+            
+            return sql;
+        },
+        
+        /**
+         * 转换为XML格式
+         */
+        convertToXML(data) {
+            if (data.length === 0) return '';
+            
+            let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<data>\n';
+            
+            data.forEach((item, index) => {
+                xml += `  <item id="${index + 1}">\n`;
+                Object.keys(item).forEach(key => {
+                    const value = item[key];
+                    xml += `    <${key}>${this.escapeXML(value)}</${key}>\n`;
+                });
+                xml += '  </item>\n';
+            });
+            
+            xml += '</data>';
+            return xml;
+        },
+        
+        /**
+         * XML字符转义
+         */
+        escapeXML(value) {
+            if (typeof value !== 'string') {
+                value = String(value);
+            }
+            return value
+                .replace(/&/g, '&amp;')
+                .replace(/</g, '&lt;')
+                .replace(/>/g, '&gt;')
+                .replace(/"/g, '&quot;')
+                .replace(/'/g, '&apos;');
+        },
+        
+        /**
+         * 计算数据大小
+         */
+        calculateSize(data) {
+            const bytes = new Blob([data]).size;
+            const sizes = ['B', 'KB', 'MB', 'GB'];
+            
+            if (bytes === 0) return '0 B';
+            
+            const i = Math.floor(Math.log(bytes) / Math.log(1024));
+            const size = (bytes / Math.pow(1024, i)).toFixed(2);
+            
+            return `${size} ${sizes[i]}`;
+        },
+        
+        /**
+         * 复制结果到剪贴板
+         */
+        async copyResult() {
+            if (!this.generatedData) {
+                alert('没有可复制的数据');
+                return;
+            }
+            
+            try {
+                await navigator.clipboard.writeText(this.generatedData);
+                this.showMessage('数据已复制到剪贴板', 'success');
+            } catch (err) {
+                console.error('复制失败:', err);
+                // 备用方法
+                this.fallbackCopyText(this.generatedData);
+            }
+        },
+        
+        /**
+         * 备用复制方法
+         */
+        fallbackCopyText(text) {
+            const textArea = document.createElement('textarea');
+            textArea.value = text;
+            textArea.style.position = 'fixed';
+            textArea.style.left = '-999999px';
+            textArea.style.top = '-999999px';
+            document.body.appendChild(textArea);
+            textArea.focus();
+            textArea.select();
+            
+            try {
+                document.execCommand('copy');
+                this.showMessage('数据已复制到剪贴板', 'success');
+            } catch (err) {
+                this.showMessage('复制失败,请手动选择复制', 'error');
+            }
+            
+            document.body.removeChild(textArea);
+        },
+        
+        /**
+         * 下载数据文件
+         */
+        downloadData() {
+            if (!this.generatedData) {
+                alert('没有可下载的数据');
+                return;
+            }
+            
+            const extensions = {
+                json: 'json',
+                csv: 'csv',
+                sql: 'sql',
+                xml: 'xml'
+            };
+            
+            const mimeTypes = {
+                json: 'application/json',
+                csv: 'text/csv',
+                sql: 'application/sql',
+                xml: 'application/xml'
+            };
+            
+            const extension = extensions[this.outputFormat] || 'txt';
+            const mimeType = mimeTypes[this.outputFormat] || 'text/plain';
+            
+            const blob = new Blob([this.generatedData], { type: mimeType });
+            const url = URL.createObjectURL(blob);
+            
+            const link = document.createElement('a');
+            link.href = url;
+            link.download = `fake-data-${Date.now()}.${extension}`;
+            document.body.appendChild(link);
+            link.click();
+            document.body.removeChild(link);
+            
+            URL.revokeObjectURL(url);
+            this.showMessage('文件下载已开始', 'success');
+        },
+        
+        /**
+         * 加载预设模板
+         */
+        loadTemplate(templateKey) {
+            const template = this.templates[templateKey];
+            if (!template) return;
+            
+            // 清空当前选择
+            this.clearAll();
+            
+            // 选择模板字段
+            template.fields.forEach(field => {
+                if (this.selectedFields.hasOwnProperty(field)) {
+                    this.selectedFields[field] = true;
+                }
+            });
+            
+            // 切换到相应的标签页
+            if (template.fields.some(field => ['name', 'email', 'phone', 'idCard', 'gender', 'age', 'birthday', 'address'].includes(field))) {
+                this.activeTab = 'personal';
+            } else if (template.fields.some(field => ['company', 'department', 'position', 'salary', 'bankCard', 'creditCard', 'price', 'currency'].includes(field))) {
+                this.activeTab = 'business';
+            } else {
+                this.activeTab = 'technical';
+            }
+            
+            this.showMessage(`已加载 ${template.name}`, 'success');
+        },
+        
+
+        // 打开工具市场页面
+        openOptionsPage: function(event){
+            event.preventDefault();
+            event.stopPropagation();
+            chrome.runtime.openOptionsPage();
+        },
+
+        openDonateModal: function(event){
+            event.preventDefault();
+            event.stopPropagation();
+            chrome.runtime.sendMessage({
+                type: 'fh-dynamic-any-thing',
+                thing: 'open-donate-modal',
+                params: { toolName: 'mock-data' }
+            });
+        },
+
+        /**
+         * 显示消息提示
+         */
+        showMessage(message, type = 'info') {
+            // 创建消息元素
+            const messageEl = document.createElement('div');
+            messageEl.className = `${type}-message`;
+            messageEl.textContent = message;
+            messageEl.style.position = 'fixed';
+            messageEl.style.top = '20px';
+            messageEl.style.right = '20px';
+            messageEl.style.zIndex = '9999';
+            messageEl.style.padding = '10px 15px';
+            messageEl.style.borderRadius = '4px';
+            messageEl.style.fontSize = '14px';
+            messageEl.style.fontWeight = '500';
+            messageEl.style.boxShadow = '0 2px 12px rgba(0, 0, 0, 0.15)';
+            
+            // 设置样式
+            if (type === 'success') {
+                messageEl.style.background = '#d4edda';
+                messageEl.style.color = '#155724';
+                messageEl.style.border = '1px solid #c3e6cb';
+            } else if (type === 'error') {
+                messageEl.style.background = '#f8d7da';
+                messageEl.style.color = '#721c24';
+                messageEl.style.border = '1px solid #f5c6cb';
+            } else {
+                messageEl.style.background = '#d1ecf1';
+                messageEl.style.color = '#0c5460';
+                messageEl.style.border = '1px solid #bee5eb';
+            }
+            
+            document.body.appendChild(messageEl);
+            
+            // 3秒后自动移除
+            setTimeout(() => {
+                if (messageEl.parentNode) {
+                    messageEl.parentNode.removeChild(messageEl);
+                }
+            }, 3000);
+        }
+    },
+    
+    watch: {
+        // 监听生成数量变化,限制范围
+        generateCount(newVal) {
+            if (newVal < 1) {
+                this.generateCount = 1;
+            } else if (newVal > 1000) {
+                this.generateCount = 1000;
+            }
+        }
+    }
+}); 

+ 89 - 2
apps/popup/index.css

@@ -6,11 +6,17 @@ html, body {
 
 .fe-whole-page {
     width: 152px;
+    min-height: 120px; /* 设置最小高度,确保工具很少时不会过于矮小 */
+    max-height: 600px; /* 设置最大高度,避免工具太多时popup过高 */
     font-size: 14px;
     user-select: none;
     padding: 0;
     margin: 0;
     position: relative;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden; /* 确保内容不会溢出 */
+    transition: min-height 0.2s ease-out; /* 添加平滑过渡效果 */
 }
 
 .fe-hide {
@@ -39,13 +45,17 @@ ul.fe-function-list {
     list-style: none;
     width: 100%;
     margin: 0;
+    flex: 1; /* 自动占用剩余空间 */
+    min-height: 40px; /* 确保即使没有工具时也有基本高度 */
+    overflow-y: auto; /* 当工具太多时允许滚动 */
+    max-height: 500px; /* 设置最大高度 */
 }
 
 ul.fe-function-list li {
     padding: 2px 10px 2px 38px;
     cursor: pointer;
     color: #4a4c6d;
-    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
+    transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1), height 0.2s ease-out, margin 0.2s ease-out;
     display: block;
     align-items: center;
     height: 28px;
@@ -118,10 +128,11 @@ ul.fe-function-list li i {
     font-size: 13px;
     border-top: 1px solid rgba(67, 97, 238, 0.08);
     padding: 8px 16px;
-    margin-top: 0px;
+    margin-top: auto; /* 自动推到底部 */
     background: linear-gradient(to right, rgba(67, 97, 238, 0.05), rgba(67, 97, 238, 0.05));
     color: var(--text-color);
     opacity: 0.9;
+    flex-shrink: 0; /* 防止被压缩 */
 }
 
 .fe-feedback a {
@@ -180,6 +191,7 @@ svg:not(:root) {
     justify-content: center;
     padding: 20px;
     min-height: 60px;
+    flex: 1; /* 占用剩余空间 */
 }
 
 .loading-spinner {
@@ -207,6 +219,10 @@ svg:not(:root) {
 .fe-no-tools {
     padding: 20px;
     text-align: center;
+    flex: 1; /* 占用剩余空间 */
+    display: flex;
+    align-items: center;
+    justify-content: center;
 }
 
 .no-tools-message p {
@@ -241,3 +257,74 @@ html[dark-mode="on"] .loading-spinner {
     border-color: rgba(255, 255, 255, 0.1);
     border-left-color: #4361ee;
 }
+
+/* 工具数量少时的优化样式 */
+.fe-whole-page.few-tools {
+    min-height: 140px; /* 当工具数量少于等于3个时,增加最小高度 */
+}
+
+.fe-whole-page.very-few-tools {
+    min-height: 110px; /* 当只有1个工具时,适度减少高度 */
+}
+
+/* 当工具列表为空时,确保有合适的间距 */
+.fe-function-list:empty {
+    min-height: 20px;
+}
+
+/* 优化工具数量少时的间距 */
+.fe-function-list li:only-child {
+    margin: 4px 0; /* 只有一个工具时增加上下间距 */
+}
+
+.fe-function-list li:first-child:nth-last-child(2),
+.fe-function-list li:first-child:nth-last-child(2) ~ li {
+    margin: 3px 0; /* 只有两个工具时的间距 */
+}
+
+.fe-function-list li:first-child:nth-last-child(3),
+.fe-function-list li:first-child:nth-last-child(3) ~ li {
+    margin: 2px 0; /* 只有三个工具时的间距 */
+}
+
+/* 工具数量少时的类样式 */
+.fe-function-list.few-tools {
+    padding: 4px 0; /* 增加上下内边距 */
+}
+
+.fe-function-list.few-tools li {
+    height: 32px; /* 稍微增加高度 */
+    line-height: 32px;
+    margin: 3px 0; /* 增加间距 */
+}
+
+.fe-function-list.few-tools li > b {
+    top: 6px; /* 调整图标位置 */
+}
+
+/* 当只有极少工具时的特殊优化 */
+.very-few-tools .fe-function-list {
+    padding: 6px 0;
+}
+
+.very-few-tools .fe-function-list li {
+    height: 34px;
+    line-height: 34px;
+    margin: 4px 0;
+}
+
+.very-few-tools .fe-function-list li > b {
+    top: 7px;
+}
+
+/* 注释:.fe-feedback的margin-top: auto样式已在主样式定义中设置 */
+
+/* 当没有工具时,优化无工具提示的显示 */
+.fe-no-tools .no-tools-message {
+    text-align: center;
+}
+
+/* 优化加载状态的显示 */
+.fe-loading {
+    justify-content: center;
+}

+ 3 - 3
apps/popup/index.html

@@ -8,7 +8,7 @@
 		<script type="text/javascript" src="../static/vendor/vue/vue.js"></script>
     </head>
     <body>
-        <div id="pageContainer" class="fe-whole-page">
+        <div id="pageContainer" class="fe-whole-page" :class="getLayoutClasses()">
             <div class="fe-function-title">FeHelper<span>({{manifest.version}})</span></div>
             
             <!-- 加载状态 -->
@@ -18,14 +18,14 @@
             </div>
             
             <!-- 工具列表 -->
-            <ul v-else class="fe-function-list">
+            <ul v-else-if="installedToolsCount > 0" class="fe-function-list" :class="{'few-tools': installedToolsCount <= 3}">
                 <li v-for="tool in Object.keys(fhTools)" :class="'-x-' + tool" @click="runHelper(tool)" v-if="fhTools[tool].installed">
                     <b>{{ fhTools[tool].icon || fhTools[tool].menuConfig[0].icon}}</b>{{fhTools[tool].name}}
                 </li>
             </ul>
             
             <!-- 如果没有工具 -->
-            <div v-if="!isLoading && Object.keys(fhTools).length === 0" class="fe-no-tools">
+            <div v-else-if="!isLoading" class="fe-no-tools">
                 <div class="no-tools-message">
                     <p>暂无已安装的工具</p>
                     <button @click="openOptionsPage()" class="install-tools-btn">去安装工具</button>

+ 51 - 0
apps/popup/index.js

@@ -38,6 +38,13 @@ new Vue({
         isLoading: true
     },
 
+    computed: {
+        // 计算已安装的工具数量
+        installedToolsCount() {
+            return Object.values(this.fhTools).filter(tool => tool.installed).length;
+        }
+    },
+
     created: function () {
         // 获取当前ctx的version
         this.manifest = chrome.runtime.getManifest();
@@ -74,6 +81,19 @@ new Vue({
     },
 
     methods: {
+        getLayoutClasses() {
+            const installedCount = this.installedToolsCount;
+            const classes = [];
+            
+            if (installedCount <= 1) {
+                classes.push('very-few-tools');
+            } else if (installedCount <= 3) {
+                classes.push('few-tools');
+            }
+            
+            return classes;
+        },
+
         async loadTools() {
             try {
                 const tools = await Awesome.getInstalledTools();
@@ -104,11 +124,21 @@ new Vue({
                 }
                 
                 this.isLoading = false;
+                
+                // 根据工具数量添加相应的CSS类来优化显示
+                this.$nextTick(() => {
+                    this.updateLayoutClasses();
+                });
             } catch (error) {
                 console.error('加载工具列表失败:', error);
                 this.isLoading = false;
                 // 即使加载失败,也不应该让popup完全无法使用
                 this.fhTools = {};
+                
+                // 加载失败时也需要更新布局类
+                this.$nextTick(() => {
+                    this.updateLayoutClasses();
+                });
             }
         },
 
@@ -204,6 +234,27 @@ new Vue({
             // 获取后台页面,返回window对象
             chrome.tabs.create({url: event.currentTarget.href});
             return false;
+        },
+
+        updateLayoutClasses() {
+            const container = document.getElementById('pageContainer');
+            if (!container) return;
+            
+            const installedCount = this.installedToolsCount;
+            
+            // 移除所有布局相关的类
+            container.classList.remove('few-tools', 'very-few-tools');
+            
+            // 根据工具数量添加相应的类
+            if (installedCount <= 1) {
+                container.classList.add('very-few-tools');
+                console.log('Popup布局:应用very-few-tools类 (工具数量:', installedCount, ')');
+            } else if (installedCount <= 3) {
+                container.classList.add('few-tools');
+                console.log('Popup布局:应用few-tools类 (工具数量:', installedCount, ')');
+            } else {
+                console.log('Popup布局:使用默认布局 (工具数量:', installedCount, ')');
+            }
         }
     }
 });

+ 185 - 0
website/docs/mock-data.md

@@ -0,0 +1,185 @@
+# Mock数据生成器
+
+> 快速生成各种测试数据,支持个人信息、商业数据、技术数据等多种类型,可自定义字段和输出格式
+
+## 功能特点
+
+- **多种数据类型**:支持个人信息、商业数据、技术数据等多个分类
+- **自定义字段**:支持添加自定义字段类型和生成规则
+- **多种输出格式**:支持JSON、CSV、SQL、XML等多种格式输出
+- **预设模板**:提供用户信息、员工信息、商品信息等常用模板
+- **批量生成**:支持一次生成1-1000条数据
+- **中文数据**:专门优化了中文姓名、地址、公司等本土化数据
+
+## 数据类型
+
+### 个人信息
+- **姓名**:随机生成中文姓名,支持单字名和双字名
+- **邮箱**:生成符合格式的邮箱地址
+- **手机号**:生成符合中国大陆格式的手机号码
+- **身份证号**:生成符合格式的身份证号码
+- **性别**:随机生成男/女
+- **年龄**:18-65岁随机年龄
+- **生日**:随机生成日期
+- **地址**:包含省市区街道的完整地址
+
+### 商业数据
+- **公司名称**:知名公司名称 + 企业性质后缀
+- **部门**:技术部、产品部、运营部等
+- **职位**:工程师、经理、专员等
+- **薪资**:5000-50000元随机薪资
+- **银行卡号**:符合格式的银行卡号
+- **信用卡号**:符合格式的信用卡号
+- **价格**:0.01-9999.99随机价格
+- **货币**:CNY、USD、EUR等货币代码
+
+### 技术数据
+- **UUID**:标准UUID格式
+- **IP地址**:IPv4地址格式
+- **MAC地址**:网卡MAC地址格式
+- **User Agent**:常见浏览器UA字符串
+- **URL**:完整的网址格式
+- **域名**:随机域名
+- **密码**:包含数字、字母、特殊符号的随机密码
+- **Token**:32位随机Token
+- **颜色值**:十六进制颜色代码
+- **时间戳**:Unix时间戳
+- **文件名**:随机文件名和扩展名
+- **MIME类型**:常见文件MIME类型
+
+## 使用方法
+
+### 1. 选择数据类型
+在顶部选择要生成的数据类型标签页:
+- **个人信息**:姓名、邮箱、电话等个人数据
+- **商业数据**:公司、职位、金融等商业数据
+- **技术数据**:UUID、IP、Token等技术数据
+- **自定义数据**:自己定义字段类型和规则
+
+### 2. 选择字段
+在每个标签页中勾选需要生成的字段。可以选择多个字段组合生成。
+
+### 3. 配置生成选项
+- **生成数量**:设置要生成的数据条数(1-1000)
+- **输出格式**:选择JSON、CSV、SQL或XML格式
+
+### 4. 生成数据
+点击"生成数据"按钮,系统会根据选择的字段和配置生成相应的假数据。
+
+### 5. 结果操作
+生成的数据可以:
+- **复制到剪贴板**:一键复制到系统剪贴板
+- **下载文件**:保存为相应格式的文件
+- **预览结果**:在页面中直接查看生成的数据
+
+## 快速模板
+
+提供5个预设模板,可以快速生成常用数据:
+
+### 用户信息模板
+包含:姓名、邮箱、电话、性别、年龄、地址
+
+### 员工信息模板  
+包含:姓名、邮箱、电话、公司、部门、职位、薪资
+
+### 商品信息模板
+包含:名称、价格、货币、UUID、时间戳
+
+### 订单信息模板
+包含:UUID、姓名、邮箱、电话、地址、价格、时间戳
+
+### API测试数据模板
+包含:UUID、Token、IP、User Agent、时间戳、布尔值
+
+## 自定义字段
+
+支持添加自定义字段:
+
+1. **字段名称**:输入字段的名称
+2. **数据类型**:选择字符串、数字、布尔值、日期或数组
+3. **生成规则**:描述字段的生成规则(可选)
+4. **添加字段**:将自定义字段加入生成列表
+
+## 输出格式
+
+### JSON格式
+```json
+[
+  {
+    "name": "王伟",
+    "email": "[email protected]",
+    "phone": "13812345678"
+  }
+]
+```
+
+### CSV格式
+```csv
+name,email,phone
+王伟,[email protected],13812345678
+李娜,[email protected],13987654321
+```
+
+### SQL INSERT格式
+```sql
+CREATE TABLE fake_data (
+  name VARCHAR(255),
+  email VARCHAR(255),
+  phone VARCHAR(255)
+);
+
+INSERT INTO fake_data (name, email, phone) VALUES ('王伟', '[email protected]', '13812345678');
+```
+
+### XML格式
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<data>
+  <item id="1">
+    <name>王伟</name>
+    <email>[email protected]</email>
+    <phone>13812345678</phone>
+  </item>
+</data>
+```
+
+## 使用场景
+
+### 开发测试
+- **数据库填充**:为开发环境生成测试数据
+- **接口测试**:为API测试生成请求数据
+- **表单测试**:为前端表单填充测试数据
+
+### 演示数据
+- **产品演示**:为产品演示准备真实感的数据
+- **用户培训**:为培训环境准备安全的虚拟数据
+- **原型设计**:为设计原型提供数据支撑
+
+### 压力测试
+- **性能测试**:生成大量数据进行系统压力测试
+- **并发测试**:模拟多用户环境进行并发测试
+
+## 注意事项
+
+1. **数据安全**:生成的数据仅用于测试,不要用于生产环境
+2. **隐私保护**:生成的个人信息为虚拟数据,请勿用于欺诈等违法行为
+3. **格式规范**:生成的数据遵循常见格式规范,但不保证100%真实有效
+4. **数量限制**:单次最多生成1000条数据,避免浏览器性能问题
+5. **中文优化**:针对中文环境进行了优化,特别是姓名、地址等字段
+
+## 常见问题
+
+**Q: 生成的身份证号是真实的吗?**
+A: 不是,生成的身份证号仅符合格式规范,为虚拟数据,不对应真实人员信息。
+
+**Q: 可以生成多少条数据?**
+A: 单次最多可生成1000条数据,如需更多数据可分批生成。
+
+**Q: 支持哪些输出格式?**
+A: 目前支持JSON、CSV、SQL INSERT和XML四种格式。
+
+**Q: 可以自定义数据生成规则吗?**
+A: 可以通过自定义字段功能添加自己的字段类型,支持字符串、数字、布尔值、日期和数组类型。
+
+**Q: 生成的数据可以保存吗?**
+A: 可以,支持复制到剪贴板或下载为文件保存到本地。