express:下载 mongoose 7版本 +配置cors
1:创建module文件夹(db.js、module.js)
连接mongodb数据库:
const mongoose = require("mongoose")
mongoose.connect("mongodb://127.0.0.1:27017/zg6_zk3_2204_koa").then(()=>{
console.log("连接成功");
})
module.exports = mongoose
创建表结构:
const mongoose = require("./db")
let Schema = mongoose.Schema
var userSchema = new Schema({
userName:String,
mobile:String,
birth:String,
duration:String,
sex:String,
xueli:String,
positionList:Array,
tagList:Array,
})
var userModel = mongoose.model("user",userSchema)
// userModel.create({
// userName:"行行行",
// mobile:"15738781657",
// birth:"2001-08-28",
// duration:"2020-09-07",
// sex:"女",
// xueli:"专科",
// positionList:["前端开发工程师","全栈开发工程师"],
// tagList:[
// {
// tag:"前端",
// state:false
// },
// {
// tag:"全栈",
// state:true
// }
// ]
// })
module.exports = { userModel }
后端接口:
const router = require('koa-router')()
const { userModel } = require("../model/model")
router.get('/basic', async (ctx, next) => {
let data = await userModel.find({_id:"6445edd4831ac2ea7b8e8c07"})
let list = data[0]
ctx.body = {
basicMsg:{
_id: list._id,
userName: list.userName,
mobile: list.mobile,
birth: list.birth,
duration: list.duration,
sex: list.sex,
xueli: list.xueli,
},
positionList: list.positionList,
tagList: list.tagList,
}
})
router.post('/update', async (ctx, next) => {
let data = ctx.request.body
await userModel.updateOne({_id:data._id},data)
ctx.body = {code:200,msg:"修改成功"}
})
router.post('/update/two', async (ctx, next) => {
let data = ctx.request.body
await userModel.updateOne({_id:"6445edd4831ac2ea7b8e8c07"},{positionList:data})
ctx.body = {code:200,msg:"修改成功"}
})
router.post('/update/tag', async (ctx, next) => {
let data = ctx.request.body
await userModel.updateOne({_id:"6445edd4831ac2ea7b8e8c07"},{tagList:data})
ctx.body = {code:200,msg:"修改成功"}
})
module.exports = router
前端:
编辑简历:
import React, { useEffect, useState } from 'react'
import { Tag, Input, DatePicker, Select, Radio, Button, Progress } from 'antd';
import { CheckCircleFilled } from '@ant-design/icons';
import axios from 'axios'
import dayjs from 'dayjs';
import { history } from 'umi'
export default function index() {
/** 基本信息 */
const [basicState, setBasicState] = useState(true)
const [basicMsg, setBasicMsg] = useState({})
const [basicUpdateMsg, setBasicUpdateMsg] = useState({})
// 姓名的改变
let onNameInputChange = (e) => {
let obj = { ...basicUpdateMsg }
// console.log(basicMsg.keys().length);
obj.userName = e.target.value
setBasicUpdateMsg(obj);
}
// 出生日期的改变
let onBirthChange = (date: any, dateString: any) => {
let obj = { ...basicUpdateMsg }
obj.birth = dateString
setBasicUpdateMsg(obj);
};
// 开始工作时间的改变
let onDurationChange = (date: any, dateString: any) => {
let obj = { ...basicUpdateMsg }
obj.duration = dateString
setBasicUpdateMsg(obj);
};
// 性别的改变
let onSexChange = (e: any) => {
let obj = { ...basicUpdateMsg }
obj.sex = e.target.value
setBasicUpdateMsg(obj);
}
// 学历的改变
let onXueliSelectChange = (value) => {
let obj = { ...basicUpdateMsg }
obj.xueli = value
setBasicUpdateMsg(obj);
}
// 手机号的改变
let onMobileInputChange = (e) => {
let obj = { ...basicUpdateMsg }
obj.mobile = e.target.value
setBasicUpdateMsg(obj);
}
// 保存Button点击事件
let onUpdateButtonClick = () => {
axios.post("http://127.0.0.1:3000/update", basicUpdateMsg).then(res => {
let obj = { ...basicUpdateMsg }
setBasicMsg(obj)
})
setBasicState(true)
}
// 取消Button点击事件
let onEscButtonClick = () => {
let obj = { ...basicMsg }
setBasicUpdateMsg(obj)
setBasicState(true)
}
// 获取基本信息数据
let getBasic = () => {
axios.get("http://127.0.0.1:3000/basic").then(res => {
setBasicMsg(res.data.basicMsg);
setBasicUpdateMsg(res.data.basicMsg)
setPositionList(res.data.positionList)
setTagList(res.data.tagList)
})
}
// 进入页面就获取基本信息
useEffect(() => {
getBasic()
}, [])
/** 求职意向 */
// 求职
const [positionList, setPositionList] = useState([])
// 移入的Index
const [mouseIndex, setMouseIndex] = useState()
// 编辑时的Index
const [updateIndex, setUpdateIndex] = useState()
// 编辑时新的值
const [updateSelectValue, setUpdateSelectValue] = useState()
// 编辑时Change事件
let onUpdateSelectChange = (e) => {
setUpdateSelectValue(e)
}
// 保存Button按钮点击事件
let onSelectUpdateClick = () => {
let list = [...positionList]
list[updateIndex] = updateSelectValue
console.log(list);
axios.post("http://127.0.0.1:3000/update/two", list).then(res => {
setPositionList(list)
setUpdateIndex("")
})
}
// 添加时的状态
const [addState, setAddState] = useState(false)
// 添加时的值
const [addSelectValue, setAddSelectValue] = useState("前端工程师")
// 添加时Change事件
let onAddSelectChange = (e) => {
setAddSelectValue(e)
}
// 添加时 保存按钮点击事件
let onSelectAddClick = () => {
let list = [...positionList]
list.push(addSelectValue)
axios.post("http://127.0.0.1:3000/update/two", list).then(res => {
setPositionList(list)
setAddState(false)
setAddSelectValue("前端工程师")
})
}
// 删除事件
let onDeleteClick = (index) => {
let list = [...positionList]
list.splice(index, 1)
axios.post("http://127.0.0.1:3000/update/two", list).then(res => {
setPositionList(list)
})
}
/** 特殊标签 */
// 存储标签的数组
let [tagList, setTagList] = useState([])
// 添加标签的状态
let [addTagState, setAddTagState] = useState(false)
// 添加标签的值
let [addTagValue, setAddTagValue] = useState()
// 添加标签Input的Change事件
let onAddTagInputChange = (e) => {
setAddTagValue(e.target.value)
}
// 添加标签的点击事件
let onAddTagClick = () => {
if (addTagValue) {
let list = [...tagList]
let obj = { tag: addTagValue, state: true }
list.push(obj)
axios.post("http://127.0.0.1:3000/update/tag", list).then(res => {
setTagList(list)
setAddTagValue("")
})
}
}
// 添加标签的 保存/取消 按钮点击事件
let onAddTagButtonClick = () => {
setAddTagState(false)
setAddTagValue("")
}
// 将标签进行高亮
let TagClick = (index) => {
let list = [...tagList]
list[index].state = !list[index].state
axios.post("http://127.0.0.1:3000/update/tag", list).then(res => {
setTagList(list)
})
}
// 预览简历
let historyClick = () => {
history.push("/home", { basicMsg, positionList, tagList })
}
return (
<div style={{ width: "100%", height: "100%", backgroundColor: "#F3F3F3", display: "flex" }}>
{/* 左侧 */}
<div style={{ width: "70%", backgroundColor: "#FFF", }}>
{/* 基本信息 */}
<div style={{ padding: "25px" }}>
<h1>基本信息 <Tag color="orange">必填</Tag></h1>
{/* 展示 */}
<div style={{ height: "100px", display: basicState ? "" : "none" }}>
<div style={{ display: "inline-block" }}>
<img style={{ width: "89px" }} src="https://img2.baidu.com/it/u=3618236253,1028428296&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1680886800&t=174f9f7c10fbdb55ff4de04788a63d4f" alt="" />
</div>
<div style={{ display: "inline-block", marginLeft: "15px" }}>
<h2 style={{ display: "inline-block" }}>{basicMsg.userName}</h2>
<div><span>{basicMsg.sex}</span> <span>{dayjs(dayjs().format('YYYY-MM-DD')).diff(basicMsg.birth, 'year')}岁</span> <span>{basicMsg.xueli}</span> <span>{dayjs(dayjs().format('YYYY-MM-DD')).diff(basicMsg.duration, 'year')}年</span></div>
</div>
<div onClick={() => { setBasicState(false) }} style={{ display: "inline-block", float: "right", marginRight: "30px", color: "#94ABFA" }}>
编辑
</div>
</div>
{/* input修改 */}
<div style={{ height: "300px", backgroundColor: "#FFF", display: basicState ? "none" : "" }}>
{/* 左侧 */}
<div style={{ height: "200px", width: "50%", float: "left" }}>
<div>
<div style={{ marginTop: "30px", display: "inline-block", width: "30%", textAlign: "right", marginRight: "15px" }}>
* 姓名
</div>
<Input onChange={onNameInputChange} value={basicUpdateMsg.userName} style={{ width: "200px", }} placeholder="请输入姓名" />
</div>
<div style={{ margin: "20px 0" }}>
<div style={{ display: "inline-block", width: "30%", textAlign: "right", marginRight: "15px" }}>
* 出生日期
</div>
<DatePicker value={dayjs(basicUpdateMsg.birth, 'YYYY-MM-DD')} format="YYYY-MM-DD" onChange={onBirthChange} placeholder="选择出生日期" />
</div><div>
<div style={{ display: "inline-block", width: "30%", textAlign: "right", marginRight: "15px" }}>
* 开始工作时间
</div>
<DatePicker value={dayjs(basicUpdateMsg.duration, 'YYYY-MM-DD')} format="YYYY-MM-DD" onChange={onDurationChange} placeholder="选择开始工作时间" />
</div>
</div>
{/* 右侧 */}
<div style={{ height: "200px", width: "50%", float: "right" }}>
<div>
<div style={{ marginTop: "30px", display: "inline-block", width: "30%", textAlign: "right", marginRight: "15px" }}>
* 性别
</div>
<Radio.Group onChange={onSexChange} value={basicUpdateMsg.sex}>
<Radio value="男">男</Radio>
<Radio value="女">女</Radio>
</Radio.Group>
</div>
<div style={{ margin: "20px 0" }}>
<div style={{ display: "inline-block", width: "30%", textAlign: "right", marginRight: "15px" }}>
* 最高学历
</div>
<Select
value={basicUpdateMsg.xueli}
style={{ width: 120 }}
onChange={onXueliSelectChange}
options={[
{ value: '专科', label: '专科' },
{ value: '本科', label: '本科' },
{ value: '研究生', label: '研究生' },
{ value: '硕士', label: '硕士' },
{ value: '博士', label: '博士' },
]}
/>
</div>
<div>
<div style={{ display: "inline-block", width: "30%", textAlign: "right", marginRight: "15px" }}>
* 联系电话
</div>
<Input onChange={onMobileInputChange} value={basicUpdateMsg.mobile} style={{ width: "200px", }} placeholder="请输入联系电话" />
</div>
</div>
{/* 底部Button按钮 */}
<div style={{ margin: "0 auto" }}>
<div style={{ textAlign: "center" }}>
<Button type="primary" style={{ marginRight: "10px" }} onClick={onUpdateButtonClick}>保存</Button>
<Button style={{ marginLeft: "10px" }} onClick={onEscButtonClick}>取消</Button>
</div>
</div>
</div>
</div>
{/* 求职意向 */}
<div style={{ padding: "25px" }}>
<h1>求职意向 <Tag color="orange">必填</Tag> <div onClick={() => { setAddState(true) }} style={{ color: "#94ABFA", fontSize: "18px", float: "right", display: "inline-block" }}>+添加一条</div> </h1>
{/* 展示的数据 */}
<div>
<ul style={{ listStyle: "none", padding: "10px 0" }}>
{
positionList.map((item, index) => {
return (
updateIndex !== index ?
<li style={{ padding: "15px 0" }} onMouseOver={() => { setMouseIndex(index) }} onMouseOut={() => { setMouseIndex(9999) }}>
职位:{item}
<div style={{ float: "right", display: mouseIndex == index ? "inline-block" : "none" }}>
<div onClick={() => { setUpdateIndex(index); setUpdateSelectValue(item) }} style={{ display: "inline-block", marginRight: "5px" }}>
编辑
</div>
/
<div onClick={() => { onDeleteClick(index) }} style={{ display: "inline-block", marginLeft: "5px" }}>
删除
</div>
</div>
</li>
:
<div>
<div style={{ display: "inline-block", marginRight: "15px" }}>
* 职位
</div>
<Select
value={updateSelectValue}
style={{ width: 120 }}
onChange={onUpdateSelectChange}
options={[
{ value: '前端工程师', label: '前端工程师' },
{ value: '后端工程师', label: '后端工程师' },
{ value: '前端架构师', label: '前端架构师' },
{ value: '全栈工程师', label: '全栈工程师' },
{ value: '算法工程师', label: '算法工程师' },
]}
/>
<div style={{ padding: "10px 0", textAlign: "center" }}>
<Button type="primary" style={{ marginRight: "10px" }} onClick={onSelectUpdateClick}>保存</Button>
<Button style={{ marginLeft: "10px" }} onClick={() => { setUpdateIndex("") }}>取消</Button>
</div>
</div>
)
})
}
</ul>
</div>
{/* 添加表单 */}
<div style={{ display: addState ? "" : "none" }}>
<div style={{ display: "inline-block", marginRight: "15px" }}>
* 职位
</div>
<Select
value={addSelectValue}
style={{ width: 120 }}
onChange={onAddSelectChange}
options={[
{ value: '前端工程师', label: '前端工程师' },
{ value: '后端工程师', label: '后端工程师' },
{ value: '前端架构师', label: '前端架构师' },
{ value: '全栈工程师', label: '全栈工程师' },
{ value: '算法工程师', label: '算法工程师' },
]}
/>
<div style={{ padding: "10px 0", textAlign: "center" }}>
<Button type="primary" style={{ marginRight: "10px" }} onClick={onSelectAddClick}>保存</Button>
<Button style={{ marginLeft: "10px" }} onClick={() => { setAddState(false); setAddSelectValue("前端工程师") }}>取消</Button>
</div>
</div>
</div>
{/* 特长标签 */}
<div style={{ padding: "25px" }}>
<h1>特长标签 <div onClick={() => { setAddTagState(true) }} style={{ float: "right", fontSize: "18px" }}>编辑</div> </h1>
<div style={{ padding: "15px 0", marginLeft: "25px", display: addTagState ? "none" : "" }}>
{
tagList.filter((item, index) => { return item.state }).map((item, index) => {
return <Tag style={{ padding: "5px 10px", marginBottom: "5px" }} color={item.state ? "orange" : ""}>{item.tag}</Tag>
})
}
</div>
<div style={{ display: addTagState ? "" : "none" }}>
<div style={{ padding: "15px 0", marginLeft: "25px", }}>
{
tagList.map((item, index) => {
return <Tag onClick={() => { TagClick(index) }} style={{ padding: "5px 10px", marginBottom: "5px" }} color={item.state ? "orange" : ""}>{item.tag}</Tag>
})
}
</div>
<div>
<Input value={addTagValue} onChange={onAddTagInputChange} style={{ width: "150px" }} placeholder='请输入自定义标签' /><Button onClick={onAddTagClick} >添加</Button>
</div>
<div style={{ padding: "10px 0", textAlign: "center" }}>
<Button type="primary" style={{ marginRight: "10px" }} onClick={onAddTagButtonClick}>保存</Button>
<Button style={{ marginLeft: "10px" }} onClick={onAddTagButtonClick}>取消</Button>
</div>
</div>
</div>
</div>
{/* 右侧 */}
<div style={{ width: "15%", backgroundColor: "#FFF", marginLeft: "25px", padding: "15px" }}>
<h3>简历完整度: <span>
{
Math.floor((((Object.values(basicMsg).filter(item => { return item }).length == 7 ? 1 : 0) + (positionList.length > 0 ? 1 : 0) + (tagList.length > 0 ? 1 : 0)) / 7) * 100)
}
%</span> </h3>
<Progress percent={Math.floor((((Object.values(basicMsg).filter(item => { return item }).length == 7 ? 1 : 0) + (positionList.length > 0 ? 1 : 0) + (tagList.length > 0 ? 1 : 0)) / 7) * 100)} showInfo={false} />
<ul style={{ listStyle: "none", margin: "0 auto", marginRight: "35px", fontSize: "16px" }}>
<li style={{ marginBottom: "25px" }}>
基本信息
<span style={{ float: "right" }}>
{
Object.values(basicMsg).filter(item => { return item }).length == 7 ? <CheckCircleFilled style={{ color: "#468afc" }} /> : <span style={{ float: "right" }}>待完善</span>
}
</span>
</li>
<li style={{ marginBottom: "25px" }}>
求职状态
<span style={{ float: "right" }}>待完善</span>
</li>
<li style={{ marginBottom: "25px" }}>
求职意向
{
positionList.length > 0 ? <CheckCircleFilled style={{ color: "#468afc", float: "right" }} /> : <span style={{ float: "right" }}>待完善</span>
}
</li>
<li style={{ marginBottom: "25px" }}>
特长标签
{
tagList.filter(item => { return item.state }).length > 0 ? <CheckCircleFilled style={{ color: "#468afc", float: "right" }} /> : <span style={{ float: "right" }}>待完善</span>
}
</li>
<li style={{ marginBottom: "25px" }}>
自我描述
<span style={{ float: "right" }}>待完善</span>
</li>
<li style={{ marginBottom: "25px" }}>
教育经历
<span style={{ float: "right" }}>待完善</span>
</li>
<li style={{ marginBottom: "25px" }}>
工作经历
<span style={{ float: "right" }}>待完善</span>
</li>
</ul>
<Button onClick={historyClick} type="primary" block style={{ backgroundColor: "#e2a12c", border: "1px solid #e2a12c" }}>
预览简历
</Button>
</div>
</div>
)
}
预览简历页面:
import React, { useEffect } from 'react'
import { useLocation } from 'umi'
import dayjs from 'dayjs';
import { Tag, Input, DatePicker, Select, Radio, Button, Progress } from 'antd';
export default function Home() {
let location = useLocation()
let basicMsg = location.state.basicMsg
let positionList = location.state.positionList
let tagList = location.state.tagList
useEffect(() => {
console.log(location.state);
}, [])
return (
<div>
<div>
<h1>个人信息</h1>
<div style={{ display: "inline-block" }}>
<img style={{ width: "89px" }} src="https://img2.baidu.com/it/u=3618236253,1028428296&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1680886800&t=174f9f7c10fbdb55ff4de04788a63d4f" alt="" />
</div>
<div style={{ display: "inline-block", marginLeft: "15px" }}>
<h2 style={{ display: "inline-block" }}>{basicMsg.userName}</h2>
<div><span>{basicMsg.sex}</span> <span>{dayjs(dayjs().format('YYYY-MM-DD')).diff(basicMsg.birth, 'year')}岁</span> <span>{basicMsg.xueli}</span> <span>{dayjs(dayjs().format('YYYY-MM-DD')).diff(basicMsg.duration, 'year')}年</span></div>
</div>
</div>
<div>
<h1>求职意向</h1>
{
positionList.map((item: any, index: any) => {
return (
<div key={index}>
期望职位: {item}
</div>
)
})
}
</div>
<div>
<h1>个性标签</h1>
{
tagList.filter((item, index) => { return item.state }).map((item, index) => {
return <Tag style={{ padding: "5px 10px", marginBottom: "5px" }} color={item.state ? "orange" : ""}>{item.tag}</Tag>
})
}
</div>
</div>
)
}
浙公网安备 33010602011771号