회원가입, 로그인, 메뉴 활성화, 슬라이드, 주문 페이지,

keep_going·2022년 12월 27일
0

vue

목록 보기
7/13

// 파일명 : ItemUpdatePage.vue _ 수정:서브이미지 삭제

<template>
            <div v-for="tmp of state.imageurl" :key="tmp" style="display:inline-block;">
                <img :src="tmp.img" style="width:100px" />
                <button @click="handleImageDelete(tmp._id)">X</button>
            </div>
</template>

<script>
import { reactive, toRefs } from '@vue/reactivity';
import { useRoute } from 'vue-router'
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';
export default {
    setup () {
        const route = useRoute();

        const state = reactive({
            no          : Number( route.query.no ), //주소창 ?no=557
            row         : null,
            cnt         : 2,
            images      : [null, null, null, null, null ],
            imageurl    : [],
        });

        // 물품번호X, 서브이미지의번호
        const handleImageDelete = async(no) =>{ 
        // no는 서브이미지의 번호! 삭제 할때는 물품번호가 아니라 서브이미지의 번호가 필요함
        // 물품번호를 넣으면 서브이미지 모두 삭제됨
            console.log(no);
            const url = `/item101/subimagedelete.json?no=${no}`;
            const headers = {"Content-Type":"application/json"};
            const body = {};
            const { data } = await axios.delete(url, {headers:headers, data:body});
            console.log(data);
            if(data.status === 200) {
                handleData1();
            }
        };

        return {
            state,
            ...toRefs(state),
            FilePlus,
            FileMinus,
            handleSubImage,
            handleImage,
            handleImageDelete,
        };
    }
}
</script>

<style lang="css" scoped>

</style>

// 파일명 : ContentPage.vue

<template>
    <div class="container">
        <div class="grid">
            <div class="item">
                <p><img :src="state.row.img" style="width: 400px;" /></p>
                <p><img :src="tmp.img" v-for="tmp of state.imageurl" :key="tmp" style="width: 100; height: 100px;"/></p>
            </div>
            <div class="item">
                <p>물품명: {{ state.row.name }} </p>
                <p>물품설명: {{ state.row.content }} </p>
                <p>물품가격: {{ state.row.price }} </p>
                <select v-model="state.cnt">
                    <option v-for="tmp of 100" :key="tmp" :value="tmp">{{ tmp }}</option>
                </select>
                <button @click="handleOrder">주문하기</button>
            </div>       
        </div>
    </div>
</template>

<script>
import { reactive } from '@vue/reactivity';
import { useRoute, useRouter } from 'vue-router'
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';
export default {
    setup () {
        const route = useRoute();
        const router = useRouter();

        const state = reactive({
            no          : Number(route.query.no), 
            row         : null,
            imageurl    : [],
            cnt         : 0,
        });

        // 물품 정보
        const handleData = async() => {
            const url = `/item101/selectone.json?no=${state.no}`;
            const headers = {"Content-Type":"application/json"};
            const { data } = await axios.get(url, {headers});
            console.log(data);
            if(data.status === 200) {
                state.row = data.result;
            }
        };

        // 서브 이미지 읽기
        const handleData1 = async() => {
            const url = `/item101/subimagecode.json?code=${state.no}`;
            const headers = {"Content-Type":"application/json"};
            const { data } = await axios.get(url, {headers});
            console.log(data);
            if(data.status === 200){
                state.imageurl = data.result;
            }
        };

        onMounted(() => {
            handleData();
            handleData1();
        });
      
        const handleOrder = () => {
            router.push({
                path:'/order', 
                query:{
                    no     : state.no, // 물품정보(물품번호)
                    cnt    : state.cnt, // 주문수량
                    userid : '주문자', // 주문자 -> 확보가 안됐으면 로그인페이지로 보내기
                }
            });
        }

        return {
            state,
            handleOrder,
        };
    }
}
</script>

<style lang="scss" scoped src="../assets/css/itemcontent.css">

</style>

// 파일명 : OrderPage.vue

<template>
    <div>
        <h3>주문페이지</h3>
        {{ state }}
    </div>
</template>

<script>
import { reactive } from '@vue/reactivity';
import { useRoute } from 'vue-router';
export default {
    setup () {
        const route = useRoute();
        const state = reactive({
            no :  Number(route.query.no),
            cnt :  Number(route.query.cnt),
            userid : route.query.userid
        });
        return {state};
    }
}
</script>

<style lang="scss" scoped>

</style>

