FirstAssignment_832201319尚天翼

832201319尚天翼 2024-10-31 17:52:28

Front-End and Back-End Separation Contacts Programming Assignment

Course for This Assignment2401_MU_SE_FZU
Student IDFZU:832201319 MU:22125329
Assignment RequirementsDesign a front-end and back-end separated contact
Objectives of This AssignmentExercise independent learning ability and learn the basic knowledge of software development

Git Repository Link and Code Standards

Assignment Description

This assignment requires the development of a contact management system with a clear separation between the front-end and back-end components. The application must support basic CRUD (Create, Read, Update, Delete) operations on contact information, allowing users to manage contact data stored in a back-end database. Here are the main requirements and goals:

  1. Core Functionalities:

    • Add Contact: Allows users to create new contacts with details such as name, gender, phone number, and remarks.

    • Modify Contact: Enables editing of contact details by retrieving the current data directly from the database.

    • Delete Contact: Provides the option to delete contacts from the database.

    • View Contacts(Additional Features): Retrieves and displays all contacts stored in the back-end database.

  2. Front-End Requirements:

    • Develop an interactive user interface that allows users to add, edit, delete, and view contacts.

    • Use HTML, CSS, and JavaScript to build the UI, ensuring that it communicates with the back end through RESTful API calls.

  3. Back-End Requirements:

    • Implement the back-end using Spring Boot, ensuring it provides RESTful APIs to support all required operations.

    • Use Java and JPA (Java Persistence API) for database operations, with a Contact entity that includes fields for ID, name, gender, phone number, and remarks

    The main objective is to develop a functional, interactive, and scalable contact management system while practicing full-stack development principles with front-end and back-end separation.

 

PSP Table

TaskEstimated Time (hours)Actual Time (hours)
Requirement Analysis22
Design22.5
Front-End Development67
Back-End Development88.5
Testing22.5
Deployment11
Documentation and Blogging11
Total2224.5

 

Present Finished Product

1. Add

Initially, there is no contact information in either our database or the front-end page.

 

Then, we click the add button at the top right corner of the front-end page to open the add contact modal. We enter the relevant information and then click save.

 

The contact information appears on both the front-end page and in the database, indicating that the addition was successful.

 

2. Modify

On the front-end page, click the three dots in the top right corner of a contact to open the delete and edit menu.

 

Click edit, modify the contact information in the popup modal, and then click confirm.

 

The content on both the front-end page and in the database has been successfully updated.

 

3. Delete

On the front-end page, click the three dots in the top right corner of a contact to open the delete and edit menu, and then click delete.

 

The contact has been successfully deleted from both the front-end page and the database.

 

 

4. display

When multiple contacts exist in the database, we use a display function to show all contact information on the front-end page, allowing users to add, delete, view, and modify multiple contacts.

 

 

Design and Implementation Process

  1. Requirements Gathering

    • Identify the core objectives and functionalities of the software.

    • Engage stakeholders through interviews and surveys to gather insights on user needs.

    • Document use cases to understand user interactions with the system.

  2. System Design

    • Architecture Design: Choose an architectural style (e.g., microservices, monolithic) that best fits the project requirements.

    • Database Design: Create an Entity-Relationship Diagram (ERD) to define the data structure, relationships, and constraints. Choose a suitable database management system (SQL or NoSQL).

    • User Interface (UI) Design: Develop wireframes and mockups using tools like Figma or Adobe XD. Focus on usability, accessibility, and aesthetics.

  3. Functional Specification

    • Develop a detailed functional specification document that describes each feature, its inputs, outputs, and how it interacts with other components.

    • Define performance requirements and security measures, ensuring data protection and compliance with regulations.

  4. Implementation

    • Development Environment Setup: Configure the necessary development tools, version control systems (e.g., Git), and project management software (e.g., Jira).

    • Coding: Follow coding standards and guidelines. Implement features in iterative cycles (sprints), focusing on unit tests to ensure code quality.

    • Integration: Continuously integrate and test components as they are developed. Use Continuous Integration/Continuous Deployment (CI/CD) tools to automate the deployment process.

  5. Testing

    • Conduct various testing phases: unit testing, integration testing, system testing, and user acceptance testing (UAT).

    • Identify and fix bugs or issues found during testing to ensure functionality and performance meet the specified requirements.

  6. Deployment

    • Prepare for deployment by creating deployment scripts and ensuring all configurations are correct.

    • Deploy the application in a production environment. Monitor system performance and resolve any post-deployment issues.

  7. Maintenance and Updates

    • Continuously monitor the application for bugs and performance issues. Provide regular updates and enhancements based on user feedback.

    • Plan for periodic evaluations to adapt the software to changing requirements or technological advancements.

