first
This commit is contained in:
487
safekiso_admin/pages/admin/lab/board.vue
Normal file
487
safekiso_admin/pages/admin/lab/board.vue
Normal file
@@ -0,0 +1,487 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="space-y-6 lg:col-start-1 lg:col-span-2">
|
||||
<!-- Description list-->
|
||||
<section aria-labelledby="applicant-indivation-title">
|
||||
<div class="bg-white shadow sm:rounded-lg">
|
||||
<div class="px-4 py-5 sm:px-6">
|
||||
<h2
|
||||
id="applicant-indivation-title"
|
||||
class="text-lg leading-6 font-medium text-gray-900"
|
||||
>
|
||||
게시판에 글을 작성하는 화면에서 API 사용 예
|
||||
</h2>
|
||||
<p class="mt-1 max-w-2xl text-sm text-gray-500">
|
||||
문제가 있는 표현을 고지하고 수정하기 전에는 저장을
|
||||
하지 못하게 합니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||
<div>
|
||||
<div
|
||||
class="shadow sm:rounded-md sm:overflow-hidden"
|
||||
>
|
||||
<div
|
||||
class="px-4 py-5 bg-white space-y-6 sm:p-6"
|
||||
>
|
||||
<div class="grid grid-cols-3 gap-6">
|
||||
<div class="col-span-3 sm:col-span-3">
|
||||
<label
|
||||
for="company-website"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
제목
|
||||
</label>
|
||||
<div
|
||||
class="mt-1 flex rounded-md shadow-sm"
|
||||
>
|
||||
<input
|
||||
id="company-website"
|
||||
v-model="boardTitle"
|
||||
type="text"
|
||||
name="company-website"
|
||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
for="about"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
내용
|
||||
</label>
|
||||
<div class="mt-1">
|
||||
<textarea
|
||||
id="about"
|
||||
v-model="boardText"
|
||||
name="about"
|
||||
rows="7"
|
||||
class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 mt-1 block w-full sm:text-sm border border-gray-300 rounded-md"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
모욕적인 표현이 포함된 경우 저장을
|
||||
하실 수 없습니다.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="px-4 py-3 bg-gray-50 text-right sm:px-6"
|
||||
>
|
||||
<SwitchGroup
|
||||
as="div"
|
||||
class="flex items-center"
|
||||
>
|
||||
<Switch
|
||||
v-model="boardErrorEnabled"
|
||||
:class="[
|
||||
boardErrorEnabled
|
||||
? 'bg-indigo-600'
|
||||
: 'bg-gray-200',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500',
|
||||
]"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
:class="[
|
||||
boardErrorEnabled
|
||||
? 'translate-x-5'
|
||||
: 'translate-x-0',
|
||||
'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200',
|
||||
]"
|
||||
/>
|
||||
</Switch>
|
||||
<SwitchLabel as="span" class="ml-3">
|
||||
<span
|
||||
class="text-sm font-medium text-gray-900"
|
||||
>API 오류 시뮬레이션
|
||||
</span>
|
||||
</SwitchLabel>
|
||||
</SwitchGroup>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
@click="handleBoard"
|
||||
>
|
||||
전송
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Comments-->
|
||||
<section aria-labelledby="notes-title">
|
||||
<div class="bg-white shadow sm:rounded-lg sm:overflow-hidden">
|
||||
<div class="divide-y divide-gray-200">
|
||||
<div class="px-4 py-5 sm:px-6">
|
||||
<h2
|
||||
id="notes-title"
|
||||
class="text-lg font-medium text-gray-900"
|
||||
>
|
||||
댓글 작성 화면에서의 API 사용 예
|
||||
</h2>
|
||||
</div>
|
||||
<div class="px-4 py-6 sm:px-6">
|
||||
<ul role="list" class="space-y-8">
|
||||
<li
|
||||
v-for="comment in comments"
|
||||
:key="comment.id"
|
||||
>
|
||||
<div class="flex space-x-3">
|
||||
<div class="flex-shrink-0">
|
||||
<img
|
||||
class="h-10 w-10 rounded-full"
|
||||
:src="`https://images.unsplash.com/photo-${comment.imageId}?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=divat&fit=facearea&facepad=2&w=256&h=256&q=80`"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm">
|
||||
<a
|
||||
href="#"
|
||||
class="font-medium text-gray-900"
|
||||
>{{ comment.name }}</a
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
class="mt-1 text-sm text-gray-700"
|
||||
>
|
||||
<p>
|
||||
{{ comment.body }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-2 text-sm space-x-2">
|
||||
<span
|
||||
class="text-gray-500 font-medium"
|
||||
>{{ comment.date }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-50 px-4 py-6 sm:px-6">
|
||||
<div class="flex space-x-3">
|
||||
<div class="flex-shrink-0">
|
||||
<img
|
||||
class="h-10 w-10 rounded-full"
|
||||
:src="user.imageUrl"
|
||||
alt=""
|
||||
/>
|
||||
</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div action="#">
|
||||
<div>
|
||||
<label for="comment" class="sr-only"
|
||||
>About</label
|
||||
>
|
||||
<textarea
|
||||
id="comment"
|
||||
v-model="commentMessage"
|
||||
name="comment"
|
||||
rows="3"
|
||||
class="shadow-sm block w-full focus:ring-blue-500 focus:border-blue-500 sm:text-sm border border-gray-300 rounded-md"
|
||||
placeholder="댓글 본문을 입력해 주세요."
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="mt-3 flex items-center justify-between"
|
||||
>
|
||||
<a
|
||||
href="javascript:void(0)"
|
||||
class="group inline-flex items-start text-sm space-x-2 text-gray-500 hover:text-gray-900"
|
||||
>
|
||||
<QuestionMarkCircleIcon
|
||||
class="flex-shrink-0 h-5 w-5 text-gray-400 group-hover:text-gray-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span>
|
||||
모욕적인 표현이 포함된 경우
|
||||
게시할 수 없습니다.
|
||||
</span>
|
||||
</a>
|
||||
<SwitchGroup
|
||||
as="div"
|
||||
class="flex items-center"
|
||||
>
|
||||
<Switch
|
||||
v-model="commentErrorEnabled"
|
||||
:class="[
|
||||
commentErrorEnabled
|
||||
? 'bg-indigo-600'
|
||||
: 'bg-gray-200',
|
||||
'relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500',
|
||||
]"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
:class="[
|
||||
commentErrorEnabled
|
||||
? 'translate-x-5'
|
||||
: 'translate-x-0',
|
||||
'pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200',
|
||||
]"
|
||||
/>
|
||||
</Switch>
|
||||
<SwitchLabel as="span" class="ml-3">
|
||||
<span
|
||||
class="text-sm font-medium text-gray-900"
|
||||
>API 오류 시뮬레이션
|
||||
</span>
|
||||
</SwitchLabel>
|
||||
</SwitchGroup>
|
||||
<button
|
||||
type="button"
|
||||
class="inline-flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
|
||||
@click="handleComment"
|
||||
>
|
||||
전송
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<!-- Global notification live region, render this permanently at the end of the document -->
|
||||
<div
|
||||
aria-live="assertive"
|
||||
class="fixed inset-0 flex items-end px-4 py-6 pointer-events-none sm:p-6 sm:items-start"
|
||||
>
|
||||
<div
|
||||
class="w-full flex flex-col items-center space-y-4 sm:items-end"
|
||||
>
|
||||
<!-- Notification panel, dynamically insert this into the live region when it needs to be displayed -->
|
||||
<transition
|
||||
enter-active-class="transform ease-out duration-300 transition"
|
||||
enter-from-class="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-2"
|
||||
enter-to-class="translate-y-0 opacity-100 sm:translate-x-0"
|
||||
leave-active-class="transition ease-in duration-100"
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<div
|
||||
v-if="notiShow"
|
||||
class="max-w-sm w-full bg-white shadow-lg rounded-lg pointer-events-auto ring-1 ring-black ring-opacity-5 overflow-hidden"
|
||||
>
|
||||
<div class="p-4">
|
||||
<div class="flex items-start">
|
||||
<div class="flex-shrink-0">
|
||||
<CheckCircleIcon
|
||||
v-if="isGoodFlag"
|
||||
class="h-6 w-6 text-green-400"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<ExclamationCircleIcon
|
||||
v-else
|
||||
class="h-6 w-6 text-red-400"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="ml-3 w-0 flex-1 pt-0.5">
|
||||
<p
|
||||
class="text-sm font-medium text-gray-900"
|
||||
>
|
||||
{{ notiTitle }}
|
||||
</p>
|
||||
<p class="mt-1 text-sm text-gray-500">
|
||||
{{ notiMessage }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="ml-4 flex-shrink-0 flex">
|
||||
<button
|
||||
type="button"
|
||||
class="bg-white rounded-md inline-flex text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
@click="notiShow = false"
|
||||
>
|
||||
<span class="sr-only">Close</span>
|
||||
<XIcon
|
||||
class="h-5 w-5"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { XMarkIcon, QuestionMarkCircleIcon } from '@heroicons/vue/24/solid';
|
||||
|
||||
import {
|
||||
CheckCircleIcon,
|
||||
ExclamationCircleIcon,
|
||||
} from '@heroicons/vue/24/outline';
|
||||
|
||||
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue';
|
||||
|
||||
const user = {
|
||||
name: 'Whitney Francis',
|
||||
email: 'whitney@example.com',
|
||||
imageUrl:
|
||||
'https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-=eyJhcHBfaWQiOjEyMDd9&auto=divat&fit=facearea&facepad=8&w=256&h=256&q=80',
|
||||
};
|
||||
|
||||
let commentSerial = 0;
|
||||
|
||||
const boardErrorEnabled = ref(false);
|
||||
const commentErrorEnabled = ref(false);
|
||||
|
||||
const comments = ref([
|
||||
{
|
||||
id: ++commentSerial,
|
||||
name: '김재순',
|
||||
date: '하루 전',
|
||||
imageId: '1506794778202-cad84cf45f1d',
|
||||
body: '짜장면이 맛이 있느냐 짬뽕이 맛이 있느냐 논쟁 같은 느낌인데요? ',
|
||||
},
|
||||
]);
|
||||
const notiShow = ref(false);
|
||||
const isGoodFlag = ref(false);
|
||||
|
||||
const notiTitle = ref('');
|
||||
const notiMessage = ref('');
|
||||
|
||||
const notiTimer = null;
|
||||
|
||||
function showNotifications(isGood, title, message) {
|
||||
isGoodFlag.value = isGood;
|
||||
notiTitle.value = title;
|
||||
notiMessage.value = message;
|
||||
notiShow.value = true;
|
||||
if (notiTimer != null) {
|
||||
clearTimeout(notiTimer);
|
||||
notiTimer = null;
|
||||
}
|
||||
notiTimer = setTimeout(() => {
|
||||
notiShow.value = false;
|
||||
}, 8000);
|
||||
}
|
||||
|
||||
const boardTitle = ref('');
|
||||
const boardText = ref('');
|
||||
const commentMessage = ref('');
|
||||
|
||||
const missingParts = 'e3';
|
||||
|
||||
async function handleFilter(source, at, errorSimulFlag, cb) {
|
||||
const responseJson = await _crossCtl.doFilter(
|
||||
'' + (errorSimulFlag == false ? '' : missingParts),
|
||||
{
|
||||
text: source,
|
||||
mode: 'quick',
|
||||
}
|
||||
);
|
||||
|
||||
// console.log('responseJson=', responseJson);
|
||||
|
||||
if (responseJson['Status']['Code'] == 2000) {
|
||||
// Detected
|
||||
if (responseJson['Detected'].length == 0) {
|
||||
cb(null);
|
||||
} else {
|
||||
showNotifications(
|
||||
false,
|
||||
'잘못된 표현',
|
||||
at +
|
||||
'에 이 표현은 쓸 수 없습니다. : ' +
|
||||
responseJson['Detected'][0][1]
|
||||
);
|
||||
cb(false);
|
||||
}
|
||||
} else {
|
||||
showNotifications(
|
||||
false,
|
||||
'오류',
|
||||
'API 호출 오류 : ' + responseJson['Status']['Message']
|
||||
);
|
||||
cb(true);
|
||||
}
|
||||
}
|
||||
|
||||
function handleBoard() {
|
||||
// console.log(boardTitle.value);
|
||||
// console.log(boardText.value);
|
||||
|
||||
if (boardTitle.value.trim() == '') {
|
||||
showNotifications(false, '오류', '제목을 입력해 주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (boardText.value.trim() == '') {
|
||||
showNotifications(false, '오류', '본문을 입력해 주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
handleFilter(
|
||||
boardTitle.value,
|
||||
'게시판 제목',
|
||||
boardErrorEnabled.value,
|
||||
function (error) {
|
||||
if (error == null) {
|
||||
handleFilter(
|
||||
boardText.value,
|
||||
'게시판 본문',
|
||||
boardErrorEnabled.value,
|
||||
function (error) {
|
||||
if (error == null) {
|
||||
showNotifications(
|
||||
true,
|
||||
'게시 가능',
|
||||
'입력하신 제목과 내용에 문제가 없습니다.'
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function handleComment() {
|
||||
if (commentMessage.value == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
handleFilter(
|
||||
commentMessage.value,
|
||||
'댓글',
|
||||
commentErrorEnabled.value,
|
||||
function (error) {
|
||||
console.log('error=', error);
|
||||
if (error == null) {
|
||||
comments.value.push({
|
||||
id: ++commentSerial,
|
||||
name: '당신',
|
||||
date: '조금 전',
|
||||
imageId: '1517365830460-955ce3ccd263',
|
||||
body: commentMessage.value,
|
||||
});
|
||||
|
||||
commentMessage.value = '';
|
||||
} else if (error == true) {
|
||||
} else {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
</script>
|
||||
77
safekiso_admin/pages/admin/lab/chat.vue
Normal file
77
safekiso_admin/pages/admin/lab/chat.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
<!--
|
||||
This example requires Tailwind CSS v2.0+
|
||||
|
||||
This example requires some changes to your config:
|
||||
|
||||
```
|
||||
// tailwind.config.js
|
||||
module.exports = {
|
||||
// ...
|
||||
plugins: [
|
||||
// ...
|
||||
require('@tailwindcss/forms'),
|
||||
],
|
||||
}
|
||||
```
|
||||
-->
|
||||
<template>
|
||||
<div>
|
||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||
<form action="#" method="POST">
|
||||
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
||||
<div class="px-4 py-5 bg-white space-y-6 sm:p-6">
|
||||
<div class="grid grid-cols-3 gap-6">
|
||||
<div class="col-span-3 sm:col-span-3">
|
||||
<label
|
||||
for="company-website"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
제목
|
||||
</label>
|
||||
<div class="mt-1 flex rounded-md shadow-sm">
|
||||
<input
|
||||
id="company-website"
|
||||
type="text"
|
||||
name="company-website"
|
||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-r-md sm:text-sm border-gray-300"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
for="about"
|
||||
class="block text-sm font-medium text-gray-700"
|
||||
>
|
||||
내용
|
||||
</label>
|
||||
<div class="mt-1">
|
||||
<textarea
|
||||
id="about"
|
||||
name="about"
|
||||
rows="7"
|
||||
class="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 mt-1 block w-full sm:text-sm border border-gray-300 rounded-md"
|
||||
placeholder=""
|
||||
/>
|
||||
</div>
|
||||
<p class="mt-2 text-sm text-gray-500">
|
||||
모욕적인 표현이 포함된 경우 저장을 하실 수
|
||||
없습니다.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
|
||||
<button
|
||||
type="submit"
|
||||
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
187
safekiso_admin/pages/admin/lab/chatting.vue
Normal file
187
safekiso_admin/pages/admin/lab/chatting.vue
Normal file
@@ -0,0 +1,187 @@
|
||||
<!-- This example requires Tailwind CSS v2.0+ -->
|
||||
<template>
|
||||
<div class="">
|
||||
<div class="container mx-auto">
|
||||
<div class="min-w-full border rounded lg:grid lg:grid-cols-3">
|
||||
<div class="hidden lg:col-span-3 lg:block">
|
||||
<div class="flex flex-col min-h-screen w-full">
|
||||
<div
|
||||
class="relative flex items-center p-3 border-b border-gray-300"
|
||||
>
|
||||
<img
|
||||
class="object-cover w-10 h-10 rounded-full"
|
||||
src="https://cdn.pixabay.com/photo/2018/01/15/07/51/woman-3083383__340.jpg"
|
||||
alt="username"
|
||||
/>
|
||||
<span class="block ml-2 font-bold text-gray-600">
|
||||
채팅 상황에서의 API 사용 예{{ ' ' }}
|
||||
|
||||
<p class="text-xs">
|
||||
{{
|
||||
messageList[messageList.length - 1][
|
||||
'elapsedServer'
|
||||
] != ''
|
||||
? messageList[
|
||||
messageList.length - 1
|
||||
]['elapsedServer'] +
|
||||
' / ' +
|
||||
messageList[
|
||||
messageList.length - 1
|
||||
]['elapsed']
|
||||
: ''
|
||||
}}
|
||||
</p>
|
||||
</span>
|
||||
<span
|
||||
class="absolute w-3 h-3 bg-green-600 rounded-full left-10 top-3"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex-grow bg-gray-50 justify-center">
|
||||
<div
|
||||
class="relative w-full p-6 overflow-y-auto max-h-fit"
|
||||
>
|
||||
<ul class="space-y-2">
|
||||
<li
|
||||
v-for="message in messageList"
|
||||
:key="message['serial']"
|
||||
class="flex"
|
||||
:class="
|
||||
message['left'] == true
|
||||
? 'justify-start'
|
||||
: 'justify-end'
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="relative max-w-xl px-4 py-2 text-gray-700 rounded shadow"
|
||||
>
|
||||
<span class="block">{{
|
||||
message['text']
|
||||
}}</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-between w-full p-3 border-t border-gray-300"
|
||||
>
|
||||
<input
|
||||
v-model="justEnteredText"
|
||||
type="text"
|
||||
placeholder="Message"
|
||||
class="block w-full py-2 pl-4 mx-3 bg-gray-100 rounded-full outline-none focus:text-gray-700"
|
||||
name="message"
|
||||
required
|
||||
@keyup.enter="checkChatInput"
|
||||
/>
|
||||
<button type="button" @click="checkChatInput">
|
||||
<svg
|
||||
class="w-5 h-5 text-gray-500 origin-center transform rotate-90"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path
|
||||
d="M10.894 2.553a1 1 0 00-1.788 0l-7 14a1 1 0 001.169 1.409l5-1.429A1 1 0 009 15.571V11a1 1 0 112 0v4.571a1 1 0 00.725.962l5 1.428a1 1 0 001.17-1.408l-7-14z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-end w-full p-3 border-t border-gray-300"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: 'check-auth-user',
|
||||
});
|
||||
|
||||
let tmpIdx = 0;
|
||||
|
||||
const messageList = ref([
|
||||
{
|
||||
serial: tmpIdx++,
|
||||
left: true,
|
||||
text: '안녕하세요?',
|
||||
elapsedServer: '',
|
||||
elapsed: '',
|
||||
},
|
||||
{
|
||||
serial: tmpIdx++,
|
||||
left: false,
|
||||
text: '테스트 하러 들어 왔습니다.',
|
||||
elapsedServer: '',
|
||||
elapsed: '',
|
||||
},
|
||||
{
|
||||
serial: tmpIdx++,
|
||||
left: true,
|
||||
text: '테스트 하면 이 문장이죠.',
|
||||
elapsedServer: '',
|
||||
elapsed: '',
|
||||
},
|
||||
{
|
||||
serial: tmpIdx++,
|
||||
left: true,
|
||||
text: 'Lorem ipsum dolor sit, amet consectetur adipisicing elit.',
|
||||
elapsedServer: '',
|
||||
elapsed: '',
|
||||
},
|
||||
]);
|
||||
|
||||
const justEnteredText = ref('');
|
||||
|
||||
const inPregressFlag = ref(false);
|
||||
const elispe = ref(0);
|
||||
|
||||
async function checkChatInput() {
|
||||
console.log('huk');
|
||||
|
||||
if (justEnteredText.value == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (inPregressFlag.value == true) {
|
||||
return;
|
||||
}
|
||||
inPregressFlag.value = true;
|
||||
|
||||
const startTime = performance.now();
|
||||
|
||||
const responseJson = await _crossCtl.doFilter('', {
|
||||
text: justEnteredText.value,
|
||||
mode: 'filter',
|
||||
});
|
||||
|
||||
const endTime = performance.now();
|
||||
|
||||
inPregressFlag.value = false;
|
||||
|
||||
elispe.value = endTime - startTime;
|
||||
|
||||
console.log('responseJson=', responseJson);
|
||||
|
||||
if (responseJson['Status']['Code'] == 2000) {
|
||||
messageList.value.push({
|
||||
serial: tmpIdx++,
|
||||
left: false,
|
||||
text: responseJson['Filtered'],
|
||||
elapsedServer: responseJson['Elapsed'].replace('0 s, ', ''),
|
||||
elapsed: elispe.value.toFixed(2) + 'ms',
|
||||
});
|
||||
|
||||
justEnteredText.value = '';
|
||||
} else {
|
||||
alert(responseJson['Status']['Message']);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
45
safekiso_admin/pages/admin/lab/index.vue
Normal file
45
safekiso_admin/pages/admin/lab/index.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<!-- This example requires Tailwind CSS v2.0+ -->
|
||||
<template>
|
||||
<div class="pb-8 px-4 sm:px-6 lg:px-8">
|
||||
<div class="sm:flex sm:items-center">
|
||||
<div class="sm:flex-auto">
|
||||
<h1 class="text-xl font-semibold text-gray-900">
|
||||
API 키 테스트 기능
|
||||
</h1>
|
||||
<p class="mt-2 text-sm text-gray-700">
|
||||
API 키가 실제 서비스 예에서 사용되는 것을 볼 수 있습니다.
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none"></div>
|
||||
</div>
|
||||
|
||||
<nav class="mt-5 space-y-1" aria-label="Sidebar">
|
||||
<a
|
||||
v-for="item in navigation"
|
||||
:key="item.name"
|
||||
href="javascript:void(0)"
|
||||
:class="[
|
||||
'text-gray-600 hover:bg-gray-100 hover:text-gray-900',
|
||||
'flex items-center px-3 py-2 text-sm font-medium rounded-md',
|
||||
]"
|
||||
:aria-current="'page'"
|
||||
@click="$router.push(item.href)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: 'check-auth-op',
|
||||
});
|
||||
|
||||
const navigation = [
|
||||
{ name: 'API 키 테스트 게시판', href: '/admin/lab/board' },
|
||||
{ name: 'API 키 테스트 웹 채팅', href: '/admin/lab/chatting' },
|
||||
];
|
||||
</script>
|
||||
79
safekiso_admin/pages/admin/lab/statistics.vue
Normal file
79
safekiso_admin/pages/admin/lab/statistics.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<!-- This example requires Tailwind CSS v2.0+ -->
|
||||
<template>
|
||||
<div class="pb-8 px-4 sm:px-6 lg:px-8">
|
||||
<div class="sm:flex sm:items-center">
|
||||
<div class="sm:flex-auto">
|
||||
<h1 class="text-xl font-semibold text-gray-900">
|
||||
통계 테스트 페이지
|
||||
</h1>
|
||||
<p class="mt-2 text-sm text-gray-700">
|
||||
통계 개발과 기능 테스트를 위해 만들어진 임시 페이지입니다.
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-4 sm:mt-0 sm:ml-16 sm:flex-none"></div>
|
||||
</div>
|
||||
|
||||
<nav class="mt-5 space-y-1" aria-label="Sidebar">
|
||||
<a
|
||||
v-for="item in navigation"
|
||||
:key="item.name"
|
||||
href="javascript:void(0)"
|
||||
:class="[
|
||||
'text-gray-600 hover:bg-gray-100 hover:text-gray-900',
|
||||
'flex items-center px-3 py-2 text-sm font-medium rounded-md',
|
||||
]"
|
||||
:aria-current="'page'"
|
||||
@click="doAction(item.actionTag)"
|
||||
>
|
||||
<span class="truncate">
|
||||
{{ item.name }}
|
||||
</span>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
definePageMeta({
|
||||
middleware: 'check-auth-op',
|
||||
});
|
||||
|
||||
const navigation = [
|
||||
{ name: 'hello?', actionTag: 'hello' },
|
||||
{ name: '2022년 통계 가공', actionTag: '2022' },
|
||||
{ name: '2022년 9월 통계 가공', actionTag: '202209' },
|
||||
{ name: '2022년 9월 27일 통계 가공', actionTag: '20220927' },
|
||||
];
|
||||
|
||||
async function doAction(tag) {
|
||||
let responseJson = null;
|
||||
switch (tag) {
|
||||
case '2022':
|
||||
responseJson = await _crossCtl.doComm('local/lab', 'makestat', {
|
||||
termTag: 'year',
|
||||
dateTag: '2022',
|
||||
});
|
||||
console.log('responseJson=', responseJson);
|
||||
break;
|
||||
case '202209':
|
||||
responseJson = await _crossCtl.doComm('local/lab', 'makestat', {
|
||||
termTag: 'month',
|
||||
dateTag: '202209',
|
||||
});
|
||||
console.log('responseJson=', responseJson);
|
||||
break;
|
||||
case '20220927':
|
||||
responseJson = await _crossCtl.doComm('local/lab', 'makestat', {
|
||||
termTag: 'day',
|
||||
dateTag: '20220927',
|
||||
});
|
||||
console.log('responseJson=', responseJson);
|
||||
break;
|
||||
|
||||
case 'hello':
|
||||
responseJson = await _crossCtl.doComm('local/lab', 'hello', {});
|
||||
console.log('responseJson=', responseJson);
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user