파일명 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>