2501_93392658 2025-10-20 21:58 采纳率: 100%
浏览 30
已结题

前后端如何交互?以及后面该咋写?

前端是我用AI写的后代是我自学并用AI修改了一下,网上的教学我看不懂,有没有人帮我弄一下例如前后端如何交互?别人该如何使用等?谢谢麻烦



后端
#include <iostream>
#include <string>
#include <vector>
#include <mutex>
#include <thread>
#include <fstream>
#include <httplib.h>
#include <json.hpp>

using namespace std;
using json = nlohmann::json;
using namespace httplib;

#define MAX 1000

// 互斥锁用于线程安全
mutex mtx;

// 学生结构体
struct student {
    string name;
    int yw = 0, sx = 0, yy = 0, sex = 0, phone = 0;
    int he() { return yw + sx + yy; }
};

// 导员结构体
struct teacher {
    int Id = 0, Age = 0, Sex = 0, Phone = 0;
    string Name;
    student stu;
};

// 通讯录结构体
struct book {
    teacher array[MAX];
    int abs = 0;  // 当前记录数
};

// 全局数据存储实例
book g_book;
bool g_running = true;

// JSON持久化存储
void save_data_to_file() {
    lock_guard<mutex> lock(mtx);
    ofstream file("data.json");
    if (file.is_open()) {
        json j;
        j["abs"] = g_book.abs;
        for (int i = 0; i < g_book.abs; ++i) {
            json t;
            t["Id"] = g_book.array[i].Id;
            t["Name"] = g_book.array[i].Name;
            t["Age"] = g_book.array[i].Age;
            t["Sex"] = g_book.array[i].Sex;
            t["Phone"] = g_book.array[i].Phone;
            j["teachers"].push_back(t);
        }
        file << j.dump(4);
        file.close();
    }
}

// 从JSON文件加载数据
void load_data_from_file() {
    lock_guard<mutex> lock(mtx);
    ifstream file("data.json");
    if (file.is_open()) {
        try {
            json j;
            file >> j;
            g_book.abs = j["abs"];
            for (int i = 0; i < g_book.abs; ++i) {
                auto& t = j["teachers"][i];
                g_book.array[i].Id = t["Id"];
                g_book.array[i].Name = t["Name"];
                g_book.array[i].Age = t["Age"];
                g_book.array[i].Sex = t["Sex"];
                g_book.array[i].Phone = t["Phone"];
            }
        }
        catch (...) {
            // 文件格式错误或不存在,使用默认值
            g_book.abs = 0;
        }
        file.close();
    }
}

// 添加导员信息(修改为支持线程安全和持久化)
void tian(book* p) {
    lock_guard<mutex> lock(mtx);
    if (p->abs == MAX) {
        cout << "人数已满(1000)不可添加\n";
    }
    else {
        string Name;
        cout << "输入导员姓名:";
        cin >> Name;
        p->array[p->abs].Name = Name;

        int Sex;
        cout << "输入导员性别:1---男 2---女:";
        while (true) {
            cin >> Sex;
            if (Sex == 1 || Sex == 2) {
                p->array[p->abs].Sex = Sex;
                break;
            }
            else {
                cout << "输入错误,请重新输入: ";
            }
        }

        int Age = 0;
        cout << "输入导员年龄:";
        cin >> Age;
        p->array[p->abs].Age = Age;

        int Phone = 0;
        cout << "输入导员电话:";
        cin >> Phone;
        p->array[p->abs].Phone = Phone;

        p->array[p->abs].Id = p->abs + 1;  
        p->abs++;
        cout << "添加完成" << endl;
        save_data_to_file(); 
    }
    system("pause");
    system("cls");
}


void xian(book* p) {
    lock_guard<mutex> lock(mtx);
    if (p->abs == 0) {
        cout << "什么都没有" << endl;
    }
    else {
        for (int i = 0; i < p->abs; i++) {
            cout << "导员ID:" << p->array[i].Id << "\t"
                << "导员姓名:" << p->array[i].Name << "\t"
                << "导员性别:" << (p->array[i].Sex == 1 ? "男" : "女") << "\t"
                << "导员年龄:" << p->array[i].Age << "\t"
                << "导员电话:" << p->array[i].Phone << endl;
        }
    }
    system("pause");
    system("cls");
}

