parent
74808ae9fa
commit
932ed5ed5a
10 changed files with 473 additions and 127 deletions
Binary file not shown.
@ -0,0 +1,96 @@ |
|||||||
|
<template> |
||||||
|
<div class="search"> |
||||||
|
<form> |
||||||
|
<input |
||||||
|
v-model="searchText" |
||||||
|
type="text" |
||||||
|
placeholder="输入搜索内容..." |
||||||
|
/> |
||||||
|
<button v-on:click.prevent="searchArticles"></button> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { ref } from "vue"; |
||||||
|
import router from "@/router/index"; |
||||||
|
|
||||||
|
export default { |
||||||
|
name: "SearchButton", |
||||||
|
setup() { |
||||||
|
let searchText = ref(""); |
||||||
|
const searchArticles = () => { |
||||||
|
const text = searchText.value.trim(); |
||||||
|
if (text.charAt(0) !== "") { |
||||||
|
router.push({ name: "home", query: { search: text } }); |
||||||
|
} |
||||||
|
}; |
||||||
|
return { |
||||||
|
searchText, |
||||||
|
searchArticles, |
||||||
|
}; |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
.search { |
||||||
|
padding-top: 22px; |
||||||
|
} |
||||||
|
|
||||||
|
/* 搜索框样式 */ |
||||||
|
* { |
||||||
|
box-sizing: border-box; |
||||||
|
} |
||||||
|
|
||||||
|
form { |
||||||
|
position: relative; |
||||||
|
width: 20vw; |
||||||
|
margin: 0 auto; |
||||||
|
} |
||||||
|
|
||||||
|
input, |
||||||
|
button { |
||||||
|
outline: none; |
||||||
|
} |
||||||
|
|
||||||
|
input { |
||||||
|
border-color: gray; |
||||||
|
width: 100%; |
||||||
|
height: 30px; |
||||||
|
padding-left: 13px; |
||||||
|
padding-right: 46px; |
||||||
|
overflow: hidden; |
||||||
|
text-overflow: ellipsis; |
||||||
|
} |
||||||
|
|
||||||
|
button { |
||||||
|
border: none; |
||||||
|
height: 30px; |
||||||
|
width: 30px; |
||||||
|
cursor: pointer; |
||||||
|
position: absolute; |
||||||
|
} |
||||||
|
|
||||||
|
.search input { |
||||||
|
border: 2px solid gray; |
||||||
|
border-radius: 5px; |
||||||
|
background: transparent; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.search button { |
||||||
|
background: gray; |
||||||
|
border-radius: 0 5px 5px 0; |
||||||
|
width: 45px; |
||||||
|
top: 0; |
||||||
|
right: 0; |
||||||
|
} |
||||||
|
|
||||||
|
.search button:before { |
||||||
|
content: "搜索"; |
||||||
|
font-size: 13px; |
||||||
|
color: white; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,59 @@ |
|||||||
|
import $ from 'jquery'; |
||||||
|
|
||||||
|
const authorization = async () => { |
||||||
|
const storage = localStorage; |
||||||
|
|
||||||
|
let haslogin = false; |
||||||
|
// 用户名
|
||||||
|
let username = storage.getItem('username_blog'); |
||||||
|
// 过期时间
|
||||||
|
const expired_time = Number(storage.getItem("expired_time")); |
||||||
|
console.log("expired_time ",new Date(expired_time).toLocaleString()); |
||||||
|
// 当前时间
|
||||||
|
const current = new Date().getTime(); |
||||||
|
// 刷新令牌
|
||||||
|
const refreshToken = storage.getItem("refresh_blog"); |
||||||
|
// 未过期
|
||||||
|
if (expired_time > current) { |
||||||
|
haslogin = true; |
||||||
|
console.log('authorization success'); |
||||||
|
} |
||||||
|
// 初始tokeng过期,则由刷新令牌申请新的token
|
||||||
|
else if (refreshToken !== null) { |
||||||
|
try { |
||||||
|
$.ajax({ |
||||||
|
url: "http://127.0.0.1:6789/api/token/refresh/", |
||||||
|
type: "POST", |
||||||
|
async: false, |
||||||
|
data: { |
||||||
|
refresh: refreshToken, |
||||||
|
}, |
||||||
|
success(resp) { |
||||||
|
const nextExpiredTime = new Date().getTime() + 60000; |
||||||
|
storage.setItem("access_blog", resp.access); |
||||||
|
storage.removeItem("refresh_blog"); // 移除刷新令牌
|
||||||
|
console.log( |
||||||
|
"令牌刷新时间: ", |
||||||
|
new Date().toLocaleString() |
||||||
|
); |
||||||
|
storage.setItem("expired_time", nextExpiredTime); |
||||||
|
haslogin = true; |
||||||
|
}, |
||||||
|
}); |
||||||
|
}catch(err){ |
||||||
|
storage.clear(); |
||||||
|
haslogin = false; |
||||||
|
console.log('authorization err'); |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
storage.clear(); // 清除所有有效信息
|
||||||
|
haslogin = false; |
||||||
|
console.log('authorization exp'); |
||||||
|
} |
||||||
|
|
||||||
|
console.log('authorization done'); |
||||||
|
return [haslogin, username]; |
||||||
|
} |
||||||
|
|
||||||
|
export default authorization; |
@ -0,0 +1,205 @@ |
|||||||
|
<template> |
||||||
|
<BlogHeader ref="header" /> |
||||||
|
<div id="user-center"> |
||||||
|
<h3>更新资料信息</h3> |
||||||
|
<form> |
||||||
|
<div class="form-elem"> |
||||||
|
<span>用户名:</span> |
||||||
|
<input |
||||||
|
v-model="username" |
||||||
|
type="text" |
||||||
|
placeholder="输入用户名" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-elem"> |
||||||
|
<span>新密码:</span> |
||||||
|
<input |
||||||
|
v-model="password" |
||||||
|
type="password" |
||||||
|
placeholder="输入密码" |
||||||
|
autocomplete="true" |
||||||
|
/> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-elem"> |
||||||
|
<button v-on:click.prevent="changeInfo">更新</button> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="form-elem"> |
||||||
|
<button |
||||||
|
v-on:click.prevent="showingDeleteAlert=true" |
||||||
|
class="delete-btn" |
||||||
|
> |
||||||
|
删除用户 |
||||||
|
</button> |
||||||
|
<div :class="{ shake: showingDeleteAlert }"> |
||||||
|
<button |
||||||
|
v-if="showingDeleteAlert" |
||||||
|
class="confirm-btn" |
||||||
|
@click.prevent="confirmDelete" |
||||||
|
> |
||||||
|
确定? |
||||||
|
</button> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
<BlogFooter /> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import BlogHeader from "@/components/BlogHeader.vue"; |
||||||
|
import BlogFooter from "@/components/BlogFooter.vue"; |
||||||
|
import authorization from "@/utils/authorization"; |
||||||
|
import $ from "jquery"; |
||||||
|
const storage = localStorage; |
||||||
|
export default { |
||||||
|
name: "UserCenter", |
||||||
|
components: { BlogHeader, BlogFooter }, |
||||||
|
data: function () { |
||||||
|
return { |
||||||
|
username: "", |
||||||
|
password: "", |
||||||
|
token: "", |
||||||
|
showingDeleteAlert: false, |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
this.username = storage.getItem("username_blog"); |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
confirmDelete() { |
||||||
|
const that = this; |
||||||
|
authorization().then(function (response) { |
||||||
|
if (response[0]) { |
||||||
|
// 获取令牌 |
||||||
|
that.token = storage.getItem("access_blog"); |
||||||
|
$.ajax({ |
||||||
|
url: 'http://127.0.0.1:6789/api/user/' + that.username + '/', |
||||||
|
type: 'DELETE', |
||||||
|
headers: { |
||||||
|
Authorization: "Bearer " + that.token |
||||||
|
}, |
||||||
|
success(resp) { |
||||||
|
console.log(resp); |
||||||
|
storage.clear(); |
||||||
|
that.$router.push({ name: "home" }); |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
}); |
||||||
|
}, |
||||||
|
changeInfo() { |
||||||
|
const that = this; |
||||||
|
authorization().then(function (response) { |
||||||
|
if (response[0] === false) { |
||||||
|
window.alert("登录已过期, 请重新登录!"); |
||||||
|
storage.clear(); |
||||||
|
that.$router.push({ name: "login" }); |
||||||
|
return; |
||||||
|
} |
||||||
|
// 密码不能少于6位 |
||||||
|
|
||||||
|
if (that.password.length >= 0 && that.password.length < 6) { |
||||||
|
window.alert("密码太短了"); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
// 旧的用户名 |
||||||
|
const oldName = storage.getItem("username_blog"); |
||||||
|
// 表单数据 |
||||||
|
let data = {}; |
||||||
|
if (that.username !== "") { |
||||||
|
data.username = that.username; |
||||||
|
} |
||||||
|
data.password = that.password; |
||||||
|
that.token = storage.getItem("access_blog"); |
||||||
|
// 修改用户名或密码 |
||||||
|
$.ajax({ |
||||||
|
url: "http://127.0.0.1:6789/api/user/" + oldName + "/", |
||||||
|
type: "PATCH", |
||||||
|
data: data, |
||||||
|
headers: { |
||||||
|
Authorization: "Bearer " + that.token, |
||||||
|
}, |
||||||
|
success(resp) { |
||||||
|
window.alert("修改成功"); |
||||||
|
const name = resp.username; |
||||||
|
storage.setItem("username_blog", name); |
||||||
|
// 跳转到用户界面 |
||||||
|
that.$router.push({ |
||||||
|
name: "UserCenter", |
||||||
|
params: { username: name }, |
||||||
|
}); |
||||||
|
that.$refs.header.refresh(); |
||||||
|
}, |
||||||
|
}); |
||||||
|
}); |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style scoped> |
||||||
|
#user-center { |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
|
||||||
|
.form-elem { |
||||||
|
padding: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
input { |
||||||
|
height: 25px; |
||||||
|
padding-left: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
button { |
||||||
|
height: 35px; |
||||||
|
cursor: pointer; |
||||||
|
border: none; |
||||||
|
outline: none; |
||||||
|
background: gray; |
||||||
|
color: whitesmoke; |
||||||
|
border-radius: 5px; |
||||||
|
width: 250px; |
||||||
|
} |
||||||
|
|
||||||
|
.confirm-btn { |
||||||
|
width: 80px; |
||||||
|
background-color: darkorange; |
||||||
|
} |
||||||
|
|
||||||
|
.delete-btn { |
||||||
|
background-color: darkred; |
||||||
|
margin-bottom: 10px; |
||||||
|
} |
||||||
|
|
||||||
|
.shake { |
||||||
|
animation: shake 0.82s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; |
||||||
|
transform: translate3d(0, 0, 0); |
||||||
|
backface-visibility: hidden; |
||||||
|
perspective: 1000px; |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes shake { |
||||||
|
10%, |
||||||
|
90% { |
||||||
|
transform: translate3d(-1px, 0, 0); |
||||||
|
} |
||||||
|
20%, |
||||||
|
80% { |
||||||
|
transform: translate3d(2px, 0, 0); |
||||||
|
} |
||||||
|
30%, |
||||||
|
50%, |
||||||
|
70% { |
||||||
|
transform: translate3d(-4px, 0, 0); |
||||||
|
} |
||||||
|
40%, |
||||||
|
60% { |
||||||
|
transform: translate3d(4px, 0, 0); |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
Loading…
Reference in new issue