mongoDB + Postman + vue

국비 코딩 풀스택 수업 25일차 커뮤니티, 레지스터, 뷰티파이

비루블 2022. 7. 26. 17:48

요약

백엔드 커뮤니티, 레지스터

프론트 마이페이지, 커뮤니티, 레지스터

 

검색기능 text , page

 

// mysql쇼핑몰, oracle병원금융, mssql게임 => SQL문으로 작성
 => ORM JPA(몽고디비랑 형태가 비슷 우리가 지금 몽고db로하는 중)
sql못쓰는 곳은 ORM JPA 많이씀

 

 

ex_community.js

var express = require('express');
var router = express.Router();

// DB연동을 위한 모델 ORM
var Community = require('../models/ex_communitymodel');


// npm i moment
// npm i moment-timezone --save
require('moment-timezone');
var moment = require('moment');
moment.tz.setDefault('Asia/Seoul'); // 표준시 UTC 시간, 아시아.서울로 설정


// 커뮤니티 목록(검색기능 + 페이지네이션)
// postman에서 => 127.0.0.1:3000/api/ex_community/selectlist.json?page=1&text=a
router.get('/selectlist.json', async function(req, res, next) {
    try{
        //? page=1&trxt=a
        const page = Number(req.query.page);
        const text = req.query.text;

        const query = {$or : [
            {name    : new RegExp(text, 'i')},
            {content : new RegExp(text, 'i')}
        ]};
        //내림차순 마지막에 등록한걸 제일위로
        // mysql쇼핑몰, oracle병원금융, mssql게임 => SQL문으로 작성 => ORM JPA
        const result = await Community.find(query)
        .sort({_id:-1})
        .skip((page-1)*10)
        .limit(10);

        if(result !== null){
            return res.send({status:200, result : result});
        }

        return res.send({status:0});
    }

    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});



