lihuayuli 2025-06-13 19:20 采纳率: 100%
浏览 10
已结题

为什么我的修改和删除功能无法正常实现?

登录后页面如图:

img


点击“删除”按钮:

img

点击“确定”,跳转到一个新页面(不知道为什么不能正常删除):

img


返回之前的留言板页面,留言没被删除:

img


点击修改按钮:

img


直接从地址栏输入'/update':

img


代码:
controllers层:


const router = require("../routes/guestBookRoutes");
const guestbookDAO = require("../models/guestbookModel");
const userModel = require("./user"); // 引入user.js
const dbDAO = new guestbookDAO("guestbook.db");
//调用model层的constructor方法(构造函数)
// 创建了一个实例对象dbDAO,用于操作嵌入式数据库。
// const dbDAO = new guestbookDAO();
// 创建了一个实例对象dbDAO,用于操作嵌入式数据库。
exports.landing_page = function (req, res) {
  res.send("Hello! Welcome to my application!");
  // dbDAO.init();
  //初始化数据库,即在内存中创建一个空的数组。
};
exports.entries_list = function (req, res) {
  dbDAO
    .getAllEntries()
    .then((entries) => {
      res.render("entries", {
        title: "Guestbook",
        entries: entries.map((entry) => ({
          ...entry,
          isCurrentUser: req.user && req.user.user === entry.author, // 判断是否是当前用户
        })),
        user: req.user, // 当前登录用户
      });
    })
    .catch((err) => {
      console.error("获取留言失败:", err);
      res.status(500).send("服务器错误");
    });
};
exports.peter_entries = function (req, res) {
  res.send("<h1>Processing Peter's Entries, see terminal</h1>");
  dbDAO
    .getPetersEntries()
    .then((list1) => {
      //then拿到promise对象,list是resolve的值,也就是数据库中的所有记录。
      res.render("entries_p", {
        //渲染名为entries的视图
        title: "Peter's Guest Book",
        //要渲染的内容,key:value形式,
        //这里的key是mustache文件的title,value是每个循环中的内容,
        // 也就是想显示的内容。
        entries_p: list1,
        //这里的entries要和mustache文件中的{{#entries}}对应起来。
        //这里的list是数据库中的所有记录,要和mustache文件中的{{entries}}对应起来。
      });
    })
    .catch((err) => {
      console.log("err:", err);
    });
};
exports.show_new_entry = function (req, res) {
  res.render("newEntry", { title: "Post a new entry" });
};
exports.post_new_entry = function (req, res) {
  const { subject, contents } = req.body;

  if (!req.user) {
    return res.status(403).send("请先登录后再添加留言");
  }

  const newEntry = {
    subject,
    contents,
    published: new Date().toISOString().split("T")[0],
    author: req.user.user,
  };

  dbDAO
    .addEntry(newEntry)
    .then(() => {
      res.redirect("/guestbook");
    })
    .catch((err) => {
      console.error("添加留言失败:", err);
      res.status(500).send("服务器错误");
    });
};
exports.show_login_page = function (req, res) {
  res.render("login", {
    error: req.flash("error"),
  });
};
exports.show_user_entries = function (req, res) {
  let user = req.params.author; // URL:后的内容,是个形参
  dbDAO
    .getUserEntries(user)
    .then((list) => {
      //then拿到promise对象,list是resolve的值,也就是数据库中的所有记录。
      res.render("entries", {
        //渲染名为entries的视图
        title: user + " Guestbook",
        //要渲染的内容,key:value形式,
        //这里的key是mustache文件的title,value是每个循环中的内容,
        // 也就是想显示的内容。
        entries: list,
        //这里的entries要和mustache文件中的{{#entries}}对应起来。
        //这里的list是数据库中的所有记录,要和mustache文件中的{{entries}}对应起来。
      });
    })
    .catch((err) => {
      console.log("err:", err);
    }); //catch在then后面,捕获then中的错误。
};
exports.show_update_entry = function (req, res) {
  const id = req.params.id;

  dbDAO
    .getEntryById(id)
    .then((entry) => {
      if (!entry) {
        return res.status(404).send("留言不存在");
      }
      res.render("updateEntry", { title: "Update Entry", entry });
    })
    .catch((err) => {
      console.error("获取留言失败:", err);
      res.status(500).send("服务器错误");
    });
};

