最近总是想不好中午吃什么。就想着自己写个小程序,解决一下我的选择困难症,抽到什么吃什么。作为一个卑微前端,写个页面自然是没问题的,可是后端接口怎么办呢?这不是有ChatGPT嘛!
体验
先看成果:
技术选型
小程序页面
微信小程序的语法感觉还是很丑陋,不是很想用,还是想写React,所以前端选择了使用Taro框架和VantUI进行开发,因为本文的重点在于后端,这里的开发步骤就先略过啦~
后端框架
好啦,这里开始,就全程让ChatGPT接管吧,先来问问它技术选型吧:
看下来好像node.js + express.js的技术栈很适合我,就选它,可是数据库咋办呢?继续问:
我就写个小程序而已,MongoDB好像够用了,就他吧。
在ChatGPT的帮助下,我选择了 Express.js + MongoDB作为我的后端开发框架。
编写后端接口
在开始让chatGPT开始写代码之前,我们可以自己定一下数据结构,这个简单的小程序也不需要什么登录态,不过一个唯一标识还是要有的,就用微信登陆接口返回的openid做唯一标识吧,那么我的数据结构应该是这样:
User {
openid:String
nickname: String,
avatar: String,
foodList: [
{
imageUrl: String,
name: String,
location: String,
// 具体时间
date: { type: Date, default: Date.now },
},
],
}
接下来就用这个简单的数据结构,让chatGPT帮我写一套增删改查的接口吧。 首先要为每一位登录的用户设置一个标识,也就是openid,根据微信小程序开发文档,openid要在后台调用接口来获取。
开始问问chatGPT吧:
真是贴心,连前端代码都写好了。再让他把增删改查接口一并写好吧,最后再一起测。
不过我感觉到一点隐患,它好像喜欢把代码写在同一个文件里,不行,良好的编码习惯还是要有,得让他把代码结构规范一下。
看来确实有点东西啊,篇幅原因就不一一截图了,直接把chatGPT生成的代码贴出来:
**models/user.js**:
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
openid: String,
nickname: String,
avatar: String,
foodList: [{
imageUrl: String,
name: String,
location: String,
date: { type: Date, default: Date.now }
}]
});
module.exports = mongoose.model('User', userSchema);
**controllers/foodListController.js**:
const User = require('../models/user');
// 添加食物记录
exports.addFood = async (req, res) => {
const { openid, name, imageUrl, location } = req.body;
try {
const user = await User.findOne({ openid });
if (!user) {
return res.status(404).json({ error: "用户不存在" });
}
const newFoodRecord = { name, imageUrl, location };
const filteredRecord = Object.fromEntries(
Object.entries(newFoodRecord).filter(
([key, value]) => value !== undefined
)
);
await user.updateOne({ $push: { foodList: filteredRecord } });
res.status(200).json({
success: true,
resMsg: "保存成功",
});
} catch (err) {
res.status(500).json({ error: "数据更新失败" });
}
};
// 获取食物记录列表
exports.getFoodList = async (req, res) => {
const { openid } = req.body;
try {
const user = await User.findOne({ openid });
if (!user) {
return res.status(404).json({ error: "用户不存在" });
}
const { foodList = [] } = user;
foodList.sort((a, b) => b.date - a.date);
res.status(200).json({
foodList: foodList,
});
} catch (err) {
res.status(500).json({ error: "数据查询失败" });
}
};
// 更新食物
exports.updateFood = async (req, res) => {
const { openid, recordId, updatedFields } = req.body;
try {
const user = await User.findOne({ openid });
if (!user) {
return res.status(404).json({ error: "用户不存在" });
}
// 找到要修改的记录在 foodList 数组中的索引
const indexToUpdate = user.foodList.findIndex(
(record) => record._id.toString() === recordId
);
if (indexToUpdate === -1) {
return res.status(404).json({ error: "记录不存在" });
}
// 构造要更新的字段和值
const updatedRecord = {
...user.foodList[indexToUpdate],
...updatedFields,
};
const filteredUpdatedRecord = Object.fromEntries(
Object.entries(updatedRecord).filter(
([key, value]) => value !== undefined
)
);
// 更新记录
user.foodList[indexToUpdate] = filteredUpdatedRecord;
await user.save();
res.status(200).json({
success: true,
resMsg: "记录已成功更新",
});
} catch (err) {
res.status(500).json({ error: "数据更新失败" });
}
};
// 删除食物记录
exports.deleteFood = async (req, res) => {
const { openid, foodName } = req.body;
try {
const user = await User.findOne({ openid });
if (!user) {
return res.status(404).json({ error: "用户不存在" });
} else {
const targetFood = user.foodList.find((food) => food.name === foodName);
if (targetFood) {
user.foodList = user.foodList.filter((food) => food.name !== foodName);
await user.save();
res.status(200).json({
success: true,
resMsg: "删除成功",
});
} else {
res.status(500).json({ error: "数据更新失败" });
}
}
} catch (error) {
res.status(500).json({ error: "数据更新失败" });
}
};
**routes/foodListRoutes.js**:
const express = require('express'); const router = express.Router(); const foodListController = require('../controllers/foodListController'); // 添加食物记录 router.post('/:openid/food', foodListController.addFood); // 获取食物记录列表 router.get('/:openid/food', foodListController.getFoodList); // 删除食物记录 router.delete('/:openid/food/:foodId', foodListController.deleteFood); module.exports = router;
**app.js**(主应用文件):
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const userRoutes = require('./routes/userRoutes');
const foodListRoutes = require('./routes/foodListRoutes');
const app = express();
const port = process.env.PORT || 3000;
mongoose.connect('mongodb://localhost:27017/mydatabase', {
useNewUrlParser: true,
useUnifiedTopology: true
});
app.use(bodyParser.json());
app.use('/users', userRoutes);
app.use('/users', foodListRoutes);
app.listen(port, () => {
console.log(`Server is listening on port ${port}`);
});
测试成果
chatGPT生成的代码看起来还挺规范的,命名什么的也都没啥问题,图片上传之类的用的腾讯云的COS,安装一下他们的SDK,复制下示例代码就可以用了,倒也用不上chatGPT帮忙了,最后整理了一下目录,"今天吃什么Pro版"小程序的后台接口就搭建完成啦!
跟我的前端配合起来看一看:
看起来登录接口没问题。
在初始化的时候就写了一些数据,看起来查询接口也没问题。
很好,新增接口依然没问题。
全部完成,chatGPT牛逼!
目前已经把小程序发布上线了,后端的部署也是通过chatGPT的帮助进行,用了我完全不熟悉的docker,将服务部署到了腾讯云服务器,AI的出现确实能减少非常多的重复工作,不过这让我这种菜鸡前端也感到了后怕,说不定真的会有AI淘汰程序员的一天啊😰。