Skip to content

Commit

Permalink
fix refresh token loop
Browse files Browse the repository at this point in the history
  • Loading branch information
atopx committed Mar 24, 2023
1 parent 81db0d2 commit 3936334
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 20 deletions.
1 change: 0 additions & 1 deletion superclient/src/constants/cacheKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ const SYSTEM_NAME = "super"

/** 缓存数据时用到的 Key */
class CacheKey {
static TOKEN = `${SYSTEM_NAME}-token`
static ACCESS_TOKEN = `${SYSTEM_NAME}-access_token`
static REFRESH_TOKEN = `${SYSTEM_NAME}-refresh_token`
static TOKEN_EXPIRES = `${SYSTEM_NAME}-token_expires`
Expand Down
24 changes: 12 additions & 12 deletions superclient/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,30 +88,30 @@ export const constantRoutes: RouteRecordRaw[] = [
]
},
{
path: "/table",
path: "/computer",
component: Layout,
redirect: "/table/element-plus",
name: "Table",
redirect: "/computer/computerManage",
name: "computer",
meta: {
title: "表格",
title: "主机管理",
elIcon: "Grid"
},
children: [
{
path: "element-plus",
component: () => import("@/views/table/element-plus/index.vue"),
name: "ElementPlus",
path: "computerManage",
component: () => import("@/views/computer/computerManage/index.vue"),
name: "computerManage",
meta: {
title: "Element Plus",
title: "设备管理",
keepAlive: true
}
},
{
path: "vxe-table",
component: () => import("@/views/table/vxe-table/index.vue"),
name: "VxeTable",
path: "portManage",
component: () => import("@/views/computer/computerManage/index.vue"),
name: "portManage",
meta: {
title: "Vxe Table",
title: "端口管理",
keepAlive: true
}
}
Expand Down
16 changes: 9 additions & 7 deletions superclient/src/store/modules/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ export const useUserStore = defineStore("user", () => {

const tagsViewStore = useTagsViewStore()

/** 登录 */
// get token
const login = (loginData: ILoginRequestData) => {
return new Promise((resolve, reject) => {
loginApi(loginData)
.then((res) => {
const login_token = {
access_token: res.data.access_token,
refresh_token: res.data.refresh_token,
expires: res.data.expires
expires: res.data.expires * 1000
}
setToken(login_token)
token.value = login_token
Expand All @@ -32,10 +32,12 @@ export const useUserStore = defineStore("user", () => {
})
})
}
// refresh token
const refreshToken = (refreshData: IRefreshRequestData) => {
return new Promise((resolve, reject) => {
refreshTokenApi(refreshData)
.then((res) => {
res.data.expires = res.data.expires * 1000
setToken(res.data)
token.value = res.data
resolve(true)
Expand All @@ -46,7 +48,7 @@ export const useUserStore = defineStore("user", () => {
})
}

/** 获取用户详情 */
// get user info
const getInfo = () => {
return new Promise((resolve, reject) => {
getUserInfoApi()
Expand All @@ -60,13 +62,13 @@ export const useUserStore = defineStore("user", () => {
})
})
}
/** 登出 */
// 登出
const logout = () => {
resetToken()
resetRouter()
_resetTagsView()
}
/** 重置 Token */
// 重置 Token
const resetToken = () => {
removeToken()
token.value = {
Expand All @@ -75,7 +77,7 @@ export const useUserStore = defineStore("user", () => {
expires: 0
}
}
/** 重置 visited views 和 cached views */
// 重置 visited views 和 cached views
const _resetTagsView = () => {
tagsViewStore.delAllVisitedViews()
tagsViewStore.delAllCachedViews()
Expand All @@ -84,7 +86,7 @@ export const useUserStore = defineStore("user", () => {
return { token, username, login, getInfo, logout, resetToken, refreshToken }
})

/** 在 setup 外使用 */
// 在 setup 外使用
export function useUserStoreHook() {
return useUserStore(store)
}
249 changes: 249 additions & 0 deletions superclient/src/views/computer/computerManage/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
<script lang="ts" setup>
import { reactive, ref, watch } from "vue"
import { createTableDataApi, deleteTableDataApi, updateTableDataApi } from "@/api/table"
import { type IGetTableData } from "@/api/table/types/table"
import { type FormInstance, type FormRules, ElMessage, ElMessageBox } from "element-plus"
import { Search, Refresh, CirclePlus, Delete, Download, RefreshRight } from "@element-plus/icons-vue"
import { usePagination } from "@/hooks/usePagination"
import { Access } from "@/api/permissions/types"
import { listPermissionAccess } from "@/api/permissions"
defineOptions({
name: "ComputerManage"
})
const loading = ref<boolean>(false)
const { paginationData, handleCurrentChange, handleSizeChange } = usePagination()
//#region 增
const dialogVisible = ref<boolean>(false)
const formRef = ref<FormInstance | null>(null)
const formData = reactive({
username: "",
password: ""
})
const formRules: FormRules = reactive({
username: [{ required: true, trigger: "blur", message: "请输入用户名" }],
password: [{ required: true, trigger: "blur", message: "请输入密码" }]
})
const handleCreate = () => {
formRef.value?.validate((valid: boolean) => {
if (valid) {
if (currentUpdateId.value === undefined) {
createTableDataApi({
username: formData.username,
password: formData.password
}).then(() => {
ElMessage.success("新增成功")
dialogVisible.value = false
getTableData()
})
} else {
updateTableDataApi({
id: currentUpdateId.value,
username: formData.username
}).then(() => {
ElMessage.success("修改成功")
dialogVisible.value = false
getTableData()
})
}
} else {
return false
}
})
}
const resetForm = () => {
currentUpdateId.value = undefined
formData.username = ""
formData.password = ""
}
//#endregion
//#region 删
const handleDelete = (row: IGetTableData) => {
ElMessageBox.confirm(`正在删除用户:${row.username},确认删除?`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}).then(() => {
deleteTableDataApi(row.id).then(() => {
ElMessage.success("删除成功")
getTableData()
})
})
}
//#endregion
//#region 改
const currentUpdateId = ref<undefined | string>(undefined)
const handleUpdate = (row: IGetTableData) => {
currentUpdateId.value = row.id
formData.username = row.username
dialogVisible.value = true
}
//#endregion
//#region 查
const tableData = ref<Access[]>([])
const searchFormRef = ref<FormInstance | null>(null)
const searchData = reactive({
username: "",
phone: ""
})
const getTableData = () => {
loading.value = true
listPermissionAccess({
page: {
index: paginationData.currentPage,
size: paginationData.pageSize,
disabled: false,
count: paginationData.total
},
filter: {}
})
.then((resp) => {
paginationData.total = resp.data.page.count
tableData.value = resp.data.search
})
.catch(() => {
tableData.value = []
})
.finally(() => {
loading.value = false
})
}
const handleSearch = () => {
if (paginationData.currentPage === 1) {
getTableData()
}
paginationData.currentPage = 1
}
const resetSearch = () => {
searchFormRef.value?.resetFields()
if (paginationData.currentPage === 1) {
getTableData()
}
paginationData.currentPage = 1
}
const handleRefresh = () => {
getTableData()
}
//#endregion
/** 监听分页参数的变化 */
watch([() => paginationData.currentPage, () => paginationData.pageSize], getTableData, { immediate: true })
</script>

<template>
<div class="app-container">
<el-card v-loading="loading" shadow="never" class="search-wrapper">
<el-form ref="searchFormRef" :inline="true" :model="searchData">
<el-form-item prop="username" label="用户名">
<el-input v-model="searchData.username" placeholder="请输入" />
</el-form-item>
<el-form-item prop="phone" label="手机号">
<el-input v-model="searchData.phone" placeholder="请输入" />
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Search" @click="handleSearch">查询</el-button>
<el-button :icon="Refresh" @click="resetSearch">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card v-loading="loading" shadow="never">
<div class="toolbar-wrapper">
<div>
<el-button type="primary" :icon="CirclePlus" @click="dialogVisible = true">新增用户</el-button>
<el-button type="danger" :icon="Delete">批量删除</el-button>
</div>
<div>
<el-tooltip content="下载">
<el-button type="primary" :icon="Download" circle />
</el-tooltip>
<el-tooltip content="刷新表格">
<el-button type="primary" :icon="RefreshRight" circle @click="handleRefresh" />
</el-tooltip>
</div>
</div>
<div class="table-wrapper">
<el-table :data="tableData">
<el-table-column type="selection" width="50" align="center" />
<el-table-column prop="id" label="ID" align="center" />
<el-table-column prop="method" label="方法" align="center" />
<el-table-column prop="path" label="路径" align="center" />
<el-table-column prop="handler" label="函数" align="center" />
<el-table-column prop="create_time" label="创建时间" align="center" />
<el-table-column prop="create_time" label="创建时间" align="center" />
<el-table-column fixed="right" label="操作" width="150" align="center">
<template #default="scope">
<el-button type="primary" text bg size="small" @click="handleUpdate(scope.row)"
>修改</el-button
>
<el-button type="danger" text bg size="small" @click="handleDelete(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
<div class="pager-wrapper">
<el-pagination
background
:layout="paginationData.layout"
:page-sizes="paginationData.pageSizes"
:total="paginationData.total"
:page-size="paginationData.pageSize"
:currentPage="paginationData.currentPage"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</el-card>
<!-- 新增/修改 -->
<el-dialog
v-model="dialogVisible"
:title="currentUpdateId === undefined ? '新增用户' : '修改用户'"
@close="resetForm"
width="30%"
>
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" label-position="left">
<el-form-item prop="username" label="用户名">
<el-input v-model="formData.username" placeholder="请输入" />
</el-form-item>
<el-form-item prop="password" label="密码" v-if="currentUpdateId === undefined">
<el-input v-model="formData.password" placeholder="请输入" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleCreate">确认</el-button>
</template>
</el-dialog>
</div>
</template>

<style lang="scss" scoped>
.search-wrapper {
margin-bottom: 20px;
:deep(.el-card__body) {
padding-bottom: 2px;
}
}
.toolbar-wrapper {
display: flex;
justify-content: space-between;
margin-bottom: 20px;
}
.table-wrapper {
margin-bottom: 20px;
}
.pager-wrapper {
display: flex;
justify-content: flex-end;
}
</style>

0 comments on commit 3936334

Please sign in to comment.