exports.update_entry = function (req, res) {
  const id = req.params.id;
  const { subject, contents } = req.body;

  dbDAO
    .updateEntry(id, req.user.user, subject, contents)
    .then(() => {
      res.redirect("/guestbook");
    })
    .catch((err) => {
      console.error("更新留言失败:", err);
      res.status(500).send("服务器错误");
    });
};

exports.delete_entry = function (req, res) {
  const id = req.params.id;

  if (!req.user) {
    return res.status(403).send("请先登录后再删除留言");
  }

  dbDAO
    .getEntryById(id)
    .then((entry) => {
      if (!entry) {
        // 留言不存在
        return Promise.reject({ message: "留言不存在", status: 404 });
      }
      if (entry.author !== req.user.user) {
        // 用户无权限
        return Promise.reject({ message: "您无权删除此留言", status: 403 });
      }

      // 删除留言
      return dbDAO.removeEntry(id);
    })
    .then((numRemoved) => {
      if (numRemoved > 0) {
        // 删除成功
        res.redirect("/guestbook");
      } else {
        // 删除失败
        return Promise.reject({ message: "删除失败,请稍后再试", status: 500 });
      }
    })
    .catch((err) => {
      if (err.status) {
        res.status(err.status).send(err.message);
      } else {
        console.error("删除留言失败:", err);
        res.status(500).send("服务器错误");
      }
    });
};
// exports.new_entry = function (req, res) {
//   res.send("<h1>Not yet implemented:show a new entry page.</h1>");
//   dbDAO.init();
// };
// exports.show_user_entries;
exports.about_page = function (req, res) {
  // 返回位于public文件夹下的about.html文件
  res.redirect("about.html");
  //直接重定向,app.use(express.static(public));的作用
  dbDAO.init();
};
exports.image = function (req, res) {
  // 返回位于public/img/logo.jpg的图片文件
  res.redirect("logo.jpg");
  dbDAO.init();
};
exports.status_404 = function (req, res) {
  res.status(404); // 设置HTTP状态码为404
  res.send("Oops! Page not found."); // 返回错误提示
};
exports.status_500 = function (err, req, res, next) {
  console.log("error:", err);
  res.status(500);
  res.type("text/plain");
  res.send("Internal Server Error");
};
exports.show_register_page = function (req, res) {
  res.render("register", {
    error: req.flash("error"),
  });
};

exports.register_user = function (req, res) {
  const { username, password } = req.body;

  if (!username || !password) {
    return res.status(400).send("用户名和密码为必填项");
  }

  const userExists = userModel.authenticate(username);
  if (userExists) {
    return res.status(400).send("用户名已存在");
  }

  userModel.addUser(username, password);
  res.redirect("/login");
};

model层:

const nedb = require("@seald-io/nedb"); //nedb是一个变量
class GuestBook {
  constructor(dbFilePath) {
    if (dbFilePath) {
      this.db = new nedb({ filename: dbFilePath, autoload: true });
      //db是该对象的一个属性,用来存储该数据库的引用信息。
      console.log("DB created:" + dbFilePath);
    } else {
      this.db = new nedb();
    }
  }

