Skip to content

Commit

Permalink
[K5P-67] [feat] 회원 대량 등록 구현 중
Browse files Browse the repository at this point in the history
  • Loading branch information
Koneweekk committed Jul 24, 2024
1 parent 3090ba3 commit e32fe2d
Show file tree
Hide file tree
Showing 25 changed files with 871 additions and 27 deletions.
15 changes: 14 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"pinia-plugin-persist": "^1.0.0",
"sass": "^1.77.6",
"vue": "^3.4.29",
"vue-router": "^4.3.3"
"vue-router": "^4.3.3",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.8.0",
Expand Down
Binary file added src/assets/excels/회원등록.xlsx
Binary file not shown.
Binary file added src/assets/images/example_member.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
161 changes: 161 additions & 0 deletions src/components/common/ExcelUpload.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<template>
<div class="excel-upload">
<header>
엑셀 파일 업로드
</header>
<div class="main-box">
<div class="sample-box">
<img :src="`/src/assets/images/${store.exampleImg}`" alt="">
<div class="guide-line">
<span>※ 위 사진처럼 이름과 형식을 맞춰서 입력해주세요</span>
<ExcelBtnVue title="샘플" :func="downloadSample" />
</div>
</div>
<FileInputVue v-model="file" />
</div>
<footer>
<ThemeWideBtnVue title="파일 업로드" :func="readExel" />
<div class="error-box">{{ errorMsg }}</div>
</footer>
</div>
<a ref="hiddenLink" style="display: none;" :href="`/src/assets/excels/${store.download}`"
:download="store.download"></a>
</template>

<script>
import ExcelBtnVue from './btn/ExcelBtn.vue';
import ThemeWideBtnVue from './btn/ThemeWideBtn.vue';
import FileInputVue from './input/FileInput.vue';
import * as XLSX from 'xlsx';
export default {
name: 'ExcelUploadVue',
components: {
ThemeWideBtnVue,
ExcelBtnVue,
FileInputVue
},
props: {
store: {
type: Object,
required: true
}
},
data() {
return {
file: null,
errorMsg: '',
}
},
watch: {
'store.file': function(newFile) {
this.file = newFile;
console.log(this.file)
}
},
methods: {
downloadSample() {
const link = this.$refs.hiddenLink;
link.click();
},
readExel() {
if (this.file === null) {
this.errorMsg = '파일을 업로드해주세요.';
return;
}
const fileName = this.file.name;
const fileExtension = fileName.split('.').pop().toLowerCase();
if (fileExtension !== 'xlsx') {
this.errorMsg = '엑셀 파일(.xlsx) 형식의 파일을 업로드해주세요.';
return;
}
this.errorMsg = ''
this.store.setFile(this.file);
this.store.setIsValid(true);
const reader = new FileReader();
reader.onload = (e) => {
if (e.target) {
const workbook = XLSX.read(e.target.result, { type: "binary" });
const sheetName = workbook.SheetNames[0];
const worksheet = workbook.Sheets[sheetName];
const json = XLSX.utils.sheet_to_json(worksheet);
this.store.setUploadData(json);
}
};
reader.readAsArrayBuffer(this.file);
}
},
mounted() { }
}
</script>

<style lang="scss" scoped>
.excel-upload {
@include flex-box(column, space-between, 60px);
width: 700px;
padding: 0px 30px;
border-radius: 10px;
box-shadow: $base-shadow;
background-color: white;
header,
footer {
@include flex-box(column, center, 10px);
width: 100%;
}
header {
font-size: 24px;
font-weight: bold;
padding: 30px 0px;
border-bottom: $light-theme-color solid 3px;
}
footer {
padding-top: 30px;
border-top: $light-theme-color solid 3px;
}
.main-box {
@include flex-box(column, space-between, 30px);
width: 100%;
}
}
.sample-box {
@include flex-box(column, center, 30px);
border: $theme-color solid 3px;
border-radius: 10px;
padding-bottom: 20px;
width: 100%;
overflow: hidden;
img {
width: 100%;
}
.guide-line {
@include flex-box(row, space-between, 0px);
padding: 0px 30px;
width: 100%;
font-size: 18px;
font-weight: bold;
}
}
.error-box {
height: 30px;
color: tomato;
font-size: 14px;
font-weight: bold
}
</style>
43 changes: 43 additions & 0 deletions src/components/common/info/IconInfo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<div class="icon-info">
<div class="icon-box">
<i :class="icon"></i>
</div>
<span>{{ info }}</span>
</div>
</template>

