react简历案例--前后端

发布时间 2023-08-01 10:18:28作者: 晚安圆圆

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>
    )
}