feat : page upload
This commit is contained in:
parent
392e846342
commit
361287b098
18
package-lock.json
generated
18
package-lock.json
generated
@ -9,7 +9,9 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.6.8",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"vue": "^3.4.21",
|
||||
"vue-router": "^4.3.0"
|
||||
},
|
||||
@ -2847,6 +2849,14 @@
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/jwt-decode": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
|
||||
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/keyv": {
|
||||
"version": "4.5.4",
|
||||
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
|
||||
@ -3239,6 +3249,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pinia-plugin-persistedstate": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-3.2.1.tgz",
|
||||
"integrity": "sha512-MK++8LRUsGF7r45PjBFES82ISnPzyO6IZx3CH5vyPseFLZCk1g2kgx6l/nW8pEBKxxd4do0P6bJw+mUSZIEZUQ==",
|
||||
"peerDependencies": {
|
||||
"pinia": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pinia/node_modules/vue-demi": {
|
||||
"version": "0.14.7",
|
||||
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.7.tgz",
|
||||
|
@ -12,7 +12,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.8",
|
||||
"jwt-decode": "^4.0.0",
|
||||
"pinia": "^2.1.7",
|
||||
"pinia-plugin-persistedstate": "^3.2.1",
|
||||
"vue": "^3.4.21",
|
||||
"vue-router": "^4.3.0"
|
||||
},
|
||||
|
@ -2,9 +2,9 @@ import { localAxios } from '@/utils/http-commons';
|
||||
|
||||
const local = localAxios;
|
||||
|
||||
function getArticles(success, fail) {
|
||||
function getArticles(params,success, fail) {
|
||||
//list
|
||||
local.get('/article/list').then(success).catch(fail);
|
||||
local.get('/article/list',{ params }).then(success).catch(fail);
|
||||
}
|
||||
|
||||
function searchArticle(keyword, success, fail) {
|
||||
|
27
src/api/member.js
Normal file
27
src/api/member.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { localAxios } from "@/utils/http-commons";
|
||||
|
||||
const local = localAxios;
|
||||
|
||||
async function userConfirm(param, success, fail) {
|
||||
await local.post(`/member/login`, param).then(success).catch(fail);
|
||||
}
|
||||
|
||||
async function findById(userid, success, fail) {
|
||||
local.defaults.headers["Authorization"] = sessionStorage.getItem("accessToken");
|
||||
await local.get(`/member/info/${userid}`).then(success).catch(fail);
|
||||
}
|
||||
|
||||
async function tokenRegeneration(user, success, fail) {
|
||||
local.defaults.headers["refreshToken"] = sessionStorage.getItem("refreshToken"); //axios header에 refresh-token 셋팅
|
||||
await local.post(`/member/refresh`, user).then(success).catch(fail);
|
||||
}
|
||||
|
||||
async function logout(userid, success, fail) {
|
||||
await local.get(`/member/logout/${userid}`).then(success).catch(fail);
|
||||
}
|
||||
|
||||
function registMember(member, success, fail) {
|
||||
local.post('/member/join',JSON.stringify(member)).then(success).catch(fail);
|
||||
}
|
||||
|
||||
export { userConfirm, findById, tokenRegeneration, logout, registMember };
|
@ -1,5 +1,21 @@
|
||||
<script setup>
|
||||
import { RouterLink } from 'vue-router';
|
||||
import { useMenuStore } from "@/stores/menu";
|
||||
import { useMemberStore } from "@/stores/member";
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
const menuStore = useMenuStore();
|
||||
const memberStore = useMemberStore();
|
||||
|
||||
const { menuList } = storeToRefs(menuStore);
|
||||
const { changeMenuState } = menuStore;
|
||||
|
||||
const { userLogout } = memberStore;
|
||||
|
||||
const logout = () => {
|
||||
userLogout();
|
||||
changeMenuState();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -11,11 +27,31 @@ import { RouterLink } from 'vue-router';
|
||||
<div class="menuWrapper">
|
||||
<div class="item"><RouterLink :to="{ name: 'home' }">검색</RouterLink></div>
|
||||
<div class="item"><RouterLink :to="{ name: 'board' }">게시판</RouterLink></div>
|
||||
<div class="item" v-if="true"><RouterLink :to="{ name: 'home' }">로그인</RouterLink></div>
|
||||
|
||||
<template v-for="menu in menuList" :key="menu.routeName">
|
||||
<template v-if="menu.show">
|
||||
<template v-if="menu.routeName === 'user-logout'">
|
||||
<div class="item">
|
||||
<router-link to="/" @click.prevent="logout" class="nav-link">{{
|
||||
menu.name
|
||||
}}</router-link>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="item">
|
||||
<router-link :to="{ name: menu.routeName }" class="nav-link">{{
|
||||
menu.name
|
||||
}}</router-link>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<!-- <div class="item" v-if="true"><RouterLink :to="{ name: 'user-login' }">로그인</RouterLink></div>
|
||||
<template v-else>
|
||||
<div class="item"><RouterLink :to="{ name: 'home' }">마이페이지</RouterLink></div>
|
||||
<div class="item"><RouterLink :to="{ name: 'home' }">로그아웃</RouterLink></div>
|
||||
</template>
|
||||
</template> -->
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
@ -1,12 +1,43 @@
|
||||
<script setup>
|
||||
import { getArticles } from '@/api/article';
|
||||
import { ref } from 'vue';
|
||||
import { ref , reactive } from 'vue';
|
||||
import { RouterLink } from 'vue-router';
|
||||
import FilledButton from '../common/FilledButton.vue';
|
||||
import PageNavigation from "../common/PageNavigation.vue";
|
||||
|
||||
const articles = ref([]);
|
||||
|
||||
getArticles(({ data }) => (articles.value = data));
|
||||
const params = reactive({
|
||||
pageNo: 1,
|
||||
key: 'all',
|
||||
word: ''
|
||||
})
|
||||
|
||||
const currentPage = ref(1)
|
||||
const totalpage = ref(1)
|
||||
|
||||
function searchList() {
|
||||
getArticles(
|
||||
params,
|
||||
({ data }) => {
|
||||
articles.value = data.articles
|
||||
currentPage.value = data.page.pageNo
|
||||
totalpage.value = data.page.total
|
||||
console.log(articles.value)
|
||||
console.log(currentPage.value)
|
||||
console.log(totalpage.value)
|
||||
},
|
||||
(error) => {
|
||||
console.log(error)
|
||||
}
|
||||
);
|
||||
}
|
||||
searchList()
|
||||
|
||||
function pageChange(value) {
|
||||
params.pageNo = value
|
||||
searchList()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -30,6 +61,7 @@ getArticles(({ data }) => (articles.value = data));
|
||||
</RouterLink>
|
||||
</li>
|
||||
</ul>
|
||||
<PageNavigation :currentPage="currentPage" :totalPage="totalpage" @page-change="pageChange" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
82
src/components/users/UserLogin.vue
Normal file
82
src/components/users/UserLogin.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<script setup>
|
||||
import { ref } from "vue"
|
||||
import { storeToRefs } from "pinia"
|
||||
import { useRouter } from "vue-router"
|
||||
import { useMemberStore } from "@/stores/member"
|
||||
import { useMenuStore } from "@/stores/menu"
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const memberStore = useMemberStore()
|
||||
|
||||
const { isLogin, isLoginError } = storeToRefs(memberStore)
|
||||
const { userLogin, getUserInfo } = memberStore
|
||||
const { changeMenuState } = useMenuStore()
|
||||
|
||||
const loginUser = ref({
|
||||
id: "",
|
||||
password: "",
|
||||
})
|
||||
|
||||
const login = async () => {
|
||||
await userLogin(loginUser.value)
|
||||
let token = sessionStorage.getItem("accessToken")
|
||||
console.log(token)
|
||||
console.log("isLogin: " + isLogin.value)
|
||||
if (isLogin.value) {
|
||||
getUserInfo(token)
|
||||
changeMenuState()
|
||||
router.replace("/")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10">
|
||||
<h2 class="my-3 py-3 shadow-sm bg-light text-center">
|
||||
<mark class="orange">로그인</mark>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="col-lg-10">
|
||||
<form>
|
||||
<div class="form-check mb-3 float-end">
|
||||
<input class="form-check-input" type="checkbox" />
|
||||
<label class="form-check-label" for="saveid"> 아이디저장 </label>
|
||||
</div>
|
||||
<div class="mb-3 text-start">
|
||||
<label for="userid" class="form-label">아이디 : </label>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
v-model="loginUser.id"
|
||||
placeholder="아이디..."
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3 text-start">
|
||||
<label for="userpwd" class="form-label">비밀번호 : </label>
|
||||
<input
|
||||
type="password"
|
||||
class="form-control"
|
||||
v-model="loginUser.password"
|
||||
@keyup.enter="login"
|
||||
placeholder="비밀번호..."
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3 text-start" v-if="isLoginError === true">
|
||||
<div class="alert alert-danger" role="alert">아이디 또는 비밀번호 확인해 주세요</div>
|
||||
</div>
|
||||
<div class="col-auto text-center">
|
||||
<button type="button" class="btn btn-outline-primary mb-3" @click="login">
|
||||
로그인
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-success ms-1 mb-3">회원가입</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
40
src/components/users/UserMyPage.vue
Normal file
40
src/components/users/UserMyPage.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10">
|
||||
<h2 class="my-3 py-3 shadow-sm bg-light text-center">
|
||||
<mark class="orange">내정보</mark>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="col-lg-10">
|
||||
<div class="card mt-3 m-auto" style="max-width: 700px">
|
||||
<div class="row g-0">
|
||||
<div class="col-md-4">
|
||||
<!-- <img
|
||||
src="https://source.unsplash.com/random/250x250/?food"
|
||||
class="img-fluid rounded-start"
|
||||
alt="..."
|
||||
/> -->
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="card-body text-start">
|
||||
<ul class="list-group list-group-flush">
|
||||
<!-- <li class="list-group-item">SSAFY</li>
|
||||
<li class="list-group-item">김싸피</li>
|
||||
<li class="list-group-item">ssafy@ssafy.com</li> -->
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-outline-secondary mt-2">수정</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
82
src/components/users/UserRegister.vue
Normal file
82
src/components/users/UserRegister.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import { registMember } from "@/api/member";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const email_id = ref("")
|
||||
const email_domain = ref("")
|
||||
|
||||
const member = ref({
|
||||
id: "",
|
||||
name: "",
|
||||
password: "",
|
||||
email: email_id.value + "@" + email_domain.value,
|
||||
})
|
||||
|
||||
function onSubmit() {
|
||||
member.value.email = email_id.value + "@" + email_domain.value
|
||||
console.log(member.value)
|
||||
registMember(
|
||||
member.value,
|
||||
(response) => {
|
||||
if (response.status == 200) console.log("회원가입 성공!")
|
||||
router.push({ name : "user-login"})
|
||||
},
|
||||
(error) => console.error(error)
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-10">
|
||||
<h2 class="my-3 py-3 shadow-sm bg-light text-center">
|
||||
<mark class="orange">회원가입</mark>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="col-lg-10 text-start">
|
||||
<form>
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">이름 : </label>
|
||||
<input type="text" class="form-control" placeholder="이름..." v-model="member.name"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="userid" class="form-label">아이디 : </label>
|
||||
<input type="text" class="form-control" placeholder="아이디..." v-model="member.id"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="userpwd" class="form-label">비밀번호 : </label>
|
||||
<input type="text" class="form-control" placeholder="비밀번호..." v-model="member.password"/>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="pwdcheck" class="form-label">비밀번호확인 : </label>
|
||||
<input type="text" class="form-control" id="pwdcheck" placeholder="비밀번호확인..." />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="emailid" class="form-label">이메일 : </label>
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" placeholder="이메일아이디" v-model="email_id"/>
|
||||
<span class="input-group-text">@</span>
|
||||
<select class="form-select" aria-label="이메일 도메인 선택" v-model="email_domain">
|
||||
<option selected>선택</option>
|
||||
<option value="ssafy.com">싸피</option>
|
||||
<option value="google.com">구글</option>
|
||||
<option value="naver.com">네이버</option>
|
||||
<option value="kakao.com">카카오</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto text-center">
|
||||
<button type="button" class="btn btn-outline-primary mb-3" @click="onSubmit">회원가입</button>
|
||||
<button type="button" class="btn btn-outline-success ms-1 mb-3">초기화</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
@ -2,13 +2,20 @@ import './assets/main.css';
|
||||
|
||||
import { createApp } from 'vue';
|
||||
import { createPinia } from 'pinia';
|
||||
import piniaPluginPersistedstate from "pinia-plugin-persistedstate";
|
||||
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
|
||||
const app = createApp(App);
|
||||
const pinia = createPinia();
|
||||
|
||||
pinia.use(piniaPluginPersistedstate);
|
||||
|
||||
app.use(createPinia());
|
||||
app.use(router);
|
||||
|
||||
app.mount('#app');
|
||||
// app.mount('#app');
|
||||
router.isReady().then(() => {
|
||||
app.mount("#app");
|
||||
});
|
||||
|
@ -1,6 +1,27 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import HomeView from '@/views/HomeView.vue';
|
||||
|
||||
import { storeToRefs } from "pinia";
|
||||
|
||||
import { useMemberStore } from "@/stores/member";
|
||||
|
||||
const onlyAuthUser = async (to, from, next) => {
|
||||
const memberStore = useMemberStore();
|
||||
const { userInfo, isValidToken } = storeToRefs(memberStore);
|
||||
const { getUserInfo } = memberStore;
|
||||
|
||||
let token = sessionStorage.getItem("accessToken");
|
||||
|
||||
if (userInfo.value != null && token) {
|
||||
await getUserInfo(token);
|
||||
}
|
||||
if (!isValidToken.value || userInfo.value === null) {
|
||||
next({ name: "user-login" });
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
};
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
routes: [
|
||||
@ -9,6 +30,34 @@ const router = createRouter({
|
||||
name: 'home',
|
||||
component: HomeView,
|
||||
},
|
||||
{
|
||||
path: "/user",
|
||||
name: "user",
|
||||
component: () => import("@/views/TheUserView.vue"),
|
||||
children: [
|
||||
{
|
||||
path: "login",
|
||||
name: "user-login",
|
||||
component: () => import("@/components/users/UserLogin.vue"),
|
||||
},
|
||||
{
|
||||
path: "join",
|
||||
name: "user-join",
|
||||
component: () => import("@/components/users/UserRegister.vue"),
|
||||
},
|
||||
{
|
||||
path: "mypage",
|
||||
name: "user-mypage",
|
||||
beforeEnter: onlyAuthUser,
|
||||
component: () => import("@/components/users/UserMyPage.vue"),
|
||||
},
|
||||
// {
|
||||
// path: "modify/:userid",
|
||||
// name: "user-modify",
|
||||
// component: () => import("@/components/users/UserModify.vue"),
|
||||
// },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/board',
|
||||
component: () => import('@/views/BoardView.vue'),
|
||||
|
139
src/stores/member.js
Normal file
139
src/stores/member.js
Normal file
@ -0,0 +1,139 @@
|
||||
import { ref } from "vue"
|
||||
import { useRouter } from "vue-router"
|
||||
import { defineStore } from "pinia"
|
||||
import { jwtDecode } from "jwt-decode"
|
||||
|
||||
import { userConfirm, findById, tokenRegeneration, logout } from "@/api/member"
|
||||
import { httpStatusCode } from "@/utils/http-status"
|
||||
|
||||
export const useMemberStore = defineStore("memberStore", () => {
|
||||
const router = useRouter()
|
||||
|
||||
const isLogin = ref(false)
|
||||
const isLoginError = ref(false)
|
||||
const userInfo = ref(null)
|
||||
const isValidToken = ref(false)
|
||||
|
||||
const userLogin = async (loginUser) => {
|
||||
await userConfirm(
|
||||
loginUser,
|
||||
(response) => {
|
||||
if (response.status === httpStatusCode.CREATE) {
|
||||
console.log("로그인 성공!!!!")
|
||||
let { data } = response
|
||||
let accessToken = data["access-token"]
|
||||
let refreshToken = data["refresh-token"]
|
||||
isLogin.value = true
|
||||
isLoginError.value = false
|
||||
isValidToken.value = true
|
||||
sessionStorage.setItem("accessToken", accessToken)
|
||||
sessionStorage.setItem("refreshToken", refreshToken)
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.log("로그인 실패!!!!")
|
||||
isLogin.value = false
|
||||
isLoginError.value = true
|
||||
isValidToken.value = false
|
||||
console.error(error)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const getUserInfo = async (token) => {
|
||||
let decodeToken = jwtDecode(token)
|
||||
console.log(decodeToken)
|
||||
await findById(
|
||||
decodeToken.userId,
|
||||
(response) => {
|
||||
if (response.status === httpStatusCode.OK) {
|
||||
userInfo.value = response.data.userInfo
|
||||
} else {
|
||||
console.log("유저 정보 없음!!!!")
|
||||
}
|
||||
},
|
||||
async (error) => {
|
||||
console.error(
|
||||
"g[토큰 만료되어 사용 불가능.] : ",
|
||||
error.response.status,
|
||||
error.response.statusText
|
||||
)
|
||||
isValidToken.value = false
|
||||
|
||||
await tokenRegenerate()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const tokenRegenerate = async () => {
|
||||
await tokenRegeneration(
|
||||
JSON.stringify(userInfo.value),
|
||||
(response) => {
|
||||
if (response.status === httpStatusCode.CREATE) {
|
||||
let accessToken = response.data["access-token"]
|
||||
sessionStorage.setItem("accessToken", accessToken)
|
||||
isValidToken.value = true
|
||||
}
|
||||
},
|
||||
async (error) => {
|
||||
// HttpStatus.UNAUTHORIZE(401) : RefreshToken 기간 만료 >> 다시 로그인!!!!
|
||||
if (error.response.status === httpStatusCode.UNAUTHORIZED) {
|
||||
// 다시 로그인 전 DB에 저장된 RefreshToken 제거.
|
||||
await logout(
|
||||
userInfo.value.userid,
|
||||
(response) => {
|
||||
if (response.status === httpStatusCode.OK) {
|
||||
console.log("리프레시 토큰 제거 성공")
|
||||
} else {
|
||||
console.log("리프레시 토큰 제거 실패")
|
||||
}
|
||||
alert("RefreshToken 기간 만료!!! 다시 로그인해 주세요.")
|
||||
isLogin.value = false
|
||||
userInfo.value = null
|
||||
isValidToken.value = false
|
||||
router.push({ name: "user-login" })
|
||||
},
|
||||
(error) => {
|
||||
console.error(error)
|
||||
isLogin.value = false
|
||||
userInfo.value = null
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const userLogout = async () => {
|
||||
console.log("로그아웃 아이디 : " + userInfo.value.userId)
|
||||
await logout(
|
||||
userInfo.value.userId,
|
||||
(response) => {
|
||||
if (response.status === httpStatusCode.OK) {
|
||||
isLogin.value = false
|
||||
userInfo.value = null
|
||||
isValidToken.value = false
|
||||
|
||||
sessionStorage.removeItem("accessToken")
|
||||
sessionStorage.removeItem("refreshToken")
|
||||
} else {
|
||||
console.error("유저 정보 없음!!!!")
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
console.log(error)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
isLogin,
|
||||
isLoginError,
|
||||
userInfo,
|
||||
isValidToken,
|
||||
userLogin,
|
||||
getUserInfo,
|
||||
tokenRegenerate,
|
||||
userLogout,
|
||||
}
|
||||
})
|
19
src/stores/menu.js
Normal file
19
src/stores/menu.js
Normal file
@ -0,0 +1,19 @@
|
||||
import { ref } from "vue";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useMenuStore = defineStore("menuStore", () => {
|
||||
const menuList = ref([
|
||||
{ name: "로그인", show: true, routeName: "user-login" },
|
||||
{ name: "회원가입", show: true, routeName: "user-join" },
|
||||
{ name: "내정보", show: false, routeName: "user-mypage" },
|
||||
{ name: "로그아웃", show: false, routeName: "user-logout" },
|
||||
]);
|
||||
|
||||
const changeMenuState = () => {
|
||||
menuList.value = menuList.value.map((item) => ({ ...item, show: !item.show }));
|
||||
};
|
||||
return {
|
||||
menuList,
|
||||
changeMenuState,
|
||||
};
|
||||
});
|
11
src/utils/http-status.js
Normal file
11
src/utils/http-status.js
Normal file
@ -0,0 +1,11 @@
|
||||
// HTTP Status Code
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
|
||||
export const httpStatusCode = {
|
||||
OK: 200,
|
||||
CREATE: 201,
|
||||
NOCONTENT: 204,
|
||||
UNAUTHORIZED: 401,
|
||||
FORBIDDEN: 403,
|
||||
NOTFOUND: 404,
|
||||
};
|
||||
|
14
src/views/TheUserView.vue
Normal file
14
src/views/TheUserView.vue
Normal file
@ -0,0 +1,14 @@
|
||||
<script setup></script>
|
||||
|
||||
<template>
|
||||
<div class="container text-center mt-3">
|
||||
<div class="alert alert-primary" role="alert">Member Service</div>
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
mark.orange {
|
||||
background: linear-gradient(to top, rgb(243, 164, 18) 20%, transparent 30%);
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user