//등록
//postman에서 => 127.0.0.1:3000/api/ex_community/insert.json
//vue에서     => /api/ex_community/insert.json
router.post('/insert.json', async function(req, res, next) {
    try{
        const name = req.body.name;
        const content = req.body.content;

        const obj = new Community();
        obj.name = name;
        obj.content = content;
        obj.regdate = moment().format('YYYY-MM-DD HH:mm:ss');

        const result = await obj.save();

        if(result !== null) {
            return res.send({status:200});
        }
        return res.send({status:0});
    }

    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

module.exports = router;

 

const query = {$or : [
    {name    : new RegExp(text, 'i')},
    {content : new RegExp(text, 'i')}
]};

 

검색기능

//내림차순 마지막에 등록한걸 제일위로
const result = await Community.find(query).sort({_id:-1})



// mysql쇼핑몰, oracle병원금융, mssql게임 => SQL문으로 작성
 => ORM JPA(몽고디비랑 형태가 비슷 우리가 지금 몽고db로하는 중)
sql못쓰는 곳은 ORM JPA 많이씀


ex_register 가장 어렵

var express = require('express');
var router = express.Router();

// 외부에서 사용
const ex_auth = require('../token/ex_auth');

// DB연동을 위한 모델 ORM
var Member = require('../models/ex_membermodel');
var Community = require('../models/ex_communitymodel');
var Grade = require('../models/ex_grademodel');
var Step = require('../models/ex_stepmodel');
var Register = require('../models/ex_registermodel');

// npm i moment
// npm i moment-timezone --save
require('moment-timezone');
var moment = require('moment');
moment.tz.setDefault('Asia/Seoul'); // 표준시 UTC 시간, 아시아.서울로 설정


//내가 개설한 커뮤니티 목록
// 127.0.0.1:3000/api/ex_register/selectlist.json
router.get('/selectlist.json', ex_auth.checkToken, async function(req, res, next) {
    try{
        const email =req.body.TID; // 이메일

        const query = {memberid : email, grade : 9}

        const result = await Register.find(query).select({communityno:1});
        if(result !== null) {
            return res.send({status:200, result:result});
        }
        return res.send({status:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});





//개설하기
// 127.0.0.1:3000/api/ex_register/register.json
// 토큰(이메일), 커뮤니티번호, grade:9, step:111
router.post('/register.json', ex_auth.checkToken, async function(req, res, next) {
    try{
        const email =req.body.TID; // 이메일
        const communityno = Number(req.body.communityno); // 커뮤니티번호
        // const grade = await Grade.findOne().select({_id:1});
        // const step = await Step.findOne().select({_id:1});

        const obj = new Register();
        obj.memberid    = email;
        obj.step        = 111;
        obj.grade       = 9;
        obj.communityno = communityno;
        obj.regdate     = moment().format('YYYY-MM-DD HH:mm:ss');
        
        const result = await obj.save();
        if(result !== null) {
            return res.send({status:200});
        }
        return res.send({status:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});


// 커뮤니티 가입(일반회원)
// 127.0.0.1:3000/api/ex_register/join.json
// 토큰(이메일), 커뮤니티번호, grade:1, step:666
router.post('/join.json', ex_auth.checkToken, async function(req, res, next) {
    try{
        const email =req.body.TID; // 이메일
        const communityno = Number(req.body.communityno); // 커뮤니티번호
        // const grade = await Grade.findOne().select({_id:1});
        // const step = await Step.findOne().select({_id:1});

        const obj = new Register();
        obj.memberid    = email;
        obj.step        = 666;
        obj.grade       = 1;
        obj.communityno = communityno;
        obj.regdate     = moment().format('YYYY-MM-DD HH:mm:ss');
        
        const result = await obj.save();
        if(result !== null) {
            return res.send({status:200});
        }
        return res.send({status:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

module.exports = router;


설계를 어떻게할지 고민해야함
등급부분부터
근데 일단 모델5개 다 끌어옴
// DB연동을 위한 모델 ORM

var Member = require('../models/ex_membermodel');
var Community = require('../models/ex_communitymodel');
var Grade = require('../models/ex_grademodel');
var Step = require('../models/ex_stepmodel');
var Register = require('../models/ex_registermodel');


몽고디비에서
grade를 건드려줌(사진참고)


db.ex_grades.insertMany([
    {_id:9, name:'개설자', regdate:'2022-07-26 10:25:00'},
    {_id:8, name:'운영자', regdate:'2022-07-26 10:25:00'},
    {_id:7, name:'스텝', regdate:'2022-07-26 10:25:00'},
    {_id:1, name:'회원', regdate:'2022-07-26 10:25:00'},
])

ex_steps 건드려줌
db.ex_steps.insertMany([
    {_id:1, content:'개설하기', regdate:'2022-07-26 10:27:00'},
    {_id:2, content:'운영자 등록', regdate:'2022-07-26 10:27:00'},
    {_id:3, content:'스텝 등록', regdate:'2022-07-26 10:27:00'},
    {_id:4, content:'운영자 해제', regdate:'2022-07-26 10:27:00'},
    {_id:5, content:'스텝 해제', regdate:'2022-07-26 10:27:00'},
    {_id:6, content:'회원 등록', regdate:'2022-07-26 10:27:00'},
    {_id:7, content:'회원 해제', regdate:'2022-07-26 10:27:00'},
])



step,grade는 내용을 정의하는 역할만하기때문에 건드릴 필요 x


ex_register
post register개설된 커뮤니티 소유만들기
개설하기에서 나중에 두번호출해야함

post join일반회원가입

 


ex_grade.js
get selectlist

var express = require('express');
var router = express.Router();


var Grade = require('../models/ex_grademodel');

// 127.0.0.1:3000/api/ex_grade/selectlist.json
router.get('/selectlist.json', async function(req, res, next) {
    try{

        const result = await Grade.find({});
        if(result !== null) {
            return res.send({status:200, result:result});
        }
        return res.send({status:0});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, result:e});
    }
});

module.exports = router;



오후일과
vue작업
stores 모듈(A/B로 나눠서 작업해줌)

각 vue마다 session부분 봐야함


index.js갈음

import { createStore } from 'vuex';

// 모듈A,  모듈B
import { moduleA } from './modules/moduleA';
import { moduleB } from '@/stores/modules/moduleB';

export default createStore({
    modules : { moduleA, moduleB }
});

 

 


stores>moduleA

// 로그인과 관련된 변수들..
export const moduleA = {
    namespaced : true,
    
    // 초기값 설정
    // ex) 로그인 상태를 저장하기 위해 저장소 값을 읽어 True / False
    state () {
        const auth = sessionStorage.getItem("AUTH");
        let tmp = false;
        if(auth !== null){
            tmp = true;
        }
        return {
            logged : tmp,
        }
    },

    // 변수값에 저장된 내용 리턴
    // ex) App.vue에서 사용
    getters :{
        getLogged(state){
            return state.logged;
        }
    },

    // 변수값을 바꿈
    // ex) LoginPage.vue, LogoutPage.vue
    mutations:{
        setLogged(state, value){
            state.logged = value;
        }
    },

    // await를 사용해야 하는 작업
    // ex) axios를 이용한 토큰 검증 등...
    actions : {

    }
};

 

 

 

stores>moduleB

// 테스트 모듈 변수들...
export const moduleB = {

    namespaced : true,

    state :{
        counter : 100
    },

    getters :{
        getCounter(state){
            return state.counter;
        }
    },

    mutations:{
        setAddCounter(state){
            state.counter = state.counter + 1;
        },

        setSubCounter(state){
            state.counter = state.counter - 1;
        }
    },

    actions : {

    }
};

 

 

 

 

 


app.vue

<template>
  <v-container>
    

    
    <v-row align="center" justify="left">
      <v-btn small text @click="handlePage('/main')">메인</v-btn>
      <v-btn v-if="!state.logged" small text @click="handlePage('/login')">로그인</v-btn>
      <v-btn v-if="!state.logged" small text @click="handlePage('/join')">회원가입</v-btn>
      <v-btn v-if="state.logged" small text @click="handlePage('/mypage')">마이페이지</v-btn>
      <v-btn v-if="state.logged" small text @click="handlePage('/logout')">로그아웃</v-btn>
    </v-row>
    <br/><br/><br/><br/><br/>
    {{state}}

    <router-view></router-view>
  </v-container>
</template>

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

export default {
  setup () {
    const router = useRouter();
    const handlePage = (path) =>{
      console.log('App.vue => HandlePage => ', path);
      router.push({path:path});
    }

    const store = useStore();
    const state = reactive({
      logged  : computed(() => store.getters["moduleA/getLogged"]),
      counter : computed(() => store.getters["moduleB/getCounter"]),
    });



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


logged : computed(() => store.getters["moduelA/getLogged"])
새롭게 넣어봄

 

 

 

 

mypage.vue 작업 해줌 게시판 불러오기(미완성 페이지네이션 없음)

<template>
    <div>
        <h3>마이페이지</h3>
        {{state}}
        <v-card>
            <v-tabs v-model="state.tab" background-color="primary">
                <v-tab value="one">회원정보변경</v-tab>
                <v-tab value="two">비밀번호변경</v-tab>
                <v-tab value="three">회원탈퇴</v-tab>
                <v-tab value="four">개설한 커뮤니티</v-tab>
                <v-tab value="five">가입한 커뮤니티</v-tab>
            </v-tabs>

            <v-card-text>
                <v-window v-model="state.tab">
                    <v-window-item value="one">
                        <br/>
                        <v-text-field label="이름"
                            v-model="name"
                            variant="underlined"
                            placeholder="이름을 입력하세요."></v-text-field>

                        <v-text-field label="폰번호"
                            v-model="phone"
                            type="text"
                            variant="underlined"
                            placeholder="폰번호를 입력하세요."></v-text-field>

                        <v-btn @click="handleUpdate" color="primary">회원정보변경</v-btn>    
                    </v-window-item>

                    <v-window-item value="two">
                        <br/>
                        <v-text-field label="비밀번호"
                            v-model="password"
                            type="password"
                            variant="underlined"
                            placeholder="현재 비밀번호를 입력하세요."></v-text-field>

                        <v-text-field label="변경할 비밀번호"
                            v-model="password1"
                            type="password"
                            variant="underlined"
                            placeholder="변경할 비밀번호를 입력하세요."></v-text-field>

                        <v-text-field label="변경할 비밀번호 확인"
                            v-model="password2"
                            type="password"
                            variant="underlined"
                            placeholder="변경할 비밀번호를 입력하세요."></v-text-field>

                        <v-btn @click="handleUpdatepw" color="primary">비밀번호변경</v-btn> 
                    </v-window-item>

                    <v-window-item value="three">
                        <br/>
                        <v-text-field label="비밀번호"
                            v-model="password"
                            variant="underlined"
                            placeholder="비밀번호를 입력하세요."></v-text-field>
                        <v-btn @click="handleUpdate" color="red">회원탈퇴</v-btn> 
                    </v-window-item>

                    <v-window-item value="four">
                        <v-btn flat color="secondary" @click="dialog=true">
                            커뮤니티 개설하기
                        </v-btn>

                        <v-table>
                            <thead>
                                <tr>
                                    <th class="text-left">
                                        번호
                                    </th>
                                    <th class="text-left">
                                        제목
                                    </th>
                                    <th class="text-left">
                                        내용
                                    </th>
                                    <th class="text-left">
                                        등록일
                                    </th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr v-for="tmp in state.rows" :key="tmp._id">
                                    <td>{{tmp._id}}</td>
                                    <td>{{tmp.name}}</td>
                                    <td>{{tmp.content}}</td>
                                    <td>{{tmp.regdate}}</td>
                                </tr>
                            </tbody>
                        </v-table>
                    </v-window-item>

                    <v-window-item value="five">
                        Five
                    </v-window-item>
                </v-window>
            </v-card-text>
        </v-card>

        <v-dialog v-model="dialog" persistent>
            <v-card style="width:500px">
                <v-card-title>
                    <span class="text-h5">커뮤니티 생성</span>
                </v-card-title>

                <v-card-text>
                    <v-container>
                        <v-row>
                            <v-col cols="12">
                                <v-text-field  label="커뮤니티명 *" required v-model="communityname"></v-text-field>
                            </v-col>
                            <v-col cols="12">   
                                <v-text-field  label="커뮤니티설명 *" required v-model="communitycontent"></v-text-field>
                            </v-col>
                        </v-row>
                    </v-container>
                    <small>* 필수항목</small>
                </v-card-text>

                <v-card-actions>
                    <v-spacer></v-spacer>
                    <v-btn color="blue-darken-1" text @click="dialog = false; handlecommunityinsert()">등록</v-btn>
                    <v-btn color="blue-darken-1" text @click="dialog = false">닫기</v-btn>
                </v-card-actions>
            </v-card>
        </v-dialog>  

    </div>
</template>

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

        const state = reactive({
            tap              : null,
            dialog           : false,
            name             : '변경할 이름',
            phone            : '010-0000-7777',
            password         : '',
            password1        : '',
            password2        : '',
            communityname    : '',
            communitycontent : '',
            page : 1,
            text : '',

            rows : [],
            token : sessionStorage.getItem("AUTH")
        });


        const handleUpdate = async() => {
            //{"name":"123", "phone":"010-1111-1111"}
            const url = `/api/ex_member/update.json`
            const headers = {"Content-Type":"application", "auth" : state.token};
            const body = {
                "name"  : state.name,
                "phone" : state.phone
            };
            const {data} = await axios.put(url, body, {headers});
            console.log(data);
            if(data.status === 200){
                alert('변경이 완료되었습니다.')
            }
        };

        //{"password":"a", "password1":"b"}
        const handleUpdatepw = async() => {
            const url = `/api/ex_member/updatepw.json`;
            const headers = {"Content-Type":"application", "auth" : state.token};
            const body = {
                "password"  : state.password,
                "password1" : state.password1
            }
            const {data} = await axios.put(url, body, {headers});
            console.log(data);
        }

        const handlecommunityinsert = async() => {
            const url = `/api/ex_community/insert.json`;
            const headers = {"Content-Type":"application/json"};
            const body = {
                "name"    : state.communityname,
                "content" : state.communitycontent
            }
            const {data} = await axios.post(url, body, {headers});
            if(data.status === 200){
                alert('커뮤니티 개설이 완료되었습니다.')
            }
        }

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

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


        return {
            state,
         ...toRefs(state),
         handleUpdate, 
         handleUpdatepw,
         handlecommunityinsert,
         handlecommunityData
         }
    }
}
</script>

<style lang="css" scoped>

    .box {
        width   : 500px;
        border  : 1px solid #cccccc;
        padding : 30px;
        margin-top:30px;
    }

</style>