node 2022/02/09

무간·2022년 2월 9일

파일명 route/seller.js

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

// 문자를 HASH하기(암호보안)
const crypto = require('crypto');

// config/mongodb.js 에서 DB내용 불러와서 연결
const db     = require('mongodb').MongoClient;
const dburl  = require('../config/mongodb').URL;
const dbname = require('../config/mongodb').DB;

// 토큰 발행을 위한 필요 정보 가져오기
const jwt        = require('jsonwebtoken');
const jwtKey     = require('../config/auth').securityKey;
const jwtOptions = require('../config/auth').options;
const checkToken = require('../config/auth').checkToken;

// 이미지 파일 전송
const multer = require('multer');

// 특정 폴더에 파일로 
// 메모리 DB에 추가
const upload = multer({storage:multer.memoryStorage()});


// 물품 일괄 수정
// localhost:3000/seller/update
router.put('/update', checkToken, upload.array("image"), async function(req, res, next) {
    try{
        // DB접속
        const dbconn = await db.connect(dburl);
        // 2. DB선택 및 컬렉션 선택
        const collection = dbconn.db(dbname).collection('item1');      

        // req.body { code:[1030,1031,1032 ], title: ['a','b'] }
        // req.files => [ { }, { } ]
        
        let cnt = 0; // 실질적으로 변경할 개수를 누적할 변수
        for(let i=0; i<req.body.title.length; i++){
            let obj = { // 4개의 키만 존재
                name     : req.body.title[i],
                price    : req.body.price[i],
                quantity : req.body.quantity[i],
                content  : req.body.content[i],        
            };
            
            // 이미지 첨부하면 키를 4개 더 추가함
            if( typeof req.files[i] !== 'undefined'){
                obj['filename'] = req.files[i].originalname;
                obj['filedata'] = req.files[i].buffer;
                obj['filetype'] = req.files[i].mimetype;
                obj['filesize'] = req.files[i].size;
            }

            const result = await collection.updateOne(
                { _id  : Number(req.body.code[i]) }, //조건
                { $set : obj } //변경내용
            );
            cnt += result.matchedCount;
        }

        //실제 변경된 개수 === 처음 변경하기 위해 반복했던 개수 일치유무
        if(cnt === req.body.title.length){
            return res.send({status : 200});
        }        
        return res.send({status : 0});
    }
    catch(e){
        console.error(e);
        return res.send({status : -1, message:e });
    } 
     
});



// 물품 일괄 삭제
// localhost:3000 /seller/delete
router.delete('/delete', checkToken, async function(req, res, next) {
    try{
        // { "code":[1019,1020,1021] }
        const code = req.body.code;
        console.log(code);
        
        // DB접속
        const dbconn = await db.connect(dburl);
        // 2. DB선택 및 컬렉션 선택
        const collection = dbconn.db(dbname).collection('item1');      

        // { $in : [ 1,2,3,4 ] } 포함 된 항목
        const result = await collection.deleteMany(
            { _id : {$in : code} }
        )
        console.log(result);
        if(result.deletedCount === code.length){
            return res.send({status : 200});
        }
        return res.send({status : 0});
        
    }
    catch(e){
        console.error(e);
        return res.send({status : -1, message:e });
    }  
});