Functional Structure Diagram

The functional structure diagram outlines the main components and their relationships within the system. Below is a simplified example of how such a diagram might look:

 

 

Explanation of Components

  1. User Interface: This is the layer that interacts directly with the users. It can be a web application, mobile app, or both, designed based on the UI/UX guidelines established in the design phase.

  2. Application Server: This layer handles requests from the user interface and routes them to the appropriate services. It serves as a mediator between the frontend and the business logic layer.

  3. Business Logic Layer: This component contains the core functionality of the application, implementing the business rules and workflows as defined in the functional specifications.

  4. Data Access Layer: Responsible for communication with the database. This layer abstracts the details of data storage and retrieval, allowing for easier maintenance and potential changes to the database system.

  5. Database: The backend data storage system where all application data is stored, managed, and retrieved.

     

Code explanation

backend:

package com.sty.entity;
​
import javax.persistence.*;
​
@Entity
public class Contact {
​
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
​
    private String name;
    private String gender;
    private String phoneNumber;
    // 添加 remarks 字段
    private String remarks;
​
    // Constructors, Getters, and Setters
​
    public Contact() {}
​
    public Contact(String name, String phoneNumber, String remarks,String gender) {
        this.name = name;
        this.phoneNumber = phoneNumber;
        this.remarks = remarks;
        this.gender = gender;
    }
​
    public Long getId() {
        return id;
    }
​
    public void setId(Long id) {
        this.id = id;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public String getPhoneNumber() {
        return phoneNumber;
    }
​
    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
​
    public String getRemarks() {
        return remarks;
    }
​
    public void setRemarks(String remarks) {
        this.remarks = remarks;
    }
​
    public String getGender() {
        return gender;
    }
​
    public void setGender(String gender) {
        this.gender = gender;
    }
}

This code defines a contact entity class Contact, which includes basic information (name, gender, phone number, and remarks) as well as necessary constructors and access methods. Through JPA annotations, it can interact with the database for persistence operations. This class serves as the foundation for building applications related to contacts.

package com.sty.service;
​
import com.sty.entity.Contact;
import com.sty.respository.ContactRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
import java.util.List;
import java.util.Optional;
​
@Service
public class ContactService {
​
    @Autowired
    private ContactRepository contactRepository;
​
    // 添加联系人
    public Contact addContact(Contact contact) {
        return contactRepository.save(contact);
    }
​
    // 修改联系人
    public Contact updateContact(Long id, Contact contactDetails) {
        Optional<Contact> optionalContact = contactRepository.findById(id);
        if (optionalContact.isPresent()) {
            Contact contact = optionalContact.get();
            contact.setName(contactDetails.getName());
            contact.setGender(contactDetails.getGender());
            contact.setPhoneNumber(contactDetails.getPhoneNumber());
            contact.setRemarks(contactDetails.getRemarks());
            return contactRepository.save(contact);
        } else {
            throw new RuntimeException("Contact not found");
        }
    }
​
    // 删除联系人
    public void deleteContact(Long id) {
        if (contactRepository.existsById(id)) {
            contactRepository.deleteById(id);
        } else {
            throw new RuntimeException("Contact not found");
        }
    }
​
    // 获取所有联系人
    public List<Contact> getAllContacts() {
        return contactRepository.findAll();
    }
​
    // 根据ID获取联系人
    public Contact getContactById(Long id) {
        return contactRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Contact not found"));
    }
}

This code defines a ContactService class that acts as a service layer for managing contact entities in a Spring application. It uses the ContactRepository to perform CRUD operations. The class includes methods to add a contact, update an existing contact by ID, delete a contact, retrieve all contacts, and find a contact by ID. Each method handles potential errors, such as when a contact is not found, by throwing a runtime exception. The @Service annotation indicates that this class is a Spring service component, and the @Autowired annotation allows for automatic dependency injection of the ContactRepository.

 

package com.sty.respository;
​
import com.sty.entity.Contact;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
​
@Repository
public interface ContactRepository extends JpaRepository<Contact, Long> {
}

This code defines a ContactRepository interface that extends JpaRepository, providing a data access layer for the Contact entity. By extending JpaRepository, it inherits various methods for CRUD operations and database interactions without needing to implement them manually. The generic parameters specify that the repository will work with Contact entities and that the type of the primary key is Long. The @Repository annotation indicates that this interface is a Spring Data repository, allowing it to be automatically detected and utilized by the Spring framework for data operations.

package com.sty.controller;
​
import com.sty.entity.Contact;
import com.sty.service.ContactService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
​
import java.util.List;
@CrossOrigin(origins = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})
@RestController
@RequestMapping("/api/contacts")
public class ContactController {
​
    @Autowired
    private ContactService contactService;
​
    // 添加联系人
    @PostMapping("/add")
    public ResponseEntity<Contact> addContact(@RequestBody Contact contact) {
        Contact newContact = contactService.addContact(contact);
        return ResponseEntity.ok(newContact);
    }
​
    // 修改联系人
    @PutMapping("/modify/{id}")
    public ResponseEntity<Contact> modifyContact(@PathVariable Long id, @RequestBody Contact contactDetails) {
        Contact updatedContact = contactService.updateContact(id, contactDetails);
        return ResponseEntity.ok(updatedContact);
    }
​
    // 删除联系人
    @DeleteMapping("/delete/{id}")
    public ResponseEntity<String> deleteContact(@PathVariable Long id) {
        contactService.deleteContact(id);
        return ResponseEntity.ok("Contact deleted successfully");
    }
​
    // 获取所有联系人
    @GetMapping("/all")
    public ResponseEntity<List<Contact>> getAllContacts() {
        List<Contact> contacts = contactService.getAllContacts();
        return ResponseEntity.ok(contacts);
    }
​
    // 根据ID获取联系人
    @GetMapping("/{id}")
    public ResponseEntity<Contact> getContactById(@PathVariable Long id) {
        Contact contact = contactService.getContactById(id);
        return ResponseEntity.ok(contact);
    }
}