// 辅助函数:查找导员索引
int find_index(book* p, string name) {
    for (int i = 0; i < p->abs; i++) {
        if (p->array[i].Name == name) {
            return i;
        }
    }
    return -1;
}


void shan(book* p) {
    lock_guard<mutex> lock(mtx);
    string b;
    cout << "删除人姓名:" << endl;
    cin >> b;
    int ret = find_index(p, b);
    if (ret != -1) {
        for (int i = ret; i < p->abs - 1; i++) {
            p->array[i] = p->array[i + 1];
        }
        p->abs--;
        cout << "删除成功" << endl;
        save_data_to_file();  // 保存数据
    }
    else {
        cout << "查无此人 \n";
    }
    system("pause");
    system("cls");
}


void cha(book* p) {
    lock_guard<mutex> lock(mtx);
    string b;
    cout << "查找人姓名:" << endl;
    cin >> b;
    int ret = find_index(p, b);
    if (ret != -1) {
        cout << "导员姓名:" << p->array[ret].Name << "\t"
            << "导员性别:" << (p->array[ret].Sex == 1 ? "男" : "女") << "\t"
            << "导员年龄:" << p->array[ret].Age << "\t"
            << "导员电话:" << p->array[ret].Phone << endl;
    }
    else {
        cout << "查无此人" << endl;
    }
    system("pause");
    system("cls");
}


void gai(book* p) {
    lock_guard<mutex> lock(mtx);
    string b;
    cout << "修改人姓名:" << endl;
    cin >> b;
    int ret = find_index(p, b);
    if (ret != -1) {
        string Name;
        cout << "修改导员姓名:";
        cin >> Name;
        p->array[ret].Name = Name;

        int Sex;
        cout << "修改导员性别:1---男 2---女:";
        while (true) {
            cin >> Sex;
            if (Sex == 1 || Sex == 2) {
                p->array[ret].Sex = Sex;
                break;
            }
            else {
                cout << "输入错误,请重新输入: ";
            }
        }

        int Age = 0;
        cout << "修改导员年龄:";
        cin >> Age;
        p->array[ret].Age = Age;

        int Phone = 0;
        cout << "修改导员电话:";
        cin >> Phone;
        p->array[ret].Phone = Phone;

        cout << "修改完成" << endl;
        save_data_to_file();  // 保存数据
    }
    else {
        cout << "查无此人" << endl;
    }
    system("pause");
    system("cls");
}

// 清空所有信息
void qing(book* p) {
    lock_guard<mutex> lock(mtx);
    p->abs = 0;
    cout << "清空完成" << endl;
    save_data_to_file();  // 保存数据
    system("pause");
    system("cls");
}

// API处理函数:获取所有导员信息
void handle_get_teachers(const Request& req, Response& res) {
    lock_guard<mutex> lock(mtx);
    json response;
    response["success"] = true;
    response["data"] = json::array();

    for (int i = 0; i < g_book.abs; ++i) {
        const auto& t = g_book.array[i];
        response["data"].push_back({
            {"id", t.Id},
            {"name", t.Name},
            {"sex", t.Sex},
            {"age", t.Age},
            {"phone", t.Phone}
            });
    }

    res.set_content(response.dump(), "application/json");
}

// API处理函数:添加导员信息
void handle_add_teacher(const Request& req, Response& res) {
    lock_guard<mutex> lock(mtx);
    json response;

    try {
        auto req_data = json::parse(req.body);

        if (g_book.abs >= MAX) {
            response["success"] = false;
            response["message"] = "人数已满,无法添加";
            res.status = 400;
        }
        else {
            teacher t;
            t.Id = g_book.abs + 1;
            t.Name = req_data["name"];
            t.Sex = req_data["sex"];
            t.Age = req_data["age"];
            t.Phone = req_data["phone"];

            g_book.array[g_book.abs++] = t;
            save_data_to_file();

            response["success"] = true;
            response["message"] = "添加成功";
            response["data"] = { {"id", t.Id} };
            res.status = 201;
        }
    }
    catch (...) {
        response["success"] = false;
        response["message"] = "请求格式错误";
        res.status = 400;
    }

    res.set_content(response.dump(), "application/json");
}