<script>
export default {
name: 'IconInfoVue',
props: {
'icon' : String,
'info': String,
},
}
</script>

<style lang='scss' scoped>
.icon-info {
@include flex-box(row, start, 20px);
width: 100%;
.icon-box {
@include flex-box(row, center, 0px);
background-color: $theme-color;
width: 40px;
height: 40px;
font-size: 20px;
color : white;
border-radius: 10px;
}
span {
font-size: 18px;
font-weight: bold;
}
}
</style>
71 changes: 71 additions & 0 deletions src/components/common/input/FileInput.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<template>
<div class="info-input">
<div class="icon-box">
<i class="bi bi-folder"></i>
</div>
<div class="file-box" @click="triggerFileInput">{{ fileName }}</div>
</div>
<input
type="file"
ref="fileInput"
@change="onFileChange"
style="display: none;">
</template>

<script>
export default {
name: 'FileInputtVue',
props: {
'modelValue': File,
},
emits: ['update:modelValue'],
computed:{
fileName() {
return this.modelValue ? this.modelValue.name : '파일 선택';
}
},
methods: {
triggerFileInput() {
this.$refs.fileInput.click();
},
onFileChange(event) {
const file = event.target.files[0];
this.$emit('update:modelValue', file);
}
}
}
</script>

<style lang='scss' scoped>
.info-input {
@include flex-box(row, center, 0px);
background-color: white;
width: 100%;
height: 40px;
.icon-box {
@include flex-box(row, center, 0px);
@include white-text(24px);
background: $theme-color;
width: 80px;
height: 100%;
padding-top: 5px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
}
.file-box {
@include flex-box(row, center, 0px);
@include base-icon;
width: 100%;
height: 100%;
padding: 0px 10px;
font-weight: bold;
border: $theme-color solid;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
}
</style>
2 changes: 1 addition & 1 deletion src/components/item/ItemCreateModal.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<transition name="fade">
<div v-if="isVisible" class="modal-overlay" @click.self="closeModal">
<div v-if="isVisible" class="modal-overlay">
<div class="modal-content">
<ModalHeaderVue :title="title" :closeModal="closeModal"/>
<div class="modal-main">
Expand Down
2 changes: 1 addition & 1 deletion src/components/item/ItemDeleteModal.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<transition name="fade">
<div v-if="isVisible" class="modal-overlay" @click.self="closeModal">
<div v-if="isVisible" class="modal-overlay">
<div class="modal-content">
<ModalHeaderVue :title="title" :closeModal="closeModal"/>
<div class="modal-main">
Expand Down
6 changes: 1 addition & 5 deletions src/components/item/ItemInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import TitleInfoVue from '@/components/common/info/TitleInfo.vue';
import DescriptionInfoVue from '../common/info/DescriptionInfo.vue';
export default {
name: 'InfoInfoVue',
name: 'ItemInfoVue',
components: {
TitleInfoVue,
DescriptionInfoVue
Expand All @@ -38,10 +38,6 @@ export default {
.info-container {
@include flex-box(column, center, 20px);
width: 100%;
padding: 40px 30px;
border-radius : 10px;
box-shadow: $base-shadow;
background-color: white;
img {
width: 320px;
height: 320px;
Expand Down
2 changes: 1 addition & 1 deletion src/components/item/ItemUpdateModal.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<transition name="fade">
<div v-if="isVisible" class="modal-overlay" @click.self="closeModal">
<div v-if="isVisible" class="modal-overlay">
<div class="modal-content">
<ModalHeaderVue :title="title" :closeModal="closeModal"/>
<div class="modal-main">
Expand Down
Loading

0 comments on commit e32fe2d

Please sign in to comment.