This code defines a ContactController class, which serves as a RESTful API controller for managing contact entities in a Spring application. It is annotated with @RestController to indicate that it handles HTTP requests and responses. The @RequestMapping("/api/contacts") annotation sets the base URL for all endpoints in this controller.

The class uses @Autowired to inject the ContactService, which provides the business logic for handling contact operations. The controller includes several endpoint methods:

  1. addContact: Handles POST requests to add a new contact, receiving a Contact object in the request body and returning the created contact.

  2. modifyContact: Handles PUT requests to update an existing contact by ID, using the ID from the URL path and the updated details from the request body.

  3. deleteContact: Handles DELETE requests to remove a contact by ID, returning a success message upon completion.

  4. getAllContacts: Handles GET requests to retrieve a list of all contacts.

  5. getContactById: Handles GET requests to fetch a specific contact by its ID.

The @CrossOrigin annotation allows cross-origin requests, making the API accessible from different domains. Each method returns a ResponseEntity, encapsulating the HTTP response and allowing for proper status codes and payloads.

 

FrontEnd:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>App</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./index.css">
</head>
<body>
<div id="mask" class="disableAddModal">
    <div id="panel">
        <div id="avatar"></div>
        <p id="random">随机头像</p>
        <input type="text" id="name" placeholder="请输入姓名">
        <input type="text" id="gender" placeholder="请输入性别">
        <input type="text" id="phoneNumber" placeholder="请输入电话号码">
        <input type="text" id="remarks" placeholder="请输入备注">
        <div id="save">保存</div>
        <div id="cancel">取消</div>
    </div>
</div>
<div id="header">
    <h1 id="title">通信录</h1>
    <img id="add" src="./img/add.png" alt="" />
</div>
<p id="tip">
    当前没有任何联系人<br />
    请点击右上角添加
</p>
<div id="content">
    <div id="template" class="card" style="display:none;">
        <div class="avatar"></div>
        <div class="group">
            <p class="name">姓名</p>
            <p class="gender">性别</p>
            <p class="phoneNumber">电话号码</p>
            <p class="remarks">备注</p>
        </div>
        <img src="./img/more.png" alt="" class="more">
        <div class="expand">
            <div class="edit">修改</div>
            <div class="line"></div>
            <div class="delete">删除</div>
        </div>
    </div>
</div>
​
<!-- 引入修改后的 JavaScript 文件 -->
<script src="./index1.js"></script>
</body>
</html>