  init() {
    this.db.insert(
      {
        subject: "I liked the exhibition",
        contents: "nice",
        published: "2020-02-16",
        author: "Peter",
      },
      function (err, newDoc) {
        if (err) {
          console.log("Error:" + err);
        } else {
          console.log("Peter inserted!");
        }
      }
    );
    this.db.insert(
      {
        subject: "Didn't like it",
        contents: "A really terrible style!",
        published: "2020-02-18",
        author: "Ann",
      },
      function (err, newDoc) {
        if (err) {
          console.log("Error:" + err);
        } else {
          console.log("Ann inserted!");
        }
      }
    );
  }
  addEntry(author_value, subject_value, contents_value) {
    this.db.insert(
      {
        subject: subject_value,
        contents: contents_value,
        published: new Date().toISOString().split("T")[0],
        author: author_value,
      },
      function (err, newDoc) {
        if (err) {
          console.log("Error:" + err);
        } else {
          console.log("日期为:" + new Date().toISOString());
          console.log("addEntry inserted!");
        }
      }
    );
  }

  getAllEntries() {
    //return a Promise object, which can be resolved or rejected
    return new Promise((resolve, reject) => {
      //Promise对象可以记录异步操作是成功还是失败
      //resolve记录成功时的状态,reject记录失败时的报错信息,
      // 同时变化了Promise的状态。
      //避免回调地狱,用Promise代替回调函数。
      this.db.find({}, function (err, entries) {
        if (err) {
          reject(err);
          console.log("getAllEntries Promise rejected:" + err);
        } else {
          resolve(entries);
          console.log("getAllEntries Promise resolved: ", entries);
        }
      });
    });
  }
  getPetersEntries() {
    return new Promise((resolve, reject) => {
      this.db.find({ author: "Peter" }, function (err, entries_p) {
        if (err) {
          reject(err);
          console.log("getPetersEntries Promise rejected:" + err);
        } else {
          resolve(entries_p);
          console.log("getPetersEntries Promise resolved:", entries_p);
        }
      });
    });
  }
  getUserEntries(userName) {
    return new Promise((resolve, reject) => {
      this.db.find({ author: userName }, function (err, entries_u) {
        if (err) {
          reject(err);
          console.log("getUserEntries Promise rejected:" + err);
        } else {
          resolve(entries_u);
          console.log("getUserEntries Promise resolved:", entries_u);
        }
      });
    });
  }

  updateEntry(id, author, subject, contents) {
    return new Promise((resolve, reject) => {
      this.db.update(
        { _id: id },
        { $set: { author, subject, contents } },
        {},
        function (err, numUpdated) {
          if (err) {
            reject(err);
          } else {
            resolve(numUpdated);
          }
        }
      );
    });
  }

  getEntryById(id) {
    return new Promise((resolve, reject) => {
      this.db.findOne({ _id: id }, (err, entry) => {
        if (err) {
          reject(err);
        } else {
          resolve(entry); // 返回找到的留言条目或 null
        }
      });
    });
  }
  removeEntry(id) {
    return new Promise((resolve, reject) => {
      this.db.remove({ _id: id }, {}, (err, numRemoved) => {
        if (err) {
          reject(err);
        } else {
          resolve(numRemoved); // 返回删除的条目数量
        }
      });
    });
  }
}

module.exports = GuestBook;


router层:

const express = require("express");
const passport = require("passport"); // 导入 Passport
const controllers = require("../controllers/guestbookControllers");
const auth = require("../controllers/auth");

const router = express.Router();

router.get("/", controllers.landing_page);
router.get("/guestbook", controllers.entries_list);
router.get("/peter", controllers.peter_entries);
router.get("/new", controllers.show_new_entry); // 显示新留言表单
router.post("/new", controllers.post_new_entry); // 处理新留言提交
router.get("/login", controllers.show_login_page);
router.post(
  "/login",
  passport.authenticate("local", {
    successRedirect: "/guestbook",
    failureRedirect: "/login",
    failureFlash: true, // 启用 flash 消消息
  })
);
router.get("/posts/:author", controllers.show_user_entries);
router.get("/update/:id", controllers.show_update_entry); // 显示修改表单
router.post("/update/:id", controllers.update_entry); // 处理修改提交
router.post("/delete/:id", controllers.delete_entry); // 处理删除操作
router.get("/register", controllers.show_register_page);
router.post("/register", controllers.register_user);

