从零构建 AI 驱动的智能用户查询系统:详解一个全栈前端原型

90 阅读5分钟

在人工智能与 Web 开发深度融合的今天,开发者不再需要庞大的团队或复杂的基础设施,就能快速构建具备自然语言理解能力的智能应用。本文将围绕一段简洁而完整的 HTML + JavaScript 代码,深入剖析如何仅用前端技术 + 两个本地服务,实现一个“用户数据展示 + AI 智能问答”的交互系统。我们将逐行解读代码逻辑、分析架构设计、指出潜在问题,并探讨其背后所代表的 AI 全栈开发新范式


一、整体功能目标

该页面的核心目标是:

  1. 自动加载用户列表(来自后端 API),并以表格形式展示;
  2. 允许用户输入自然语言问题(如“谁来自北京?”);
  3. 将问题连同用户数据发送给 AI 服务
  4. 在页面底部实时显示 AI 的回答

整个系统由三部分组成:

  • 前端页面(本文重点分析的 HTML/JS)
  • 用户数据服务(运行于 http://localhost:3001,提供 /users 接口)
  • AI 问答服务(运行于 http://localhost:1314,接收问题并调用大模型)

尽管只有几十行代码,却完整实现了“数据 → 交互 → 智能响应”的闭环。


二、HTML 结构深度解析

1. 基础设置

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Users Chatbot</title>
  <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
  • 使用标准 HTML5 文档类型;
  • 设置字符编码为 UTF-8,确保中文正常显示;
  • 引入 Bootstrap 3.0.3 的 CDN 链接,用于快速构建响应式布局和美观组件。

💡 虽然 Bootstrap 3 已较老旧(当前主流为 v5),但其网格系统和表单样式在此场景下完全够用。


2. 用户数据表格区域

<div class="container">
  <div class="row col-md-6 col-md-offset-3">
    <table class="table table-striped" id="user_table">
      <thead>...</thead>
      <tbody></tbody>
    </table>
  </div>

关键点分析:

  • .container:Bootstrap 的固定宽度容器,居中对齐;

  • class="row col-md-6 col-md-offset-3"

    • 在中等及以上屏幕(≥768px)上,该列占据 6/12 宽度(即 50%);

    • col-md-offset-3 表示左侧留白 3 列,实现水平居中

    • ⚠️ 语法瑕疵:严格来说,.row 和 .col-* 应分属不同 <div>,即:

      <div class="row">
        <div class="col-md-6 col-md-offset-3">...</div>
      </div>
      

      但 Bootstrap 3 的 CSS 容错性较强,当前写法通常仍可渲染正确。

  • <table id="user_table">:赋予唯一 ID,便于 JavaScript 精准操作;

  • <tbody> 初始为空,等待 JS 动态填充数据。


3. AI 提问表单

<div class="row">
  <form name="aiForm">
    <div class="form-group">
      <label for="questionInput">请输入问题:</label>
      <input type="text" class="form-control" id="questionInput" name="question" required placeholder="...">
    </div>
    <button type="submit" class="btn btn-primary">提交</button>
  </form>
</div>
  • 表单命名为 aiForm,可通过 document.forms["aiForm"] 直接访问;
  • 输入框具有 required 属性,浏览器会自动校验非空;
  • 使用 Bootstrap 的 .form-control 和 .btn-primary 实现统一视觉风格。

布局问题:此表单未使用 col-md-*,在 PC 端会撑满整行,与上方居中的表格不对齐。建议将其也包裹在 col-md-6 col-md-offset-3 中。


4. AI 回答展示区

<div class="row" id="message"></div>
</div> <!-- 多余的闭合标签 -->
  • id="message" 用于后续插入 AI 返回的内容;

  • 严重结构错误:多了一个 </div>,导致 HTML 树形结构异常。正确应为:

    <div class="row" id="message"></div>
    

* * *

## 三、JavaScript 逻辑逐行拆解

### 1. DOM 元素获取与初始化

js 编辑 const oForm = document.forms["aiForm"]; // 获取表单 const oBody = document.querySelector('#user_table tbody'); // 获取表格 body const oBtn = document.querySelector(".btn"); // 获取提交按钮 let users; // 全局变量存储用户数据

**亮点**:精准选择 `#user_table tbody`,避免覆盖 `<thead>`,确保表格结构完整。


### 2. 表单提交事件处理(核心交互)

js 编辑 oForm.addEventListener("submit", (event) => { event.preventDefault(); // 阻止默认跳转 const question = oForm["question"].value;

if (!question) { alert("请输入问题"); return; }

oBtn.disabled = true; // 防重复提交

fetch(http://localhost:1314/?question=${question}&data=${JSON.stringify(users)}) .then(res => res.json()) .then(data => { oBtn.disabled = false; document.getElementById('message').innerHTML = data.result; }); });


#### 流程详解:

1.  **阻止默认行为**:防止表单提交导致页面刷新;

1.  **获取问题文本**:通过 `oForm["question"].value` 读取输入值;

1.  **简单校验**:若为空则弹窗提示(实际应优先依赖 HTML5 的 `required`);

1.  **禁用按钮**:防止用户多次点击造成重复请求;

1.  **构造 GET 请求**    -   URL 包含两个参数:

        -   `question`:用户输入的问题;
        -   `data`:将全局 `users` 数组序列化为 JSON 字符串;

1.  **处理响应**    -   解析 JSON;
    -   恢复按钮状态;
    -   将 `data.result` 插入 `#message` 区域。

#### ⚠️ 三大隐患:

| 问题          | 风险                                           | 建议                                |
| ----------- | -------------------------------------------- | --------------------------------- |
| **URL 过长**  | 若 `users` 数据量大,GET 请求可能超限(浏览器通常限制 ~2000 字符)  | 改用 POST,将数据放入请求体                  |
| **特殊字符未编码** | `JSON.stringify()` 含空格、引号等,直接拼接会破坏 URL       | 使用 `encodeURIComponent()` 或改 POST |
| **XSS 攻击**  | `innerHTML = data.result` 若含 `<script>` 会被执行 | 改用 `textContent` 或 HTML 转义        |

* * *

### 3. 初始化:加载用户数据

js 编辑 fetch('http://localhost:3001/users') .then(res => res.json()) .then(data => { users = data; oBody.innerHTML = data.map(user => <tr> <td>${user.id}</td> <td>${user.name}</td> <td>${user.hometown}</td> </tr> ).join(""); });


-   从 `http://localhost:3001/users` 获取用户列表(假设返回数组);
-   将数据存入全局变量 `users`,供后续 AI 请求使用;
-   使用 `Array.prototype.map()` 生成表格行,高效且可读性强;
-   **字段一致性**:代码使用 `user.name`,需确保后端返回字段名一致(而非 `username` 等)。

* * *

## 四、系统架构与工作流

整个应用依赖两个本地服务:

1.  **数据服务**`json-server`    ```
    json-server --watch users.json --port 3001
    ```

    -   提供 RESTful API;
    -   无需数据库,JSON 文件即数据源。

1.  **AI 服务**(Node.js + OpenAI)

    -   接收 `question` 和 `data`    -   构造 Prompt 调用大模型;
    -   返回结构化答案。

**用户操作流程**1.  页面加载 → 自动请求 `/users` → 渲染表格;
1.  用户输入问题 → 点击提交;
1.  前端拼接 URL → 请求 `http://localhost:1314/...`1.  AI 服务调用 LLM → 返回 `{ result: "韩梅梅" }`1.  前端显示结果。

* * *

## 五、总结:小代码,大意义

这段看似简单的代码,实则体现了现代 Web 开发的三大趋势:

1.  **轻量化全栈**:无需复杂后端,用工具链快速搭建 MVP;
1.  **AI 原生集成**:将大模型作为“智能函数”嵌入业务流;
1.  **开发者效能革命**:一人即可完成从前端到智能服务的全流程。

尽管存在安全、健壮性、可扩展性等方面的不足,但它完美诠释了 **“用最小成本验证最大价值”** 的产品哲学。对于学习者,它是理解前后端通信、API 设计、Prompt Engineering 的绝佳范例;对于从业者,它是构建内部工具、智能助手的高效起点。

未来,随着 AI 工具链的进一步成熟,“全干工程师”将不再是调侃,而是新常态——而这一切,或许就始于这样一个小小的 HTML 文件。