회원가입 => /member101/insert.json => 키정보 {id:"a", pw:"b", name:"c", email:"a@a.com", age:13 }
아이디중복확인 => /member101/idcheck.json?id=a
로그인 => /member101/select.json => 키정보 {id:"a", pw:"a"}


// 파일명 : JoinPage.vue _컴포넌트 적용시키는 연습

<template>
    <div class="container">
        <el-form :model="state" label-width="120px">
            <el-form-item label="아이디">
                <el-input v-model="state.id" style="width: 200px;" @keyup="handleIDCheck()"/>
                <label style="padding: 0px 10px;" v-html="state.check"></label>
            </el-form-item>

            <el-form-item label="암호">
                <el-input type="password" v-model="state.pw" style="width: 200px;" />
            </el-form-item>

            <el-form-item label="암호확인">
                <el-input type="password" v-model="state.pw1" style="width: 200px;" />
            </el-form-item>

            <el-form-item label="이름">
                <el-input v-model="state.name" style="width: 200px;" />
            </el-form-item>

            <el-form-item label="이메일">
                <el-input v-model="state.email" style="width: 200px;" />
                <label>@</label>
                <el-select v-model="state.email1" placeholder="이메일 주소를 선택하세요">
                    <el-option value="google.com" />
                    <el-option value="naver.com" />
                    <el-option value="daum.net" />
                </el-select>
            </el-form-item>

            <el-form-item label="나이">
                <el-input type="number" v-model="state.age" style="width: 200px;" />
            </el-form-item>

            <el-form-item>
                <el-button type="info" size="small" :plain="true" @click="handleJoin()">회원가입</el-button>
                <el-button type="info" size="small"><router-link to="/" style="text-decoration: none; color: white;">홈으로</router-link></el-button>
            </el-form-item> 
        </el-form>
    </div>
</template>