This code defines the structure of an HTML page for a contact management application. It includes several key components:

  1. Document Structure: The <!DOCTYPE html> declaration indicates that this is an HTML5 document, with the html tag setting the language to English.

  2. Head Section: The <head> section contains metadata, including character encoding (UTF-8), the page title ("App"), viewport settings for responsive design, and a link to an external CSS stylesheet (index.css) for styling.

  3. Body Content:

    • Modal for Adding Contacts: A div with the ID mask serves as a modal for adding a new contact, which includes input fields for the contact's name, gender, phone number, and remarks, along with buttons to save or cancel the action.

    • Header: Contains a title ("通信录" or "Contacts") and an "add" button represented by an image.

    • Tip Message: A paragraph indicating that there are currently no contacts and prompting the user to add one.

    • Content Section: A div for displaying contact cards, which includes a template for each contact. This template, initially hidden, has fields for displaying the contact's avatar, name, gender, phone number, and remarks, along with buttons for editing and deleting the contact.

  4. Script Inclusion: The page includes an external JavaScript file (index1.js) for implementing functionality, such as handling user interactions and managing contacts.

Overall, this HTML structure sets up a user interface for a contact management app, allowing users to view, add, edit, and delete contacts.

 

 

 

BODY,
HTML {
    width: 100%;
    height: 100%;
    margin: 0px;
    font-family: "PingFang SC", "微软雅黑", sans-serif;
    font-weight: 300;
    color: #333;
}
​
.header {
    width: 100%;
    padding: 32px;
}
​
h1 {
    margin: 32px;
    float: left;
    font-weight: 300;
    font-size: 24px;
}
​
#add {
    margin: 32px;
    margin-top: 38px;
    float: right;
    width: 24px;
}
​
#tip {
    width: 100%;
    text-align: center;
    position: fixed;
    top: 240px;
    color: #9E9E9E;
}
​
#mask {
    position: fixed;
    width: 100%;
    height: 100%;
    background: rgba(33, 33, 33, 0.72);
    z-index: 999;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: all 500ms;
}
​
#panel {
    width: 330px;
    background: #FFF;
    border-radius: 10px;
    box-shadow: 0 15px 30px 0 rgba(0, 0, 0, 0.08),
    0 4px 8px 0 rgba(0, 0, 0, 0.08);
    text-align: center;
    padding-bottom: 24px;
    transition: all 300ms;
}
​
#avatar {
    margin: 0px auto;
    margin-top: -48px;
    width: 96px;
    height: 96px;
    border-radius: 50%;
    background: #FFF;
    background-size: cover !important;
    border: 2px solid #FFFFFF;
    box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.12);
    transition: all 500ms;
}
​
#random {
    color: #4A90E2;
    text-decoration: underline;
}
​
input {
    margin: 0px;
    width: 80%;
    background: #FFFFFF;
    border: 2px solid #EEEEEE;
    border-radius: 10px;
    font-size: 16px;
    padding: 12px 16px;
    outline: none;
    transition: all 500ms;
    margin-top: 8px;
}
​
input:first-child {
    margin-top: 24px;
}
​
input:focus {
    border: 2px solid #4A90E2;
}
​
#save {
    width: 26%;
    background: #4A90E2;
    border-radius: 10px;
    padding: 12px;
    color: #FFF;
    margin-top: 24px;
    float: left;
    margin-left: 48px;
    cursor: pointer;
}
​
#cancel {
    width: 26%;
    background: #EEEEEE;
    border-radius: 10px;
    padding: 12px;
    color: #333;
    margin-top: 24px;
    float: right;
    margin-right: 48px;
    cursor: pointer;
}
​
/* 禁用鼠标 */
.disableAddModal {
    background: rgba(33, 33, 33, 0) !important;
    pointer-events: none;
}
​
/* 完全透明 */
.disableAddModal #panel {
    transform: scale(0.9);
    opacity: 0;
}
​
#content {
    padding: 16px;
    padding-top: 97px;
}
​
.card {
    margin-top: 8px;
    width: 100%;
    height: 110px;  /* 增大高度以适应内容 */
    background: #FFFFFF;
    box-shadow: 0 15px 30px 0 rgba(0, 0, 0, 0.08),
    0 4px 8px 0 rgba(0, 0, 0, 0.08);
    border-radius: 10px;
    overflow: hidden;
    position: relative;
    transition: all 300ms;
}
​
.card_expand {
    height: 160px !important;
}
​
.card_expand .expand {
    margin-top: 16px !important;
}
​
.avatar {
    margin-top: 24px;
    margin-left: 24px;
    float: left;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: #9E9E9E;
    background-size: cover !important;
    border: 2px solid #FFFFFF;
    border: 3px solid #EEEEEE;
}
​
/* 使用 Grid 布局确保内容对齐 */
.group {
    margin-left: 16px;
    margin-top: 24px;
    float: left;
    display: grid;  /* 启用 Grid 布局 */
    grid-template-columns: 1fr 1fr 1fr 1fr;  /* 四列均分 */
    column-gap: 16px;  /* 设置列之间的间距 */
    align-items: center;  /* 垂直方向居中对齐 */
    width: calc(100% - 120px);  /* 动态计算宽度 */
}
​
.group p {
    margin: 0;  /* 移除默认 margin */
    padding: 8px 0;  /* 添加上下内边距 */
    font-size: 18px;  /* 设置字体大小 */
    line-height: 24px;  /* 设置行高,确保垂直居中 */
    color: #333;  /* 文本颜色 */
    text-align: center;  /* 文本居中对齐 */
    overflow: hidden;  /* 隐藏溢出文本 */
    text-overflow: ellipsis;  /* 溢出时显示省略号 */
    white-space: nowrap;  /* 禁止换行 */
}
​
.info {
    color: #666;
}
​
.number {
    color: #4A90E2;
}
​
.description {
    color: #9E9E9E;
}
​
.more {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 24px;
    cursor: pointer;
}
​
.expand {
    width: 100%;
    float: left;
    margin-top: 24px;
}
​
.edit {
    text-align: center;
    vertical-align: middle;
    display: flex;
    align-items: center;
    justify-content: center;
    background: url("./img/edit.png");
    background-size: cover;
    float: left;
    width: 50%;
    height: 43px;
    cursor: pointer;
    transition: all 200ms;
}
​
.edit:hover {
    background: url("./img/edit-active.png");
    background-size: cover;
}
​
.delete {
    background: url("./img/delete.png");
    background-size: cover;
    float: right;
    width: 50%;
    height: 43px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: all 200ms;
}
​
.delete:hover {
    background: url("./img/delete-active.png");
    background-size: cover;
}
​
.line {
    float: left;
    height: 24px;
    border-right: #EEE 1px solid;
    margin-left: -1px;
    margin-top: 8px;
}

