국비 코딩 풀스택 수업 21일차(시험날)
요약정리
코드를 짜는 것도 중요하지만, erd가 3개다보니 이해에 조금 더 치중을 했음.
결과적으로 잘 이해했고, 코드도 원만하게 짤 수 있는 하루가 된듯.
변수 초기 선언이 null일때 화면 안나오는거 v-if로 해결
원인은 null로 화면을 먼저 표기하고 handleData가 실행되기 때문
오전일과
백엔드
itemimage.js
selectimage
// 판매자가 등록한 물품의 이미지 정보를 조회
// 127.0.0.1:3000/itemimage/selectimage.json?code=9
router.get('/selectimage.json', auth.checkToken1,
async function(req, res, next) {
try {
const id = req.body.SID; // 토큰에서 꺼내기
const code = Number(req.query.code); // 물품번호
// 물품컬렉션에서 물품번호가 현재로그인한 판매자 것인가?
const query = {
_id : code,
seller : id
};
const obj = await Item.findOne(query);
if(obj !== null) {
const projection = {code : 1};
const obj1 = await ItemImage
.find({code:code}).select(projection);
for(let i=0; i<obj1.length; i++){
//obj1의 i위치에 imageurl키를 추가
obj1[i].imageurl = `/itemimage/image?no=${obj1[i]._id}`;
}
return res.send({status:200, result:obj, result1:obj1});
}
return res.send( {status : 0} );
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
원리과정
req로 토큰에서 id, query에서 code를 꺼낸다.
따로 변수선언하고const query = { _id : code, seller : id}; (안하고 바로 넣어도 됨)
백엔드에 찾아봄 const obj = await Item.findOne(query);
obj가 호출이 성공하면 if(obj !== null)
const obj1 = await ItemImage.find({code:code}).select(projection);
해당 글의 코드와 projection(여기선 code:1)만 불러와라.
요약
토큰과 커리에서 id와 코드를 받아오고
그것을 토대로 백엔드에서 호출
code와 id가 일치하면 공백으로 오지 않기에 if문으로 설정
그리고 원하는 정보만 호출
get image 이미지 URL정보
Board.js에서 불러옴( 똑같음 게시글에 이미지 불러오기)
// 이미지 URL정보
// 127.0.0.1:3000/itemimage/image?no=14
router.get('/image', async function(req, res, next) {
try{
const query = {_id:Number(req.query.no)};
const projection = { filedata:1, filesize:1, filetype:1, filename:1};
const result = await ItemImage.findOne(query).select(projection);
res.contentType(result.filetype); // contentType변경
return res.send(result.filedata); // 파일데이터
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
이미지하다가 이미지 여러개 정보를 불러오기위해
판매자가 등록한 물품의 이미지 정보 조회할때
imageurl을 불러오도록 get selectimage를 추가함.(for문으로 url)
// 판매자가 등록한 물품의 이미지 정보를 조회
// 127.0.0.1:3000/itemimage/selectimage.json?code=9
router.get('/selectimage.json', auth.checkToken1,
async function(req, res, next) {
try {
const id = req.body.SID; // 토큰에서 꺼내기
const code = Number(req.query.code); // 물품번호
// 물품컬렉션에서 물품번호가 현재로그인한 판매자 것인가?
const query = {
_id : code,
seller : id
};
const obj = await Item.findOne(query);
if(obj !== null) {
const projection = {code : 1};
const obj1 = await ItemImage
.find({code:code}).select(projection);
for(let i=0; i<obj1.length; i++){
//obj1의 i위치에 imageurl키를 추가
obj1[i].imageurl = `/itemimage/image?no=${obj1[i]._id}`;
}
return res.send({status:200, result:obj, result1:obj1});
}
return res.send( {status : 0} );
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
목적 : 데이터 불러올떄 이미지랑 같이 불러오려고~~
ORM기반은 새로운 변수를 만들 수 없음.
(이쪽으로는 아직 개념이 안서있어서 이해가 안되는데 그렇다고만 알고 있으면 될듯)
그래서 obj2를 선언하고 obj1.toObject()로 옮긴뒤에
obj2로 for문 돌림 (해보니 이것도 안된다고 그냥 아래처럼 함)
위와 같은 이유로 그냥
itemimagemodel.js
에서 imageurl을 추가해줌
원래라면 DB에 생성되면 안되는데 그냥 원활한 진행을 위해 추가함.
var itemimageSchema = new Schema({
_id : Number, // 물품번호, 숫자, 기본키, 고유값, not null
code : Number, // 물품의 코드, 외래키, not null
filedata : { type:Buffer, default:null }, //파일데이터
filesize : { type:Number, default:0 }, // 파일의 크기 용량
filename : { type:String, default:'' }, // 파일 이름
filetype : { type:String, default:'' }, // 파일의 종류, jpeg, png 등..
idx : { type:Number, default:1 }, // 대표이미지 표시
regdate : { type:String, default:'' }, // 등록일, 문자
// 이미지 URL 저장용 (DB에 생성되면 안되는 변수)
imageurl : { type:String, default:'' },
});
delete deleteimage만듬
// 이미지 삭제(판매자의 토큰, 물품번호, 이미지번호)
// 127.0.0.1:3000/itemimage/deleteimage.json?code=9&no=14
router.delete('/deleteimage.json', auth.checkToken1,
async function(req, res, next) {
try {
const seller = req.body.SID; // 토큰에서 꺼내기
const code = Number(req.query.code); // 물품번호
const no = Number(req.query.no); // 이미지번호
// 물품컬렉션에서 물품번호가 현재로그인한 판매자 것인가?
const query = {
_id : code,
seller : seller
};
const obj = await Item.findOne(query);
if(obj !== null) {
const result = await ItemImage.deleteOne({_id:no});
console.log(result);
if(result.deletedCount === 1){
return res.send({status:200, result:result});
}
}
return res.send( {status : 0} );
}
catch(e){
console.error(e);
return res.send({status:-1, result:e});
}
});
포스트맨 찍어보고 result에 deletedCount 확인하고 if문 기입해줌.
프론트
SellerItemImage.vue

<template>
<div>
<h3>물품이미지</h3>
{{state}}
<hr/>
<div v-if="state.result">
이름 : {{state.result.name}} <br/>
내용 : {{state.result.content}} <br/>
가격 : {{state.result.price}} <br/>
수량 : {{state.result.quantity}} <br/>
카테고리 : {{state.result.category}} <br/>
판매자 : {{state.result.seller}} <br/>
날짜 : {{state.result.regdate}} <br/>
</div>
<table border="1">
<tr v-for="tmp of state.result1" :key="tmp">
<td>{{tmp._id}}</td>
<td><img :src="tmp.imageurl" style="width:50px" /></td>
<td><button @click="handleImageDelete(tmp._id)">삭제</button></td>
</tr>
</table>
<button @click="handleAppend()">항목추가(+)</button>
<button @click="handleRemove()">항목삭제(-)</button>
<div v-for="(tmp, idx) of state.cnt" :key="tmp">
<img :src="state.imageurl[idx]" style="width: 30px"/>
<input type="file" @change="handleChangeImage($event, idx)"/>
</div>
<button @click="handleImageAction()">이미지일괄등록</button>
</div>
</template>
<script>
import { reactive } from '@vue/reactivity';
import { useRoute } from 'vue-router'
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';
export default {
setup () {
const route = useRoute();
const state = reactive({
code : Number(route.query.code),
cnt : 2,
imageurl : [],
imagedata : [],
token : sessionStorage.getItem("TOKEN"),
result : null,
result1 : null,
});
onMounted(()=>{
for(let i=0; i<5; i++){
state.imageurl.push(require('../../assets/logo.png'))
state.imagedata.push( new File([""], ""))
//빈파일데이터( new File(["파일내용"], "파일이름"))
}
handleData();
});
const handleData = async() =>{
const url = `itemimage/selectimage.json?code=${state.code}`;
const headers = {"Content-Type" : "application/json", "token" : state.token }
const {data} = await axios.get(url, {headers});
if(data.status === 200){
console.log(data.result);
console.log(data.result1);
state.result = data.result;// 물품 정보
state.result1 = data.result1;// 이미지 정보
}
}
const handleAppend = () =>{
state.cnt++;
if(state.cnt > 5){
state.cnt = 5;
}
};
const handleRemove = () =>{
state.cnt--;
if(state.cnt < 2){
state.cnt = 2;
}
};
const handleChangeImage = (e, idx) =>{
console.log(e, idx);
if(e.target.files.length>0){// 파일을 선택함
state.imageurl[idx] = URL.createObjectURL(e.target.files[0])
state.imagedata[idx] = e.target.files[0];
}
else{//파일을 취소함
state.imageurl[idx] = require('../../assets/logo.png')
state.imagedata[idx] = new File([""], "")
//빈파일데이터( new File(["파일내용"], "파일이름"))
}
}
const handleImageAction = async() =>{
const url = `/itemimage/insertbatch.json`
const headers = {
"Content-Type":"multipart/form-data",
token : sessionStorage.getItem("TOKEN")
}
const body = new FormData();
body.append("code", state.code);
for(let i=0; i<state.cnt; i++){
body.append("image", state.imagedata[i])
}
const {data} = await axios.post(url, body, {headers});
console.log(data);
if(data.status === 200){
handleData();
}
}
const handleImageDelete = async(tmp) =>{
const ret = confirm('삭제할까요?')
if(ret === true){
const url = `/itemimage/deleteimage.json?code=${state.code}&no=${tmp}`;
const headers = {"Content-Type" : "application", "token" : state.token};
const {data} = await axios.delete(url, {headers:headers});
console.log(data);
if(data.status === 200){
alert('삭제되었습니다.')
handleData();
}
}
}
return {state, handleAppend, handleRemove, handleChangeImage, handleImageAction, handleImageDelete}
}
}
</script>
<style lang="scss" scoped>
</style>
handledata이용해서 정보 기입
이미지 기입
삭제버튼 만듬
데이터의 결과값이 저장되는 result, result1이
변수 초기 선언이 null일때 화면 안나오는거 v-if로 해결
원인은 null로 화면을 먼저 표기하고 handleData가 실행되기 때문
<div v-if="state.result">
테이블 만들어주고, 정보 출력 해줌.
시험 시간 만든 코드는 따로 올리도록 하겠음~
끝-