<script>
import { reactive } from '@vue/reactivity'
import axios from 'axios';
import { ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';
export default {
    setup () {
        const router = useRouter();
        const state = reactive({
            id : '',
            pw : '',
            pw1 : '',
            name : '',
            email : '',
            email1 : '이메일 주소를 선택하세요',
            age : '',
            check : '<label style="color: blue">중복확인</label>',
        });

        const handleIDCheck = async() => {
            console.log('handleIDCheck');
            if(state.id.length > 0){
                const url=`/member101/idcheck.json?id=${state.id}`;
                const headers={"Content-Type":"application/json"};
                const { data } = await axios.get(url, {headers});
                console.log(data); 
                //result가 1이면 사용불가 0이면 사용 가능
                if(data.result === 1) {
                    state.check = '<label style="color: red">사용 불가</label>'
                }
                else if(data.result === 0) {
                    state.check = '<label style="color: greenyellow">사용 가능</label>'
                }
                else{
                    state.check =  '<label style="color: blue">중복확인</label>'
                }
            }
            else{
                state.check = '<label style="color: blue">중복확인</label>'
            }
        };

        const handleJoin = async() => {
            if(state.id === '') {
                ElMessage({
                    message: '아이디를 입력하세요',
                    type: 'warning',
                });
                return false;
            }
            if(state.pw === '') {
                ElMessage({
                    message: '암호를 입력하세요',
                    type: 'warning',
                });
                return false;
            }
            if(state.pw1 === '') {
                ElMessage({
                    message: '암호를 다시 입력하세요',
                    type: 'warning',
                });
                return false;
            }
            if(state.pw !== state.pw1) {
                ElMessage({
                    message: '암호를 확인하세요',
                    type: 'warning',
                });
                return false;
            }
            if(state.name === '') {
                ElMessage({
                    message: '이름을 입력하세요',
                    type: 'warning',
                });
                return false;
            }
            if(state.email === '') {
                ElMessage({
                    message: '이메일을 입력하세요',
                    type: 'warning',
                });
                return false;
            }
            if(state.email1 === '이메일 주소를 선택하세요') {
                ElMessage({
                    message: '이메일 주소를 선택하세요',
                    type: 'warning',
                });
                return false;
            }
            if(state.age === '') {
                ElMessage({
                    message: '나이를 입력하세요',
                    type: 'warning',
                });
                return false;
            }

            const url = `/member101/insert.json`;
            const headers = {"Content-Type":"application/json"};
            const body = {
                id : state.id,
                pw : state.pw,
                name : state.name,
                email : `${state.email}@${state.email1}`,
                age : state.age
            }
            const { data } = await axios.post(url, body, {headers});
            console.log(data);
            if(data.status === 200) {
                ElMessage({
                    message: '회원 가입 성공!',
                    type: 'success',
                });
                router.push({path:"/"});
            }
        };

        return {
            state,
            handleJoin,
            handleIDCheck,
        }
    }
}
</script>

<style lang="css" scoped>
    .container {
        width: 900px;
        padding: 10px;
        margin: 10px auto;
    }

</style>

============================================

// 파일명 : stores/index.js


import axios from "axios";
import { createStore } from "vuex";

const stores = createStore({
    state (){ //변수지정
        let tmp = false;
        let tmp1 = '';

        if(sessionStorage.getItem("TOKEN") !== null) {
            tmp = true;
            tmp1 = sessionStorage.getItem("ID");
        }

        return {
            logged : tmp,
            userid : tmp1,
            defaultActive : '/',
        }
    },

    getters:{ // 가지고 가는 내용
        getLogged(state) {
            return state.logged;
        },
        getUserid : (state) => {
            return state.userid;
        },
        getDefaultActive(state){
            return state.defaultActive;
        }
    },

    mutations: { // 1. 변수값을 변경, 비동기 사용 불가
        setDefaultActive(state, value){
            state.defaultActive = value;
        },
        setLogged(state, value) {
            state.logged = value;
        },
        setUserid(state, value) {
            state.userid = value;
        }
    },

    actions :{ // 2. 변수값을 변경, 비동기 호출 수행 (백엔드 연동)
        async handleData(context) {
            const url = ``;
            const headers = {};
            const {data} = await axios.get(url,{headers});
            if(data.status === 200){
                context.commit('setUserid', 'aaa');
            }
        }
    }
    // 백엔드로 갔다가 다시 받은 데이터를 userid에 넣고싶은데 mutation에 바로 넣을수가 없다! 
    // actions를 이용하면 mutation을 호출해서 setUserid를 변경가능
    // 예시로 입력한 것이고 지금 사용되는것 아님
});

export default stores;

// 파일명 : LoginPage.vue

<template>
    <div class="container">
        <el-form :model="state" label-width="120px">
            <el-form-item label="아이디">
                <el-input v-model="state.id" style="width: 200px;"/>
            </el-form-item>

            <el-form-item label="암호">
                <el-input type="password" v-model="state.pw" style="width: 200px;" />
            </el-form-item>

            <el-form-item>
                <el-button type="info" size="small" :plain="true" @click="handleLogin()">로그인</el-button>
                <el-button type="info" size="small"><router-link to="/join" style="text-decoration: none; color: white;">회원가입 하러가기</router-link></el-button>
            </el-form-item> 
        </el-form>
    </div>
</template>

<script>
import { reactive } from '@vue/reactivity'
import axios from 'axios';
import { ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';

export default {
    setup () {

        const router = useRouter();
        const store = useStore();

        const state = reactive ({
            id : '',
            pw : '',
        });

        const handleLogin = async() => {
            const url = `/member101/select.json`;
            const headers = {"Content-type":"application/json"};
            const body = {
                id : state.id,
                pw : state.pw,
            }
            const { data } = await axios.post(url, body, {headers});
            console.log(data);
            if(data.status === 200) {
                // 저장소 보관
                sessionStorage.setItem("TOKEN", data.result);
                sessionStorage.setItem("ID", data.test._id);
                
                // stores의 state 값을 변경
                store.commit('setLogged', true);
                store.commit('setUserid', data.test._id);
                store.commit('setDefaultActive', "/");

                ElMessage({
                    message: '로그인 성공!',
                    type: 'success',
                });
                router.push({path:"/"});
            }
            else {
                ElMessage({
                    message: '아이디 또는 비밀번호를 확인하세요',
                    type: 'warning',
                });
            }
        }

        return {
            state,
            handleLogin,
        }
    }
}
</script>

<style lang="css" scoped>
    .container {
        width: 900px;
        padding: 10px;
        margin: 10px auto;
    }
</style>

// 파일명 : LogoutPage.vue

<template>
    <div>

    </div>
</template>

<script>
import { onMounted } from '@vue/runtime-core';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';

export default {
    setup () {
        const store = useStore()
        const router = useRouter();
        
        onMounted(async() => {
            if(await confirm('로그아웃할까요?')) {
                sessionStorage.removeItem("TOKEN");
                sessionStorage.removeItem("ID");
                
                //stores의 mutations state값을 변경
                store.commit('setLogged', false);
                store.commit('setUserid', '');

                // 예시) stores의 action호출
                // store.dispatch('handleData');
            }

            store.commit('setDefaultActive', "/")
            router.push({path:'/'});
        });

        return {}
    }
}
</script>

<style lang="scss" scoped>

</style>

https://antoniandre.github.io/vueper-slides/

npm i vueperslides

  • 슬라이드 띄우기 위해서 컴포넌트 설치

// 파일명 : HomePage.vue

<template>
    <div class="container">
        <h3>홈화면</h3>
		<vueper-slides>
            <vueper-slide v-for="tmp of slides" :key="tmp" :title="tmp.title" :image="tmp.image">
            </vueper-slide>
        </vueper-slides>
		// 슬라이드 띄우기 위해 컴포넌트 설치

        <div class="grid">
            <div class="item" v-for="tmp of state.rows" :key="tmp" style="cursor:pointer;" @click="handleContent(tmp._id)">
                <img :src="tmp.img" style="width:100%; height: 140px;" />
                <p>{{ tmp.name }}</p>
                <p>{{ tmp.price }}</p>
            </div>
        </div>
    </div>
</template>

<script>
import { reactive } from '@vue/reactivity'
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';
import { useRouter } from 'vue-router';
import { VueperSlides, VueperSlide } from 'vueperslides'
import 'vueperslides/dist/vueperslides.css'
export default {
    components: { 
        // 컴포넌트 표기법 VueperSlides(파스칼), vueper-slides(케밥)
        VueperSlides, // vueper-slides
        VueperSlide  // vueper-slide
    },
    setup () {
        const router = useRouter();

        const state = reactive({
            rows : [],
            page : 1,
        });
        
        const slides = [
            { title: 'Slide #1', image:'https://picsum.photos/500/300?image=12' },
            { title: 'Slide #2', image:'https://picsum.photos/500/300?image=13' },
            { title: 'Slide #3', image:'https://picsum.photos/500/300?image=14' },
            { title: 'Slide #4', image:'https://picsum.photos/500/300?image=15' },
        ]

        const handleData = async() => {
            const url = `/item101/selectlistpage.json?page=${state.page}`;
            const headers = {"Content-Type":"application/json"};
            const { data } = await axios.get(url, {headers});
            console.log(data);
            if(data.status === 200){
                state.rows  = data.result;
            }
        };

        const handleContent = async(no) => {
            router.push({path:'/content', query:{no:no}});
        };

        onMounted(()=>{
            handleData();
        });

        return {
            state,
            slides,
            handleContent,
        };
    }
}
</script>

<style lang="css" scoped src="../assets/css/home.css">
 // scoped는 이 페이지에서만 적용된다는 뜻

</style>

// 파일명 : App.vue _수정:메뉴 기본값 활성화

<template>
  <div>
    <el-menu :mode="state.mode" :router="state.router" :default-active="state.defaultActive" @select="handleSelect"> 
	// 컴포넌트 event보고 select 써야겠다 정한것
      <el-menu-item index="/"></el-menu-item>
      <el-menu-item index="/seller">판매자</el-menu-item> 
      <el-menu-item index="/login" v-if="state.logged === false">로그인</el-menu-item> 
      <el-menu-item index="/join" v-if="state.logged === false">회원가입</el-menu-item>
      <el-menu-item index="/logout" v-if="state.logged === true">{{ state.userid }}님 로그아웃</el-menu-item>
    </el-menu>

    <router-view></router-view>
  </div>
</template>

<script>
import { reactive } from '@vue/reactivity'
import { useStore } from 'vuex';
import { computed } from '@vue/runtime-core';
export default {
  setup () {
    const store = useStore()
    const state = reactive({
      mode : 'horizontal',
      router : true, 
      logged : computed(()=>store.getters.getLogged),
      userid : computed(()=>store.getters.getUserid),
      defaultActive : computed(()=>store.getters.getDefaultActive),
    });

    // 메뉴를 클릭할때 마다 defaultActive를 변경 -> 그렇게 되야지만 로그인, 로그아웃할때 홈으로 활성화됨
    // element plus 썼더니 같은페이지에서는 활성화 안되네! 다른 메뉴 클릭할때마다 바꿔줘야함. 다른 component 썼으면 다른 방식으로 해야함...
    const handleSelect = (e) => {
      console.log(e);
      // store의 값을 바꾸기
      store.commit('setDefaultActive', e);
    }
    
    return {
      state,
      handleSelect
    }
  }
}
</script>

<style lang="css" scoped>

</style>
profile
keep going

2개의 댓글

comment-user-thumbnail
2022년 12월 27일

참고)) DOM이란 무엇인가? https://wit.nts-corp.com/2019/02/14/5522

답글 달기
comment-user-thumbnail
2022년 12월 29일

참고 )) 비동기 호출 ? https://learnjs.vlpt.us/async/

답글 달기