This code is a CSS stylesheet that defines the styles for a web page layout. Here’s a breakdown of its key components:

  1. General Styles:

    • Sets the overall width and height of the BODY and HTML elements to 100%, removes default margins, and applies a specific font family and color.

  2. Header Styles:

    • .header: Full-width with padding.

    • h1: Custom margins, font size, and weight.

  3. Button and Input Styles:

    • #add, #save, and #cancel: Positioned elements with specific margins, sizes, colors, and cursor styles.

    • input: Styles for input fields, including focus effects and padding.

  4. Modal and Panel Styles:

    • #mask and #panel: Styles for a modal overlay and content panel, including positioning, backgrounds, shadows, and transitions.

  5. Card and Content Styles:

    • .card: Card components with set heights, shadows, rounded corners, and transitions.

    • .group: Uses CSS Grid to layout content in four equal columns with spacing.

  6. Text and Description Styles:

    • Various classes for text, like .info, .number, and .description, to style color and alignment.

  7. Interactive Elements:

    • .edit and .delete: Styles for buttons with background images that change on hover.

  8. Miscellaneous:

    • .line: A vertical separator styled with a border.

The stylesheet emphasizes a clean, modern design with responsive layouts and hover effects, enhancing user interaction and readability.

// index1.js
​
document.addEventListener('DOMContentLoaded', function () {
    var DOM = {
        mask: document.getElementById('mask'),
        add: document.getElementById('add'),
        avatar: document.getElementById('avatar'),
        name: document.getElementById('name'),
        gender: document.getElementById('gender'),
        phoneNumber: document.getElementById('phoneNumber'),
        remarks: document.getElementById('remarks'),
        save: document.getElementById('save'),
        cancel: document.getElementById('cancel'),
        random: document.getElementById('random'),
        content: document.getElementById('content'),
        template: document.getElementById('template'),
        tip: document.getElementById('tip'),
    };
​
    var nowNode;
    const API_BASE_URL = 'http://localhost:8080/api/contacts';
​
    // 控制模态框的显示与隐藏
    function disableAddModal(show) {
        if (show) {
            DOM.mask.className = '';
            DOM.avatar.style.backgroundImage =
                "url('./avatar/" + Math.floor(Math.random() * 47) + ".jpg')";
            // 如果是编辑模式,保留原有信息
            if (!nowNode) {
                DOM.name.value = '';
                DOM.gender.value = '';
                DOM.phoneNumber.value = '';
                DOM.remarks.value = '';
            }
        } else {
            DOM.mask.className = 'disableAddModal';
        }
    }
​
    // 添加新联系人按钮事件
    DOM.add.addEventListener('click', function () {
        nowNode = undefined;
        disableAddModal(true);
    });
​
    // 关闭模态框
    DOM.cancel.addEventListener('click', function () {
        nowNode = undefined;
        disableAddModal(false);
    });
​
    // 随机生成头像
    DOM.random.addEventListener('click', function () {
        DOM.avatar.style.backgroundImage =
            "url('./avatar/" + Math.floor(Math.random() * 47) + ".jpg')";
    });
​
    // 切换卡片展开状态
    function expand(element) {
        element.parentNode.classList.toggle('card_expand');
    }
​
    // 编辑联系人
    function edit(node) {
        nowNode = node;
        disableAddModal(true);
        DOM.avatar.style.backgroundImage = node.querySelector('.avatar').style.backgroundImage;
        DOM.name.value = node.querySelector('.name').innerText;
        DOM.gender.value = node.querySelector('.gender').innerText;
        DOM.phoneNumber.value = node.querySelector('.phoneNumber').innerText;
        DOM.remarks.value = node.querySelector('.remarks').innerText;
    }
​
    // 删除联系人
    function remove(node) {
        const contactId = node.dataset.id;
        fetch(API_BASE_URL + '/delete/' + contactId, {
            method: 'DELETE'
        })
            .then(response => {
                if (response.ok) {
                    node.remove();
                    if (DOM.content.children.length === 1) {
                        DOM.tip.style.display = 'block';
                    }
                } else {
                    console.error('Failed to delete contact');
                }
            })
            .catch(error => {
                console.error('Error deleting contact:', error);
            });
    }
​
    // 保存联系人(添加或修改)
    DOM.save.addEventListener('click', function () {
        const contactData = {
            name: DOM.name.value,
            gender: DOM.gender.value,
            phoneNumber: DOM.phoneNumber.value,
            remarks: DOM.remarks.value
        };
​
        if (nowNode) {
            // 更新联系人
            const contactId = nowNode.dataset.id;
            fetch(API_BASE_URL + '/modify/' + contactId, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(contactData)
            })
                .then(response => response.json())
                .then(updatedContact => {
                    // 更新界面
                    nowNode.querySelector('.name').innerText = updatedContact.name;
                    nowNode.querySelector('.gender').innerText = updatedContact.gender;
                    nowNode.querySelector('.phoneNumber').innerText = updatedContact.phoneNumber;
                    nowNode.querySelector('.remarks').innerText = updatedContact.remarks;
                    disableAddModal(false);
                    nowNode = undefined;
                })
                .catch(error => {
                    console.error('Error updating contact:', error);
                });
        } else {
            // 添加新联系人
            fetch(API_BASE_URL + '/add', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(contactData)
            })
                .then(response => response.json())
                .then(newContact => {
                    // 创建新节点并添加到界面
                    const node = DOM.template.cloneNode(true);
                    node.style.display = 'block';
                    node.removeAttribute('id');
                    node.dataset.id = newContact.id;
                    node.querySelector('.name').innerText = newContact.name;
                    node.querySelector('.gender').innerText = newContact.gender;
                    node.querySelector('.phoneNumber').innerText = newContact.phoneNumber;
                    node.querySelector('.remarks').innerText = newContact.remarks;
                    node.querySelector('.avatar').style.backgroundImage = DOM.avatar.style.backgroundImage;
​
                    // 添加事件监听器
                    node.querySelector('.more').addEventListener('click', function () {
                        expand(this);
                    });
                    node.querySelector('.edit').addEventListener('click', function () {
                        edit(node);
                    });
                    node.querySelector('.delete').addEventListener('click', function () {
                        remove(node);
                    });
​
                    DOM.content.appendChild(node);
                    disableAddModal(false);
                    if (DOM.content.children.length > 1) {
                        DOM.tip.style.display = 'none';
                    }
                })
                .catch(error => {
                    console.error('Error adding contact:', error);
                });
        }
    });
