support.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. <template>
  2. <main>
  3. <TopVisual :className="className" :title="title" :navigation="navigation" />
  4. <section id="out--container">
  5. <div class="out--container">
  6. <h2 class="m--title">고객센터</h2>
  7. <div class="form--contents--wrap">
  8. <div class="contact-form">
  9. <div class="form--contents half--cont">
  10. <h3>작성자 (성명) <span class="required">*</span></h3>
  11. <div>
  12. <UInput
  13. v-model="formData.name"
  14. placeholder="성명을 입력해주세요"
  15. />
  16. </div>
  17. </div>
  18. <div class="form--contents half--cont">
  19. <h3>직책</h3>
  20. <div>
  21. <UInput
  22. v-model="formData.etc1"
  23. placeholder="직책을 입력해주세요"
  24. />
  25. </div>
  26. </div>
  27. <div class="form--contents half--cont">
  28. <h3>회사명</h3>
  29. <div>
  30. <UInput
  31. v-model="formData.etc2"
  32. placeholder="회사명을 입력해주세요"
  33. />
  34. </div>
  35. </div>
  36. <div class="form--contents half--cont">
  37. <h3>연락처 <span class="required">*</span></h3>
  38. <div class="tel-group">
  39. <USelect
  40. v-model="formData.tel_1"
  41. :options="phoneOptions"
  42. />
  43. <span>-</span>
  44. <UInput
  45. v-model="formData.tel_2"
  46. maxlength="4"
  47. pattern="[0-9]{3,4}"
  48. />
  49. <span>-</span>
  50. <UInput
  51. v-model="formData.tel_3"
  52. maxlength="4"
  53. pattern="[0-9]{4}"
  54. />
  55. </div>
  56. </div>
  57. <div class="form--contents half--cont">
  58. <h3>이메일 <span class="required">*</span></h3>
  59. <div>
  60. <UInput
  61. type="email"
  62. v-model="formData.email"
  63. placeholder="이메일을 입력해주세요"
  64. />
  65. </div>
  66. </div>
  67. <div class="form--contents half--cont">
  68. <h3>문의항목 <span class="required">*</span></h3>
  69. <div class="radio-group">
  70. <label>
  71. <input
  72. type="radio"
  73. v-model="formData.category"
  74. value="원료"
  75. />
  76. <span>원료</span>
  77. </label>
  78. <label>
  79. <input
  80. type="radio"
  81. v-model="formData.category"
  82. value="제품"
  83. />
  84. <span>제품</span>
  85. </label>
  86. <label>
  87. <input
  88. type="radio"
  89. v-model="formData.category"
  90. value="기술"
  91. />
  92. <span>기술</span>
  93. </label>
  94. <label>
  95. <input
  96. type="radio"
  97. v-model="formData.category"
  98. value="기타"
  99. />
  100. <span>기타</span>
  101. </label>
  102. </div>
  103. </div>
  104. <div class="form--contents">
  105. <h3>제목 <span class="required">*</span></h3>
  106. <div>
  107. <UInput
  108. v-model="formData.title"
  109. placeholder="제목을 입력해주세요"
  110. />
  111. </div>
  112. </div>
  113. <div class="form--contents">
  114. <h3>내용 <span class="required">*</span></h3>
  115. <div>
  116. <client-only>
  117. <SummernoteEditor
  118. v-model="formData.contents"
  119. :height="editorHeight"
  120. :placeholder="editorPlaceholder"
  121. />
  122. <template #fallback>
  123. <textarea
  124. v-model="formData.contents"
  125. rows="10"
  126. placeholder="문의 내용을 입력해주세요"
  127. ></textarea>
  128. </template>
  129. </client-only>
  130. </div>
  131. </div>
  132. <div class="form--contents">
  133. <h3>개인 정보 수집 및 이용 동의</h3>
  134. <div class="privacy-box">
  135. <div class="privacy-content">
  136. 그린웨일 글로벌 주식회사 ('www.greenwhaleglobal.com'이하 '그린웨일 글로벌')은(는) 「개인정보 보호법」 제30조에 따라 정부주체의 개인정보를 보호하고 이와 관련한 고충을 신속하고 원활하게 처리할 수 있도록 하기 위하여 다음과 같이 개인정보 처리방침을 수립·공개합니다.<br/><br/>
  137. <strong>● 이 개인정보처리방침은 2022년 11월 01일부터 적용됩니다.</strong><br/><br/>
  138. <strong>제1조(개인정보의 처리 목적)</strong><br/>
  139. 그린웨일 글로벌은 다음의 목적을 위하여 개인정보를 처리합니다. 처리하고 있는 개인정보는 다음의 목적 이외의 용도로는 이용되지 않으며 이용 목적이 변경되는 경우에는 「개인정보 보호법」 제18조에 따라 별도의 동의를 받는 등 필요한 조치를 이행할 예정입니다.<br/>
  140. ▶ 재화 또는 서비스 제공: 맞춤 서비스 제공을 목적으로 개인정보를 처리합니다.<br/><br/>
  141. <strong>제2조(개인정보의 처리 및 보유 기간)</strong><br/>
  142. ① 그린웨일 글로벌은 법령에 따른 개인정보 보유·이용 기간 또는 정보 주체로부터 개인정보를 수집할 때 동의받은 개인정보 보유·이용 기간 내에서 개인정보를 처리·보유합니다.<br/>
  143. ② 각각의 개인정보 처리 및 보유 기간은 다음과 같습니다.<br/>
  144. • 재화 또는 서비스 제공과 관련한 개인정보는 수집.이용에 관한 동의일로부터 3년까지 위 이용목적을 위하여 보유.이용됩니다.<br/>
  145. • 보유근거 : 지속적인 피드백 관리를 위해<br/>
  146. • 관련법령 :<br/>
  147. 1) 신용정보의 수집/처리 및 이용 등에 관한 기록 : 3년<br/>
  148. 2) 소비자의 불만 또는 분쟁처리에 관한 기록 : 3년<br/>
  149. 3) 대금결제 및 재화 등의 공급에 관한 기록 : 5년<br/>
  150. 4) 계약 또는 청약철회 등에 관한 기록 : 5년<br/><br/>
  151. <strong>제3조(정보주체와 법정대리인의 권리·의무 및 그 행사방법)</strong><br/>
  152. 정보 주체는 그린웨일 글로벌에 대해 언제든지 개인정보 열람·정정·삭제·처리정지 요구 등의 권리를 행사할 수 있습니다.<br/>
  153. ① 제1항에 따른 권리 행사는 그린웨일 글로벌에 대해 「개인정보 보호법」 시행령 제41조 제1항에 따라, 서면 또는 전자우편, 모사전송(FAX) 등을 통하여 하실 수 있으며 그린웨일 글로벌은 이에 대해 지체 없이 조치하겠습니다.<br/>
  154. ② 제1항에 따른 권리 행사는 정보 주체의 법정대리인이나 위임을 받은 자 등 대리인을 통하여 하실 수 있습니다.<br/>
  155. ③ 개인정보 열람 및 처리정지 요구는 「개인정보 보호법」 제35조 제4항, 제37조 제2항에 의하여 정보 주체의 권리가 제한될 수 있습니다.<br/>
  156. ④ 개인정보의 정정 및 삭제 요구는 다른 법령에서 그 개인정보가 수집 대상으로 명시되어 있는 경우에는 그 삭제를 요구할 수 없습니다.<br/>
  157. ⑤ 그린웨일 글로벌은 정보 주체 권리에 따른 열람의 요구, 정정·삭제의 요구, 처리정지의 요구 시 열람 등 요구를 한 자가 본인이거나 정당한 대리인인지를 확인합니다.<br/><br/>
  158. <strong>제4조(처리하는 개인정보의 항목 작성)</strong><br/>
  159. 그린웨일 글로벌은 다음의 개인정보 항목을 처리하고 있습니다.<br/>
  160. • 재화 또는 서비스 제공<br/>
  161. • 필수항목 : 이메일, 휴대 전화번호, 이름, 회사 전화번호, 회사명<br/>
  162. • 선택항목 : 직책, 부서<br/><br/>
  163. <strong>제5조(개인정보의 파기)</strong><br/>
  164. ① 그린웨일 글로벌은 개인정보 보유기간의 경과, 처리목적 달성 등 개인정보가 불필요하게 되었을 때는 지체없이 해당 개인정보를 파기합니다.<br/>
  165. ② 정보 주체로부터 동의받은 개인정보 보유기간이 경과하거나 처리목적이 달성되었음에도 불구하고 다른 법령에 따라 개인정보를 계속 보존하여야 하는 경우에는, 해당 개인정보를 별도의 데이터베이스(DB)로 옮기거나 보관장소를 달리하여 보존합니다.<br/>
  166. ③ 개인정보 파기의 절차 및 방법은 다음과 같습니다.<br/>
  167. • 파기 절차: 그린웨일 글로벌은 파기 사유가 발생한 개인정보를 선정하고, 그린웨일 글로벌의 개인정보 보호 책임자의 승인을 받아 개인정보를 파기합니다.<br/>
  168. • 파기 방법: 전자적 파일 형태의 정보는 기록을 재생할 수 없는 기술적 방법을 사용합니다<br/><br/>
  169. <strong>제6조(개인정보의 안전성 확보 조치)</strong><br/>
  170. 그린웨일글로벌은 개인정보의 안전성 확보를 위해 다음과 같은 조치를 취하고 있습니다.<br/>
  171. ① 정기적인 자체 감사 실시<br/>
  172. ② 개인정보 취급 직원의 최소화 및 교육<br/>
  173. ③ 내부관리계획의 수립 및 시행<br/>
  174. ④ 개인정보에 대한 접근 제한<br/>
  175. ⑤ 비인가자에 대한 출입 통제<br/><br/>
  176. <strong>제7조(개인정보 자동 수집 장치의 설치•운영 및 거부에 관한 사항)</strong><br/>
  177. ① 그린웨일글로벌는 이용자에게 개별적인 맞춤서비스를 제공하기 위해 이용정보를 저장하고 수시로 불러오는 '쿠키(cookie)'를 사용합니다.<br/>
  178. ② 쿠키는 웹사이트를 운영하는데 이용되는 서버(http)가 이용자의 컴퓨터 브라우저에게 보내는 소량의 정보이며 이용자들의 PC 컴퓨터내의 하드디스크에 저장되기도 합니다.<br/><br/>
  179. <strong>제8조(개인정보 보호책임자 등)</strong><br/>
  180. ① 그린웨일 글로벌은 개인정보 처리에 관한 업무를 총괄해서 책임지고, 개인정보 처리와 관련한 정보주체의 불만 처리 및 피해구제 등을 위하여 아래와 같이 개인정보 보호책임자를 지정하고 있습니다.<br/>
  181. • 담당자 : 경영지원팀 이안나 대리<br/>
  182. • 전화번호 : 02-3447-8802<br/>
  183. • 이메일 : green@greenwhaleglobal.com<br/><br/>
  184. <strong>제9조(권익침해 구제방법)</strong><br/>
  185. 정보 주체는 개인정보침해로 인한 구제를 받기 위하여 개인정보분쟁조정위원회, 한국인터넷진흥원 개인정보침해신고센터 등에 분쟁해결이나 상담 등을 신청할 수 있습니다.<br/>
  186. 1. 개인정보분쟁조정위원회 : (국번없이) 1833-6972 (www.kopico.go.kr)<br/>
  187. 2. 개인정보침해신고센터 : (국번없이) 118 (privacy.kisa.or.kr)<br/>
  188. 3. 대검찰청 : (국번없이) 1301 (www.spo.go.kr)<br/>
  189. 4. 경찰청 : (국번없이) 182 (cyberbureau.police.go.kr)<br/>
  190. </div>
  191. <div class="agree-check">
  192. <h4>개인정보 수집 및 이용에 동의합니까?</h4>
  193. <div class="radio-group">
  194. <label>
  195. <input
  196. type="radio"
  197. v-model="formData.agree"
  198. value="Y"
  199. />
  200. <span>동의합니다.</span>
  201. </label>
  202. <label>
  203. <input
  204. type="radio"
  205. v-model="formData.agree"
  206. value="N"
  207. />
  208. <span>동의하지 않습니다.</span>
  209. </label>
  210. </div>
  211. </div>
  212. </div>
  213. </div>
  214. <div class="form--contents">
  215. <div class="btn--wrap">
  216. <UButton
  217. :loading="isSubmitting"
  218. @click="submitForm"
  219. size="lg"
  220. color="primary"
  221. >
  222. {{ isSubmitting ? '전송중...' : '보내기' }}
  223. </UButton>
  224. </div>
  225. </div>
  226. </div>
  227. </div>
  228. </div>
  229. </section>
  230. </main>
  231. </template>
  232. <script setup>
  233. import { ref, onMounted } from 'vue'
  234. import TopVisual from '~/components/topVisual.vue'
  235. import SummernoteEditor from '~/components/SummernoteEditor.vue'
  236. // 전화번호 옵션
  237. const phoneOptions = [
  238. { value: '010', label: '010' },
  239. { value: '011', label: '011' },
  240. { value: '016', label: '016' },
  241. { value: '017', label: '017' },
  242. { value: '018', label: '018' },
  243. { value: '019', label: '019' },
  244. { value: '02', label: '02' },
  245. { value: '031', label: '031' },
  246. { value: '032', label: '032' },
  247. { value: '033', label: '033' }
  248. ]
  249. // 반응형 데이터
  250. const isSubmitting = ref(false)
  251. const formData = ref({
  252. name: '',
  253. etc1: '', // 직책
  254. etc2: '', // 회사명
  255. tel_1: '010',
  256. tel_2: '',
  257. tel_3: '',
  258. email: '',
  259. category: '',
  260. title: '',
  261. contents: '',
  262. agree: ''
  263. })
  264. // Summernote 에디터 설정
  265. const editorHeight = 400
  266. const editorPlaceholder = '문의 내용을 입력해주세요'
  267. // 페이지 설정
  268. const className = "contact"
  269. const title = "Contact"
  270. const navigation = [
  271. {
  272. name: "Contact",
  273. link: "/contact",
  274. gnbList: [
  275. { name: "공지사항", link: "/" },
  276. { name: "FAQ", link: "/" },
  277. { name: "고객센터", link: "/contact/support" }
  278. ]
  279. },
  280. { name: "고객센터", link: "/contact/support" }
  281. ]
  282. // 폼 유효성 검증
  283. const validateForm = () => {
  284. if (!formData.value.name) {
  285. alert('성명을 입력해주세요.')
  286. return false
  287. }
  288. if (!formData.value.tel_2 || !formData.value.tel_3) {
  289. alert('연락처를 입력해주세요.')
  290. return false
  291. }
  292. if (!formData.value.email) {
  293. alert('이메일을 입력해주세요.')
  294. return false
  295. }
  296. if (!formData.value.category) {
  297. alert('문의항목을 선택해주세요.')
  298. return false
  299. }
  300. if (!formData.value.title) {
  301. alert('제목을 입력해주세요.')
  302. return false
  303. }
  304. if (!formData.value.contents || formData.value.contents === '<p><br></p>' || formData.value.contents === '') {
  305. alert('내용을 입력해주세요.')
  306. return false
  307. }
  308. if (formData.value.agree !== 'Y') {
  309. alert('개인정보 수집 및 이용에 동의해주세요.')
  310. return false
  311. }
  312. return true
  313. }
  314. // 폼 제출
  315. const submitForm = async () => {
  316. if (!validateForm()) return
  317. isSubmitting.value = true
  318. try {
  319. const submitData = {
  320. act: 'ins',
  321. boardId: 'contact',
  322. name: formData.value.name,
  323. etc1: formData.value.etc1,
  324. etc2: formData.value.etc2,
  325. tel_1: formData.value.tel_1,
  326. tel_2: formData.value.tel_2,
  327. tel_3: formData.value.tel_3,
  328. email: formData.value.email,
  329. category: formData.value.category,
  330. title: formData.value.title,
  331. contents: formData.value.contents
  332. }
  333. const response = await $api.postForm('/board_proc', submitData)
  334. if (response && response.success) {
  335. alert('문의가 정상적으로 접수되었습니다.')
  336. resetForm()
  337. } else {
  338. console.error('API 응답 오류:', response)
  339. alert(`문의 접수 중 오류가 발생했습니다. 응답: ${JSON.stringify(response)}`)
  340. }
  341. } catch (error) {
  342. if (error.response) {
  343. alert(`API 호출 오류: ${error.response.status} - ${error.response.statusText}`)
  344. } else if (error.request) {
  345. alert('서버에 연결할 수 없습니다. 네트워크 연결을 확인해주세요.')
  346. } else {
  347. alert(`요청 설정 오류: ${error.message}`)
  348. }
  349. } finally {
  350. isSubmitting.value = false
  351. }
  352. }
  353. // 폼 초기화
  354. const resetForm = () => {
  355. formData.value = {
  356. name: '',
  357. etc1: '',
  358. etc2: '',
  359. tel_1: '010',
  360. tel_2: '',
  361. tel_3: '',
  362. email: '',
  363. category: '',
  364. title: '',
  365. contents: '',
  366. agree: ''
  367. }
  368. }
  369. onMounted(() => {
  370. })
  371. </script>