// 물품 등록 : 로그인, 이미지를 포함한 n개
// localhost:3000 /seller/insert
// 로그인을 한 사용자가 판매자
router.post('/insert', upload.array("image"), checkToken, async function(req, res, next) {
    try{
        console.log(req.body);
        // 여러개 일 경우  전송1, body  => {  title : [1,2], price : [3,4]}
        // 1개일 경우      전송1, body  => {  title : 1, price : 3]} 

        // 전송2, files => [ {originalname }, { } ]
        // 최종,  arr   => [ { }, { } ]
        // console.log(req.body);   // 물품명, 가격, 수량, 내용        

        // DB접속
        const dbconn = await db.connect(dburl);
        // 2. DB선택 및 컬렉션 선택(sequence값 1씩 증가시키는 DB)
        const collection = dbconn.db(dbname).collection('sequence');
        // 3. 시퀀스에서 값을 가져오고, 그 다음을 위해서 가지고 올때 값 증가

        const arr = [];
        for(let i=0; i<req.body.title.length; i++){
            const result = await collection.findOneAndUpdate(
                { _id  : 'SEQ_ITEM1_NO' }, // sequence 값( _id 자동 생성)
                { $inc : {seq : 1} }      
            );        
            // console.log('========================');
            // console.log(result.value.seq);
            // console.log('========================');
            arr.push({
                _id      : result.value.seq,
                name     : req.body.title[i],
                price    : req.body.price[i],
                quantity : req.body.quantity[i],
                content  : req.body.content[i],
                filename : req.files[i].originalname,
                filedata : req.files[i].buffer,
                filetype : req.files[i].mimetype,
                filesize : req.files[i].size,
                regdate  : new Date(),
                seller   : req.body.uid //checkToken에서 넣어줌
            });
        }
        console.log(arr); // 물품명, 가격, 수량, 내용        
        //console.log(req.files);  // 물품대표이미지

        // DB선택.컬렉션 생성 및 선택
        const collection1 = dbconn.db(dbname).collection('item1');
        // 선택된 컬렉션에 데이터 추가
        const result1 = await collection1.insertMany(arr);
        console.log(result1);
        if(result1.insertedCount === req.body.title.length) {
            return res.send({status : 200});
        }
        res.send({status : 0}) ;

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

// 1. 물품1개 조회(물품코드가 전달되면)
// localhost:3000/seller/selectone?code=111
router.get('/selectone', checkToken, async function(req, res, next) {
    try{    
        // 키가 uid인 이유는 로그인시에 토큰생성시 사용했던 키 정보
        const email = req.body.uid;
        const code = Number(req.query.code);
        
        const dbconn     = await db.connect(dburl);
        const collection = dbconn.db(dbname).collection('item1');
        // 조회하면 나오는 키정보 확인
        const result     = await collection.findOne(
            { _id : code, seller : email },
            { projection : { filename:0, filedata:0, filesize:0, filetype:0 } }
        );
        
        // 변수에 없는키를 넣어야 추가됨. 있는 키는 변경
        result['imageUrl'] = `/seller/image?code=${code}`;
        // result.imageUrl = `/seller/image?code=${code}`;

        // 서브이미지 정보가 필요함
        // 물품 1개를 조회할때 서브 이미지의 정보를 전송하는 부분
        const collection1 = dbconn.db(dbname).collection('itemimg1');

        const result1 = await collection1.find(
            { itemcode : code },
            { projection : { _id : 1 } }
        ).sort({ _id : 1 }).toArray();
        
        // 수동으로 서버이미지 PK정보를 저장함
        // result1 => [ { "_id": 10009 }, { "_id": 10010 }, { "_id": 10011 } ]
        let arr = [];
        for(let i=0; i<result1.length; i++){
            arr.push({
              imageUrl : `/seller/image1?code=${result1[i]._id}`
            });
        }

        result['supImage'] = arr;
        
        
        console.log(result);
        
        return res.send({status : 200, result:result});
       
    }
    catch(e){
        console.error(e);
        res.send({status : -1, message:e});        
    }  
});

// 2. 물품전체 조회(판매자 토큰에 해당하는 것만)
// localhost:3000/seller/selectlist
router.get('/selectlist', checkToken, async function(req, res, next) {
    try{
        const email = req.body.uid;
        const dbconn     = await db.connect(dburl);
        const collection = dbconn.db(dbname).collection('item1');     

        const result     = await collection.find(
            { seller : email },
            { projection : { filename:0, filedata:0, filesize:0, filetype:0 } }
        ).sort({ _id : 1 }).toArray();

        // result => [ { result[0] }, { result[1] }, { result[2] }]
        // 변수에 없는키를 넣어야 추가됨. 있는 키는 변경
        for(let i=0; i<result.length; i++){
            result[i]['imageUrl'] = `/seller/image?code=${result[i]._id}`;
        }

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


// 3. 물품 이미지 표시(물품코드가 전달되면 이미지 표시)
// 대표이미지르 가져옴 item1 컬렉션에서 가져욤(코드로 가져옴)
// localhost:3000/seller/image?code=1050
router.get('/image', async function(req, res, next) {
    try{
        const code       = Number(req.query.code);
        const dbconn     = await db.connect(dburl);
        const collection = dbconn.db(dbname).collection('item1');     

        const result     = await collection.findOne(
            { _id : code },
            { projection : { filename:1, filedata:1, filesize:1, filetype:1 } }
        );
        console.log(result);
        res.contentType(result.filetype);
        return res.send(result.filedata.buffer);
    }
    catch(e){
        console.error(e);
        res.send({status : -1, message:e});        
    }  
});

// 3. 서브 이미지 표시(물품코드가 전달되면 이미지 표시)
// 서브이미지르 가져옴 itemimg1 컬렉션에서 가져욤(코드로 가져옴)
// localhost:3000/seller/image1?code=1050
router.get('/image1', async function(req, res, next) {
    try{
        const code       = Number(req.query.code);
        const dbconn     = await db.connect(dburl);
        const collection = dbconn.db(dbname).collection('itemimg1');     

        const result     = await collection.findOne(
            { _id : code },
            { projection : { filename:1, filedata:1, filesize:1, filetype:1 } }
        );
        console.log(result);
        res.contentType(result.filetype);
        return res.send(result.filedata.buffer);
    }
    catch(e){
        console.error(e);
        res.send({status : -1, message:e});        
    }  
});

// 조회 get => req.query => URL에 정보가 포함
// 추가 post => req.body => URL에 정보가 없으면
// 변경 put =>
// 삭제 delete =>


// 4. 물품번호 n개에 해당하는 항목 조회(물품코드 배열로 전달)
// localhost:3000/seller/selectcode?c=1050&c=1049
// { code : [ 1049, 1050 ] }
router.get('/selectcode', async function(req, res, next) {
    try{        
        // query 로 전달되는 값을 변수로 저장(타입이 문자로 옴) const는 변경 불가여서 let 사용
        let code = req.query.c;

        // 반복문을 통해서 문자를 숫자로 변경(n개)
        for(let i=0; i<code.length; i++){
            code[i] = Number(code[i]);
        };

        console.log(code);

        const dbconn     = await db.connect(dburl);
        const collection = dbconn.db(dbname).collection('item1');     

        // 조회하면 나오는 키 정보 확인
        const result     = await collection.find(
            { _id : { $in : code } },
            { projection : { filename:0, filedata:0, filesize:0, filetype:0 } }
        ).sort({ name : 1 }).toArray();

        // 변수에 없는키를 넣어야 추가됨. 있는 키는 변경
        for(let i=0; i<result.length; i++){
            result[i]['imageUrl'] = `/seller/image?code=${result[i]._id}`;
        }

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

// 서버이미지 등록하기(n개)
// 물품에 따라서 개수가 다 다르다.
// 게시판원본글(게시글번호(기본키), 1) -------- (n)원본글에 다는 댓글(게시판 글번호)
// 물품(물품번호(기본키), 1) ------- (n)서브이미지(물품 번호) 물품번호의 기본키 = 서브이미지의 외래키로 들어옴
// localhost:3000/seller/subimage
router.post('/subimage', upload.array("image"), checkToken, async function(req, res, next) {
    try{

        const code = Number(req.body.code)// 원본 물품 번호
        // [ {}, {}, {} ]
        //console.log(req.files);

        // DB접속
        const dbconn = await db.connect(dburl);
        // 2. DB선택 및 컬렉션 선택(sequence값 1씩 증가시키는 DB)
        const collection = dbconn.db(dbname).collection('sequence');
        // 3. 시퀀스에서 값을 가져오고, 그 다음을 위해서 가지고 올때 값 증가

        let arr = [];
        for(let i=0; i<req.files.length; i++){
            const result = await collection.findOneAndUpdate(
                { _id  : 'SEQ_ITEMIMG1_NO' }, // sequence 값( _id 자동 생성)
                { $inc : {seq : 1} } // 1씩 증가     
            );   

            arr.push({
                _id      : result.value.seq, // PK 기본키
                filename : req.files[i].originalname,
                filedata : req.files[i].buffer,
                filetype : req.files[i].mimetype,
                filesize : req.files[i].size,
                itemcode : code,     // FK 외래키 (물품코드)
                idx      : (i+1),    // 서브이미지에 등록하는 순서   
                regdate  : new Date(),
            })
            
        }
        // [{},{},{}] => insertMany(arr)        

        const collection1 = dbconn.db(dbname).collection('itemimg1');
        const result1     = await collection1.insertMany(arr);
        console.log(result1);
        if(result1.insertedCount === req.files.length){
            return res.send({status : 200});    
        }
        return res.send({status : 0});
    }
    catch(e) {
        console.error(e);
        return res.send({status : -1, message:e});
    }
});

module.exports = router;

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

파일명 src/component/Seller.vue

<template>
    <div>
        <h3>src/component/Seller.vue</h3>
        <hr />

        <button @click="state.menu = 1">물품관리</button>
        <button @click="state.menu = 2">회원관리</button>
        <button @click="state.menu = 3">주문관리</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>   

    </div>
</template>

<script>
import {reactive} from 'vue';
import Menu1 from './seller/Menu1.vue';
import Menu2 from './seller/Menu2.vue';
import Menu3 from './seller/Menu3.vue';

export default {
    components:{
            Menu1,Menu2,Menu3
    },
    setup () {
        const state = reactive({
            menu:1
        });
        

        return {state}
    }
}
</script>

<style lang="scss" scoped>

</style>

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

파일명 src/component/seller/Menu1.vue

<template>
    <div style="border:1px solid #cccccc;padding:20px;">
        <h3>물품관리</h3>

        <button @click="handlePage">일괄추가</button>
        <button>일괄삭제</button>
        <button>일괄수정</button>

        <hr />

        <table border="1">

            <thead>
                <tr>
                    <th>체크</th>
                    <th>물품코드</th>
                    <th>이미지</th>
                    <th>이름</th>
                    <th>가격</th>
                    <th>수량</th>
                    <th>내용</th>
                    <th>등록일자</th>
                    <th>버튼</th>
                </tr>                
            </thead>

            <tbody>
                <tr v-for="item in state.items" :key="item">
                    <td><input type="checkbox" /></td>
                    <td>{{item._id}}</td>
                    <td><img :src="item.imageUrl" style="width:50px; heigh:50px" /></td>
                    <td>{{item.name}}</td>
                    <td>{{item.price}}</td>
                    <td>{{item.quantity}}</td>
                    <td>{{item.content}}</td>
                    <td>{{item.regdate}}</td>
                    <td>
                        <button>삭제</button> <br/>                        
                        <button>수정</button>
                    </td>
                </tr>
            </tbody>

        </table>

        

    </div>
</template>

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

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

        const handlePage = () => {
            router.push({name:"Menu1Insert"});

        }

        //생명주기
        onMounted( async()=>{
            const url =`/seller/selectlist`;
            const headers = { "Content-Type":"application/json", "token":state.token };
            const response = await axios.get(url,{headers});
            console.log(response.data);
            if(response.data.status === 200 ){
                state.items = response.data.result;
            }
        });

        
        

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

<style lang="scss" scoped>

</style>

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

파일명 src/component/seller/Menu1Insert.vue

<template>
    <div>
        <h3>파일명 src/component/seller/Menu1Insert.vue</h3>

        <hr />

        <button @click="handleAdd">항목추가</button>
        <button @click="handleSub">항목삭제</button>
        <hr />

        <table border="1">
            <tr v-for="(tmp, idx) in state.cnt" :key="tmp">
                <td><input type="file"  @change="handleImage($event,idx)"/></td>
                <td><input type="text" v-model="state.items[idx].name" placeholder="물품명" /></td>
                <td><input type="text" v-model="state.items[idx].price" placeholder="가격" /></td>
                <td><input type="text" v-model="state.items[idx].quantity" placeholder="수량" /></td>
                <td><input type="text" v-model="state.items[idx].content" placeholder="설명" /></td>
            </tr>
        </table>
        <hr />
        <button @click="handleInsertAction">일괄추가</button>

    </div>
</template>

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

export default {
    setup () {
        const router = useRouter();
        const state = reactive({
            cnt      : 2,
            token    : sessionStorage.getItem("TOKEN"),
            items    : [
                {
                    image    :'',
                    name     :'사과',
                    price    : 1000,
                    quantity : 100,
                    content  : '맛있는 사과',
                },
                {
                    image    :'',
                    name     :'오렌지',
                    price    : 2000,
                    quantity : 200,
                    content  : '맛있는 오렌지',
                },
            ],            
        });

        const handleAdd = () => {
            state.cnt++; // 1씩 증가
            // state.items의 마지막에 {}것을 추가
            state.items.push({
                image    :'',
                name     :'오렌지',
                price    : 2000,
                quantity : 200,
                content  : '맛있는 오렌지',
            });
        }        

        const handleSub = () => {            
            if( state.cnt >= 3 ) { // 1개를 뺐을때 2이상이면
                state.cnt--;         // 실제적으로 숫자를 뺌
                // pop => state.items의 마지막에 {}것을 제거
                state.items.pop();   // 추가했던 항목의 마지막을 제거함
            }
        }

        // 파일을 첨부하거나 또는 취소하거나
        const handleImage = (e, idx) =>{
            if(e.target.files[0]){
                console.log(e);     // 첨부한 파일 정보
                console.log(idx);   // 위치
                state.items[idx].image = e.target.files[0];
            }
            else{
                state.items[idx].image ='';
            }

        }

        const handleInsertAction = async() =>{
            const url = `/seller/insert`;
            const headers = { "Content-Type" : "multipart/form-data", "token" : state.token };
            const body = new FormData();
            //state.items => [{},{},{},{}]
            for(let i=0; i<state.items.length; i++){
                body.append("image", state.items[i].image);
                body.append("title", state.items[i].name);
                body.append("price", state.items[i].price);
                body.append("quantity", state.items[i].quantity);
                body.append("content", state.items[i].content);
            }

            const response = await axios.post(url, body, { headers });
            console.log(response);
            if(response.data.status === 200){
                alert('추가가 완료 되었습니다.');
                router.push({name:"Seller"});
            }
            alert('추가하지 않은 항목을 확인하세요');


        }

        return {state, handleAdd, handleSub, handleInsertAction, handleImage}
    }
}
</script>

<style lang="scss" scoped>

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

0개의 댓글