add comment module

pangu
PeterAlbus 3 years ago
parent 628f922fe6
commit 95f26e2dd2

3
components.d.ts vendored

@ -5,10 +5,13 @@
declare module 'vue' { declare module 'vue' {
export interface GlobalComponents { export interface GlobalComponents {
Banner: typeof import('./src/components/Banner.vue')['default'] Banner: typeof import('./src/components/Banner.vue')['default']
Comment: typeof import('./src/components/Comment.vue')['default']
ElAvatar: typeof import('element-plus/es')['ElAvatar'] ElAvatar: typeof import('element-plus/es')['ElAvatar']
ElButton: typeof import('element-plus/es')['ElButton'] ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard'] ElCard: typeof import('element-plus/es')['ElCard']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCol: typeof import('element-plus/es')['ElCol'] ElCol: typeof import('element-plus/es')['ElCol']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider'] ElDivider: typeof import('element-plus/es')['ElDivider']
ElForm: typeof import('element-plus/es')['ElForm'] ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElFormItem: typeof import('element-plus/es')['ElFormItem']

@ -0,0 +1,353 @@
<template>
<div class="module">
<h2 class="title"><el-icon style="vertical-align: -10%"><comment /></el-icon> </h2>
<div class="content paragraph">
<div style="padding: 3px;display: flex;justify-content: center;align-items: end;flex-direction: column">
<el-input
v-model="newComment.commentContent"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
placeholder="请友善交流,文明用语"
/>
<div>
<el-checkbox v-model="hideMyself" label="1" size="small"></el-checkbox>
<el-button
size="small" @click="addComment"
style="position: relative;float: right;margin: 3px"
type="primary" color="#63a35c">发布</el-button>
</div>
</div>
<el-scrollbar max-height="20vh">
<div v-for="item in comments" class="main-comment">
<div class="comment-user">
<el-avatar :src="item.userAvatar" :size="30"></el-avatar>
<span style="padding: 0 10px 0 10px;display: flex;align-items: center">{{item.userUsername}}<el-tag :type="identityType(item.userIdentity)" effect="dark" size="small">{{ userIdentity(item.userIdentity) }}</el-tag></span>
</div>
<div style="padding: 10px 10px 10px 40px" class="comment-box">
<div style="width: 100%">{{item.commentContent}}</div>
</div>
<div class="comment-buttons">
<el-icon class="comment-button" @click="openComment(item,item)"><chat-line-square /></el-icon>
</div>
<div class="side-comment" v-if="item.hasComment">
<div v-for="i in item.comments" class="comment-box">
<div style="width: 100%"><span style="font-weight: bold;color: #56AD93">{{ i.userUsername }}</span> {{i.commentContent}}</div>
<div class="comment-buttons">
<el-icon class="comment-button" @click="openComment(i,item)"><chat-line-square /></el-icon>
</div>
</div>
</div>
</div>
</el-scrollbar>
</div>
</div>
<div class="float-comment" :class="{'hide-float-comment':!showFloatComment}">
<div style="display: flex;justify-content: space-between;align-items: center;width: 100%">
<span>回复:{{commentUsername}}</span>
<el-icon style="vertical-align: -10%" class="comment-button" @click="showFloatComment=false"><close /></el-icon>
</div>
<el-input
v-model="newCommentToComment.commentContent"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
placeholder="请友善交流,文明用语"
/>
<div>
<el-checkbox v-model="hideMyself" label="1" size="small"></el-checkbox>
<el-button
size="small" @click="showFloatComment=false"
style="position: relative;float: right;margin: 3px"
plain color="#63a35c">关闭</el-button>
<el-button
size="small" @click="addCommentToComment"
style="position: relative;float: right;margin: 3px"
type="primary" color="#63a35c">发布</el-button>
</div>
</div>
</template>
<script setup lang="ts">
import {computed, onMounted, reactive, ref, watch} from "vue";
import axios from "axios";
import {Comment,ChatLineSquare,Close} from "@element-plus/icons-vue"
import qs from "qs";
import {useUserStore} from "@/store/user";
import {ElMessage} from "element-plus";
const userStore = useUserStore()
const showFloatComment = ref(false)
const hideMyself = ref(false)
const commentUsername= ref('')
const props = defineProps({
blogId: {
default() {
return ''
},
}
});
let comments=ref([
{
commentId:"1",
commentTarget:1,
commentTargetId:"1505910717547618306",
commentUserId:"-1",
userUsername:"匿名",
userAvatar:"https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
userIdentity:-1,
commentContent:"数据加载中",
gmtCreate:null,
gmtModified:null,
hasComment:false,
comments:[{
commentUserId:"-1",
commentContent:"",
userUsername:"匿名",
userAvatar:"https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
userIdentity:-1
}]
}
])
const newComment=reactive({
commentTarget:1,
commentTargetId:"",
commentUserId:"-1",
commentContent:"",
})
const newCommentToComment=reactive({
commentTarget:2,
commentTargetId:"",
commentUserId:"-1",
commentContent:"",
})
const openComment=(comment:any,bigComment:any)=>{
commentUsername.value=comment.userUsername
newCommentToComment.commentTargetId=bigComment.commentId
showFloatComment.value=true
}
const getComments=()=>{
axios.get("/comment/getCommentByBlogId?blogId="+props.blogId)
.then((res)=>{
comments.value=res.data
for(let comment of comments.value)
{
if(comment.commentUserId!=='-1')
{
axios.get("/user/getUserById?userId="+comment.commentUserId)
.then((result)=>{
comment.userUsername=result.data.userUsername
comment.userAvatar=result.data.userAvatar
comment.userIdentity=result.data.userIdentity
})
}
else
{
comment.userUsername="匿名";
comment.userAvatar="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png";
}
axios.get("/comment/getCommentByCommentId?commentId="+comment.commentId)
.then((result)=>{
comment.comments=result.data
comment.hasComment = comment.comments.length !== 0
for(let item of comment.comments)
{
if(item.commentUserId!=='-1')
{
axios.get("/user/getUserById?userId="+comment.commentUserId)
.then((result)=>{
item.userUsername=result.data.userUsername
item.userAvatar=result.data.userAvatar
item.userIdentity=result.data.userIdentity
})
}
else
{
item.userUsername="匿名";
item.userAvatar="https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png";
}
}
})
}
})
}
const addComment=()=>{
newComment.commentTarget=1
newComment.commentTargetId=props.blogId
newComment.commentUserId=userStore.userId
if(hideMyself.value)
{
newComment.commentUserId='-1'
}
axios.post("/comment/addComment",qs.stringify(newComment))
.then((res)=>{
if(res.data=="notLogin")
{
ElMessage.error("没有登录不可评论!")
}
else if(res.data=="fail")
{
ElMessage.error("评论发布失败")
}
else
{
ElMessage.success("发布成功!")
newComment.commentContent=""
getComments()
}
})
}
const addCommentToComment=()=>{
newCommentToComment.commentTarget=2
newCommentToComment.commentUserId=userStore.userId
newCommentToComment.commentContent='回复 @'+commentUsername.value+": "+newCommentToComment.commentContent
if(hideMyself.value)
{
newCommentToComment.commentUserId='-1'
}
axios.post("/comment/addComment",qs.stringify(newCommentToComment))
.then((res)=>{
if(res.data=="notLogin")
{
ElMessage.error("没有登录不可评论!")
}
else if(res.data=="fail")
{
ElMessage.error("评论发布失败")
}
else
{
ElMessage.success("发布成功!")
newCommentToComment.commentContent=""
showFloatComment.value=false
getComments()
}
})
}
const identityType = (userIdentity:any)=>{
if(userIdentity==0)
{
return "warning"
}
else if(userIdentity==1)
{
return "success"
}
else if(userIdentity==5)
{
return ""
}
else
{
return "info"
}
}
const userIdentity = (userIdentity:any)=>{
if(userIdentity==0)
{
return "站长"
}
else if(userIdentity==1)
{
return "管理员"
}
else if(userIdentity==5)
{
return "普通用户"
}
else
{
return "游客"
}
}
watch(() => props.blogId,
() => {
getComments()
})
onMounted(()=>{
getComments()
})
</script>
<style scoped>
.main-comment{
background-color: #F7F7F7;
margin: 5px;
padding: 5px;
border-radius: 5px;
text-align: left;
}
.side-comment{
background-color: #E3E3E3;
margin: 5px 5px 5px 40px ;
padding: 5px;
text-align: left;
}
.comment-user{
display: flex;
justify-content: left;
align-items: center;
}
.comment-box{
display: flex;
justify-content: center;
align-items: end;
word-wrap:break-word;
white-space:pre-wrap;
flex-direction: column;
}
.comment-buttons{
display: flex;
justify-content: right;
align-items: center;
padding: 5px;
}
.comment-button{
color: black;
cursor: pointer;
}
.comment-button:hover{
color: #63a35c;
}
.float-comment{
background-color: white;
padding: 0 10px 10px 10px;
display: flex;
justify-content: center;
align-items: end;
flex-direction: column;
position: fixed;
right: 10px;
top: 40vh;
z-index: 101;
border-radius: 5px;
box-shadow: 0 3px 8px 6px rgba(7,17,27,0.05);
width: 300px;
transition-property:opacity,transform;
transition-duration:0.3s;
transition-timing-function:ease;
}
.hide-float-comment{
transform: translateX(300px);
opacity: 0;
}
</style>

@ -1,6 +1,6 @@
<template> <template>
<div class="module"> <div class="module">
<h2 class="title"><el-icon style="vertical-align: -10%"><link-icon /></el-icon></h2> <h2 class="title"><el-icon style="vertical-align: -10%"><link-icon /></el-icon> </h2>
<div class="content paragraph"> <div class="content paragraph">
<p v-for="item in friendLinkList"><a :href="item.linkUrl" target="_blank">{{ item.linkName }}</a></p> <p v-for="item in friendLinkList"><a :href="item.linkUrl" target="_blank">{{ item.linkName }}</a></p>
</div> </div>

@ -27,6 +27,7 @@
<div class="operations" v-if="userStore.userId!==''"> <div class="operations" v-if="userStore.userId!==''">
<el-divider /> <el-divider />
<div class="operation" @click="toLink('/userCenter')"><el-icon style="vertical-align: -10%"><avatar /></el-icon> </div> <div class="operation" @click="toLink('/userCenter')"><el-icon style="vertical-align: -10%"><avatar /></el-icon> </div>
<div class="operation"><el-icon style="vertical-align: -10%"><message /></el-icon> </div>
<div class="operation"><el-icon style="vertical-align: -10%"><setting /></el-icon> </div> <div class="operation"><el-icon style="vertical-align: -10%"><setting /></el-icon> </div>
<el-divider /> <el-divider />
<div class="operation" @click="logout"><el-icon style="vertical-align: -10%"><close /></el-icon> 退</div> <div class="operation" @click="logout"><el-icon style="vertical-align: -10%"><close /></el-icon> 退</div>
@ -81,7 +82,8 @@ import {
Close, Close,
Avatar, Avatar,
Lollipop, Lollipop,
Tickets Tickets,
Message
} from "@element-plus/icons-vue"; } from "@element-plus/icons-vue";
import {useUserStore} from "@/store/user"; import {useUserStore} from "@/store/user";
import axios from "axios"; import axios from "axios";

@ -204,6 +204,7 @@ router.beforeEach((to, from, next)=>{
if((to.name=='Login'||to.name=='Register')&&userStore.userId!='') if((to.name=='Login'||to.name=='Register')&&userStore.userId!='')
{ {
next('/userCenter') next('/userCenter')
return
} }
if(to.meta.content) { if(to.meta.content) {
// @ts-ignore // @ts-ignore

@ -21,7 +21,7 @@
<PersonalInfo></PersonalInfo> <PersonalInfo></PersonalInfo>
<div class="sticky-box"> <div class="sticky-box">
<div class="module anchors" :class="{'hide-small-screen':hideCatalogue}" v-if="titleList.length!==0"> <div class="module anchors" :class="{'hide-small-screen':hideCatalogue}" v-if="titleList.length!==0">
<h2 class="title"><el-icon style="vertical-align: -10%"><notebook /></el-icon></h2> <h2 class="title"><el-icon style="vertical-align: -10%"><notebook /></el-icon> </h2>
<div class="content" style="padding: 10px"> <div class="content" style="padding: 10px">
<el-scrollbar max-height="30vh"> <el-scrollbar max-height="30vh">
<div <div
@ -35,8 +35,9 @@
</el-scrollbar> </el-scrollbar>
</div> </div>
</div> </div>
<Comment :blogId="blogId"></Comment>
<div class="module"> <div class="module">
<h2 class="title"><el-icon style="vertical-align: -10%"><share-icon /></el-icon></h2> <h2 class="title"><el-icon style="vertical-align: -10%"><share-icon /></el-icon> </h2>
<div class="content paragraph"> <div class="content paragraph">
<Share <Share
:url="'https://www.peteralbus.com/%23/blog?id%3D'+blog.blogId" :url="'https://www.peteralbus.com/%23/blog?id%3D'+blog.blogId"
@ -64,8 +65,10 @@ import {useRoute} from "vue-router";
import {ArrowRight,Notebook,Share as shareIcon} from "@element-plus/icons-vue"; import {ArrowRight,Notebook,Share as shareIcon} from "@element-plus/icons-vue";
import axios from "axios"; import axios from "axios";
import PersonalInfo from '@/components/PersonalInfo.vue' import PersonalInfo from '@/components/PersonalInfo.vue'
import Comment from '@/components/Comment.vue'
import type {vMdEditor} from "@kangc/v-md-editor" import type {vMdEditor} from "@kangc/v-md-editor"
const route=useRoute() const route=useRoute()
let mdRef=ref<InstanceType<typeof vMdEditor>>() let mdRef=ref<InstanceType<typeof vMdEditor>>()
let titleList:any=ref([]) let titleList:any=ref([])
@ -87,6 +90,8 @@ let blog=ref({
isTop:1 isTop:1
}) })
let blogId:string='-1'
const getBlog=()=>{ const getBlog=()=>{
if(blog.value.blogId!==undefined) if(blog.value.blogId!==undefined)
{ {
@ -153,6 +158,10 @@ const getFriendLinkList=function () {
} }
onMounted(()=>{ onMounted(()=>{
if(route.query.id!=null)
{
blogId=route.query.id.toString()
}
getBlog() getBlog()
getFriendLinkList() getFriendLinkList()
}) })

@ -22,7 +22,7 @@
:on-success="handleAvatarSuccess" :on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload" :before-upload="beforeAvatarUpload"
> >
<img style="width: 200px; height: 200px" v-if="imageUrl" :src="imageUrl" class="avatar" alt=""> <el-image style="width: 200px; height: 200px" v-if="imageUrl" :src="imageUrl" class="avatar" fit="cover" alt=""/>
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload> </el-upload>
</el-form-item> </el-form-item>

@ -8,8 +8,8 @@
<h2 v-if="registerByPhone"></h2> <h2 v-if="registerByPhone"></h2>
<h2 v-if="!registerByPhone"></h2> <h2 v-if="!registerByPhone"></h2>
<div class="switch" > <div class="switch" >
<span @click="registerByPhone=false" v-if="registerByPhone">使</span> <span @click="registerByPhone=false;canGetVerifyCode=true;time=0" v-if="registerByPhone">使</span>
<span @click="registerByPhone=true" v-if="!registerByPhone">使</span> <span @click="registerByPhone=true;canGetVerifyCode=false;time=0" v-if="!registerByPhone">使</span>
</div> </div>
</div> </div>
<el-form <el-form
@ -41,7 +41,7 @@
</el-form-item> </el-form-item>
<div> <div>
<el-button type="primary" @click="submitForm(ruleFormRef)" color="#63a35c">注册</el-button>&emsp; <el-button type="primary" @click="submitForm(ruleFormRef)" color="#63a35c">注册</el-button>&emsp;
<router-link to="/login"><el-button plain color="#63a35c">登录</el-button></router-link> <el-button plain color="#63a35c" @click="toLoginPage"></el-button>
</div> </div>
</el-form> </el-form>
</el-col> </el-col>
@ -249,7 +249,7 @@ const rules = reactive({
{ required: true, message: '请输入用户名', trigger: 'change' }, { required: true, message: '请输入用户名', trigger: 'change' },
], ],
userVerifyCode: [ userVerifyCode: [
{ required: true, message: '请输入用户名', trigger: 'change' }, { required: true, message: '请输入验证码', trigger: 'change' },
], ],
userPassword: [ userPassword: [
{ validator: validatePass, trigger: 'blur' }, { validator: validatePass, trigger: 'blur' },
@ -285,6 +285,21 @@ const submitForm = async (formEl: FormInstance | undefined) => {
}) })
} }
const toLoginPage= ()=>{
ElMessageBox.confirm(
'确定要离开本页面前往登录页?你将丢失填写的所有信息',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
router.push('/login')
})
.catch(() => {})
}
</script> </script>
<style scoped> <style scoped>

@ -24,7 +24,7 @@
:auto-upload="false" :auto-upload="false"
:on-change="onFileChange" :on-change="onFileChange"
> >
<img style="width: 178px; height: 178px" v-if="imageUrl" :src="imageUrl" class="avatar" alt=""> <el-image style="width: 178px; height: 178px" v-if="imageUrl" :src="imageUrl" class="avatar" alt="" fit="cover"/>
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon> <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload> </el-upload>
</el-form-item> </el-form-item>

@ -1,26 +1,595 @@
<template> <template>
<Banner title="用户中心"></Banner> <Banner title="用户中心"></Banner>
<div class="main-container"> <div class="main-container flex-box">
<el-button @click="logout"></el-button> <div class="user-box">
<el-upload
class="avatar-uploader"
action="https://www.peteralbus.com:8089/user/uploadAvatar/"
ref="uploadRef"
:data="upData"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<el-avatar :size="178" :src="userStore.userAvatar" v-if="userStore.userAvatar"></el-avatar>
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
<h2 style="display: flex;align-items: center;justify-content: center" v-if="!changingName">
{{userStore.userUsername}}<el-button @click="editName" plain color="#63a35c" :icon="Edit" size="small"/>
</h2>
<h2 style="display: flex;align-items: center;justify-content: center" v-if="changingName">
<el-input v-model="username" style="width: 300px"/><el-button @click="changeName" plain color="#63a35c" :icon="Check" size="small"/>
</h2>
<p style="font-size: 0.8em;color: #3eaf7c">点击头像可更换</p>
<p style="padding: 4px">
<el-tag
:type="identityType"
effect="dark"
>
{{ userIdentity }}
</el-tag>
</p>
<div style="text-align: left;max-width: 400px;margin: 0 auto">
<div class="user-center-info" v-if="userStore.userPhone!==null">{{userStore.userPhone}}<el-button @click="phoneFormVisible=true" plain color="#63a35c" :icon="Edit" circle style="float: right;" /></div>
<div class="user-center-info" v-if="!userStore.userPhone"><el-button @click="phoneFormVisible=true" color="#63a35c" :icon="Edit" type="primary">前往绑定</el-button></div>
<div class="user-center-info" v-if="userStore.userMail!==null">{{userStore.userMail}}<el-button @click="mailFormVisible=true" plain color="#63a35c" :icon="Edit" circle style="float: right;" /></div>
<div class="user-center-info" v-if="!userStore.userMail"><el-button @click="mailFormVisible=true" color="#63a35c" :icon="Edit" type="primary">前往绑定</el-button></div>
<div class="user-center-info">注册时间{{userStore.gmtCreate}}</div>
</div>
<div style="display: flex;justify-content: space-around;margin: 0 auto;padding: 20px;max-width: 200px;">
<el-button color="#63a35c" type="primary" @click="changePasswordFormVisible=true"></el-button>
<el-button color="#63a35c" plain @click="logout"></el-button>
</div>
</div>
</div> </div>
<el-dialog v-model="changePasswordFormVisible" title="修改密码">
<el-form :model="changePasswordForm"
ref="changePasswordFormRef"
:rules="psswordRules"
style="margin: 0 auto;max-width: 400px">
<el-form-item>
原密码
</el-form-item>
<el-form-item prop="oldPassword">
<el-input v-model="changePasswordForm.oldPassword" type="password"/>
</el-form-item>
<el-form-item>
新密码
</el-form-item>
<el-form-item prop="newPassword">
<el-input v-model="changePasswordForm.newPassword" type="password"/>
</el-form-item>
<el-form-item>
确认密码
</el-form-item>
<el-form-item prop="userConfirmPassword">
<el-input v-model="changePasswordForm.userConfirmPassword" type="password"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" color="#63a35c" @click="changePassword(changePasswordFormRef)"></el-button>
<el-button plain color="#63a35c" @click="changePasswordFormVisible = false">取消</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="phoneFormVisible" title="绑定/修改手机">
<el-form :model="phoneForm"
ref="phoneFormRef"
:rules="phoneRules"
style="margin: 0 auto;max-width: 400px">
<el-form-item>
手机
</el-form-item>
<el-form-item prop="userPhone">
<el-input v-model="phoneForm.userPhone" />
</el-form-item>
<el-form-item>
验证码
</el-form-item>
<el-form-item prop="verifyCode" style="justify-content: space-between!important;">
<el-input v-model="phoneForm.verifyCode" style="width: 60%"/>
&emsp;
<el-button type="primary" style="width: 30%" :disabled="!canGetPhoneVerifyCode" @click="getPhoneVerifyCode">{{ phoneVerifyText }}</el-button>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" color="#63a35c" @click="setPhone(phoneFormRef)"></el-button>
<el-button plain color="#63a35c" @click="phoneFormVisible = false">取消</el-button>
</span>
</template>
</el-dialog>
<el-dialog v-model="mailFormVisible" title="绑定/修改邮箱">
<el-form :model="mailForm"
ref="mailFormRef"
:rules="mailRules"
style="margin: 0 auto;max-width: 400px">
<el-form-item>
邮箱
</el-form-item>
<el-form-item prop="userMail">
<el-input v-model="mailForm.userMail" />
</el-form-item>
<el-form-item>
验证码
</el-form-item>
<el-form-item prop="verifyCode" style="justify-content: space-between!important;">
<el-input v-model="mailForm.verifyCode" style="width: 60%"/>
&emsp;
<el-button type="primary" style="width: 30%" :disabled="!canGetMailVerifyCode" @click="getMailVerifyCode">{{ mailVerifyText }}</el-button>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" color="#63a35c" @click="setMail(mailFormRef)"></el-button>
<el-button plain color="#63a35c" @click="mailFormVisible = false">取消</el-button>
</span>
</template>
</el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import Banner from '@/components/Banner.vue' import Banner from '@/components/Banner.vue'
import axios from "axios"; import axios from "axios";
import {ElMessage} from "element-plus"; import {Edit,Plus,Check} from '@element-plus/icons-vue'
import {
ElMessage,
ElMessageBox,
ElUpload
} from "element-plus";
import type {FormInstance, UploadFile, UploadProgressEvent, UploadRawFile} from 'element-plus'
import router from "@/router"; import router from "@/router";
import {useUserStore} from "@/store/user";
import {computed, reactive, ref} from "vue";
import qs from "qs";
const userStore=useUserStore()
const changingName=ref(false)
const username=ref('')
const editName= ()=>{
username.value=userStore.userUsername
changingName.value=true
}
const changeName= ()=>{
axios.get('/user/changeUsername?userId='+userStore.userId+"&username="+username.value)
.then((res)=>{
if(res.data=='noPermission')
{
ElMessage.error('登录认证异常,请重新登陆重试')
}
else if(res.data=='wrongUserId')
{
ElMessage.error('本地用户id存储异常请重新登陆重试')
}
else if(res.data=='fail')
{
ElMessage.error('修改失败,请联系管理员')
}
else
{
ElMessage.success('修改用户名成功!')
userStore.userUsername=username.value
}
})
changingName.value=false
}
const changePasswordFormRef = ref<FormInstance>()
const phoneFormRef = ref<FormInstance>()
const mailFormRef = ref<FormInstance>()
const changePasswordFormVisible = ref(false)
const phoneFormVisible = ref(false)
const mailFormVisible = ref(false)
const changePasswordForm = reactive({
userId: '',
oldPassword: '',
newPassword: '',
userConfirmPassword: ''
})
const phoneForm = reactive({
userId: '',
userPhone: '',
verifyCode: ''
})
const mailForm = reactive({
userId: '',
userMail: '',
verifyCode: ''
})
let phoneVerifyText=ref('获取')
let mailVerifyText=ref('获取')
let phoneTime=0
let mailTime=0
let canGetMailVerifyCode=ref(true)
let canGetPhoneVerifyCode=ref(true)
const logout = () => { const logout = () => {
axios.get('/user/logout') ElMessageBox.confirm(
'确定要退出登录吗?',
'警告',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
axios.get('/user/logout')
.then((res)=>{
ElMessage.success('登出成功');
localStorage.removeItem("token")
router.push('/login')
})
})
.catch(() => {})
}
const validateOldPass = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('请输入密码'))
}
else {
callback()
}
}
const validatePass = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('请输入密码'))
}
else {
if (changePasswordForm.userConfirmPassword !== '') {
if (!changePasswordFormRef.value) return
changePasswordFormRef.value.validateField('userConfirmPassword', () => null)
}
callback()
}
}
const validateConfirmPass = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('请再次输入密码'))
} else if (value !== changePasswordForm.newPassword) {
callback(new Error("输入的两次密码不一致!"))
} else {
callback()
}
}
const validateEmail = (rule: any, value: any, callback: any) => {
if (!value) {
callback(new Error("请输入邮箱"))
}
else if (value.indexOf('@')==-1)
{
callback(new Error("请输入正确格式的邮箱"))
}
else {
callback()
}
}
const validatePhone = (rule: any, value: any, callback: any) => {
if (!value) {
callback(new Error("请输入手机号"))
}
else if (!Number(value))
{
callback(new Error("请输入数字"))
}
else if (value.length!=11)
{
callback(new Error("请输入正确格式的11位手机号"))
}
else {
callback()
}
}
const phoneRules = reactive({
userPhone: [
{ validator: validatePhone, trigger: 'blur' },
],
verifyCode: [
{ required: true, message: '请输入验证码', trigger: 'change' },
]
})
const mailRules = reactive({
userMail: [
{ validator: validateEmail, trigger: 'blur' },
],
verifyCode: [
{ required: true, message: '请输入验证码', trigger: 'change' },
]
})
const psswordRules = reactive({
oldPassword: [
{ validator: validateOldPass, trigger: 'blur' },
{ min: 6, max: 60, message: '密码长度必须在6到60位之间', trigger: 'blur' },
],
newPassword: [
{ validator: validatePass, trigger: 'blur' },
{ min: 6, max: 60, message: '密码长度必须在6到60位之间', trigger: 'blur' },
],
userConfirmPassword: [
{ validator: validateConfirmPass, trigger: 'blur' },
{ min: 6, max: 60, message: '密码长度必须在6到60位之间', trigger: 'blur' },
],
})
const changePassword = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
changePasswordForm.userId=userStore.userId
axios.post('/user/changePassword',qs.stringify(changePasswordForm))
.then(res=>{
if(res.data=="wrongPassword")
{
ElMessage.error('密码输入错误');
}
else if(res.data=="error")
{
ElMessage.error('修改发生错误')
}
else
{
ElMessage.success('密码修改成功,请重新登陆!')
axios.get('/user/logout')
.then((res)=>{
ElMessage.success('登出成功');
localStorage.removeItem("token")
router.push('/login')
})
}
})
}
})
}
const setPhone = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
phoneForm.userId=userStore.userId
axios.post('/user/setPhone',qs.stringify(phoneForm))
.then(res=>{
if(res.data=="wrongVerifyCode")
{
ElMessage.error('验证码输入错误');
}
else if(res.data=="needRequestVerifyCode")
{
ElMessage.error('还未申请验证码或验证码已经过期')
}
else
{
ElMessage.success('手机绑定成功!')
userStore.userPhone=phoneForm.userPhone
phoneFormVisible.value=false
}
})
}
})
}
const setMail = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
mailForm.userId=userStore.userId
axios.post('/user/setMail',qs.stringify(mailForm))
.then(res=>{
if(res.data=="wrongVerifyCode")
{
ElMessage.error('验证码输入错误');
}
else if(res.data=="needRequestVerifyCode")
{
ElMessage.error('还未申请验证码或验证码已经过期')
}
else
{
ElMessage.success('邮箱绑定成功!')
userStore.userMail=mailForm.userMail
mailFormVisible.value=false
}
})
}
})
}
const getPhoneVerifyCode = () => {
if(phoneForm.userPhone.length!=11)
{
ElMessageBox.alert('请输入正确的手机号','格式错误',{confirmButtonText:'确认'})
return
}
axios.get('/user/applyPhoneVerifyCode?account='+phoneForm.userPhone)
.then((res)=>{ .then((res)=>{
ElMessage.success('登出成功'); if(res.data=='haveVerifyCode')
localStorage.removeItem("token") {
router.push('/') ElMessageBox.alert('请求验证码过于频繁,请检查收件箱','验证码已发送',{confirmButtonText:'确认'})
}
else if(res.data=='haveAccount')
{
ElMessageBox.alert('该手机号已被注册','已注册',{confirmButtonText:'确认'})
}
else if(res.data=='sendSmsSuccess')
{
ElMessage.success('验证码已发送!')
phoneTime=60*10
phoneTimer()
}
else
{
ElMessageBox.alert('错误原因:'+res.data,'验证码发送失败',{confirmButtonText:'确认'})
}
}) })
} }
const getMailVerifyCode = () => {
if(mailForm.userMail.indexOf('@')==-1)
{
ElMessageBox.alert('请输入正确的邮箱','格式错误',{confirmButtonText:'确认'})
return;
}
else
{
axios.get('/user/applyMailVerifyCode?account='+mailForm.userMail)
.then((res)=>{
if(res.data=='haveVerifyCode')
{
ElMessageBox.alert('请求验证码过于频繁,请检查收件箱','验证码已发送',{confirmButtonText:'确认'})
}
else if(res.data=='haveAccount')
{
ElMessageBox.alert('该邮箱已被注册','已注册',{confirmButtonText:'确认'})
}
else if(res.data=='sendMailSuccess')
{
ElMessage.success('验证码已发送!')
mailTime=60*10
mailTimer()
}
else
{
ElMessageBox.alert('请检查邮箱是否正确若无问题请联系PeterAlbus','验证码发送失败',{confirmButtonText:'确认'})
}
})
}
}
const phoneTimer = () => {
if(phoneTime>0)
{
phoneVerifyText.value=phoneTime+'s'
phoneTime--
canGetPhoneVerifyCode.value=false
setTimeout(phoneTimer,1000)
}
else
{
canGetPhoneVerifyCode.value=true
phoneVerifyText.value='获取'
}
}
const mailTimer = () => {
if(mailTime>0)
{
mailVerifyText.value=mailTime+'s'
mailTime--
canGetMailVerifyCode.value=false
setTimeout(mailTimer,1000)
}
else
{
canGetMailVerifyCode.value=true
mailVerifyText.value='获取'
}
}
const uploadRef=ref<InstanceType<typeof ElUpload>>()
const submitUpload = ()=>{
uploadRef.value!.submit();
}
const handleAvatarSuccess = (res: UploadProgressEvent, file: UploadFile) => {
ElMessage.success("更换头像成功成功")
userStore.userAvatar=res+''
}
const beforeAvatarUpload = (file: UploadRawFile) => {
const isIMG = file.type === 'image/jpeg'||file.type === 'image/png'||file.type === 'image/gif'
const isLt10M = file.size / 1024 / 1024 < 10
if (!isIMG) {
ElMessage.error('选择的文件不是jpg/png格式')
}
if (!isLt10M) {
ElMessage.error('图片大小不能超过10M')
}
return isIMG && isLt10M
}
const upData=computed(()=>{
return {userId: userStore.userId}
})
const identityType = computed(()=>{
if(userStore.userIdentity==0)
{
return "warning"
}
else if(userStore.userIdentity==1)
{
return "success"
}
else if(userStore.userIdentity==5)
{
return ""
}
else
{
return "info"
}
})
const userIdentity = computed(()=>{
if(userStore.userIdentity==0)
{
return "站长"
}
else if(userStore.userIdentity==1)
{
return "管理员"
}
else if(userStore.userIdentity==5)
{
return "普通用户"
}
else
{
return "游客"
}
})
</script> </script>
<style scoped> <style scoped>
.user-box{
width: 80vw;
max-width: 800px;
background-color: white;
border-radius: 5px;
padding: 30px;
box-shadow: 0 3px 8px 6px rgba(7,17,27,0.05);
}
.user-box:hover
{
box-shadow: 0 5px 12px 8px rgba(7,17,27,0.1);
}
.flex-box{
display: flex;
justify-content: center;
align-items: center;
}
.user-center-info{
margin: 20px;
line-height: 32px;
height: 32px;
}
</style> </style>

Loading…
Cancel
Save