파일명 routes/seller.js
// 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}&ts=${new Date().getTime()}`;
}
console.log(result);
return res.send({status : 200, result:result});
}
catch(e){
console.error(e);
res.send({status : -1, message:e});
}
});
============================================
파일명 src/component/seller/Menu1Insert.vue
<template>
<div>
<h3>파일명 src/component/seller/Menu1Insert.vue</h3>
<hr />
<button @click="handleAdd">항목추가</button>
<button @click="handleSub">항목삭제</button>
<hr />
{{ state.items }}
<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({ // push는 추가
image :'',
name :'오렌지',
price : 2000,
quantity : 200,
content : '맛있는 오렌지',
});
}
const handleSub = () => {
if( state.cnt >= 3 ) { // 1개를 뺐을때 2이상이면
state.cnt--; // 실제적으로 숫자를 뺌
// pop => state.items의 마지막에 {}것을 제거
state.items.pop(); // 추가했던 항목의 마지막을 제거함 pop은 제거
}
}
// 파일을 첨부하거나 또는 취소하거나
const handleImage = (e, idx) =>{
console.log(e); // 첨부한 파일 정보
console.log(idx); // 위치
if(e.target.files[0]){
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"});
}
else{
alert('추가하지 않은 항목을 확인하세요');
}
}
return {state, handleAdd, handleSub, handleInsertAction, handleImage}
}
}
</script>
<style lang="scss" scoped>
</style>
============================================
파일명 src/components/seller/Menu1.vue
<template>
<div style="border:1px solid #cccccc;padding:20px;">
<h3>물품관리</h3>
<button @click="handlePage">일괄추가</button>
<button @click="handleDelete">일괄삭제</button>
<button @click="handleUpdate">일괄수정</button>
<hr />
<!-- <el-table :data="state.items" style="width: 100%">
<el-table-column label="체크" width="50"><input type="checkbox" /></el-table-column>
<el-table-column prop="_id" label="물품코드" width="80" />
<el-table-column label="이미지">
<template #default="scope">
<div>
<img :src="scope.row.imageUrl" style="width:50px; heigh:50px"/>
</div>
</template></el-table-column>
<el-table-column prop="name" label="이름" />
<el-table-column prop="price" label="가격" />
<el-table-column prop="quantity" label="수량" />
<el-table-column prop="content" label="내용" />
<el-table-column prop="regdate" label="등록일자" width="200" />
<el-table-column label="버튼" >
<el-button size="small" type="primary">수정</el-button><br/>
<el-button size="small" type="info" @click="handleDeleteAction(item._id)">삭제</el-button>
</el-table-column>
</el-table> -->
<hr />
{{state.items}}
{{state.chk}}
<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, idx) in state.items" :key="item">
<td><input type="checkbox" :value="item._id" v-model="state.chk" /></td>
<td><button @click="handleDetailPage(item._id)">{{item._id}}</button></td>
<td>
<img :src="item.imageUrl" style="width:50px; heigh:50px" /><br/>
<input type="file" @change="handleImage($event, idx)" />
</td>
<td><input type="text" v-model="item.name" style="width:50px" /></td>
<td><input type="text" v-model="item.price" style="width:50px" /></td>
<td><input type="text" v-model="item.quantity" style="width:50px" /></td>
<td><input type="text" v-model="item.content" style="width:150px" /></td>
<td>{{item.regdate}}</td>
<td>
<button @click="handleUpdateAction(idx)" >수정</button><br/>
<button @click="handleDeleteAction([item._id])" >삭제</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"),
chk : []
});
const handleDetailPage = (code) => {
router.push({name:'Menu1Detail',query:{code:code}});
}
const handleUpdate = async() => {
let arr = [];
// 전체 개수 (1,2,3,4,5,6,7,8)
for(let i=0; i<state.items.length; i++){
// 체크한 개수(2,4,6)
for(let j=0; j<state.chk.length; j++){
// 전체 내용에서 체크한 번호가 일치하면
if(state.items[i]._id === state.chk[j]){
//console.log(state.items[i]._id, state.chk[j]);
// arr변수에 일치하는 것만 저장
arr.push(state.items[i]);
}
}
}
// arr는 사용자가 체크한 항목만 복사된 변수
console.log(arr);
const url =`/seller/update`;
const headers ={ "Content-Type" : "multipart/form-data", "token" : state.token };
// {code : [1050], title:['a']}
const body = new FormData();
for(let i=0; i<arr.length; i++){
body.append('image', arr[i].image ); // 배열X
body.append('code', arr[i]._id );
body.append('title', arr[i].name );
body.append('price', arr[i].price );
body.append('quantity', arr[i].quantity );
body.append('content', arr[i].content );
}
const response = await axios.put(url, body, { headers });
console.log(response);
if(response.data.status === 200 ){
alert('수정되었습니다.')
await handleLoadData();
state.chk=[];
}
}
const handleUpdateAction = async(idx) => {
const url =`/seller/update`;
const headers ={ "Content-Type" : "multipart/form-data", "token" : state.token };
// {code : [1050], title:['a']}
const body = new FormData();
body.append('image', state.items[idx].image ); // 배열X
body.append('code', state.items[idx]._id );
body.append('title', state.items[idx].name );
body.append('price', state.items[idx].price );
body.append('quantity', state.items[idx].quantity );
body.append('content', state.items[idx].content );
// steat.items => [ { 수정}, { 수정}, { 수정} ]
// state.items[idx];
const response = await axios.put(url, body, { headers });
console.log(response);
if(response.data.status === 200 ){
alert('수정되었습니다.')
await handleLoadData();
}
}
const handleImage = (e, idx) => {
if(e.target.files[0]){
state.items[idx].image = e.target.files[0];
}
else{
state.items[idx].image ='';
}
}
const handleDelete = async() => {
await handleDeleteAction(state.chk);
}
const handleDeleteAction = async(code) => {
if(confirm('삭제할까요?')){
const url =`/seller/delete`;
const headers = {"Content-Type":"application/json", "token":state.token };
const body = {code:code};
const response = await axios.delete(url,{headers:headers, data:body});
console.log(response.data);
if(response.data.status === 200 ){
await handleLoadData();
state.chk=[];
}
}
}
const handlePage = () => {
router.push({name:"Menu1Insert"});
}
const handleLoadData = 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;
}
}
//생명주기
onMounted( async()=>{
await handleLoadData();
});
return {state, handlePage, handleDeleteAction, handleUpdateAction, handleImage, handleDelete, handleUpdate, handleDetailPage }
}
}
</script>
<style lang="scss" scoped>
</style>
============================================
파일명 src/component/seller/Menu1Detail.vue
<template>
<div v-if="state.items">
<h3>파일명 src/component/seller/Menu1Detail.vue</h3>
<table border="1">
<thead>
<tr>
<th>물품코드</th>
<th>이미지</th>
<th>이름</th>
<th>가격</th>
<th>수량</th>
<th>내용</th>
<th>등록일자</th>
<th>서브이미지</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{state.items._id}}</td>
<td><img :src="state.items.imageUrl" style="width:50px; heigh:50px" /></td>
<td>{{state.items.name}}</td>
<td>{{state.items.price}}</td>
<td>{{state.items.quantity}}</td>
<td>{{state.items.content}}</td>
<td>{{state.items.regdate}}</td>
<td>
<div v-for="tmp in state.items.subImage" :key="tmp" style="display:inline-block">
<img :src="tmp.imageUrl" style="width:50px; heigh:50px" />
</div>
</td>
</tr>
</tbody>
</table>
<table border="1">
<thead>
<tr>
<th>물품코드</th>
<td>{{state.items._id}}</td>
</tr>
<tr>
<th>이미지</th>
<td>
<img :src="state.items.imageUrl" style="width:50px; heigh:50px" />
</td>
</tr>
<tr>
<th>이름</th>
<td>{{state.items.name}}</td>
</tr>
<tr>
<th>가격</th>
<td>{{state.items.price}}</td>
</tr>
<tr>
<th>수량</th>
<td>{{state.items.quantity}}</td>
</tr>
<tr>
<th>내용</th>
<td>{{state.items.content}}</td>
</tr>
<tr>
<th>등록일자</th>
<td>{{state.items.regdate}}</td>
</tr>
<tr>
<th>서브이미지</th>
<td>
<div v-for="tmp in state.items.subImage" :key="tmp" style="display:inline-block">
<img :src="tmp.imageUrl" style="width:50px; heigh:50px" />
</div>
</td>
</tr>
</thead>
</table>
</div>
</template>
<script>
import { onMounted, reactive } from 'vue';
import { useRoute } from 'vue-router';
import axios from 'axios'
export default {
setup () {
const route = useRoute(); // 이동 하기
const state = reactive({
code : route.query.code,
token : sessionStorage.getItem("TOKEN"),
})
// 생명주기 onMounted에서
// /seller/selectone?code=111 을 호출해서 화면에 표시하시오.
const handleLoadData = async() => {
const url = `/seller/selectone?code=${state.code}`;
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;
}
}
//생명주기
onMounted( async()=>{
await handleLoadData();
});
return {state}
}
}
</script>
<style lang="scss" scoped>
</style>