20211230

팡태(❁´◡`❁)·2022년 1월 4일
0

ihongss

목록 보기
6/11


CMD> nodemon --inspect ./bin/www

-----------------------------------
// 파일명 : item.js
var express = require('express');
var router = express.Router();

// CMD> npm i mongodb --save
const db      = require('mongodb').MongoClient;

// config/db.js 파일의 내용 가져오기
const DBURL   = require('../config/db').mongodbURL;
const DBNAME  = require('../config/db').mongodbDB;


// CMD> npm i multer --save
const multer = require('multer');
// 특정폴더에 파일을 보관 or 메모리(DB에 저장)
const upload = multer({storage:multer.memoryStorage()});

/*
db.sequence.insert([
    {_id : 'SEQ_BOARD_NO', seq : 1},
    {_id : 'SEQ_BOARDREPLY_NO', seq : 1},
    {_id : 'SEQ_ITEM_NO', seq  : 10001}
]);
*/

// 물품등록 : http://localhost:3000/item/insert
// 이미지1, 물품코드(X), 물품명, 물품내용, 물품가격, 재고수량, 등록일(X)
router.post('/insert', upload.single("file"), async function(req, res, next) {
    try {
        const dbConn = await db.connect(DBURL);
        const coll   = dbConn.db(DBNAME).collection("sequence");
        const result = await coll.findOneAndUpdate(
            { _id:'SEQ_ITEM_NO' }, { $inc : { seq : 1} }
        );
        //console.log(result.value.seq);

        const obj = {
            _id  : result.value.seq,  // 물품번호(자동부여)
            name : req.body.name, //물품명, 물품내용, 가격, 수량
            content : req.body.content,
            price : req.body.price ,
            quantity : req.body.quantity,
            filename : req.file.originalname, //파일명
            filetype : req.file.mimetype,
            filedata : req.file.buffer,
            filesize : req.file.size,
            regdate  : new Date()
        };

        const coll1   = dbConn.db(DBNAME).collection("item");
        const result1 = await coll1.insertOne(obj);
        if( result1.insertedId > 0 ){
            return res.send({status:200});
        }
        return res.send({status:0});
    }
    catch(err) {
        console.error(err);
        return res.send({status:-1, result : err});
    }
});

// 이미지(1개) : http://localhost:3000/item/image?no=2
router.get('/image', async function(req, res, next) {
    try {
        const no =  Number(req.query.no);
        const dbConn = await db.connect(DBURL);
        const coll   = dbConn.db(DBNAME).collection("item");

        const result = await coll.findOne(
            { _id : no }, //조건
            { projection : {filedata:1, filetype:1} } //필요한 항목만
        );
        console.log(result);
        res.contentType(result.filetype);// json ->image/jpeg
        return res.send(result.filedata.buffer);
    }
    catch(err) {
        console.error(err);
        return res.send({status:-1, result : err});
    }
});

// 물품목록 : http://localhost:3000/item/select?page=1
router.get('/select', async function(req, res, next) {
    try {
        const page     = Number(req.query.page);
        const dbConn   = await db.connect(DBURL);
        const coll     = dbConn.db(DBNAME).collection("item");
 
        // 물품코드, 물품명, 가격, 수량, 등록일
        const result = await coll.find(
                {},    // 조건
                { projection : {_id:1, name:1, price:1, quantity:1, regdate:1} }  // 가져올 항목만
            )
            .sort({_id:-1})  // 1 오름차순, -1 내림차순
            .skip((page-1) * 10 )     // 생략할 개수
            .limit(10)       // 10개 까지만
            .toArray();

        const total = await coll.countDocuments({});
        return res.send({status:200, result:result, total:total});
    }
    catch(err) {
        console.error(err);
        return res.send({status:-1, result : err});
    }
});

// 물품1개조회(이미지포함) : http://localhost:3000/item/selectone?code=10001
router.get('/selectone', async function(req, res, next) {
    try {
        const code     = Number(req.query.code);
        const dbConn   = await db.connect(DBURL);
        const coll     = dbConn.db(DBNAME).collection("item");
        
        const result   = await coll.findOne(
            {_id : code},   //조건
            {projection : {filename:0, filedata:0, filesize:0, filetype:0 } }   //필요한 항목만
        );
        console.log(result); // 확인

        // 이미지 데이터를 전달X,  
        // 이미지를 볼수있는 URL정보 전달
        result['image'] = '/item/image?no=' + code;
        return res.send({status:200, result: result});
    }
    catch(err) {
        console.error(err);
        return res.send({status:-1, result : err});
    }
});

// 물품삭제 : http://localhost:3000/item/delete?code=10004
router.delete('/delete', async function(req, res, next) {
    try {
        const code     = Number(req.query.code);
        const dbConn   = await db.connect(DBURL);
        const coll     = dbConn.db(DBNAME).collection("item");

        const result = await coll.deleteOne({_id:code});
        if(result.deletedCount === 1){
            return res.send({status:200});
        }
        return res.send({status:0});
    }
    catch(err) {
        console.error(err);
        return res.send({status:-1, result : err});
    }
});

// 물품수정 : http://localhost:3000/item/update?code=10004
// query + body
router.put('/update', upload.single("file"), 
                        async function(req, res, next) {
    try {
        const code = Number(req.query.code);
        // 물품명, 물품내용, 물품가격, 재고수량, 이미지

        // const 상수 처음만든 값에 +, -  안됨.
        // let, var 변수 처음만든값에 +, - 가능함.
        let obj = {
            name        : req.body.name,
            content     : req.body.content,
            price       : req.body.price,
            quantity    : req.body.quantity                
        };

        if(typeof req.file !== 'undefined') {
            obj['filename'] = req.file.originalname;
            obj.filetype    = req.file.mimetype;
            obj.filedata    = req.file.buffer;
            obj.filesize    = req.file.size;
        }

        console.log(code);
        console.log(obj);

        const dbConn    = await db.connect(DBURL);
        const coll      = dbConn.db(DBNAME).collection("item");
        const result    = await coll.updateOne(
            { _id  : code  }, //조건
            { $set : obj } //실제변경할내용
        );
        console.log(result);
        if(result.modifiedCount === 1) {
            return res.send({status:200});
        }
        return res.send({status:0});
    }
    catch(err) {
        console.error(err);
        return res.send({status:-1, result : err});
    }
});


module.exports = router;

-----------------------------------------

// 파일명 : Seller.vue
<template>
    <div>
        <el-card shadow="always">
            <h4>판매자</h4>
            <hr />

            <p>물품목록</p>
            <el-button size="small" type="primary">물품등록</el-button>
            
            <el-table :data="items" size="mini" style="width: 100%">
                <el-table-column prop="_id" label="코드" width="180" />
                <el-table-column prop="name" label="물품명" width="180" />
                <el-table-column prop="price" label="가격" />
                <el-table-column prop="quantity" label="재고수량" />
                <el-table-column prop="regdate" label="등록일" />
                <el-table-column fixed="right" label="버튼" width="120">
                    <template #default="scope">
                        <el-button size="small" type="danger" @click.prevent="deleteRow(scope.$index, scope.row)">
                            삭제
                        </el-button>
                    </template>
                </el-table-column>  
            </el-table>
            <el-pagination layout="prev, pager, next" :total="total" @current-change="currentChange"></el-pagination>
        </el-card>
    </div>
</template>

<script>
    export default {
        created() {
            this.handleData();
        },
        data() {
            return{
                items : [],
                page  : 1,
                total : 0,
            }
        },
        methods : {
            async deleteRow(idx, row){
                if( confirm('삭제할까요?') ) {
                    console.log('Seller.vue => deleteRow');
                    console.log(idx, row);

                    const url = `/item/delete?code=${row._id}`;
                    const headers = {"Content-Type":"application/json"};
                    const response = await this.axios.delete(url, {headers:headers});

                    if( response.data.status === 200 ){
                        alert('삭제되었습니다.');
                        this.page = 1;
                        this.handleData();
                    }
                }
            },

            currentChange(page) {
                this.page = page;
                this.handleData();
            },

            async handleData() {
                const url = `/item/select?page=${this.page}`;
                const headers = {"Content-Type":"application/json"};
                const response = await this.axios.get(url, {headers:headers});

                if( response.data.status === 200 ){
                    this.items = response.data.result; // [{},{}]
                    this.total = response.data.total;
                }
            }
        }        
    }
</script>

<style scoped>

</style>


----------------------------
// 파일명 : ItemInsert.vue
<template>
    <div>
        <el-card shadow="always">
            <el-upload action="#"
                list-type="picture-card"
                :on-preview="handlePreview" 
                :on-remove="handleRemove"
                :on-change="handleChange"
                :auto-upload="false">
                <el-icon><plus /></el-icon>
            </el-upload>
            
            <el-dialog v-model="dialogVisible">
                <img style="width:100%" :src="dialogImageUrl" alt="" />
            </el-dialog>

            <input type="text" v-model="item.name" placeholder="물품명"/>
            <input type="text" v-model="item.content" placeholder="내용" />
            <input type="text" v-model="item.price" placeholder="가격" />
            <input type="text" v-model="item.quantity" placeholder="수량" />

            <button @click="handleInsert">등록</button>
        </el-card>
    </div>
</template>

<script>
    import { Plus } from '@element-plus/icons-vue'
    export default {
        components: {
            Plus,
        },
        data() {
            return {
                dialogImageUrl  : '',
                dialogVisible   : false,

                item : {
                    image       : null,
                    name        : '사과',
                    content     : '사과내용',
                    price       : 0,
                    quantity    : 1000
                }
            }
        },

        methods: {
            async handleInsert(){
                // 유효성 검사
                if(this.item.image === null){
                    alert('이미지 첨부하세요');
                    return false;
                }

                const url     = `/item/insert`;
                const headers = {"Content-Type":"multipart/form-data"};
                let body      = new FormData();
                body.append("file", this.item.image);
                body.append("name", this.item.name);
                body.append("content", this.item.content);
                body.append("price", this.item.price);
                body.append("quantity", this.item.quantity);

                const response 
                    = await this.axios.post(url, body, {headers:headers});
                
                console.log(response.data);
                if(response.data.status === 200){
                    alert('등록되었습니다.');
                    this.$router.push({name:"Seller"});
                }
            },

            handleChange(file, fileList) {
                console.log('handleChange');
                //console.log(URL.createObjectURL(file.raw));
                console.log(file, fileList);
                this.item.image = file.raw;
            },

            handleRemove(file, fileList) {
                //삭제
                console.log(file, fileList);
                this.item.image = null;
            },

            handlePreview(file) {
                console.log('handlePreview');
                console.log(file);
                // console.log(URL.createObjectURL(file.raw));

                this.dialogImageUrl = file.url; //임시이미지주소
                this.dialogVisible = true;  //다이얼로그표시
            },
        },
    }
</script>

<style scoped>

</style>


--------------------------------------
// 파일명 : ItemContent.vue
<template>
    <div>
        <el-card shadow="always">
            <h4>물품상세정보</h4>

            {{item._id}}
            {{item.name}}
            <img :src="item.image" style="width:100px;" />
        </el-card>    
    </div>
</template>

<script>
    export default {
        created(){
            this.handleData();
        },
        data(){
            return{
                item  : '',
                code  : this.$route.query.code, // 목록에서 전달되는 코드를 보관
            }
        },
        methods:{
            async handleData(){
                const url = `/item/selectone?code=${this.code}`;
                const headers = {"Content-Type":"application/json"};

                const response = await this.axios.get(url, {headers:headers});
                // console.log(response.data);
                if(response.data.status=== 200) {
                    // state변수 item에 보관
                    this.item = response.data.result;
                    console.log(this.item); //확인용
                }
            }
        }
    }
</script>

<style scoped>

</style>


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

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

// 파일명 : Home.vue
<template>
  <div>
    <el-card shadow="always">
      <h3>Home.vue</h3>
      <vueper-slides>
        <vueper-slide v-for="(tmp, idx) in items" 
          :key="idx" :title="tmp.title" 
          :content="tmp.content" :image="tmp.image" />
      </vueper-slides>
    </el-card>      
  </div>
</template>

<script>
  import { VueperSlides, VueperSlide } from 'vueperslides';
  import 'vueperslides/dist/vueperslides.css';
  export default {
    components: { 
      VueperSlides, VueperSlide 
    },
    data(){
      return {
        items :[
          { title:'a', content:'b', image: 'https://picsum.photos/500/300?image=1'},
          { title:'a', content:'b', image: 'https://picsum.photos/500/300?image=2'},
          { title:'a', content:'b', image: 'https://picsum.photos/500/300?image=3'},
        ]
      }
    }
  }
</script>

<style scoped>

</style>

0개의 댓글