​
    // 从后端获取所有联系人并渲染
    function fetchContacts() {
        fetch(API_BASE_URL + '/all')
            .then(response => {
                if (!response.ok) {
                    throw new Error('网络响应失败,状态码:' + response.status);
                }
                return response.json();
            })
            .then(data => {
                renderContacts(data);
            })
            .catch(error => {
                console.error('Error fetching contacts:', error);
                alert('获取联系人列表失败:' + error.message);
            });
    }
​
    // 渲染联系人列表
    function renderContacts(contacts) {
        DOM.content.innerHTML = ''; // 清空内容
        if (contacts.length === 0) {
            DOM.tip.style.display = 'block';
        } else {
            DOM.tip.style.display = 'none';
        }
        contacts.forEach(contact => {
            const node = DOM.template.cloneNode(true);
            node.style.display = 'block';
            node.removeAttribute('id');
            node.dataset.id = contact.id;
            node.querySelector('.name').innerText = contact.name;
            node.querySelector('.gender').innerText = contact.gender;
            node.querySelector('.phoneNumber').innerText = contact.phoneNumber;
            node.querySelector('.remarks').innerText = contact.remarks;
            node.querySelector('.avatar').style.backgroundImage = `url('./avatar/${Math.floor(Math.random() * 47)}.jpg')`;
​
            // 添加事件监听器
            node.querySelector('.more').addEventListener('click', function () {
                expand(this);
            });
            node.querySelector('.edit').addEventListener('click', function () {
                edit(node);
            });
            node.querySelector('.delete').addEventListener('click', function () {
                remove(node);
            });
​
            DOM.content.appendChild(node);
        });
    }