module.exports = router; // 导出路由


views层:entries.mustache:

<html lang="en">
<head>
    {{>header}}
</head>

<body class="container">
  <h1>{{title}}</h1>
  {{#user}}
  <p>Welcome, {{user.user}}!</p>
  <div class="text-right">
    <a href="/new" class="btn btn-primary">添加新留言</a>
  </div>
  {{/user}}
  {{^user}}
  <div class="text-right">
    <a href="/login" class="btn btn-primary">登录</a>
    <a href="/register" class="btn btn-secondary">注册</a>
  </div>
  {{/user}}
  {{#entries}}
  <div class="card">
    <div class="card-header">
      {{subject}}
    </div>
    <div class="card-body">
      <div class="card-text">
        {{contents}}
      </div>
      <div class="card-text">
        Written by <a href="/posts/{{author}}">{{author}}</a>, on {{published}}
        {{#user}}
        {{#isCurrentUser}}
        <br>
        <div class="btn-group" role="group"> <!-- 使用btn-group实现按钮水平排列 -->
          <a href="/update/{{_id}}" class="btn btn-primary" style="height:80%">修改</a>
          <form action="/delete/{{_id}}" method="post" style="display: inline;" onsubmit="return confirm('确定要删除这条留言吗?');">
            <button type="submit" class="btn btn-danger">删除</button>
          </form>
        </div>
        {{/isCurrentUser}}
        {{/user}}
      </div>
    </div>
  </div>
  {{/entries}}
  {{^entries}}
  <p>No entries yet!</p>
  {{/entries}}
</body>

</html>



  • 写回答

6条回答 默认 最新

  • 阿里嘎多学长 2025-06-13 19:20
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    问题分析

    根据你的描述,修改和删除功能无法正常实现,点击“删除”按钮后跳转到一个新页面,但是留言没有被删除。点击修改按钮直接从地址栏输入'/update',也没有生效。

    可能原因

    1. 服务器端处理不正确:可能是服务器端的处理逻辑有问题,导致删除和修改功能无法正常实现。
    2. 客户端 JavaScript 代码错误:可能是客户端的 JavaScript 代码有错误,导致点击按钮后无法正确地发送请求。

    解决方案

    1. 检查服务器端代码:检查服务器端的代码,确保删除和修改功能的处理逻辑正确。
    2. 检查客户端 JavaScript 代码:检查客户端的 JavaScript 代码,确保点击按钮后可以正确地发送请求。
    3. 使用浏览器的调试工具:使用浏览器的调试工具,检查请求是否发送成功,检查响应结果是否正确。

    核心代码

    以下是一个简单的示例代码,用于演示删除和修改功能的实现:

    // 删除按钮点击事件
    document.getElementById('delete-btn').addEventListener('click', function() {
      const id = document.getElementById('id').value;
      fetch('/delete', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id: id })
      })
      .then(response => response.json())
      .then(data => {
        if (data.success) {
          alert('删除成功!');
          window.location.href = '/'; // 跳转到首页
        } else {
          alert('删除失败!');
        }
      })
      .catch(error => console.error(error));
    });
    
    // 修改按钮点击事件
    document.getElementById('update-btn').addEventListener('click', function() {
      const id = document.getElementById('id').value;
      const title = document.getElementById('title').value;
      const content = document.getElementById('content').value;
      fetch('/update', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id: id, title: title, content: content })
      })
      .then(response => response.json())
      .then(data => {
        if (data.success) {
          alert('修改成功!');
          window.location.href = '/'; // 跳转到首页
        } else {
          alert('修改失败!');
        }
      })
      .catch(error => console.error(error));
    });
    

    请注意,这只是一个简单的示例代码,实际实现中可能需要根据你的具体需求进行修改。

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

报告相同问题?

问题事件

  • 系统已结题 7月8日
  • 已采纳回答 6月30日
  • 创建了问题 6月13日