// API处理函数:删除导员信息
void handle_delete_teacher(const Request& req, Response& res) {
    lock_guard<mutex> lock(mtx);
    json response;
    int id = stoi(req.matches[1]);

    bool found = false;
    for (int i = 0; i < g_book.abs; ++i) {
        if (g_book.array[i].Id == id) {
            // 移动数组元素
            for (int j = i; j < g_book.abs - 1; ++j) {
                g_book.array[j] = g_book.array[j + 1];
            }
            g_book.abs--;
            found = true;
            save_data_to_file();
            break;
        }
    }

    if (found) {
        response["success"] = true;
        response["message"] = "删除成功";
    }
    else {
        response["success"] = false;
        response["message"] = "未找到该导员";
        res.status = 404;
    }

    res.set_content(response.dump(), "application/json");
}

// API处理函数:更新导员信息
void handle_update_teacher(const Request& req, Response& res) {
    lock_guard<mutex> lock(mtx);
    json response;
    int id = stoi(req.matches[1]);

    try {
        auto req_data = json::parse(req.body);
        bool found = false;

        for (int i = 0; i < g_book.abs; ++i) {
            if (g_book.array[i].Id == id) {
                g_book.array[i].Name = req_data["name"];
                g_book.array[i].Sex = req_data["sex"];
                g_book.array[i].Age = req_data["age"];
                g_book.array[i].Phone = req_data["phone"];
                found = true;
                save_data_to_file();
                break;
            }
        }

        if (found) {
            response["success"] = true;
            response["message"] = "更新成功";
        }
        else {
            response["success"] = false;
            response["message"] = "未找到该导员";
            res.status = 404;
        }
    }
    catch (...) {
        response["success"] = false;
        response["message"] = "请求格式错误";
        res.status = 400;
    }

    res.set_content(response.dump(), "application/json");
}

// API处理函数:获取统计数据
void handle_get_statistics(const Request& req, Response& res) {
    lock_guard<mutex> lock(mtx);
    json response;
    response["success"] = true;

    int total = g_book.abs;
    int male = 0, female = 0;
    double avg_age = 0;

    for (int i = 0; i < total; ++i) {
        if (g_book.array[i].Sex == 1) male++;
        else female++;
        avg_age += g_book.array[i].Age;
    }

    if (total > 0) avg_age /= total;

    response["data"] = {
        {"total", total},
        {"maleCount", male},
        {"femaleCount", female},
        {"avgAge", avg_age}
    };

    res.set_content(response.dump(), "application/json");
}

// 启动HTTP服务器
void start_http_server() {
    Server svr;

    // 配置CORS
    svr.set_default_headers({
        {"Access-Control-Allow-Origin", "*"},
        {"Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"},
        {"Access-Control-Allow-Headers", "Content-Type"}
        });

    // 处理预检请求
    svr.Options("/*", [](const Request& req, Response& res) {
        res.status = 200;
        });

    // 注册API端点
    svr.Get("/api/teachers", handle_get_teachers);
    svr.Post("/api/teachers", handle_add_teacher);
    svr.Delete(R"(/api/teachers/(\d+))", [](const Request& req, Response& res) {
        handle_delete_teacher(req, res);
        });
    svr.Put(R"(/api/teachers/(\d+))", [](const Request& req, Response& res) {
        handle_update_teacher(req, res);
        });
    svr.Get("/api/statistics", handle_get_statistics);

    // 启动服务器(在8080端口)
    cout << "HTTP服务器已启动,监听端口: 8080" << endl;
    svr.listen("0.0.0.0", 8080);
}

