node 2022/02/15

무간·2022년 2월 15일

파일명 /routes/seller.js


// 시간대별 주문수량
// localhost:3000/seller/grouphour
router.get('/grouphour', async function(req, res, next) {
    try{
        const dbconn = await db.connect(dburl);
        const collection = dbconn.db(dbname).collection('order1');

        const result = await collection.aggregate([
            {
                $project : {
                    orderdate: 1, //주문일자
                    ordercnt : 1, //주문수량
                    month    : {$month  : '$orderdate'}, // 주문일자를 이용해서 달
                    hour     : {$hour   : '$orderdate'}, // 주문일자를 이용해서 시
                    minute   : {$minute : '$orderdate'} // 주문일자를 이용해서 분
                }
            },
            {
                $group : {
                    _id     : '$hour', // 그룹할 항목
                    count   : { $sum : '$ordercnt' }
                }
            },
        ]).toArray();

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

// 상품별 주문수량(판매자 정보가 필요하기 때문에)
// localhost:3000/seller/groupitem?code=1051
// item1(판매자내용만 꺼냄) + order1에 itemcode가 일치하는 것만
router.get('/groupitem', checkToken, async function(req, res, next) {
    try{
        const email = req.body.uid;
        const dbconn = await db.connect(dburl);

        // 물품에서 판매자가 email과 같은 것 => 물품코드
        const collection = dbconn.db(dbname).collection('item1');
        // 고유값 꺼내기 distinct(교유값컬럼명,조건)
        const result = await collection.distinct("_id",{ seller : email });    
        console.log('groupitem',result);



        const collection1 = dbconn.db(dbname).collection('order1');
        // 그룹별 통계 aggregate
        const result1 = await collection1.aggregate([
            { $match : { itemcode : { $in : result } } },
            { $project : { _id : 1, itemcode : 1, ordercnt : 1 } },//가져올 항목( 물품코드, 주문수량 )
            {
                $group : {
                    _id     : '$itemcode', // 그룹할 항목                    
                    count   : { $sum : '$ordercnt' }
                }
            },            
        ]).toArray();
        
        return res.send({status:200, result:result1});
    }
    catch(e){
        console.error(e);
        return res.send({status:-1, message:e});
    }
});



// 주문회원 목록 : 판매자가 등록한 물품에 대해 주문한 고객 정보
// localhost:3000/seller/memberlist
router.get('/memberlist', checkToken, async function(req, res, next){
    try{
        const email = req.body.uid; // 판매자의 이메일
        // DB접속
        const dbconn = await db.connect(dburl);
        // DB선택 및 컬렉션 선택        
        const collection = dbconn.db(dbname).collection('item1');
        const result = await collection.find(
            { seller     : email },          // 조건
            { projection : { _id : 1 } } // 가지고올 컬럼 설정
        ).toArray();
        //console.log(result);        
        
        let code = [];
        for(let tmp of result){
            code.push(tmp._id);
        }       
        
        const collection1 = dbconn.db(dbname).collection('order1');
        // 고유값 꺼내기 distinct(교유값컬럼명,조건)
        const result1 = await collection1.distinct("orderid",{ itemcode : { $in : code } });        
        // console.log(result1);

        const collection2 = dbconn.db(dbname).collection('member1');
        const result2 = await collection2.find(
            { _id   : { $in : result1 } },          // 조건            
            { projection : { pw : 0 } }
        ).toArray();
        // console.log(result2);
        
        
        return res.send({status:200, result:result2});
    }
    catch(e){
        console.error(e);
        return res.send({status : -1, message:e });
    }
})



// 주문목록 : 판매자가 등록한 물품에 대해서 고객이 주문한 내역
// localhost:3000/seller/orderlist
router.get('/orderlist', checkToken, async function(req, res, next){
    try{
        const email = req.body.uid; // 판매자의 이메일
        // DB접속
        const dbconn = await db.connect(dburl);
        // DB선택 및 컬렉션 선택
        // 1. 판매자가 등록한 물품의 코드들 가져오기
        const collection = dbconn.db(dbname).collection('item1');
        const result = await collection.find(
            { seller : email },          // 조건
            { projection : { _id : 1 } } // 가지고올 컬럼 설정
        ).toArray();

        console.log(result);        
        // result => [{_id:1051},{_id:1052},{_id:..}...]
        // $in = [] => [1,2,3,4]

        // 2.  받은 결과를 배열로 변경
        // [ {_id:1},{_id:2},{_id:3} ] =>[1,2,3]
        let code = [];
        for(let tmp of result){
            code.push(tmp._id);
        }

        //for(let i=0;i< result.length;i++){
        //    code.push(result[i]._id)
        //}

        // 3. 주문내역에서 자겨온 코드에 대한 정보만
        const collection1 = dbconn.db(dbname).collection('order1');
        const result1 = await collection1.find(
            { itemcode : { $in : code } },          // 조건            
        ).toArray();
        
        // 4. result1에 있는 내용을 리턴함
        return res.send({status:200, result:result1});

        
        

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

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

파일명 src/stores/index.js

// npm install vuex@next --save
// 파일명 : src/stores/index.js
import {createStore} from "vuex";
import axios from 'axios';

// 모든 컴포넌트에서 공통으로 사용할 변수 설정
// props 와 emit 를 여기에서 처리함
const stores = createStore({

    // 공통 상태 변수
    state : {
        menu   : sessionStorage.getItem("CURL"), // 선택된 메뉴
        logged : false,                          // 로그인 상태
        uid    : '',                             // 로그인한 사용자의 이메일정보
        uname  : '',                             // 로그인한 사용자의 이름
        token  : '',                             // 토큰을 저장소에 보관하지 않고 사용
    },
    //가져가기 (getter)
    getters : {
        getMenu(state){
            return state.menu;
        },

        getLogged(state){
            return state.logged;
        },
        
        getUid(state) {
            return state.uid;
        },

        getUname(state) {
            return state.uname;
        },

    },

    // 변경하기 (mutation) : 증시변경
    mutations:{
        setMenu(state,value){
            state.menu = value;
        },
        setLogged(state,value){
            state.logged = value;
        },

        setUid(state, val) {
            state.uid = val;
        },

        setUname(state, val) {
            state.uname = val;
        },

    },

    // 변경하기(action) : 기다려야 되는 상황, 벡엔드 연동이 필요할 경우
    actions:{
        async handleData(context, payload){
            console.log(payload);
            const token = sessionStorage.getItem("TOKEN");
            if(typeof token !== 'undefined'&& token !== null){
                const url = `/member/validation`;
                const headers = {"Content-Type":"application/json", "token":token };
                const response = await axios.get(url, {headers:headers});
                if(response.data.status === 200){
                    // mutations의 setUid, setUname을 호출해서 내용변경
                    context.commit("setUid", response.data.uid);
                    context.commit("setUname", response.data.uname);
                }
                else{
                    // 토큰의 유효성을 검사하여 통과하지 못할경우
                    context.commit("setLogged", false);
                }
            }
        }
    },
});

export default stores;

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

파일명 src/component/Login.vue

<template>
    <div>
        <h3>src/component/Login.vue</h3>
        {{state}}
        <hr />
        <input type="text" v-model="state.userid"/>
        <input type="password" v-model="state.userpw"/>
        <input type="button" value="로그인" @click="handleLogin"/>

    </div>
</template>

<script>
import { reactive } from 'vue';
import axios from 'axios';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';


export default {
    // ver 3.0
    setup () { // this를 사용할 수 없음
        const router = useRouter();
        const store  = useStore();

        const state  = reactive({
            userid : 'aaa@gmail.com',
            userpw : 'aaa',

        });
        const handleLogin = async() => {
            const url = `/member/select`;
            const headers = {"Content-Type":"application/json"};
            const body = {
                email    : state.userid,
                password : state.userpw
            };
            const response = await axios.post(url, body, {headers});
            console.log(response.data.status);

            if(response.data.status === 200){
                console.log(response.data.token)
                // 저장소에 보관하기(공통변수)
                sessionStorage.setItem("TOKEN", response.data.token); 
                alert('로그인 되었습니다.');

                // 이메일, 이름정보 (공통변수)
                store.commit("setUid",response.data.uid);
                store.commit("setUname",response.data.uname);

                const curl = sessionStorage.getItem("CURL");
                if(curl === null){
                    // 주소창만 바뀜
                    router.push({name:'Home'});
                    // app.vue에 메뉴의 선택항목을 변경하도록 알려줌
                    // 메뉴 활성화
                    store.commit("setMenu","/");
                }
                else {
                    const query = JSON.parse(sessionStorage.getItem("CURL_QUERY"));
                    const params = JSON.parse(sessionStorage.getItem("CURL_PARAMS"));
                    router.push({name:curl, query:query, params:params});
                }

                
                // 로그인 상태
                store.commit("setLogged",true);

            }
            else{
                alert('아이디와 암호를 확인하세요');
            }

            
        };
        return {state, handleLogin}
    
    },   

}
</script>

<style lang="scss" scoped>

</style>

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

파일명 src/App.vue

<template>
  <div>

    <!-- ElMenu.vue -->
    <!-- props로 default-active숫자값을 전달 -->
    <!-- props로 router TRUE값을 전달 -->
    <!-- 자식컴포넌트 emit 를 통해서 select이벤트 -->
    <el-menu :default-active="state.activeIndex"
    class="el-menu-demo"
    mode="horizontal"
    :router="true"
    @select="handleSelect">

    <el-menu-item index="/">Home</el-menu-item>
    <el-menu-item v-show="logged === false" index="/login">Login</el-menu-item>
    <el-menu-item v-show="logged === true" index="/logout">Logout</el-menu-item>
    <el-menu-item v-show="logged === true" index="/seller">Seller</el-menu-item>
    <el-menu-item v-show="logged === true" index="/mypage">Mypage</el-menu-item>
    <el-menu-item index="/board">Board</el-menu-item>    
    <el-menu-item index="/admin">Admin</el-menu-item>    
    <el-menu-item index="/join">Join</el-menu-item>    
    <el-menu-item index="/chart">Chart</el-menu-item>    
    <div style="padding:17px" v-if="logged === true">{{uid}}//{{uname}}님 로그인</div>
    
    </el-menu>
    
    {{menu}},{{logged}}

    <hr />

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

<script>
import {useStore} from 'vuex';
import {computed, reactive, onMounted } from 'vue';

export default {
  setup () {
    const store = useStore();

    // store의 menu값 실시간으로 가져오기
    // 마지막으로 방문한 페이지를 session저장소에 보관후에 변환
    const menu = computed(()=>{      
      return store.getters.getMenu
    });

    // store의 logged값 실시간으로 확인
    const logged = computed(()=>{      
      return store.getters.getLogged
    });
    
    const uid = computed(()=>{      
      return store.getters.getUid
    });

    const uname = computed(()=>{      
      return store.getters.getUname
    });

    // store에서 읽은 메뉴값으로 초기값으로 세팅
    const state = reactive({
      activeIndex : menu
    })

    onMounted( async () => {
      // 저장소에 있는 TOKEN값을 읽어서 존재 유무 확인
      // TOKEN을 추가하는 시점은 로그인이 완료 되었을때
      // TOKEN의 값을 제거하는 시점은 로그아웃되었을때
      if(sessionStorage.getItem("TOKEN")===null){
        // store의 logged변수 값을 false
        store.commit("setLogged", false);
      }
      else{
        // mutation을 호출하는 경우
        store.commit("setLogged", true);
        // actions를 호출할 경우
        store.dispatch("handleData", {});
      }
    })

    
    // 메뉴를 클릭했을 떄 
    // store값 변경하기
    const handleSelect = (idx) =>{
      console.log(idx);
      // 메소드명,value 값
      store.commit("setMenu", idx);
    }

    
    // // store의 state 변수가 변경되는 시점을 바로 알 수 있음. 
    // store.subscribe((mutation, state) => {
    //   console.log('store.subscribe',mutation,state);
    // })

    return {state, menu, logged, handleSelect, uid, uname}
  }
}
</script>

<style lang="scss" scoped>

</style>

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

파일명 src/component/Seller.vue

<template>
    <div style="padding:10px">
        <h3>src/component/Seller.vue</h3>
        <hr />

        <button @click="handleMenu(1)">물품관리</button>
        <button @click="handleMenu(2)">회원관리</button>
        <button @click="handleMenu(3)">주문관리</button>     
        <button @click="handleMenu(4)">물품별 주문 수량 (차트)</button>     
        <button @click="handleMenu(5)">시간대별 주문 수량 (차트)</button>     

        <hr />

        <menu-1 v-if="state.menu === 1"></menu-1>
        <menu-2 v-if="state.menu === 2"></menu-2>
        <menu-3 v-if="state.menu === 3"></menu-3>   
        <menu-4 v-if="state.menu === 4"></menu-4>   
        <menu-5 v-if="state.menu === 5"></menu-5>   

    </div>
</template>

<script>
import {onMounted, reactive} from 'vue';
import Menu1 from './seller/Menu1.vue';
import Menu2 from './seller/Menu2.vue';
import Menu3 from './seller/Menu3.vue';
import Menu4 from './seller/Menu4.vue';
import Menu5 from './seller/Menu5.vue';
import { useRouter } from 'vue-router';
import { useRoute } from 'vue-router';


export default {
    components:{
            Menu1,Menu2,Menu3,Menu4,Menu5
    },
    setup () {
        const router = useRouter();
        const route = useRoute();

        const state = reactive({
            menu: Number(route.query.menu)
        });

        onMounted( ()=>{
            console.log('menu Number ===',route.query.menu)
            if(typeof route.query.menu === 'undefined'){
                state.menu = 1
            }
        })

        const handleMenu = (idx)=> {
            router.push({name:'Seller', query:{menu:idx}});
            state.menu = idx;
        }

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

<style lang="scss" scoped>

</style>

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

파일명 src/components/seller/Menu3.vue

<template>
    <div>
        <h3>주문관리</h3>

        <div v-if="state.items">
            <table border="1">
                <tr>
                    <th>주문번호</th>
                    <th>물품코드</th>
                    <th>주문수량</th>
                    <th>주문자</th>
                    <th>주문일자</th>
                </tr>

                <tr v-for="item in state.items" :key="item">        
                    <td>{{item._id}}</td>
                    <td>{{item.itemcode}}</td>
                    <td>{{item.ordercnt}}</td>
                    <td>{{item.orderid}}</td>
                    <td>{{item.orderdate}}</td>
                </tr>    
            </table>    
        </div>    

    </div>
</template>

<script>
import axios from 'axios';
import { onMounted, reactive } from 'vue';

export default {
    setup () {
        const state = reactive({
            token: sessionStorage.getItem("TOKEN")

        })

        const handleLoadData = async() =>{
            const url =`/seller/orderlist`;
            const headers = {"Content-Type":"application/json","token":state.token};
            const response = await axios.get(url, {headers});

            console.log('seller/Menu3/handleData',response.data);
            if(response.data.status === 200){
                state.items = response.data.result;
            }
        }
        
        onMounted(()=>{
            handleLoadData();
        })

        return {state}
    }
}
</script>

<style lang="scss" scoped>

</style>

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

파일명 src/components/seller/Menu2.vue

<template>
    <div>
        <h3>회원관리</h3>
         <div v-if="state.items">
            <table border="1">
                <tr>                    
                    <th>아이디</th>
                    <th>이름</th>
                    <th>등록일</th>                    
                </tr>

                <tr v-for="item in state.items" :key="item">        
                    <td>{{item._id}}</td>
                    <td>{{item.name}}</td>
                    <td>{{item.regdate}}</td>
                    
                </tr>    
            </table>    
         </div>

    </div>
</template>

<script>
import axios from 'axios';
import { onMounted, reactive } from 'vue';

export default {
    setup () {
        const state = reactive({
            token: sessionStorage.getItem("TOKEN")

        })

        const handleLoadData = async() =>{
            const url =`/seller/memberlist`;
            const headers = {"Content-Type":"application/json","token":state.token};
            const response = await axios.get(url, {headers});

            console.log('seller/Menu2/handleData',response.data);
            if(response.data.status === 200){
                state.items = response.data.result;
            }
        }
        
        onMounted(()=>{
            handleLoadData();
        })

        return {state}
    }
}
</script>

<style lang="scss" scoped>

</style>

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

파일명 src/components/seller/Menu4.vue

<template>
    <div>
        <h3>src/components/seller/Menu4.vue</h3>
        <div style="width:500px; height:300px">
            <vue3-chart-js 
                :id = "state.id" 
                :type = "state.type"                 
                ref ="chartRef"
                :data = "state.data">
            </vue3-chart-js>           
        </div>
    </div>
</template>

<script>
import { ref, onMounted, reactive } from 'vue';
import Vue3ChartJs from '@j-t-mcc/vue3-chartjs'
import axios from 'axios';

export default {
    components:{
            Vue3ChartJs
    },
    setup () {  
        
        const chartRef = ref(null); // 차트를 업데이트하기 위해서 연결
        const state = reactive({ // Read
            id   :'doughnut',
            type : 'doughnut',
            data :{
                labels   : [],
                datasets : [{ 
                    backgroundColor: [],
                    data : []
                }],
            },
            token : sessionStorage.getItem("TOKEN")
        })

        // 현재 로그인한 판매자를 조건으로 물품별 주문수량
        const handleLoadData = async () =>{
            const url = `/seller/groupitem`;
            const headers = {"Content-Type":"application/json", "token":state.token}
            const response = await axios.get(url,{headers});
            console.log("seller/Menu4/handleLoadData",response.data);
            if(response.data.status === 200){
                // [{_id:1051,count:2},{_id:1052,count:4}]

                let label      = []; // _id가 추가됨
                let background = []; // '#41B883'
                let data       = []; // count 추가됨

                for(let tmp of response.data.result){
                    label.push( tmp._id );
                    background.push( '#6569b5' );
                    data.push(tmp.count);
                }                
                state.data.labels = label;
                state.data.datasets[0]['backgroundColor'] = background;
                state.data.datasets[0]['data'] = data;

                chartRef.value.update(250);
            }            
        }
        onMounted(()=>{
            handleLoadData();
        })
        


        // 리턴함
        return {state,chartRef}
    }
}
</script>

<style lang="scss" scoped>

</style>
profile
당신을 한 줄로 소개해보세요

0개의 댓글