no message
This commit is contained in:
parent
2f2ccf7039
commit
7e4a538f5e
94
src/Api/request.js
Normal file
94
src/Api/request.js
Normal file
@ -0,0 +1,94 @@
|
||||
import axios from 'axios'
|
||||
import { MessageBox, Message } from 'element-ui'
|
||||
import store from '@/store'
|
||||
import { getToken } from '@/utils/auth'
|
||||
|
||||
// create an axios instance
|
||||
const service = axios.create({
|
||||
baseURL: 'https://lean.zhanhongzhu.top' || process.env.NODE_ENV === 'production' ? window.PROD_CONFIG.BASE_URL : process.env.VUE_APP_BASE_API, // url = base url + request url
|
||||
// withCredentials: true, // send cookies when cross-domain requests
|
||||
timeout: 50000 // request timeout
|
||||
})
|
||||
|
||||
// request interceptor
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
// do something before request is sent
|
||||
|
||||
if (store.getters.token) {
|
||||
// let each request carry token
|
||||
// ['X-Token'] is a custom headers key
|
||||
// please modify it according to the actual situation
|
||||
config.headers['X-Token'] = getToken()
|
||||
}
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
// do something with request error
|
||||
console.log(error) // for debug
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// response interceptor
|
||||
service.interceptors.response.use(
|
||||
/**
|
||||
* If you want to get http information such as headers or status
|
||||
* Please return response => response
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determine the request status by custom code
|
||||
* Here is just an example
|
||||
* You can also judge the status by HTTP Status Code
|
||||
*/
|
||||
response => {
|
||||
const res = response.data
|
||||
|
||||
if (res.status === 400) {
|
||||
Message({
|
||||
message: '入参错误',
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
return false
|
||||
}
|
||||
|
||||
// if the custom code is not 0, it is judged as an error.
|
||||
if (res.code !== 0 && res.code !== 200) {
|
||||
Message({
|
||||
message: res.message || 'Error',
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
|
||||
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
|
||||
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
|
||||
// to re-login
|
||||
MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
|
||||
confirmButtonText: 'Re-Login',
|
||||
cancelButtonText: 'Cancel',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
store.dispatch('user/resetToken').then(() => {
|
||||
location.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
return Promise.reject(new Error(res.message || 'Error'))
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
},
|
||||
error => {
|
||||
console.log('err' + error) // for debug
|
||||
Message({
|
||||
message: error.message,
|
||||
type: 'error',
|
||||
duration: 5 * 1000
|
||||
})
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export default service
|
68
src/Api/user.js
Normal file
68
src/Api/user.js
Normal file
@ -0,0 +1,68 @@
|
||||
import AV from 'leancloud-storage'
|
||||
// 用户登录
|
||||
const login = (username, password) => {
|
||||
console.log(username, password)
|
||||
return new Promise((resolve, reject) => {
|
||||
AV.User.logIn(username, password).then(user => {
|
||||
resolve(user)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 用户登录
|
||||
const loginEmail = (username, password) => {
|
||||
console.log(username, password)
|
||||
return new Promise((resolve, reject) => {
|
||||
AV.User.loginWithEmail(username, password).then(user => {
|
||||
resolve(user)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
// 用户登出
|
||||
const logout = (username, password) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
AV.User.logOut(username, password).then(user => {
|
||||
resolve(user)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 用户注册
|
||||
const register = (username, password) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const user = new AV.User()
|
||||
user.setUsername(username)
|
||||
user.setPassword(password)
|
||||
user.signUp().then((user) => {
|
||||
resolve(user)
|
||||
}, (error) => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
const getInfo = (params) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const user = new AV.User()
|
||||
user.loginWithAuthData({
|
||||
openid: params.openid,
|
||||
access_token: params.access_token,
|
||||
expires_in: params.expires_in
|
||||
}, 'weixin').then(function (user) {
|
||||
resolve(user)
|
||||
}).catch(function (error) {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
export default {
|
||||
login,
|
||||
logout,
|
||||
register,
|
||||
loginEmail,
|
||||
getInfo
|
||||
}
|
80
src/App.vue
80
src/App.vue
@ -14,9 +14,10 @@
|
||||
<img src="./assets/svg/add.svg" class="tool-icon" @click="add({},'add')" />
|
||||
<a title="我的博客" href="https://zhanhongzhu.top" target="_blank"><img src="./assets/svg/blog.svg" class="tool-icon" /></a>
|
||||
<a title="在线翻译" href="https://translate.google.cn" target="_blank"><img src="./assets/svg/translate.svg" class="tool-icon" /></a>
|
||||
<a title="我的码云" href="https://gitee.com/zhanhongzhu/kestrel-bookmark" target="_blank"><img src="./assets/svg/gitee.svg" class="tool-icon" /></a>
|
||||
<a title="我的github" href="https://github.com/zhanhongzhu/kestrel-bookmark" target="_blank"><img src="./assets/svg/github.svg" class="tool-icon" /></a>
|
||||
<span class="login-s" @click="loginClick"><img src="./assets/svg/user.svg" class="tool-icon" /><span class="login-status" :title="userInfo.username">{{userInfo.username.slice(0, 5)}}</span></span>
|
||||
</div>
|
||||
|
||||
<!-- userInfo.objectId?LoginOut:handleUserLogin -->
|
||||
</div>
|
||||
<!-- 侧边导航栏 -->
|
||||
<div class="box-m">
|
||||
@ -45,7 +46,6 @@
|
||||
<i class="el-icon-edit" @click.stop="add(card,'modify')"></i>
|
||||
<i class="el-icon-delete" @click.stop="deleteClick(card)"></i>
|
||||
</span>
|
||||
|
||||
<span class="title">{{card.title || 'Kestrel-bookmark'}}</span>
|
||||
<span class="subtitle">{{card.desc || "红隼书签-为中国 Web 前端开发人员提供优质网站导航"}}</span>
|
||||
</div>
|
||||
@ -69,16 +69,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 新增/修改弹窗 -->
|
||||
<Dialog class="my-dialog" v-model="isDetailVisible" @closeViews="closeViews" :detail="detail" :selectType="activeIndex" @fresh="search" />
|
||||
<!-- 登录弹窗 -->
|
||||
<Login v-model="isLoginVisible" @closeViews="closeLoginViews" @setUser="setUsername"/>
|
||||
</template>
|
||||
<script>
|
||||
import { reactive, toRefs } from '@vue/reactivity'
|
||||
import { myData } from './assets/Json/印象笔记.js'
|
||||
import { watch } from '@vue/runtime-core'
|
||||
import Dialog from './components/Dialog.vue'
|
||||
import Login from './components/Login.vue'
|
||||
import gsap from 'gsap'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { importBookmark, exportBookmark } from './components/utils.js'
|
||||
import Cookie from 'js-cookie'
|
||||
import Api from './Api/user.js'
|
||||
var rowData = []
|
||||
function getData(fn = () => {}) {
|
||||
// 数据持久化
|
||||
@ -93,7 +99,7 @@ function getData(fn = () => {}) {
|
||||
}
|
||||
getData()
|
||||
export default {
|
||||
components: { Dialog },
|
||||
components: { Dialog, Login },
|
||||
name: 'kestrel-bookmark',
|
||||
setup() {
|
||||
// 扁平化数组
|
||||
@ -113,9 +119,22 @@ export default {
|
||||
searchVal: '',
|
||||
allData: flatten(rowData),
|
||||
isDetailVisible: false,
|
||||
detail: {}
|
||||
isLoginVisible: false,
|
||||
detail: {},
|
||||
userInfo: {
|
||||
username: '未登录'
|
||||
}
|
||||
})
|
||||
|
||||
const setUsername = () => {
|
||||
if (Cookie.get('userInfo')) {
|
||||
data.userInfo = JSON.parse(Cookie.get('userInfo'))
|
||||
} else {
|
||||
data.userInfo = {username: '未登录'}
|
||||
}
|
||||
}
|
||||
setUsername()
|
||||
|
||||
// 全部数据筛选功能
|
||||
watch(
|
||||
() => data.searchVal,
|
||||
@ -150,8 +169,15 @@ export default {
|
||||
}
|
||||
data.isDetailVisible = true
|
||||
}
|
||||
|
||||
// 用户登录
|
||||
const handleUserLogin = () => {
|
||||
data.isLoginVisible = true
|
||||
}
|
||||
|
||||
// 关闭弹窗事件
|
||||
const closeViews = (v) => (data.isDetailVisible = v)
|
||||
const closeLoginViews = (v) => (data.isLoginVisible = v)
|
||||
|
||||
// 获取数据
|
||||
const search = async () => {
|
||||
@ -180,6 +206,29 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
// 退出登录
|
||||
const LoginOut = () => {
|
||||
ElMessageBox.confirm('确认要退出登录?', '温馨提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
const params = { username: '', password: '' }
|
||||
Api.logout(params.username, params.password).then((res) => {
|
||||
Cookie.remove('userInfo')
|
||||
setUsername()
|
||||
})
|
||||
ElMessage({
|
||||
type: 'success',
|
||||
message: '删除成功!'
|
||||
})
|
||||
})
|
||||
}
|
||||
// 登录或退出
|
||||
const loginClick = () => {
|
||||
data.userInfo.objectId ? LoginOut() : handleUserLogin()
|
||||
}
|
||||
|
||||
return {
|
||||
deleteClick,
|
||||
...toRefs(data),
|
||||
@ -187,9 +236,12 @@ export default {
|
||||
navigate,
|
||||
add,
|
||||
closeViews,
|
||||
closeLoginViews,
|
||||
search,
|
||||
importBookmark,
|
||||
exportBookmark
|
||||
exportBookmark,
|
||||
loginClick,
|
||||
setUsername
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -525,4 +577,18 @@ export default {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.login-status {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
padding-right: 8px;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.login-s .tool-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
.login-s:hover .login-status {
|
||||
color: #e03b5d;
|
||||
}
|
||||
</style>
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@ -33,14 +33,13 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="closeViews">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="closeViews" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm" size="small">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import gsap from 'gsap'
|
||||
import { reactive, ref, toRefs } from '@vue/reactivity'
|
||||
import { nextTick, watch } from '@vue/runtime-core'
|
||||
import { ElMessage } from 'element-plus'
|
||||
@ -154,26 +153,6 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
beforeEnter(el) {
|
||||
el.style.opacity = 0
|
||||
el.style.height = 0
|
||||
},
|
||||
enter(el, done) {
|
||||
gsap.to(el, {
|
||||
opacity: 1,
|
||||
height: '1.6em',
|
||||
delay: el.dataset.index * 0.15,
|
||||
onComplete: done
|
||||
})
|
||||
},
|
||||
leave(el, done) {
|
||||
gsap.to(el, {
|
||||
opacity: 0,
|
||||
height: 0,
|
||||
delay: el.dataset.index * 0.15,
|
||||
onComplete: done
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
107
src/components/Login.vue
Normal file
107
src/components/Login.vue
Normal file
@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<el-dialog custom-class="my-dialog" title="用户登录" :visible="isLoginVisible" width="400px">
|
||||
<el-form status-icon ref="refruleForm" :rules="rules" :model="ruleForm" label-width="80px" size="small">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="ruleForm.email" placeholder="请输入邮箱"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="密码" prop="password">
|
||||
<el-input v-model="ruleForm.password" show-password placeholder="请输入密码"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="closeViews" size="small">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm" size="small">确 定</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import Cookie from 'js-cookie'
|
||||
import { reactive, ref, toRefs } from '@vue/reactivity'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import Api from '../Api/user.js' // register
|
||||
export default {
|
||||
model: {
|
||||
value: 'isLoginVisible',
|
||||
events: 'closeViews'
|
||||
},
|
||||
props: {
|
||||
isLoginVisible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
const form = reactive({
|
||||
ruleForm: {
|
||||
username: '',
|
||||
password: ''
|
||||
}
|
||||
})
|
||||
// 用户
|
||||
// 定义校验规则 表单代码中必须以 :rules 接收
|
||||
const rules = {
|
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
||||
email: [{type: 'email', required: true, message: '请输入邮箱', trigger: 'blur' }]
|
||||
}
|
||||
const refruleForm = ref(null)
|
||||
// 确定按钮的格式
|
||||
const submitForm = () => {
|
||||
refruleForm.value.validate((valid) => {
|
||||
if (valid) {
|
||||
const formData = { ...form.ruleForm }
|
||||
Api.loginEmail(formData.email, formData.password)
|
||||
.then((res) => {
|
||||
// 存储token
|
||||
Cookie.set('userInfo', JSON.stringify(res))
|
||||
ElMessage.success('登记成功')
|
||||
closeViews()
|
||||
})
|
||||
.catch(() => {
|
||||
Api.register(formData.email, formData.password).then((res) => {
|
||||
Cookie.set('userInfo', JSON.stringify(res))
|
||||
context.emit('setUser')
|
||||
ElMessage.success('注册成功')
|
||||
closeViews()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
// 关闭弹窗
|
||||
function closeViews() {
|
||||
refruleForm.value.resetFields()
|
||||
context.emit('closeViews', false)
|
||||
}
|
||||
return {
|
||||
...toRefs(form),
|
||||
closeViews,
|
||||
submitForm,
|
||||
refruleForm,
|
||||
rules
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.my-dialog {
|
||||
background: red;
|
||||
}
|
||||
.my-dialog /deep/.el-dialog__header {
|
||||
border-bottom: 1px solid #eee !important;
|
||||
}
|
||||
.my-dialog /deep/.el-dialog__title {
|
||||
font-size: 16px;
|
||||
color: #e03b5d;
|
||||
}
|
||||
</style>
|
@ -4,6 +4,14 @@ import App from './App.vue'
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/lib/theme-chalk/index.css'
|
||||
|
||||
// 接入了Leancloud
|
||||
import AV from 'leancloud-storage'
|
||||
AV.init({
|
||||
appId: 'BwLrCgdVyLs52mJO1HcrXakI-gzGzoHsz',
|
||||
appKey: '25gNwzw4dV7IAh7i0IzDnYvV',
|
||||
serverURL: 'https://bwlrcgdv.lc-cn-n1-shared.com' // 临时域名
|
||||
})
|
||||
|
||||
const app = createApp(App)
|
||||
app.use(ElementPlus)
|
||||
app.mount('#app')
|
||||
|
Loading…
Reference in New Issue
Block a user