​
    // 页面加载时获取联系人列表
    fetchContacts();
});

This JavaScript code manages a contact management interface on a web page. Here’s a breakdown of its functionality:

  1. DOM Elements:

    • The code initializes a DOM object that references various elements in the HTML (like modal mask, buttons, input fields, and content area) for easy access.

  2. API Base URL:

    • A constant API_BASE_URL is defined for making API requests to a local server managing contacts.

  3. Modal Control:

    • The disableAddModal function shows or hides a modal for adding/editing contacts. It sets the avatar to a random image if a new contact is being added and clears input fields unless editing an existing contact.

  4. Event Listeners:

    • Add Button: Opens the modal for adding a new contact.

    • Cancel Button: Closes the modal without saving changes.

    • Random Avatar Button: Changes the avatar to a new random image.

  5. Contact Editing and Removal:

    • The edit function pre-fills the modal with the selected contact's details.

    • The remove function deletes a contact using a DELETE request to the server and removes it from the DOM.

  6. Saving Contacts:

    • The save button handles both adding new contacts and updating existing ones. It sends the appropriate API request (POST for adding, PUT for updating) and updates the displayed contact information accordingly.

  7. Fetching Contacts:

    • The fetchContacts function retrieves all contacts from the server and renders them in the UI.

    • The renderContacts function populates the content area with contact cards and sets up event listeners for each card's actions (expand, edit, delete).

  8. Initialization:

    • The script fetches the contact list when the page loads, ensuring that the UI is populated with existing data.

Overall, this code provides a dynamic and interactive contact management system, enabling users to add, edit, delete, and view contacts seamlessly.

Personal Journey and Learnings

This project helped solidify my understanding of full-stack development, particularly in managing separated front and back ends. Challenges included synchronizing data updates and ensuring cross-origin communication, which were resolved by configuring CORS in the Spring Boot application.

