提交 986d8eef authored 作者: 龙菲's avatar 龙菲

修改密码

上级 2f08d0cb
......@@ -26,6 +26,43 @@ export function register(data) {
})
}
// 修改用户信息
export function editUserInfo(data) {
return request({
url: '/sys/user/info',
method: 'put',
data
})
}
// 修改密码
export function editUserPwd(data) {
return request({
url: '/sys/user/pwd',
method: 'put',
data
})
}
// 注册时验证账号是否唯一
export function checkUserName(data) {
return request({
url: '/sys/user/checkAccount',
method: 'post',
data
})
}
// 注册时验证手机号是否唯一
export function checkPhone(data) {
return request({
url: '/sys/user/checkPhone',
method: 'post',
data
})
}
export function updateUserInfo(data) {
return request({
url: '/sys/user',
......
......@@ -32,48 +32,20 @@
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
><span
v-if="!hasToken"
@click="handleToLogin"
@click.native="handleToLogin"
class="operation-item"
>登陆</span
></el-dropdown-item
>
>登陆
</el-dropdown-item>
<el-dropdown-item
><router-link
v-if="hasToken"
to="/personal"
class="operation-item"
>个人中心</router-link
></el-dropdown-item
>
<el-dropdown-item>
<span v-if="hasToken" @click="handleLogOut">退出</span>
<!-- <span class="logout" v-if="hasToken">
<el-popover
placement="bottom"
width="200"
trigger="click"
v-model="logoutDialogVisible"
>
<p>确定退出吗?</p>
<div style="text-align: right; margin: 0">
<el-button
size="mini"
type="text"
@click="logoutDialogVisible = false"
>取消</el-button
@click.native="handleToPersonal"
>
<el-button
type="primary"
size="mini"
>确定</el-button
个人中心</el-dropdown-item
>
</div>
</el-popover> -->
<!-- </span> -->
<el-dropdown-item v-if="hasToken" @click.native="handleLogOut">
<span>退出</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
......@@ -81,19 +53,35 @@
</div>
</div>
</div>
<el-dialog :visible.sync="loginVisible" append-to-body title="账号登陆">
<el-dialog :visible.sync="loginVisible" append-to-body>
<div slot="title" class="login-title">
<div
:class="['title-item', isLoginByUsername ? 'active' : '']"
@click="handleChangeLoginWay('username')"
>
账号登录
</div>
<div
:class="['title-item', isLoginByUsername ? '' : 'active']"
@click="handleChangeLoginWay('phone')"
>
手机号登录
</div>
<div class="line"></div>
</div>
<div class="login">
<el-form
:model="loginForm"
:label-position="labelPosition"
ref="loginForm"
:rules="loginRules"
>
<el-form-item :label-width="formLabelWidth" prop="username">
<el-form-item :label-width="formLabelWidth" prop="account">
<el-input
v-model="loginForm.username"
v-model="loginForm.account"
autocomplete="off"
clearable
placeholder="用户名/手机号"
:placeholder="isLoginByUsername ? '账号' : '手机号'"
></el-input>
</el-form-item>
<el-form-item :label-width="formLabelWidth" prop="password">
......@@ -205,8 +193,30 @@ export default {
showLoginDialog(value) {
this.loginVisible = value;
},
loginVisible(value) {
if (value) {
this.handleGetCaptcha();
}
},
},
data() {
var validateAccout = (rule, value, callback) => {
if (value === "") {
let text = this.isLoginByUsername ? "账号" : "手机号";
callback(new Error("请输入" + text));
} else {
if (!this.isLoginByUsername) {
var pattern = /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/;
if (!pattern.test(value)) {
callback(new Error("请输入合法手机号/电话号"));
} else {
callback();
}
} else {
callback();
}
}
};
return {
pages: [
{
......@@ -234,8 +244,6 @@ export default {
path: "/museum",
},
],
userName: "",
logoutDialogVisible: false,
currentTab: {
name: "首页",
path: "/",
......@@ -245,7 +253,7 @@ export default {
offsetTop: 0,
loginVisible: false,
loginForm: {
username: "",
account: "",
password: "",
captcha: "",
},
......@@ -255,17 +263,15 @@ export default {
labelPosition: "right",
loading: false,
loginRules: {
username: [
{ required: true, trigger: "blur", message: "请输入用户名" },
account: [
{ validator: validateAccout, required: true, trigger: "blur" },
],
password: [{ required: true, trigger: "blur", message: "请输入密码" }],
captcha: [{ required: true, trigger: "blur", message: "请输入验证码" }],
},
isLoginByUsername: true,
};
},
created() {
this.handleGetCaptcha();
},
mounted() {
window.addEventListener("scroll", this.initHeight);
this.$nextTick(() => {
......@@ -290,13 +296,27 @@ export default {
this.loginVisible = true;
},
handleToPersonal() {
this.$router.push("/personal");
},
async handleLogOut() {
this.$confirm("是否确定退出?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(async () => {
await this.$store.dispatch("user/logout");
this.logoutDialogVisible = false;
let path = this.$route.fullPath;
if (path.indexOf("/personal") != -1) {
this.$router.push("/");
}
this.$message.success("已成功退出!");
})
.catch((err) => {
console.log();
});
},
handleClickTab(tab) {
......@@ -306,15 +326,33 @@ export default {
handleLoginSubmit() {
this.$refs.loginForm.validate((valid) => {
if (valid) {
// debugger
this.loading = true;
const { account, password, captcha } = this.loginForm;
const params = {
captcha,
password,
};
if (this.isLoginByUsername) {
params.username = account;
} else {
params.phone = account;
}
this.$store
.dispatch("user/login", this.loginForm)
.then(() => {
this.$router.push({ path: this.$route.query.redirect || "/" });
this.loading = false;
.dispatch("user/login", params)
.then((res) => {
if (res.code == "0") {
this.handleCloseLogin();
if (this.$route.name !== "home") {
this.$router.push({
path: this.$route.query.redirect || "/",
});
}
}
this.loading = false;
})
.catch(() => {
.catch((err) => {
console.log(err);
this.loading = false;
});
} else {
......@@ -341,6 +379,16 @@ export default {
this.requestCodeSuccess = false;
});
},
handleChangeLoginWay(type) {
this.isLoginByUsername = type === "username";
let line = document.getElementsByClassName("line")[0];
if (this.isLoginByUsername) {
line.style.left = "24px";
} else {
line.style.left = "136px";
}
},
},
destroyed() {
......@@ -535,7 +583,7 @@ export default {
::v-deep .loginBtn {
padding: 16px !important;
border-radius: 26px !important;
border-radius: 0 !important;
width: 100%;
background-color: #2069c4;
color: #fff;
......@@ -545,7 +593,7 @@ export default {
background-color: #2069c4;
color: #fff;
border: none;
border-radius: 26px !important;
border-radius: 0 !important;
padding: 16px !important;
width: 100%;
font-size: 14px;
......@@ -553,7 +601,7 @@ export default {
}
::v-deep .el-dialog {
width: 380px;
border-radius: 16px;
border-radius: 0;
.el-dialog__body {
padding: 20px 30px 60px !important;
}
......@@ -575,4 +623,31 @@ export default {
font-size: 24px;
right: 30px;
}
.login-title {
display: flex;
position: relative;
.title-item {
margin-right: 40px;
cursor: pointer;
position: relative;
&:hover {
color: #2069c4;
}
}
.active {
color: #2069c4;
}
.line {
width: 18px;
height: 4px;
background-color: #2069c4;
// border-radius: 4px;
position: absolute;
left: 24px;
bottom: -14px;
transition: all 0.3s ease;
}
}
</style>
......@@ -41,9 +41,6 @@ const mutations = {
SET_USERINFO: (state, userInfo) => {
state.userInfo = userInfo
},
// SET_DEPTLIST:(state,deptList)=>{
// state.deptList = deptList
// }
}
const actions = {
......@@ -51,17 +48,8 @@ const actions = {
login({
commit
}, userInfo) {
const {
username,
password,
captcha
} = userInfo
return new Promise((resolve, reject) => {
login({
username: username.trim(),
password: password,
captcha: captcha
}).then(response => {
login(userInfo).then(response => {
const {
data
} = response
......@@ -71,7 +59,7 @@ const actions = {
setToken(data.accessToken)
setUserInfo(data)
// window.location.reload()
resolve()
resolve(response)
// window.location.reload()
}).catch(error => {
reject(error)
......
import axios from 'axios'
var validatePhoneUrl = process.env.VUE_APP_BASE_API + "/sys/user/checkPhone"
var validateUserNameUrl = process.env.VUE_APP_BASE_API + "/sys/user/checkAccount"
/**
* 验证电话是否重复
* @param data
* @returns {Promise}
*/
export function checkPhone(data) {
return new Promise((resolve, reject) => {
axios.post(validatePhoneUrl, data).then(response => {
resolve(response.data)
}).catch(error => {
reject(error)
})
})
}
/**
* 验证用户名是否重复
* @param data
* @returns {Promise}
*/
export function checkUserName(data) {
return new Promise((resolve, reject) => {
axios.post(validateUserNameUrl, data, {
headers: {
'Content-Type': 'multipart/form-data;boundary = ' + new Date().getTime(),
}
}).then(response => {
resolve(response.data)
}).catch(error => {
reject(error)
})
})
}
\ No newline at end of file
<template>
<div class="display-detail">
<div class="content" id="content">
<div class="content-item sliders" ref="imgs">
<div
class="content-item sliders"
ref="imgs"
v-if="displayDetail.imagesVo && displayDetail.imagesVo.length > 0"
>
<div class="view-box">
<div
class="slide-group"
......@@ -78,7 +82,14 @@
<div class="divider"></div>
<div class="intro-and-video">
<el-row :gutter="70">
<el-col class="intro-container" :span="12">
<el-col
class="intro-container"
:span="
displayDetail.videosVo && displayDetail.videosVo.length > 0
? 12
: 24
"
>
<div class="intro-title">展览简介</div>
<div class="intro-content">
{{ displayDetail.intro }}
......@@ -102,13 +113,17 @@
</el-col>
</el-row>
</div>
<div class="audio wow animate__animated animate__fadeRight" @click="handleClickAudio" >
<div
class="audio"
:style="{ animationPlayState: audioPlaying ? 'running' : 'paused' }"
@click="handleClickAudio"
v-if="displayDetail.audiosVo && displayDetail.audiosVo.length > 0"
>
<img src="@/assets/imgs/display/audio.png" alt="" />
<AudioPlayer
style="display: none"
:url="$getFullUrl(displayDetail.audiosVo[0].url)"
ref="AudioPlayer"
v-if="displayDetail.audiosVo && displayDetail.audiosVo.length > 0"
/>
</div>
</div>
......@@ -151,7 +166,7 @@
</div>
</div>
</div>
<div class="content-item lts wow animate__animated animate__fadeInUp">
<div class="content-item lts">
<div class="wrapper">
<div class="custom-title">
<div class="custom-title-prefix">
......@@ -163,6 +178,7 @@
</div>
</div>
</div>
<div
class="lts-content"
v-if="
......@@ -271,6 +287,13 @@ export default {
]);
this.loadDetail();
},
destroyed() {
//同时在destroyed回调中移除监听:
if (navigator.userAgent.toLowerCase().indexOf("firefox") >= 0) {
//firefox支持onmousewheel
removeEventListener("DOMMouseScroll", firefoxListenFun);
}
},
methods: {
async loadDetail() {
let exhibitionId = this.$route.params.exhibitionId;
......@@ -299,19 +322,30 @@ export default {
}
this.$nextTick(() => {
this.loadWidth();
if (
this.displayDetail.videosVo &&
this.displayDetail.videosVo.length > 0
) {
this.$message.info("正在播放当前文物讲解音频,点击按钮可关闭");
this.$refs.AudioPlayer.play();
}
});
}
}
},
loadWidth() {
if (
this.displayDetail.imagesVo &&
this.displayDetail.imagesVo.length > 0
) {
let slideImage = document.getElementsByClassName("slide-item")[0];
this.slideImageWidth = slideImage.offsetWidth;
this.sildeGroupWidth =
this.slideImageWidth * this.displayDetail.imagesVo.length;
this.slideGroupleft = -3 * this.slideImageWidth;
}
},
handleImgsSlide(e) {
......@@ -320,7 +354,21 @@ export default {
},
addImgsEventListener(e) {
let firefoxListenFun = function (e) {
e = e || window.event;
if (navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
// IE
e.returnValue = false;
} else {
// Chrome
e.preventDefault();
}
if (navigator.userAgent.toLowerCase().indexOf("firefox") >= 0) {
//firefox支持onmousewheel
addEventListener("DOMMouseScroll", this.firefoxListenFun, false);
}
},
firefoxListenFun(e) {
var obj = e.target;
var onmousewheel;
while (obj) {
......@@ -342,20 +390,6 @@ export default {
obj.onmousewheel(e);
}, 1);
}
};
e = e || window.event;
if (navigator.userAgent.toLowerCase().indexOf("msie") >= 0) {
// IE
e.returnValue = false;
} else {
// Chrome
e.preventDefault();
}
if (navigator.userAgent.toLowerCase().indexOf("firefox") >= 0) {
//firefox支持onmousewheel
addEventListener("DOMMouseScroll", firefoxListenFun, false);
}
},
pageUpOrDown(e) {
......@@ -419,6 +453,7 @@ export default {
this.audioPlaying = !this.audioPlaying;
if (this.audioPlaying) {
this.$refs["AudioPlayer"].play();
// console.log(this.$refs['audioContainer']);
} else {
this.$refs["AudioPlayer"].pause();
}
......@@ -461,6 +496,7 @@ export default {
overflow-x: hidden;
.content {
width: 100%;
overflow-y: hidden;
.content-item {
width: 100%;
}
......@@ -468,7 +504,8 @@ export default {
/**轮播图 */
.sliders {
height: 434px;
margin: 52px 0 84px 0;
// margin: 52px 0 84px 0;
margin-top: 52px;
display: flex;
justify-content: center;
position: relative;
......@@ -507,12 +544,13 @@ export default {
width: 1200px;
transform: translateY(-25px);
position: relative;
filter:drop-shadow(2px 4px 6px #f8f8f8);
filter: drop-shadow(2px 4px 6px #f8f8f8);
img {
transform: translateX(-10px);
}
}
.left-layer,.right-layer {
.left-layer,
.right-layer {
flex: 1;
height: 100%;
background-color: rgba(#f8f8f8, 0.8);
......@@ -522,7 +560,7 @@ export default {
/**展览信息 */
.intro {
margin-bottom: 96px;
margin-top: 84px;
display: flex;
justify-content: center;
......@@ -622,11 +660,15 @@ export default {
border: 1px solid #892325;
border-radius: 50%;
// padding: 10px;
width: 90px;
height: 90px;
width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
img {
width: 28px;
height: 28px;
}
}
}
}
......@@ -656,7 +698,7 @@ export default {
/**展览单元 */
.units {
margin-bottom: 100px;
margin-top: 94px;
display: flex;
flex-direction: column;
align-items: center;
......@@ -700,6 +742,7 @@ export default {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 100px;
.lts-content {
display: flex;
justify-content: center;
......
<!-- -->
<template>
<div class="display-detail">
<!-- <div class="search">
<SearchBar
:options="options"
:selectValue="selectValue"
:keyword="keyword"
/>
</div> -->
<div class="empty-space"></div>
<div class="wrapper">
<div class="back">
<el-button
type="text"
icon="el-icon-arrow-left"
@click.native="handleBack"
>返回上页</el-button
>
</div>
<el-row class="detail-container" :gutter="30">
<el-col class="cr-images" :span="16">
<el-carousel
indicator-position="outside"
:autoplay="false"
height="600px"
>
<el-carousel-item
v-for="(item, index) in displayDetail.imagesVo"
:key="index"
>
<el-image
style="width: 100%; height: 100%"
:src="$getFullUrl(item.url)"
fit="contain"
></el-image>
</el-carousel-item>
</el-carousel>
<div class="enlarge" @click="handelPreviewImages">
<img src="@/assets/imgs/enlarge-s.png" alt="" />
</div>
</el-col>
<el-col class="relic-info" :span="8">
<div class="info-title">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
"
>
<h4>
{{ displayDetail.title }}
</h4>
<span class="view-container">
<svg-icon icon-class="view" class="view-svg-icon"></svg-icon>
<span class="view-text">{{ displayDetail.browseCount }}</span>
</span>
</div>
<AudioPlayer
:url="$getFullUrl(displayDetail.audiosVo[0].url)"
ref="AudioPlayer"
v-if="displayDetail.audiosVo && displayDetail.audiosVo.length > 0"
/>
</div>
<div class="info-body">
<div class="basic-info">
<!-- <div class="body-item">
<span class="label">年份</span>
<span class="value">{{ displayDetail.yearsLabel }}</span>
</div>
<div class="body-item">
<span class="label">类别</span>
<span class="value">
{{ displayDetail.typeLabel }}
</span>
</div>-->
<div class="body-item">
<span class="label">开始日期</span>
<span class="value">{{ displayDetail.startDate }}</span>
</div>
<div class="body-item">
<span class="label">结束日期</span>
<span class="value">{{ displayDetail.endDate }}</span>
</div>
<div class="body-item">
<span class="label">关键词</span>
<span class="value">{{ displayDetail.keyword }}</span>
</div>
<div class="body-item">
<span class="label">展览单位</span>
<span class="value">{{ displayDetail.deptName }}</span>
</div>
</div>
</div>
<!-- <div class="qrcode" ref="qrCodeUrl"></div> -->
<!-- </div> -->
<ReaderOperations
:loveCount="displayDetail.loveCount"
:loveCountStatus="Boolean(displayDetail.loveCountStatus)"
:collectCount="displayDetail.collectCount"
:collectCountStatus="Boolean(displayDetail.collectCountStatus)"
:sourceId="displayDetail.exhibitionId"
:title="displayDetail.title"
:sourceType="'biz_exhibition'"
@reload="loadDetail"
/>
</el-col>
</el-row>
<div class="margin-bottom-32">
<CustomTitle text="展览介绍" />
<div class="intro text-indent">
{{ displayDetail.intro }}
</div>
</div>
<div
class="margin-bottom-32"
v-if="
displayDetail.exhibitionUnits &&
displayDetail.exhibitionUnits.length > 0
"
>
<CustomTitle text="展览单元" />
<el-row :gutter="20">
<el-col :span="8">
<!-- 只能单开 unique-opened -->
<menu-list
:items="displayDetail.exhibitionUnits"
:isCollapse="false"
@open="handleOpenUnit"
></menu-list>
</el-col>
<el-col :span="16">
<el-card>
<div slot="header" class="clearfix">
<span>单元介绍</span>
</div>
<div class="unit-content">
<div class="intro text-indent" v-if="curUnit.intro">
{{ curUnit.intro }}
</div>
<div
class="images"
v-if="curUnit.imagesVo && curUnit.imagesVo.length > 0"
>
<el-row :gutter="20">
<el-col
:span="24 / curUnit.imagesVo.length"
v-for="item in curUnit.imagesVo"
:key="item.euId"
class="margin-bottom-32"
>
<img :src="$getFullUrl(item.url)" alt="" srcset="" width="100%" />
<div class="desc flex-center">
{{ item.name }}
</div>
</el-col>
</el-row>
</div>
<div
class="videos"
v-if="curUnit.videosVo && curUnit.videosVo.length > 0"
>
<el-row :gutter="20">
<el-col
:span="24 / curUnit.videosVo.length"
v-for="item in curUnit.videosVo"
:key="item.euId"
>
<Video :url="$getFullUrl(item.url)" />
</el-col>
</el-row>
</div>
</div>
</el-card>
</el-col>
</el-row>
</div>
<div
class="margin-bottom-32"
v-if="
displayDetail.culturalRelicVo &&
displayDetail.culturalRelicVo.length > 0
"
>
<CustomTitle text="关联文物" />
<el-row :gutter="20">
<el-col
:span="6"
v-for="(item, index) in displayDetail.culturalRelicVo"
:key="index"
>
<Card :title="item.name" :url="$getFullUrl(item.faceImageUrl)"
/></el-col>
</el-row>
</div>
<div
class="relate-video margin-bottom-32"
v-if="displayDetail.videosVo && displayDetail.videosVo.length > 0"
>
<CustomTitle text="关联视频" />
<el-carousel :interval="4000" type="card" height="400px">
<el-carousel-item
v-for="item in displayDetail.videosVo"
:key="item.fileId"
>
<div class="video-container">
<div class="video-box">
<Video :url="$getFullUrl(item.url)" />
</div>
<div class="info-box">
<h4 class="name">{{ item.name.split(".")[0] }}</h4>
</div>
</div>
</el-carousel-item>
</el-carousel>
</div>
<div class="relate-book margin-bottom-32">
<CustomTitle text="相关文献" />
<div
class="book-item"
v-for="(item, index) in displayDetail.literatureVo"
:key="index"
>
<span class="mr-20">{{ item.name }}</span>
<span class="mr-20">{{ item.author }}</span>
<span>{{ item.source }}</span>
</div>
</div>
<!-- <div class="relate-cultual-relic margin-bottom-32">
<CustomTitle text="关联文物" />
<div class="display-group">
<div
class="display-item"
v-for="(item, index) in relateRelics"
:key="index"
@click="handleToDetail(item.exhibitionId)"
>
<img :src="item.faceImageUrl" width="100%" :alt="item.title" />
<div class="display-desc">
<div class="desc-title">
<h4>{{ item.name }}</h4>
</div>
</div>
</div>
</div>
</div> -->
</div>
<el-image-viewer
v-if="imgViewerVisible"
:on-close="closeImgViewer"
:url-list="imgList"
/>
</div>
</template>
<script>
import SearchBar from "@/components/SearchBar";
import AudioPlayer from "@/components/AudioPlayer";
import CustomTitle from "@/components/CustomTitle";
import ReaderOperations from "@/components/ReaderOperations";
import Card from "@/views/personal/components/Card";
import Video from "@/components/Video";
import QRCode from "qrcodejs2";
import { getDisplayById } from "@/api/display";
import MenuList from "@/components/MenuList";
export default {
components: {
SearchBar,
CustomTitle,
AudioPlayer,
ReaderOperations,
MenuList,
Video,
Card,
"el-image-viewer": () =>
import("element-ui/packages/image/src/image-viewer"),
},
data() {
return {
options: [
{
value: "name",
label: "文物名称",
},
],
selectValue: "",
keyword: "",
displayDetail: {},
slideImageWidth: "",
imgViewerVisible: false,
relateRelics: [],
curUnit: [],
};
},
mounted() {
// this.creatQrCode();
this.loadDetail();
},
methods: {
creatQrCode() {
this.$nextTick(() => {
var qrcode = new QRCode(this.$refs.qrCodeUrl, {
text: "http://www.gzmuseum.com/", // 需要转换为二维码的内容
width: 100,
height: 100,
colorDark: "#000000",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.H,
});
});
},
async loadDetail() {
let exhibitionId = this.$route.params.exhibitionId;
if (exhibitionId) {
let res = await getDisplayById({ exhibitionId });
if (res.code == 0) {
this.displayDetail = res.data;
// debugger
// 处理单元数据
if (
this.displayDetail.exhibitionUnits &&
this.displayDetail.exhibitionUnits.length > 0
) {
this.curUnit = this.displayDetail.exhibitionUnits[0];
}
processUnit(this.displayDetail.exhibitionUnits);
// console.log(unit);
function processUnit(list) {
for (let o of list || []) {
if (o.children) {
if (o.children.length == 0) {
o.children = null;
} else {
processUnit(o.children);
}
}
}
}
// 获取关联文物
// this.loadCrRecommend();
this.$nextTick(() => {
// this.$message.info("正在播放当前文物讲解音频,点击按钮可关闭");
// this.$refs.AudioPlayer.play();
});
}
}
},
handleBack() {
this.$router.go(-1);
},
closeImgViewer() {
this.imgViewerVisible = false;
},
handelPreviewImages() {
this.imgViewerVisible = true;
this.imgList = this.displayDetail.imagesVo.map((item) => this.$getFullUrl(item.url));
},
handleToDetail(exhibitionId) {
console.log(crId);
this.$router.replace({ name: "displayDetail", params: { exhibitionId } });
},
handleOpenUnit(item) {
this.curUnit = item;
},
},
};
</script>
<style lang="scss" scoped>
.mr-20 {
margin-right: 20px;
}
$label: #9f9c9a;
.search {
width: 1200px;
margin: auto;
margin-bottom: 32px;
}
.wrapper {
width: 1200px;
margin: 60px auto;
background-color: #fff;
padding: 60px;
.back {
font-size: 18px;
font-weight: bold;
margin-bottom: 40px;
.el-button {
color: $label;
}
}
.detail-container {
margin-bottom: 32px;
// display: flex;
img {
max-width: 100%;
height: auto;
}
.cr-images {
width: 700px;
// margin-right: 32px;
position: relative;
.el-image {
background-color: #f5f5f9;
}
.enlarge {
position: absolute;
bottom: 60px;
right: 40px;
display: flex;
z-index: 9;
background-color: #c1925b;
width: 40px;
height: 40px;
border-radius: 12px;
display: flex;
justify-content: center;
align-items: center;
margin-right: 10px;
cursor: pointer;
img {
width: 24px;
height: 24px;
}
}
}
.relic-info {
.info-title {
display: flex;
// align-items: center;
flex-direction: column;
margin-bottom: 40px;
.play {
margin-left: 10px;
font-size: 32px;
cursor: pointer;
}
}
.info-body {
display: flex;
justify-content: space-between;
align-items: flex-end;
.basic-info {
.body-item {
display: flex;
.label {
display: block;
width: 80px;
margin-right: 26px;
margin-bottom: 10px;
font-weight: bold;
color: #9f9c9a;
}
}
}
}
.view-3d {
margin-top: 32px;
padding: 6px 10px;
width: 100%;
background-color: #c1925b;
border-radius: 48px;
display: flex;
justify-content: center;
align-items: center;
color: white;
cursor: pointer;
img {
margin-right: 10px;
}
}
}
.title-container {
display: flex;
justify-content: center;
position: relative;
.operation {
position: absolute;
right: 0;
display: flex;
align-items: center;
height: 100%;
}
}
.content {
text-indent: 32px;
}
}
.relate-book {
.book-item {
margin-bottom: 10px;
}
}
.relate-cultual-relic {
.display-group {
margin-top: 24px;
display: flex;
flex-flow: row wrap;
.display-item {
width: 282px;
margin-bottom: 32px;
border-radius: 16px;
border: 1px solid rgba(0, 0, 0, 0.1);
// padding: 0 0 32px 0;
background-color: #fff;
margin-right: 10px;
cursor: pointer;
img {
border-radius: 16px 16px 0 0;
}
.display-desc {
padding: 0 16px;
.desc-content {
text-indent: 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: block;
}
}
.display-source {
margin-top: 8px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 16px;
}
}
}
}
.relate-video {
.video-container {
display: flex;
flex-direction: column;
align-items: center;
.video-box {
display: flex;
justify-content: center;
border: 1px solid #000;
video {
width: 800px;
}
}
.info-box {
width: 800px;
display: flex;
justify-content: space-between;
}
}
}
}
.text-indent {
text-indent: 28px;
}
.margin-bottom-32 {
margin-bottom: 32px;
}
</style>
<template>
<div class="personal-info">
<el-descriptions class="margin-top" title="个人信息" :column="3" border>
<template slot="extra">
<div v-if="!isEditing">
<el-button
type="primary"
size="small"
@click.native="handleEdit('userInfo')"
>编辑个人信息</el-button
>
<el-button
type="primary"
size="small"
@click.native="handleEdit('pwd')"
>修改密码</el-button
>
</div>
<div v-else>
<el-button type="primary" size="small" @click.native="handleReSet"
>取消修改</el-button
>
<el-button
type="primary"
size="small"
@click.native="handleSubmit('userInfo')"
>保存</el-button
>
</div>
</template>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-user"></i>
用户名
</template>
<div class="name">个人信息</div>
<div class="info-item">
<div class="label">用户名</div>
<el-input
size="small"
v-if="isEditing"
v-model="userInfoForm.username"
style="width: 300px"
></el-input>
<div class="value" v-else>{{ userInfoForm.username || "暂未填写" }}</div>
</div>
<div class="info-item">
<div class="label">昵称</div>
<el-input
size="small"
v-if="isEditing"
v-model="userInfoForm.nickName"
style="width: 300px"
></el-input>
<span v-else> {{ userInfo.username }}</span>
</el-descriptions-item>
<el-descriptions-item>
<template slot="label">
<i class="el-icon-mobile-phone"></i>
手机号
</template>
<div class="value" v-else>{{ userInfoForm.nickName || "暂未填写" }}</div>
</div>
<div class="info-item">
<div class="label">手机号</div>
<el-input
size="small"
v-if="isEditing"
v-model="userInfoForm.phone"
style="width: 300px"
></el-input>
<span v-else> {{ userInfo.phone }}</span>
</el-descriptions-item>
</el-descriptions>
<div class="value" v-else>{{ userInfoForm.phone || "暂未填写" }}</div>
</div>
<div class="buttons">
<div
class="edit-button"
v-if="!isEditing"
@click="handleEdit('userInfo')"
>
修改个人信息
</div>
<div class="edit-button" v-if="!isEditing" @click="handleEdit('pwd')">
修改密码
</div>
<div class="edit-button" v-if="isEditing" @click="handleReSet">
取消修改
</div>
<div class="edit-button" v-if="isEditing" @click="handleSubmit">保存</div>
</div>
<el-dialog
title="修改密码"
:visible.sync="dialogFormVisible"
:visible="dialogFormVisible"
width="400px"
:modal="false"
append-to-body
@close="handleCloseChangePwd"
>
<el-form
:model="pwdForm"
label-position="right"
label-width="80px"
:rules="pwdRules"
ref="pwdForm"
>
<!-- <el-form :model="pwdData" label-position="right" label-width="80px">
<el-form-item label="旧密码">
<el-input v-model="pwdData.oldPwd" type="password"></el-input>
<el-form-item label="旧密码" prop="oldPwd">
<el-input v-model="pwdForm.oldPwd" type="password"></el-input>
</el-form-item>
<el-form-item label="新密码">
<el-input v-model="pwdData.newPwd" type="password"></el-input>
<el-form-item label="新密码" prop="newPwd">
<el-input v-model="pwdForm.newPwd" type="password"></el-input>
</el-form-item>
<el-form-item label="重复密码">
<el-input v-model="pwdData.repeatPwd" type="password"></el-input>
<el-form-item label="重复密码" prop="checkPass">
<el-input v-model="pwdForm.checkPass" type="password"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogFormVisible = false"
>确 定</el-button
>
</div> -->
<el-button type="primary" @click="handleChangePwd">确 定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import { editUserInfo, editUserPwd } from "@/api/user";
import { setUserInfo } from "@/utils/auth";
export default {
name: "Info",
data() {
var validatePass = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入新密码"));
} else {
var pattern =
/^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\W_!@#$%^&*`~()-+=]{8,30}$/;
if (!pattern.test(value)) {
callback(
new Error(
"密码长度至少8位,至少含数字,大写字母,小写字母,特殊符其中三种"
)
);
}
if (this.pwdForm.checkPass !== "") {
this.$refs.pwdForm.validateField("checkPass");
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"));
} else if (value !== this.pwdForm.newPwd) {
callback(new Error("两次输入密码不一致!"));
} else {
callback();
}
};
return {
dialogFormVisible: false,
pwdData: {
isEditBasicInfo: true,
isEditing: false,
userInfoForm: {},
pwdForm: {
oldPwd: "",
newPwd: "",
repeatPwd: "",
},
isEditBasicInfo: true,
isEditing: false,
userInfoForm: {},
pwdRules: {
oldPwd: [
{ trigger: "blur", required: true, message: "请输入当前密码" },
],
newPwd: [{ validator: validatePass, trigger: "blur", required: true }],
checkPass: [
{ validator: validatePass2, trigger: "blur", required: true },
],
},
};
},
computed: {
......@@ -114,30 +153,45 @@ export default {
if (this.isEditing) {
this.isEditing = false;
}
this.dialogFormVisible = true;
break;
}
},
handleSubmit(type) {
switch (type) {
case "userInfo":
console.log(this.userInfoForm);
break;
case "pwd":
break;
async handleSubmit(type) {
let res = await editUserInfo(this.userInfoForm);
if (res.code == "0") {
this.$message.success("修改成功!");
this.$store.commit("user/SET_USERINFO", this.userInfoForm);
setUserInfo(this.userInfoForm);
}
this.isEditing = false;
},
handleReSet() {
this.isEditing = false;
this.userInfoForm = this.userInfo;
},
editInfo() {
this.dialogFormVisible = true;
this.isEditBasicInfo = true;
async handleChangePwd() {
const { newPwd, oldPwd } = this.pwdForm;
const params = {
newPwd,
oldPwd,
};
let res = await editUserPwd(params);
if (res.code == "0") {
let path = this.$route.fullPath;
if (path.indexOf("/personal") != -1) {
this.$router.push("/");
}
this.$message.success("修改成功,请重新登录!");
this.$store.commit("app/OPEN_LOGIN_DIALOG", true);
}
},
editPassword() {
this.dialogFormVisible = true;
this.isEditBasicInfo = false;
handleCloseChangePwd() {
this.dialogFormVisible = false;
},
},
};
......@@ -153,4 +207,42 @@ export default {
border: none;
}
}
.personal-info {
margin-left: 40px;
.name {
margin-bottom: 40px;
font-weight: bold;
}
.info-item {
display: flex;
margin-bottom: 30px;
border-bottom: 1px solid #f3f5f6;
padding-bottom: 30px;
.label {
width: 100px;
color: #666;
}
.value {
color: #333;
}
}
.buttons {
display: flex;
.edit-button {
width: 160px;
height: 50px;
background-color: #2069c4;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
margin-right: 10px;
cursor: pointer;
&:hover {
filter: brightness(0.9);
}
}
}
}
</style>
\ No newline at end of file
<template>
<div class="personal">
<div class="content-wrapper">
<div class="title wow animate__animated animate__fadeInLeft">个人中心</div>
<div class="bottom-line wow animate__animated animate__fadeInLeft"></div>
<div class="main">
<el-tabs :tab-position="'left'" type="card" class="wrapper">
<el-tab-pane label="我的点赞">
......@@ -16,32 +18,24 @@
</el-tabs>
</div>
</div>
<!-- <Footer /> -->
</div>
</template>
<script>
import { relateRelics, exhibitions } from "@/mock/mock";
import Like from "./components/Like.vue";
import Collection from "./components/Collection.vue";
import Footprint from "./components/Footprint.vue";
import Info from "./components/Info.vue";
import NavBar from "@/components/NavBar";
import Footer from "@/components/Footer";
export default {
components: {
Like,
Collection,
Footprint,
Info,
NavBar,
Footer,
},
name: "Personal",
data() {
return {
relateRelics: relateRelics,
exhibitions: exhibitions,
list: ["我的点赞", "我的收藏", "浏览记录", "个人信息"],
};
},
......@@ -60,17 +54,29 @@ export default {
$blue: #2069c4;
.personal {
// width: 1200px;
padding-bottom: 100px;
display: flex;
justify-content: center;
background-color: #fff;
.content-wrapper {
display: flex;
justify-content: center;
align-items: center;
align-items: flex-start;
padding: 60px 0;
width: 1200px;
.title {
font-family: KaiTi;
font-size: 44px;
margin-bottom: 16px;
}
.bottom-line {
width: 50px;
background-color: #b8b8b8;
height: 2px;
margin-bottom: 40px;
}
.main {
padding: 40px;
width: 100%;
}
}
......@@ -108,7 +114,7 @@ $blue: #2069c4;
color: #2069c4;
}
}
::v-deep .el-descriptions{
::v-deep .el-descriptions {
margin-left: 30px;
}
</style>
\ No newline at end of file
......@@ -2,7 +2,17 @@
<div class="wrapper">
<div class="register">
<div class="title">
<div class="text">账号注册</div>
<div class="text">
账号注册
<el-tooltip
class="item"
effect="dark"
content="提示:若您已经使用微信账号在小程序平台登陆过后,系统将自动为您注册账号,初始密码为您的手机号,请直接登录"
placement="top-start"
>
<i class="el-icon-question tips"></i>
</el-tooltip>
</div>
<div class="close" @click="handleCloseLogin">×</div>
</div>
<el-form
......@@ -18,7 +28,7 @@
v-model="form.username"
autocomplete="off"
clearable
placeholder="账号长度6-20个字符,只能包括字母、数字、下划线"
placeholder="账号长度4-20个字符,只能包括字母、数字、下划线"
></el-input>
</el-form-item>
<el-form-item label="手机号" prop="phone">
......@@ -33,7 +43,7 @@
v-model="form.nickName"
autocomplete="off"
clearable
placeholder="昵称长度8~10个字符"
placeholder="2~10个字符,只能包含中英文、数字及下划线,不能以下划线开头或结尾"
></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
......@@ -55,11 +65,13 @@
</el-form-item>
<el-form-item class="submit-buttons">
<el-button @click="resetForm('registerForm')">重置</el-button>
<el-button @click.native="resetForm('registerForm')" v-if="!loading"
>重置</el-button
>
<el-button
:loading="loading"
type="primary"
@click="submitForm('registerForm')"
@click.native="submitForm"
class="submit"
>提交</el-button
>
......@@ -70,6 +82,8 @@
</template>
<script>
import { register } from "@/api/user";
import { checkUserName, checkPhone } from "@/utils/validate";
export default {
data() {
var validatePass = (rule, value, callback) => {
......@@ -101,13 +115,53 @@ export default {
callback();
}
};
var validateNickName = (rule, value, callback) => {
var validateUserName = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入昵称"));
callback(new Error("请输入账号"));
} else {
var pattern = /[^\a-\z\A-\Z0-9\u4E00-\u9FA5]{6,10}/g;
var pattern = /^[0-9a-zA-Z|_]{4,20}$/g;
if (!pattern.test(value)) {
callback(new Error("密码长度6~10位,只能包含中文、英文及数字"));
callback(new Error("账号长度4-20个字符,只能包括字母、数字、下划线"));
} else {
const formData = new FormData();
formData.append("userName", value);
checkUserName(formData)
.then((res) => {
if (res.code == "0") {
callback();
} else {
callback(res.msg);
}
})
.catch((err) => {
console.error(err);
});
}
}
};
var validatePhone = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入手机号"));
} else {
var pattern = /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/;
if (!pattern.test(value)) {
callback(new Error("请输入合法手机号/电话号"));
} else {
const formData = new FormData();
formData.append("phone", value);
checkPhone(formData)
.then((res) => {
console.log(res);
if (res.code == "0") {
callback();
} else {
callback(res.msg);
}
})
.catch((err) => {
console.error(err);
});
}
}
};
......@@ -123,18 +177,15 @@ export default {
second: 60,
rules: {
username: [
{ message: "请输入账号", trigger: "blur", required: true },
{
pattern: /^[0-9a-zA-Z|_]{6,20}$/g,
message: "账号长度6-20个字符,只能包括字母、数字、下划线",
trigger: "blur",
},
{ validator: validateUserName, trigger: "blur", required: true },
],
phone: [
{ required: true, message: "请输入手机号", trigger: "blur" },
phone: [{ validator: validatePhone, trigger: "blur", required: true }],
nickName: [
{ required: true, message: "请输入昵称", trigger: "blur" },
{
pattern: /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/,
message: "请输入合法手机号/电话号",
pattern: /^(?!_)(?!.*?_$)[a-zA-Z0-9_\u4e00-\u9fa5]+$/,
message:
"昵称长度2~10位,只能包含中文、英文大小写、数字及下划线,不能以下划线开头或结尾",
trigger: "blur",
},
],
......@@ -148,34 +199,24 @@ export default {
loading: false,
};
},
watch: {
"form.phone": {
handler: function (value) {
this.$refs["registerForm"].validateField("phone", (errorMessage) => {
let valid = errorMessage == "";
if (valid) {
this.isDisabled = false;
} else {
this.isDisabled = true;
}
});
},
deep: true,
},
},
methods: {
submitForm(formName) {
this.$refs[formName].validate(async (valid) => {
submitForm() {
// debugger
// console.log(123);
this.$refs["registerForm"].validate((valid) => {
// debugger
if (valid) {
this.loading = true;
const { username, password, phone } = this.form;
const { username, password, phone, nickName } = this.form;
let params = {
username,
password,
phone,
nickName,
status: 1,
};
let res = await register(params);
register(params)
.then((res) => {
if (res.code == "0") {
this.$confirm("注册成功, 是否去登录?", "提示", {
confirmButtonText: "确定",
......@@ -190,6 +231,10 @@ export default {
});
}
this.loading = false;
})
.catch((err) => {
this.loading = false;
});
} else {
console.log("error submit!!");
return false;
......@@ -226,7 +271,7 @@ export default {
.register {
width: 580px;
background-color: #fff;
border-radius: 16px;
// border-radius: 16px;
padding: 48px 32px;
box-shadow: 0 4px 8px 0 rgb(7 17 27 / 10%);
.title {
......@@ -235,9 +280,13 @@ export default {
align-items: center;
margin-bottom: 30px;
.text {
font-weight: bold;
font-size: 24px;
// font-weight: bold;
font-size: 36px;
color: #666;
font-family: "KaiTi";
.tips {
font-size: 24px;
}
}
.close {
font-size: 34px;
......@@ -258,7 +307,7 @@ export default {
display: flex;
justify-content: flex-end;
.el-button {
border-radius: 8px;
border-radius: 0px;
&:last-child {
width: 160px;
background-color: #2069c4;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论