AI 写代码太狠了!我一句话就搞定年会抽奖系统,老板看了都说妙!

0 阅读7分钟

我正在参加Trae「超级体验官」创意实践征文,本文所使用的 Trae 免费下载链接:www.trae.com.cn/?utm_source…

每年年会一到,咱们老板总是照例发几句牢骚,话说得那叫一个熟练:“公司养这么多程序员,连个抽奖网站都没人有空写,最后还得我自己花钱去外面买?!”

每次听到这,我内心的小剧场就开始轰轰烈烈地上演了:老板啊,咱真不是不想写,实在是日常项目一个接一个地压过来,改 Bug、赶进度、熬夜加班,哪儿还有空给您老整抽奖网站啊?再说了,年会项目这玩意,年年用一年一更新,写起来精力不小,回头您一句“今年换个花样”,我们又得推翻重来。就说实话吧,哪有那么多时间啊!

不过今年,我决定不一样了。今年不让您再破费买什么现成的抽奖工具,也不让您再对我们程序员指指点点地吐槽。抽奖网站这活儿,今年我自己接了——就让我亲手给咱年会整一个炫酷又实用的抽奖系统,顺便也在全公司面前亮一把技术肌肉,让您刮目相看!

说干就干。既然是年会抽奖,光是普通转盘可不够看,得加点花活儿才行——比如奖品弹幕、实时中奖名单、背景音乐,最好还能连上投影,动静大点儿才有年会气氛。关键是,开发周期又不能太长,毕竟业务的活儿可一个都不少。那怎么办?聪明如我,当然要借助点“神器”——Trae AIIDE,程序员提升效率的秘密武器!

可能还有人没听说过 Trae AIIDE 是啥,那我就稍微介绍一下。这是一个集智能代码补全、项目自动结构搭建、语义理解为一体的开发辅助平台,说白了,它能理解你想干什么,然后自动帮你搭出一个项目雏形,还能快速生成页面、逻辑、样式,连后端接口也能带着搞定。就像有个不眠不休、从不抱怨的“AI搭子”天天陪着你干活。这样的工具,做个抽奖助手那不是分分钟的事?

我先把抽奖流程理了一遍:主持人一声令下,页面开始倒计时,屏幕上滚动所有参会人员的头像,最终定格显示中奖人,然后弹出炫酷的特效动画和奖品信息。除此之外,后台还要有个小型的管理系统,用来添加奖品、设定奖项数量、查看中奖历史,顺便还能做点数据分析,看看哪个部门中奖最多,谁又是“非酋之王”。

发出指令:请使用html写一美观的抽奖助手,支持人员信息录入。

有了 Trae,我不再从零开始搭建项目结构,而是通过自然语言告诉它: “我要一个抽奖助手的前端页面,支持人员滚动、奖项设置和动画效果;后端要能处理奖品数据、中奖记录和用户信息。” 几分钟内,基础代码就自动生成好了,大概相当于平时我两三个小时才能撸完的初版页面。这效率,真的不是吹。

接着我开始定制前端页面,Trae 帮我把 UI 框架搭好,我稍微调整了一下配色,配上公司 Logo 和年会主题,“Lucky Draw 2025 欢欢喜喜中大奖”几个大字一打上去,年味儿立马就出来了。动画部分我用了 CSS3 和 canvas 做了爆炸效果,每次抽奖都会有小彩球飞溅,视觉冲击力直接拉满。

发出指令:帮我写一个有渐变背景和奖项动画效果的 HTML 页面,并加入年会主题。

看下新效果:

在看一下效果吧

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>幸运抽奖助手</title>
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet">
  <style>
    :root {
      --primary: #FFD700;
      --secondary: #C41E3A;
      --error: #ff4757;
      --gold-gradient: linear-gradient(135deg, #FFD700 0%, #B8860B 100%);
    }

    * {
      box-sizing: border-box;
      font-family: 'Poppins', sans-serif;
    }

    body {
      background: var(--gold-gradient);
      min-height: 100vh;
      padding: 2rem;
      position: relative;
      overflow-x: hidden;
    }

    /* 节日装饰 */
    .lantern {
      position: absolute;
      width: 60px;
      animation: float 3s ease-in-out infinite;
      filter: drop-shadow(0 5px 15px rgba(255, 215, 0, 0.5));
    }

    .ribbon {
      position: absolute;
      height: 100vh;
      width: 50px;
      background: repeating-linear-gradient(
        45deg,
        #C41E3A,
        #C41E3A 10px,
        #FFD700 10px,
        #FFD700 20px
      );
      animation: sway 5s linear infinite;
    }

    .container {
      max-width: 800px;
      margin: 0 auto;
      background: rgba(255,255,255,0.95);
      border-radius: 1rem;
      box-shadow: 0 10px 30px rgba(0,0,0,0.1);
      padding: 2rem;
    }

    .form-group {
      margin-bottom: 1.5rem;
    }

    label {
      display: block;
      margin-bottom: 0.5rem;
      color: #333;
      font-weight: 600;
    }

    input {
      width: 100%;
      padding: 0.8rem;
      border: 2px solid #e0e0e0;
      border-radius: 0.5rem;
      font-size: 1rem;
      transition: border-color 0.3s ease;
    }

    input:focus {
      outline: none;
      border-color: var(--primary);
      box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.1);
    }

    .error-message {
      color: var(--error);
      font-size: 0.875rem;
      margin-top: 0.5rem;
      display: none;
    }

    .button {
      background: var(--primary);
      color: white;
      border: none;
      padding: 1rem 2rem;
      border-radius: 0.5rem;
      cursor: pointer;
      font-size: 1rem;
      transition: transform 0.2s, box-shadow 0.2s;
    }

    .button:hover {
      transform: translateY(-2px);
      box-shadow: 0 5px 15px rgba(74, 144, 226, 0.3);
    }

    /* 参与者列表 */
    .participant-container {
      display: grid;
      gap: 1rem;
      margin-top: 1rem;
      max-height: 300px;
      overflow-y: auto;
    }

    .participant-item {
      display: flex;
      justify-content: space-between;
      padding: 1rem;
      background: #f8f9fa;
      border-radius: 0.5rem;
      animation: slideIn 0.3s ease;
    }

    /* 结果弹窗 */
    .result-popup {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: rgba(0,0,0,0.5);
      display: flex;
      justify-content: center;
      align-items: center;
      animation: fadeIn 0.3s ease;
    }

    .popup-content {
      background: linear-gradient(45deg, #C41E3A, #FFD700);
      border: 3px solid #FFD700;
      animation: blink 1.5s ease infinite;
      padding: 2rem;
      border-radius: 1rem;
      text-align: center;
      box-shadow: 0 10px 30px rgba(0,0,0,0.2);
    }

    .winner-info {
      margin: 1.5rem 0;
      font-size: 1.2rem;
    }

    @keyframes slideIn {
      from { transform: translateY(20px); opacity: 0; }
      to { transform: translateY(0); opacity: 1; }
    }

    @keyframes float {
      0%, 100% { transform: translateY(0); }
      50% { transform: translateY(-20px); }
    }

    @keyframes sway {
      0% { transform: rotate(0deg); }
      25% { transform: rotate(2deg); }
      75% { transform: rotate(-2deg); }
      100% { transform: rotate(0deg); }
    }

    @keyframes blink {
      0% { opacity: 0.8; }
      50% { opacity: 1; text-shadow: 0 0 10px #FFD700; }
      100% { opacity: 0.8; }
    }

    @keyframes firework {
      0% { transform: scale(0); opacity: 1; }
      100% { transform: scale(1); opacity: 0; }
    }

    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }
  </style>
</head>
<body>
  <!-- 节日装饰 -->
  <div class="lantern" style="left:10%;top:5%">🎉</div>
  <div class="lantern" style="right:10%;top:15%">🏮</div>
  <div class="ribbon" style="left:-25px"></div>
  <div class="ribbon" style="right:-25px"></div>
  
  <div class="container">
    <h1>幸运抽奖系统</h1>
    
    <!-- 报名表单 -->
    <form id="registrationForm">
      <div class="form-group">
        <label for="name">姓名:</label>
        <input type="text" id="name" required>
        <div class="error-message" id="nameError"></div>
      </div>

      <div class="form-group">
        <label for="phone">手机号:</label>
        <input type="tel" id="phone" pattern="\d{11}" required>
        <div class="error-message" id="phoneError"></div>
      </div>

      <button type="submit" class="button">立即报名</button>
    </form>

    <!-- 参与者列表 -->
    <div id="participantList"></div>

    <!-- 抽奖按钮 -->
    <button class="button" id="startLottery" style="margin-top: 2rem;">开始抽奖</button>
  </div>

  <script>
    // 数据存储逻辑
    let participants = JSON.parse(localStorage.getItem('participants')) || [];
    const MAX_PARTICIPANTS = 200;

    // 初始化渲染
    renderParticipantList();
    updateLotteryButton();

    // 表单提交处理
    document.getElementById('registrationForm').addEventListener('submit', (e) => {
      e.preventDefault();
      if (validateForm()) {
        const name = document.getElementById('name').value.trim();
        const phone = document.getElementById('phone').value.trim();
        
        // 检查重复报名
        if (participants.some(p => p.phone === phone)) {
          showError('phoneError', '该手机号已报名');
          return;
        }

        participants.push({ name, phone });
        localStorage.setItem('participants', JSON.stringify(participants));
        
        // 清空表单
        e.target.reset();
        document.querySelectorAll('.error-message').forEach(el => el.style.display = 'none');
        renderParticipantList();
        updateLotteryButton();
      }
    });

    // 抽奖按钮点击
    document.getElementById('startLottery').addEventListener('click', startLottery);

    // 表单验证
    function validateForm() {
      const name = document.getElementById('name').value.trim();
      const phone = document.getElementById('phone').value.trim();
      let isValid = true;

      // 清空错误提示
      document.querySelectorAll('.error-message').forEach(el => el.style.display = 'none');

      // 姓名验证
      if (name.length < 2) {
        showError('nameError', '请输入有效姓名(至少2个字符)');
        isValid = false;
      }

      // 手机号验证
      if (!/^\d{11}$/.test(phone)) {
        showError('phoneError', '请输入有效的11位手机号');
        isValid = false;
      }

      return isValid;
    }

    // 显示错误信息
    function showError(elementId, message) {
      const errorElement = document.getElementById(elementId);
      errorElement.textContent = message;
      errorElement.style.display = 'block';
    }

    // 渲染参与者列表
    function renderParticipantList() {
      const listDiv = document.getElementById('participantList');
      listDiv.innerHTML = `<h2>已报名人员 (${participants.length}/${MAX_PARTICIPANTS})</h2>
        <div class="participant-container">
          ${participants.map(p => 
            `<div class="participant-item">
              <span>${p.name}</span>
              <span>${p.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')}</span>
            </div>`
          ).join('')}
        </div>`;
    }

    // 更新抽奖按钮状态
    function updateLotteryButton() {
      const btn = document.getElementById('startLottery');
      btn.disabled = participants.length < 2;
      btn.textContent = participants.length >= 2 
        ? `开始抽奖 (剩余${participants.length}人)` 
        : '至少需要2人参与抽奖';
    }

    // 抽奖逻辑
    function startLottery() {
      const btn = document.getElementById('startLottery');
      btn.disabled = true;
      
      // 抽奖动画
      let count = 0;
      const animation = setInterval(() => {
        btn.textContent = `抽奖进行中 ${['⣾','⣽','⣻','⢿','⡿','⣟','⣯','⣷'][count++ % 8]}`;
      }, 100);

      // 模拟抽奖过程
      setTimeout(() => {
        clearInterval(animation);
        const winnerIndex = Math.floor(Math.random() * participants.length);
        const winner = participants.splice(winnerIndex, 1)[0];
        localStorage.setItem('participants', JSON.stringify(participants));
        
        showResultPopup(winner);
        renderParticipantList();
        updateLotteryButton();
      }, 2000);
    }

    // 显示结果弹窗
    function showResultPopup(winner) {
      // 礼花特效
function createFirework(x, y) {
  const firework = document.createElement('div');
  firework.className = 'firework';
  firework.style = `left:${x}px;top:${y}px;`;
  firework.innerHTML = '🎆';
  document.body.appendChild(firework);
  setTimeout(() => firework.remove(), 1000);
}

// 显示结果弹窗
const popup = document.createElement('div');
      popup.className = 'result-popup';
      popup.innerHTML = `
        <div class="popup-content">
          <h3>🎉 中奖者 🎉</h3>
          <div class="winner-info">
            <p>姓名:${winner.name}</p>
            <p>电话:${winner.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')}</p>
          </div>
          <button onclick="this.parentElement.parentElement.remove()">关闭</button>
        </div>
      `;
      document.body.appendChild(popup);
// 触发礼花特效
for(let i=0; i<8; i++) {
  setTimeout(() => {
    createFirework(Math.random()*window.innerWidth, Math.random()*window.innerHeight);
  }, i*100);
}
    }
  </script>
</body>
</html>

从开始构思到完成测试,我一共用了不到小时天时间,就完成了这样一个功能齐全、界面美观、体验顺滑的抽奖系统。最重要的是,我还整了个“彩蛋”——每次高管中奖,背景会自动播放一段配乐,然后屏幕弹出“老板吉祥,财源滚滚来!”的标语。是不是很有意思?

项目上线后,年会那天效果果然惊艳到了所有人,尤其是老板。当他看到抽奖页面那一刻,先是愣了一下,然后嘴角就不自觉地上扬了。主持人一声“开始抽奖”,滚动头像、烟花动画、中奖提示一气呵成,全场一片掌声。最后老板忍不住感慨:“哎哟,今年这抽奖做得不错,是谁搞的?”

我默默走上台,假装谦虚地说:“老板,不用买了,以后年会抽奖,我一手包办。”

台下同事们笑声一片,我心里却暗自得意:这波,不仅证明了自己,也顺带让 Trae AIIDE 成了大家眼中的“神助攻”。以后谁还说程序员不浪漫、不懂氛围?咱不仅能写代码,还能点亮全场!