JWT
相关无css
//更新文件:client/src/views/personal-panel/index.vue ... <script> import http from '@/utils/http' export default { data () { return { loginer: {} } }, async created () { const { id } = this.$store.state.loginer const res = await http.get(`/users/${id}`) this.loginer = res.data } } </script>
在登陆的时候,已经将登陆用户信息存储到vuex
中,经过用户ID查询用户详细信息。html
// 更新文件: server/router/users.js ... const { list, get, register, login, update } = require('../control/users'); ... { path: '/:id', method: 'GET', handle: get }, ...
// 更新文件:server/control/users.js async function get (ctx) { const { id } = ctx.params; try { const user = await userModel.findOne({ _id: id }).select('+telephone +email'); //新增查询除默认外的字段 if (user) { ctx.body = { code: '200', data: user, msg: '成功' } return; } throw('请核对参数') } catch (err) { ctx.body = { code: '403', data: null, msg: err.message } } } ... module.exports = { ... get, ... }
userModel.findOne({_id: id})
默认查出的是Schema
没有设置select: false
的字段,若是须要其它字段的话,须要userModel.findOne({_id: id}).select('+telephone +email');
新增字段ctx.params
获取匹配路由:id
参数。// 更新文件:client/src/views/personal-panel/index.vue <template> <div class="panel-container"> <div class="panel-avatar"> <el-upload class="avatar-uploader" v-bind="uploadForm"> <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-user"></i> </el-upload> </div> <div class="panel-main"> <h3 class="panel-title">{{loginer.alias || loginer.account}}</h3> <ul class="panel-content"> <li class="panel-item"> <label class="panel-item-lanel">账号:</label> <span class="panel-item-value">{{loginer.account}}</span> </li> <li class="panel-item"> <label class="panel-item-lanel">邮箱:</label> <span class="panel-item-value">{{loginer.email}}</span> </li> <li class="panel-item"> <label class="panel-item-lanel">电话:</label> <span class="panel-item-value">{{loginer.telephone}}</span> </li> </ul> <div class="panel-controls"> <el-button class="btn-edit" type="default" @click="openFormDialog">编辑</el-button> </div> </div> </div> </template> <script> import http from '@/utils/http' export default { methods: { openFormDialog () { } }, data () { return { uploadForm: { action: '' }, imageUrl: '', loginer: {} } }, async created () { const { id } = this.$store.state.loginer const res = await http.get(`/users/${id}`) this.loginer = res.data } } </script> <style lang="scss" scoped> @import '~@/stylesheets/layout.scss'; @import './index.scss'; </style>
// 新建文件:client/src/views/personal-panel/index.scss .panel-container { @include flex($item: flex-start); .panel-avatar { width: 160px; } .panel-main { flex: 1; color: #525975; line-height: 2; padding: 0 40px; font-size: 14px; .panel-title { color: #2e3242; font-size: 24px; } } .panel-controls { margin-top: 20px; } } .avatar-uploader{ /deep/ { .el-upload { border: 1px dashed #d9d9d9; border-radius: 100px; cursor: pointer; position: relative; overflow: hidden; } .el-upload:hover { border-color: #409EFF; } .el-icon-user { font-size: 70px; color: #8c939d; width: 160px; height: 160px; line-height: 160px; text-align: center; } .avatar { width: 160px; height: 160px; display: block; } } }
展现效果前端
// 更新文件:client/src/views/personal-panel/index.vue <template> <div class="panel-container"> <div class="panel-avatar"> <el-upload class="avatar-uploader" v-bind="uploadForm"> <img v-if="imageUrl" :src="imageUrl" class="avatar"> <i v-else class="el-icon-user"></i> </el-upload> </div> <div class="panel-main"> <h3 class="panel-title">{{loginer.alias || loginer.account}}</h3> <ul class="panel-content"> <li class="panel-item"> <label class="panel-item-lanel">账号:</label> <span class="panel-item-value">{{loginer.account}}</span> </li> <li class="panel-item"> <label class="panel-item-lanel">邮箱:</label> <span class="panel-item-value">{{loginer.email}}</span> </li> <li class="panel-item"> <label class="panel-item-lanel">电话:</label> <span class="panel-item-value">{{loginer.telephone}}</span> </li> </ul> <div class="panel-controls"> <el-button class="btn-edit" type="default" @click="openFormDialog">编辑</el-button> </div> </div> <el-dialog :title="dialogForm.title" :visible.sync="dialogForm.visible"> <el-form :ref="dialogForm.formRef" :model="dialogForm.form" :rules="dialogForm.rules"> <el-form-item label="账号" prop="account"> <el-input v-model="dialogForm.form.account"></el-input> </el-form-item> <el-form-item label="昵称" prop="alias"> <el-input v-model="dialogForm.form.alias"></el-input> </el-form-item> <el-form-item label="邮箱" prop="email"> <el-input type="email" v-model="dialogForm.form.email"></el-input> </el-form-item> <el-form-item label="电话" prop="telephone"> <el-input type="telephone" v-model="dialogForm.form.telephone"></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dialogForm.visible = false">取 消</el-button> <el-button type="primary" @click="submitForm">确 定</el-button> </div> </el-dialog> </div> </template> <script> import http from '@/utils/http' export default { methods: { openFormDialog () { this.dialogForm.visible = true }, async submitForm () { try { const valid = await this.$refs[this.dialogForm.formRef].validate() if (valid) { const res = await http.patch( `/users/${this.userId}`, { ...this.dialogForm.form } ) if (res.code === '200') { const { account, alias } = res.data this.$store.commit( 'putLoginer', { account, alias } ) // 更新vuex状态 this.loginer = Object.assign( {}, this.loginer, { ...res.data } ) // 更新展现的默认值 this.$set(this.dialogForm, 'form', Object.assign( {}, this.dialogForm.form, { ...res.data } )) // 更新弹窗默认值 this.dialogForm.visible = false } else { this.$message({ type: 'error', message: res.msg }) } } } catch (err) { console.error(err) } } }, data () { return { uploadForm: { action: '' }, imageUrl: '', loginer: {}, dialogForm: { visible: false, title: '编辑', formRef: 'dialogForm', form: { account: '', alias: '', email: '', telephone: '' }, rules: { account: [ { required: true, message: '请输入账号', trigger: 'blur' }, { min: 5, message: '长度至少5个字符', trigger: 'blur' } ], alias: [ { required: true, message: '请输入昵称', trigger: 'blur' }, { min: 1, max: 15, message: '长度不能超过十五个字符', trigger: 'blur'} ], email: [ { type: 'email', required: true, message: '请输入邮箱', trigger: 'blur' } ], telephone: [ { required: true, message: '请输入手机号码', trigger: 'blur' }, { validator: (rule, value, cb) => { if (/^1[0-9]{10}$/.test(value)) { cb() } else { cb(new Error('手机号码格式错误')) } }, trigger: 'blur' } ] } } } }, computed: { userId () { return this.$store.state.loginer.id } }, async created () { // 调用完初始化接口时,须要赋展现初始值 const res = await http.get(`/users/${this.userId}`) if (res.code === '200') { this.loginer = res.data this.dialogForm.form = {...res.data} this.imageUrl = res.data.avatar } else { this.$message({ type: 'error', message: '获取用户信息失败' }) } } } </script>
get
方法调用/users/:id
接口后,须要给用户设初始值。patch
方法调用/users/:id
接口,更新用户信息后,要更新vuex
存储的状态,更新展现的用户信息,更新弹窗初始值。展现效果:vue
// 更新文件:server/control/users.js ... async function update (ctx) { const { id } = ctx.params; const payload = ctx.request.body; try { await userModel.updateOne( { _id: id }, { ...payload } ); ctx.body = { code: '200', data: { id, ...payload }, msg: '更新成功' } } catch (err) { ctx.body = { code: '403', data: null, msg: '请核查参数' } } } ...
测试结果:vuex
Model操做api