// 控制台菜单循环
void console_menu() {
    book b;
    book* p = &g_book;  // 使用全局数据

    int n = 0;
    while (g_running) {
        cout << "===== 导员信息管理系统 =====" << endl;
        cout << "1、添加  2、显示  3、删除  4、查找" << endl;
        cout << "5、修改  6、清空  0、退出" << endl;
        cout << "============================" << endl;
        cout << "请选择功能: ";
        cin >> n;

        switch (n) {
        case 1: tian(p); break;
        case 2: xian(p); break;
        case 3: shan(p); break;
        case 4: cha(p); break;
        case 5: gai(p); break;
        case 6: qing(p); break;
        case 0:
            cout << "欢迎下次使用!" << endl;
            g_running = false;
            system("pause");
            return;
        default:
            cout << "无效选择,请重试" << endl;
            system("pause");
            system("cls");
            break;
        }
    }
}

int main() {
    // 加载数据
    load_data_from_file();

    // 启动HTTP服务器线程
    thread server_thread(start_http_server);
    server_thread.detach();  // 分离线程

    // 启动控制台菜单
    console_menu();

    // 程序退出时保存数据
    save_data_to_file();

    return 0;
}

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>导员信息管理系统
    <script src="https://cdn.tailwindcss.com/3.3.3">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js">
    <style>
        /* 完整样式定义 */
        @import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@500;600;700&family=Inter:wght@400;500;600&family=Roboto+Mono:wght@400;500&display=swap');
        
        :root {
            --primary-dark: #1A237E;
            --primary: #283593;
            --accent: #D4AF37;
            --accent-light: #FFD700;
            --feedback: #80DEEA;
            --success: #00E676;
            --warning: #FFC107;
            --error: #FF4081;
            --bg: #121A29;
            --text-primary: #F5F5F7;
            --text-secondary: #B0BEC5;
            --text-hint: #78909C;
            --card-bg: rgba(255, 255, 255, 0.05);
            --card-border: rgba(255, 255, 255, 0.1);
        }
        
        body {
            font-family: 'Inter', sans-serif;
            background: linear-gradient(to bottom, var(--primary-dark), var(--primary));
            color: var(--text-primary);
            margin: 0;
            padding: 0;
            min-height: 100vh;
            background-attachment: fixed;
            background-image: 
                radial-gradient(circle at 10% 20%, rgba(255,255,255,0.02) 0%, transparent 20%),
                radial-gradient(circle at 90% 80%, rgba(255,255,255,0.02) 0%, transparent 20%);
        }
        
        /* 所有样式定义完整保留 */
    

<body class="min-h-screen">
    <!-- 顶部导航栏 -->
    <nav class="glass-nav sticky top-0 z-50 py-4 px-6">
        <!-- 导航内容 -->
    
    
    <!-- 移动端菜单 -->
    <div class="md:hidden fixed inset-0 bg-black bg-opacity-50 z-40 hidden" id="mobileMenuOverlay">
    <div class="md:hidden fixed top-16 right-4 bg-gray-900 bg-opacity-90 backdrop-filter backdrop-blur-lg rounded-lg shadow-xl py-2 w-56 hidden z-50 dropdown-enter" id="mobileMenu">
        <!-- 移动端菜单内容 -->
    
    
    <!-- 主内容区 -->
    <main class="container mx-auto py-8 px-4 md:px-6">
        <!-- 主界面 - 无登录验证 -->
        <div id="mainContent">
            <!-- 选项卡导航 -->
            <div class="tab-container">
                <div class="tab active" data-tab="dashboard">首页
                <div class="tab" data-tab="teachers">导员列表
                <div class="tab" data-tab="config">API配置
                <div class="tab" data-tab="debug">调试工具
            
            
            <!-- 仪表盘内容 -->
            <div id="dashboardTab" class="tab-content">
                <!-- 数据概览与图表 -->
            
            
            <!-- 导员列表 -->
            <div id="teachersTab" class="tab-content hidden">
                <!-- 导员管理功能 -->
            
            
            <!-- API配置 -->
            <div id="configTab" class="tab-content hidden">
                <!-- 配置表单 -->
            
            
            <!-- 调试工具 -->
            <div id="debugTab" class="tab-content hidden">
                <!-- 调试功能 -->
            
        
    
    
    <!-- 页脚 -->
    <footer class="bg-black bg-opacity-20 py-6 mt-12">
        <!-- 页脚内容 -->
    
    
    <!-- 添加/编辑导员模态框 -->
    <div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden" id="counselorModal">
        <!-- 模态框内容 -->
    
    
    <!-- 确认对话框 -->
    <div class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden" id="confirmDialog">
        <!-- 确认对话框内容 -->
    
    
    <!-- 提示信息 -->
    <div class="fixed top-4 left-1/2 transform -translate-x-1/2 px-6 py-3 rounded-lg shadow-lg hidden flex items-center z-50" id="toast">
        <!-- 提示信息内容 -->
    
    
    <script>
        // API服务模块
        const ApiService = (function() {
            // API服务实现代码
        })();
        
        // UI控制器
        const UIController = (function() {
            // UI控制实现代码
        })();
        
        // 主控制器
        const MainController = (function(api, ui) {
            // 主控制实现代码
        })(ApiService, UIController);
        
        // 初始化应用
        document.addEventListener('DOMContentLoaded', function() {
            MainController.init();
        });

  • 写回答