...全文
82 回复 打赏 收藏 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
内容概要:本文提出了一种基于高保真电磁暂态仿真的智能电网虚假数据注入攻击(FDIA)数据集构建与影响分析方法,依托PSCAD与MATLAB联合仿真平台,构建IEEE标准测试系统(如9节点或39节点系统)的精细化电磁暂态模型,精确模拟电网在正常运行及遭受FDIA下的动态响应过程,采集高精度、高时间分辨率的电压、电流、功率等电气量时序数据,生成具有强物理约束性和可复现性的攻击数据集。研究进一步结合现代状态估计理论、残差检测机制与机器学习分类算法,对FDIA的隐蔽性特征、攻击传播路径、系统关键变量偏移程度及暂态稳定性影响进行系统性量化评估,旨在为智能电网安全防护体系的设计、入侵检测模型的训练与攻防策略的有效性验证提供高可信度的数据基础与理论支撑。; 适合人群:面向电力系统自动化、能源互联网安全、工业控制系统安全等方向的研究生、科研人员及工程技术人员,要求具备电力系统分析、状态估计基础、MATLAB/PSCAD联合仿真能力以及基本的网络安全背景知识。; 使用场景及目标:① 复现和验证主流FDIA相关学术论文中的攻击模型与检测算法;② 构建符合实际物理规律、可用于训练深度学习或机器学习驱动的入侵检测系统(IDS)的真实攻击数据集;③ 深入探究虚假数据注入对电网暂态稳定性、继电保护动作逻辑、频率调节等关键功能的影响机理。; 阅读建议:本资源以高保真仿真为核心,强调数据生成的真实性与实验可重复性,读者应重点关注PSCAD与MATLAB之间的数据交互机制、攻击向量的设计原则与注入方式、以及多维度影响评估指标体系的构建方法,建议结合所提供的仿真模型与代码进行动手实践与结果验证。
内容概要:本文系统阐述了基于格子Boltzmann方法(Lattice Boltzmann Method, LBM)对二维通道内多孔介质流动进行数值模拟的理论体系、Matlab代码实现流程及结果验证方法。深入剖析了LBM在处理复杂流体系统尤其是不规则几何结构多孔介质流动中的独特优势,详细介绍了模型构建过程、边界条件设定、碰撞与传播环节的算法实现机制,并通过Matlab编程完成仿真运算,实现了对速度场、压力场等关键物理量的可视化分析与精度验证,确保模拟结果具备良好的准确性与可靠性。; 适合人群:具备流体力学基础知识和一定Matlab编程能力的研究生、科研人员及工程技术人员,尤其适合从事多孔介质流动、计算流体力学(CFD)或LBM方法研究的相关领域研究人员。; 使用场景及目标:①掌握格子Boltzmann方法的核心原理及其在多孔介质流动模拟中的具体应用;②学习利用Matlab实现LBM算法并开展科学计算与结果可视化的方法;③为相关科研项目、学术论文复现或实际工程仿真提供可复用的代码框架与技术实施路径。; 阅读建议:建议读者结合流体力学与数值计算相关背景知识,逐步理解算法推导过程,动手运行并调试所提供的Matlab代码,通过调整参数或几何模型加深对LBM方法灵活性与适用性的认识,同时鼓励将该方法拓展至三维流动或多物理场耦合问题的研究中。
内容概要:本文聚焦于“基于变频与移相协同控制的全桥LLC变换器模式切换平滑性优化”这一关键技术问题,通过Simulink仿真平台构建全桥LLC谐振变换器的详细模型,深入研究其在不同工作模式间切换时的动态响应特性。针对传统控制方式在模式切换过程中易引发电压电流冲击、导致系统效率下降与稳定性恶化的问题,提出一种融合变频控制(Frequency Modulation)与移相控制(Phase-Shift Control)的混合协同控制策略。该策略通过精确设计控制逻辑切换时序,优化谐振腔参数匹配,并分析过渡过程中的能量流动规律,有效抑制瞬态波动,实现高效、平稳的模式切换。仿真结果验证了该方法在提升系统动态性能、增强运行可靠性方面的优越性; 适合人群:电力电子、电气工程及其自动化等相关领域的研究生、科研人员以及从事高频电源、新能源变换系统设计的工程技术人员,尤其适合具备电路拓扑分析能力与Simulink建模经验的专业人士; 使用场景及目标:①用于高效率DC-DC变换器中复杂模式切换控制策略的研究与改进;②为电动汽车车载充电机、数据中心电源、光伏微逆变器等对动态性能要求严苛的应用场景提供平滑切换的技术方案;③支撑高水平学术论文的复现、验证与创新性拓展,服务于科研项目中的关键控制算法开发与仿真验证; 阅读建议:建议结合提供的Simulink模型进行同步操作,重点关注变频与移相控制的切换逻辑、参数整定方法及过渡过程的能量管理机制,深入理解两种控制方式的协同作用原理,并可通过调整负载条件、输入电压或谐振元件参数开展多工况仿真分析,以全面掌握系统动态特性。

173

社区成员

发帖
与我相关
我的任务
社区描述
2401_MU_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 助教-吴可仪
  • 助教-孔志豪
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