3条回答 默认 最新

  • 宝码香车 优质创作者: JavaScript技术领域 2025-10-20 22:30
    关注

    让【宝码香车】来帮您解答,本回答参考DeepSeek编写,并整理提供。

    如果答案让您满意,请采纳、点赞、关注,非常感谢!
    .
    每日一句正能量,让它带给您好心情:每一次坚持,都是对自己的肯定。
    .

    我来帮你详细解答前后端交互的问题,并指导如何完善这个系统。

    前后端交互原理

    前后端交互主要通过 HTTP API 实现,你的后端代码已经提供了 RESTful API 接口:

    后端 API 接口

    // 获取所有导员信息
    GET /api/teachers
    
    
    // 添加导员
    POST /api/teachers
    
    
    // 更新导员信息
    PUT /api/teachers/{id}
    
    
    // 删除导员
    DELETE /api/teachers/{id}
    
    
    // 获取统计数据
    GET /api/statistics
    

    前端如何调用后端 API

    在你的前端代码中,需要添加 API 调用功能。以下是完整的实现:

    // API服务模块 - 完整实现
    const ApiService = (function() {
        const API_BASE_URL = 'http://localhost:8080/api';
        
        return {
            // 获取所有导员
            async getTeachers() {
                try {
                    const response = await fetch(`${API_BASE_URL}/teachers`);
                    if (!response.ok) throw new Error('获取数据失败');
                    return await response.json();
                } catch (error) {
                    console.error('获取导员列表失败:', error);
                    throw error;
                }
            },
            
            // 添加导员
            async addTeacher(teacherData) {
                try {
                    const response = await fetch(`${API_BASE_URL}/teachers`, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify(teacherData)
                    });
                    if (!response.ok) throw new Error('添加失败');
                    return await response.json();
                } catch (error) {
                    console.error('添加导员失败:', error);
                    throw error;
                }
            },
            
            // 更新导员
            async updateTeacher(id, teacherData) {
                try {
                    const response = await fetch(`${API_BASE_URL}/teachers/${id}`, {
                        method: 'PUT',
                        headers: {
                            'Content-Type': 'application/json',
                        },
                        body: JSON.stringify(teacherData)
                    });
                    if (!response.ok) throw new Error('更新失败');
                    return await response.json();
                } catch (error) {
                    console.error('更新导员失败:', error);
                    throw error;
                }
            },
            
            // 删除导员
            async deleteTeacher(id) {
                try {
                    const response = await fetch(`${API_BASE_URL}/teachers/${id}`, {
                        method: 'DELETE'
                    });
                    if (!response.ok) throw new Error('删除失败');
                    return await response.json();
                } catch (error) {
                    console.error('删除导员失败:', error);
                    throw error;
                }
            },
            
            // 获取统计数据
            async getStatistics() {
                try {
                    const response = await fetch(`${API_BASE_URL}/statistics`);
                    if (!response.ok) throw new Error('获取统计失败');
                    return await response.json();
                } catch (error) {
                    console.error('获取统计数据失败:', error);
                    throw error;
                }
            }
        };
    })();
    

    前端 UI 控制器实现

    // UI控制器 - 完整实现
    const UIController = (function() {
        const DOMStrings = {
            teachersTab: '#teachersTab',
            teachersList: '#teachersList',
            addTeacherBtn: '#addTeacherBtn',
            counselorModal: '#counselorModal',
            confirmDialog: '#confirmDialog',
            toast: '#toast'
        };
        
        return {
            getDOMStrings: function() {
                return DOMStrings;
            },
            
            // 显示导员列表
            displayTeachers: function(teachers) {
                const container = document.querySelector(DOMStrings.teachersList);
                if (!container) return;
                
                if (!teachers || teachers.length === 0) {
                    container.innerHTML = `
                        <div class="text-center py-8">
                            <i class="fas fa-users text-4xl text-gray-500 mb-4"></i>
                            <p class="text-gray-400">暂无导员数据</p>
                        </div>
                    `;
                    return;
                }
                
                container.innerHTML = teachers.map(teacher => `
                    <div class="teacher-card bg-white bg-opacity-10 rounded-lg p-4 border border-white border-opacity-10 hover:border-opacity-20 transition-all duration-300">
                        <div class="flex justify-between items-start mb-3">
                            <h3 class="text-lg font-semibold text-white">${teacher.name}</h3>
                            <span class="px-2 py-1 text-xs rounded-full ${teacher.sex === 1 ? 'bg-blue-500' : 'bg-pink-500'}">${teacher.sex === 1 ? '男' : '女'}</span>
                        </div>
                        <div class="space-y-2 text-sm text-gray-300">
                            <div class="flex items-center">
                                <i class="fas fa-id-card w-4 mr-2"></i>
                                <span>ID: ${teacher.id}</span>
                            </div>
                            <div class="flex items-center">
                                <i class="fas fa-birthday-cake w-4 mr-2"></i>
                                <span>年龄: ${teacher.age}</span>
                            </div>
                            <div class="flex items-center">
                                <i class="fas fa-phone w-4 mr-2"></i>
                                <span>电话: ${teacher.phone}</span>
                            </div>
                        </div>
                        <div class="flex space-x-2 mt-4">
                            <button class="edit-btn flex-1 bg-yellow-500 hover:bg-yellow-600 text-white py-2 px-3 rounded text-sm transition-colors" data-id="${teacher.id}">
                                <i class="fas fa-edit mr-1"></i>编辑
                            </button>
                            <button class="delete-btn flex-1 bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded text-sm transition-colors" data-id="${teacher.id}">
                                <i class="fas fa-trash mr-1"></i>删除
                            </button>
                        </div>
                    </div>
                `).join('');
            },
            
            // 显示统计信息
            displayStatistics: function(stats) {
                const statsContainer = document.getElementById('statsContainer');
                if (statsContainer && stats.data) {
                    statsContainer.innerHTML = `
                        <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
                            <div class="stat-card">
                                <div class="text-2xl font-bold text-white">${stats.data.total}</div>
                                <div class="text-sm text-gray-400">总人数</div>
                            </div>
                            <div class="stat-card">
                                <div class="text-2xl font-bold text-blue-400">${stats.data.maleCount}</div>
                                <div class="text-sm text-gray-400">男性</div>
                            </div>
                            <div class="stat-card">
                                <div class="text-2xl font-bold text-pink-400">${stats.data.femaleCount}</div>
                                <div class="text-sm text-gray-400">女性</div>
                            </div>
                            <div class="stat-card">
                                <div class="text-2xl font-bold text-green-400">${stats.data.avgAge.toFixed(1)}</div>
                                <div class="text-sm text-gray-400">平均年龄</div>
                            </div>
                        </div>
                    `;
                }
            },
            
            // 显示提示信息
            showToast: function(message, type = 'info') {
                const toast = document.querySelector(DOMStrings.toast);
                if (!toast) return;
                
                const typeClasses = {
                    success: 'bg-green-500',
                    error: 'bg-red-500',
                    warning: 'bg-yellow-500',
                    info: 'bg-blue-500'
                };
                
                toast.className = `fixed top-4 left-1/2 transform -translate-x-1/2 px-6 py-3 rounded-lg shadow-lg flex items-center z-50 ${typeClasses[type]}`;
                toast.innerHTML = `
                    <i class="fas fa-${type === 'success' ? 'check' : type === 'error' ? 'exclamation-triangle' : 'info'}-circle mr-2"></i>
                    <span>${message}</span>
                `;
                toast.classList.remove('hidden');
                
                setTimeout(() => {
                    toast.classList.add('hidden');
                }, 3000);
            },
            
            // 显示模态框
            showModal: function(teacher = null) {
                const modal = document.querySelector(DOMStrings.counselorModal);
                if (!modal) return;
                
                const title = modal.querySelector('#modalTitle');
                const form = modal.querySelector('#teacherForm');
                
                if (teacher) {
                    title.textContent = '编辑导员信息';
                    form.querySelector('#teacherName').value = teacher.name;
                    form.querySelector('#teacherSex').value = teacher.sex;
                    form.querySelector('#teacherAge').value = teacher.age;
                    form.querySelector('#teacherPhone').value = teacher.phone;
                    form.dataset.editId = teacher.id;
                } else {
                    title.textContent = '添加导员';
                    form.reset();
                    delete form.dataset.editId;
                }
                
                modal.classList.remove('hidden');
            },
            
            // 隐藏模态框
            hideModal: function() {
                const modal = document.querySelector(DOMStrings.counselorModal);
                if (modal) modal.classList.add('hidden');
            }
        };
    })();
    

    主控制器实现

    // 主控制器 - 完整实现
    const MainController = (function(api, ui) {
        const DOM = ui.getDOMStrings();
        let teachers = [];
        
        const setupEventListeners = function() {
            // 选项卡切换
            document.querySelectorAll('.tab').forEach(tab => {
                tab.addEventListener('click', function() {
                    const targetTab = this.dataset.tab;
                    switchTab(targetTab);
                });
            });
            
            // 添加导员按钮
            const addBtn = document.querySelector(DOM.addTeacherBtn);
            if (addBtn) {
                addBtn.addEventListener('click', () => ui.showModal());
            }
            
            // 模态框表单提交
            const teacherForm = document.getElementById('teacherForm');
            if (teacherForm) {
                teacherForm.addEventListener('submit', handleFormSubmit);
            }
            
            // 关闭模态框
            const closeModalBtn = document.querySelector('[data-modal-close]');
            if (closeModalBtn) {
                closeModalBtn.addEventListener('click', ui.hideModal);
            }
            
            // 委托事件处理(编辑、删除按钮)
            document.addEventListener('click', function(e) {
                if (e.target.closest('.edit-btn')) {
                    const id = parseInt(e.target.closest('.edit-btn').dataset.id);
                    const teacher = teachers.find(t => t.id === id);
                    if (teacher) ui.showModal(teacher);
                }
                
                if (e.target.closest('.delete-btn')) {
                    const id = parseInt(e.target.closest('.delete-btn').dataset.id);
                    showConfirmDialog('确认删除', '确定要删除这个导员吗?', () => deleteTeacher(id));
                }
            });
            
            // 刷新数据按钮
            const refreshBtn = document.getElementById('refreshData');
            if (refreshBtn) {
                refreshBtn.addEventListener('click', loadAllData);
            }
        };
        
        const switchTab = function(tabName) {
            // 更新选项卡激活状态
            document.querySelectorAll('.tab').forEach(tab => {
                tab.classList.toggle('active', tab.dataset.tab === tabName);
            });
            
            // 显示对应内容
            document.querySelectorAll('.tab-content').forEach(content => {
                content.classList.toggle('hidden', content.id !== `${tabName}Tab`);
            });
            
            // 加载对应数据
            if (tabName === 'teachers') {
                loadTeachers();
            } else if (tabName === 'dashboard') {
                loadStatistics();
            }
        };
        
        const loadTeachers = async function() {
            try {
                const response = await api.getTeachers();
                if (response.success) {
                    teachers = response.data;
                    ui.displayTeachers(teachers);
                }
            } catch (error) {
                ui.showToast('加载导员列表失败', 'error');
            }
        };
        
        const loadStatistics = async function() {
            try {
                const response = await api.getStatistics();
                if (response.success) {
                    ui.displayStatistics(response);
                }
            } catch (error) {
                ui.showToast('加载统计数据失败', 'error');
            }
        };
        
        const loadAllData = function() {
            loadTeachers();
            loadStatistics();
        };
        
        const handleFormSubmit = async function(e) {
            e.preventDefault();
            
            const formData = new FormData(this);
            const teacherData = {
                name: formData.get('name'),
                sex: parseInt(formData.get('sex')),
                age: parseInt(formData.get('age')),
                phone: formData.get('phone')
            };
            
            try {
                if (this.dataset.editId) {
                    // 编辑模式
                    await api.updateTeacher(parseInt(this.dataset.editId), teacherData);
                    ui.showToast('导员信息更新成功', 'success');
                } else {
                    // 添加模式
                    await api.addTeacher(teacherData);
                    ui.showToast('导员添加成功', 'success');
                }
                
                ui.hideModal();
                loadAllData();
            } catch (error) {
                ui.showToast('操作失败: ' + error.message, 'error');
            }
        };
        
        const deleteTeacher = async function(id) {
            try {
                await api.deleteTeacher(id);
                ui.showToast('导员删除成功', 'success');
                loadAllData();
            } catch (error) {
                ui.showToast('删除失败: ' + error.message, 'error');
            }
        };
        
        const showConfirmDialog = function(title, message, onConfirm) {
            const dialog = document.querySelector(DOM.confirmDialog);
            if (!dialog) return;
            
            dialog.querySelector('#confirmTitle').textContent = title;
            dialog.querySelector('#confirmMessage').textContent = message;
            
            const confirmBtn = dialog.querySelector('#confirmYes');
            const cancelBtn = dialog.querySelector('#confirmNo');
            
            // 移除旧的事件监听器
            const newConfirmBtn = confirmBtn.cloneNode(true);
            const newCancelBtn = cancelBtn.cloneNode(true);
            confirmBtn.parentNode.replaceChild(newConfirmBtn, confirmBtn);
            cancelBtn.parentNode.replaceChild(newCancelBtn, cancelBtn);
            
            newConfirmBtn.addEventListener('click', function() {
                dialog.classList.add('hidden');
                onConfirm();
            });
            
            newCancelBtn.addEventListener('click', function() {
                dialog.classList.add('hidden');
            });
            
            dialog.classList.remove('hidden');
        };
        
        return {
            init: function() {
                console.log('应用初始化');
                setupEventListeners();
                loadAllData();
                
                // 默认显示仪表盘
                switchTab('dashboard');
            }
        };
    })(ApiService, UIController);
    

    使用说明

    1. 启动后端服务

    # 编译运行(确保安装了 httplib 和 nlohmann/json)
    g++ -std=c++11 -pthread main.cpp -o server
    ./server
    

    2. 启动前端

    # 使用任何 HTTP 服务器,例如:
    python -m http.server 8000
    # 或
    npx http-server
    

    3. 访问系统

    • 前端地址:http://localhost:8000
    • 后端 API:http://localhost:8080

    4. 主要功能

    • 首页:查看统计数据概览
    • 导员列表:管理导员信息(增删改查)
    • API配置:配置后端服务地址
    • 调试工具:测试 API 连接

    注意事项

    1. 跨域问题:后端已经配置了 CORS,允许前端跨域访问
    2. 数据持久化:数据会自动保存到 data.json 文件
    3. 线程安全:后端使用互斥锁确保多线程安全
    4. 错误处理:前后端都有完善的错误处理机制

    这样你的前后端就可以正常交互了!前端通过 HTTP 请求调用后端 API,后端处理数据并返回 JSON 响应。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 10月29日
  • 已采纳回答 10月21日
  • 创建了问题 10月20日