no message
This commit is contained in:
parent
d4ed0f9ebc
commit
b770d6f989
24 changed files with 1384 additions and 356 deletions
|
|
@ -1,142 +1,372 @@
|
|||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br />
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-cli documentation</a
|
||||
>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>babel</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>pwa</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>eslint</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>typescript</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://forum.vuejs.org" target="_blank" rel="noopener"
|
||||
>Forum</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://chat.vuejs.org" target="_blank" rel="noopener"
|
||||
>Community Chat</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener"
|
||||
>Twitter</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
|
||||
</li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://router.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-router</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/vue-devtools#vue-devtools"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>vue-devtools</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener"
|
||||
>vue-loader</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://github.com/vuejs/awesome-vue"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>awesome-vue</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="col-12 row justify-center">
|
||||
<div class="col-xs-12 col-sm-12 col-md-12">
|
||||
<q-card flat class="row col-12 cardNone">
|
||||
<div :class="getClass(checkIn)">
|
||||
<!-- <div class="col-2">
|
||||
<q-btn
|
||||
icon="mdi-arrow-left"
|
||||
unelevated
|
||||
round
|
||||
dense
|
||||
flat
|
||||
color="white"
|
||||
@click="router.go(-1)"
|
||||
/>
|
||||
</div> -->
|
||||
<span class="text-body1 text-weight-bold col-12 text-center">
|
||||
<span v-if="checkIn">ลงเวลาเข้างาน</span>
|
||||
<span v-else>ลงเวลาออกงาน</span>
|
||||
</span>
|
||||
<!-- <div class="col-2 text-right">
|
||||
<q-btn
|
||||
icon="mdi-history"
|
||||
unelevated
|
||||
rounded
|
||||
dense
|
||||
flat
|
||||
color="white"
|
||||
:label="$q.screen.gt.xs ? 'ประวัติการลงเวลา' : ''"
|
||||
:class="$q.screen.gt.xs ? 'q-px-sm' : ''"
|
||||
@click="router.push('/check-in/history')"
|
||||
/>
|
||||
</div> -->
|
||||
</div>
|
||||
<div class="col-12 q-pa-md text-grey-9">
|
||||
<div class="col-12 row justify-center">
|
||||
<div class="col-12 row q-py-sm justify-center">
|
||||
<div
|
||||
class="col-xs-12 col-sm-10 text-h6 text-center text-weight-bold"
|
||||
>
|
||||
{{ date2Thai(Thai) }}
|
||||
</div>
|
||||
<div class="row col-12 justify-center q-py-sm">
|
||||
<div class="colunm">
|
||||
<div class="text-h3 text-weight-bold">
|
||||
{{ formattedH }}<span class="q-ma-md">:</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="colunm">
|
||||
<div class="text-h3 text-weight-bold">
|
||||
{{ formattedM }}<span class="q-ma-md">:</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="colunm">
|
||||
<div class="text-h3 text-weight-bold">{{ formattedS }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-md-11 row q-col-gutter-md">
|
||||
<div class="col-12 col-sm-8">
|
||||
<q-card
|
||||
bordered
|
||||
flat
|
||||
class="col-12 bg-grey-2 shadow-0"
|
||||
:style="$q.screen.gt.xs ? 'height: 350px;' : 'height: 220px;'"
|
||||
>
|
||||
<q-img
|
||||
src="@/assets/map1.png"
|
||||
:style="
|
||||
$q.screen.gt.xs ? 'height: 300px;' : 'height: 168px;'
|
||||
"
|
||||
></q-img>
|
||||
<div class="q-pa-md text-weight-medium text-grey-8">
|
||||
พื้นที่ใกล้เคียง
|
||||
<span class="q-px-sm">:</span>
|
||||
{{ location }}
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
<div class="col-12 col-sm-4">
|
||||
<q-card
|
||||
flat
|
||||
bordered
|
||||
class="cardImg col-12 bg-grey-2 items-center row cursor-pointer shadow-0"
|
||||
@click="photo()"
|
||||
:style="$q.screen.gt.xs ? 'height: 350px;' : 'height: 220px;'"
|
||||
>
|
||||
<div class="column col-12" v-if="!camera">
|
||||
<div class="text-center">
|
||||
<q-icon
|
||||
name="photo_camera"
|
||||
color="blue-grey-3"
|
||||
size="100px"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div v-if="hasPhoto">
|
||||
<video
|
||||
ref="video"
|
||||
autoplay
|
||||
:style="{
|
||||
width: videoWidth + 'px',
|
||||
height: videoHeight + 'px',
|
||||
}"
|
||||
></video>
|
||||
<canvas
|
||||
ref="canvas"
|
||||
:width="videoWidth"
|
||||
:height="videoHeight"
|
||||
></canvas>
|
||||
</div>
|
||||
|
||||
<div v-else class="q-mt-sm">
|
||||
<q-img
|
||||
:src="img"
|
||||
:style="{
|
||||
width: videoWidth + 'px',
|
||||
height: videoHeight + 'px',
|
||||
}"
|
||||
class="q-mt-lg"
|
||||
></q-img>
|
||||
<canvas
|
||||
ref="canvas"
|
||||
:width="canvasWidth"
|
||||
:height="canvasHeight"
|
||||
:style="{
|
||||
width: videoWidth + 'px',
|
||||
height: videoHeight + 'px',
|
||||
}"
|
||||
></canvas>
|
||||
</div>
|
||||
|
||||
<div class="absolute-bottom-right q-ma-md">
|
||||
<q-btn
|
||||
round
|
||||
push
|
||||
icon="photo_camera"
|
||||
size="md"
|
||||
color="positive"
|
||||
@click="capturePhoto"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
<div class="col-12 q-mb-md">
|
||||
<q-card
|
||||
bordered
|
||||
flat
|
||||
:class="
|
||||
$q.screen.gt.xs
|
||||
? 'q-px-md q-py-sm row items-center shadow-0'
|
||||
: 'q-pa-md row items-center shadow-0'
|
||||
"
|
||||
>
|
||||
<div class="text-weight-bold">สถานที่ทำงาน</div>
|
||||
<div
|
||||
:class="
|
||||
$q.screen.gt.xs
|
||||
? 'row q-gutter-md q-pl-md col-sm-6 col-md-3'
|
||||
: 'column col-12'
|
||||
"
|
||||
>
|
||||
<q-radio
|
||||
v-model="workplace"
|
||||
checked-icon="task_alt"
|
||||
unchecked-icon="panorama_fish_eye"
|
||||
val="in-place"
|
||||
label="ในสถานที่"
|
||||
/>
|
||||
<q-radio
|
||||
v-model="workplace"
|
||||
checked-icon="task_alt"
|
||||
unchecked-icon="panorama_fish_eye"
|
||||
val="off-site"
|
||||
label="นอกสถานที่"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6 col-md-4">
|
||||
<q-select
|
||||
v-if="workplace == 'off-site'"
|
||||
dense
|
||||
class="q-ml-md"
|
||||
outlined
|
||||
v-model="model"
|
||||
:options="options"
|
||||
prefix="ระบุสถานที่ :"
|
||||
/>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 text-right" v-if="camera">
|
||||
<div class="col-12">
|
||||
<q-separator />
|
||||
</div>
|
||||
<div class="col-12 q-pa-md">
|
||||
<q-btn
|
||||
:label="checkIn == true ? 'ลงเวลาเข้างาน' : 'ลงเวลาออกงาน'"
|
||||
:color="checkIn == true ? 'primary' : 'red-9'"
|
||||
push
|
||||
size="14px"
|
||||
:class="$q.screen.gt.xs ? 'q-px-md' : 'full-width'"
|
||||
@click="confirm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</q-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<q-dialog v-model="dialogTime">
|
||||
<q-card class="full-width cardNone">
|
||||
<div :class="getClass(checkIn)">
|
||||
<div class="text-body1 text-center col-12 text-weight-bold">
|
||||
<span v-if="checkIn">ลงเวลาเข้างานของคุณ</span>
|
||||
<span v-else>ลงเวลาออกงานของคุณ</span>
|
||||
</div>
|
||||
</div>
|
||||
<q-card-section class="row col-12 justify-center">
|
||||
<div class="bg-grey-2 rounded-borders q-pa-md col-11">
|
||||
<div class="col-12 text-subtitle1 text-center text-weight-medium">
|
||||
{{ Thai }}
|
||||
</div>
|
||||
<div class="row col-12 justify-center q-pt-sm">
|
||||
<div class="text-h3 text-weight-bold">
|
||||
{{ formattedH }}<span class="q-ma-md">:</span>
|
||||
</div>
|
||||
<div class="text-h3 text-weight-bold">{{ formattedM }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 text-center row q-pt-md">
|
||||
<div class="col-12 text-subtitle1 text-weight-medium text-secondary">
|
||||
{{ location }}
|
||||
</div>
|
||||
<div class="col-12 text-grey-7">{{ coordinates }}</div>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-actions align="center" class="q-mb-md row">
|
||||
<q-btn
|
||||
class="col-xs-11 col-sm-6"
|
||||
push
|
||||
label="ตกลง"
|
||||
color="secondary"
|
||||
v-close-popup
|
||||
/>
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Options, Vue } from "vue-class-component";
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
import { useCounterMixin } from "@/stores/mixin";
|
||||
// import { useRouter } from "vue-router";
|
||||
import moment, { Moment } from "moment";
|
||||
const mixin = useCounterMixin();
|
||||
const { date2Thai } = mixin;
|
||||
|
||||
@Options({
|
||||
props: {
|
||||
msg: String,
|
||||
},
|
||||
})
|
||||
export default class HelloWorld extends Vue {
|
||||
msg!: string;
|
||||
// const router = useRouter();
|
||||
const dateNow = ref(new Date());
|
||||
const Thai = ref(dateNow.value);
|
||||
const checkIn = ref(true); //เช็คการเช็คอิน ถ้าลงเวลาครั้งแรกเป็นเช็คอิน(สีเขียว) true แต่ถ้าครั้ง 2 เป็นเช็คเอ้าท์(สีแดง)
|
||||
|
||||
const location = ref("สำนักงาน ก.ก");
|
||||
const coordinates = ref("13° 43’ 45” N 100° 31’ 26” E");
|
||||
const workplace = ref("in-place");
|
||||
const model = ref(null);
|
||||
const options = ref([
|
||||
"ปฏิบัติงานที่บ้าน",
|
||||
"ลืมลงเวลาปฏิบัติงาน",
|
||||
"ไปประชุม/อบรม/สัมมนา/ปฏิบัติงานที่บ้านนอกสถานที่",
|
||||
"ขออนุญาตออกนอกสถานที่",
|
||||
]);
|
||||
|
||||
const camera = ref(false);
|
||||
const dialogTime = ref(false);
|
||||
|
||||
const mediaStream = ref<MediaStream | null>(null);
|
||||
const video = ref<HTMLVideoElement | null>(null);
|
||||
const canvas = ref<HTMLCanvasElement | null>(null);
|
||||
const hasPhoto = ref<boolean>(true);
|
||||
const img = ref<any>();
|
||||
|
||||
const videoWidth = ref<number>(335);
|
||||
const videoHeight = ref<number>(350);
|
||||
const canvasWidth = ref<number>(335);
|
||||
const canvasHeight = ref<number>(350);
|
||||
|
||||
const photo = () => {
|
||||
camera.value = true;
|
||||
camera.value && setupCamera();
|
||||
};
|
||||
const confirm = () => {
|
||||
dialogTime.value = true;
|
||||
};
|
||||
|
||||
function capturePhoto() {
|
||||
const videoElement = video.value;
|
||||
const canvasElement = canvas.value;
|
||||
if (!videoElement || !canvasElement) {
|
||||
console.error("Video or Canvas element not available");
|
||||
return;
|
||||
}
|
||||
const context = canvasElement.getContext("2d");
|
||||
if (!context) {
|
||||
console.error("Canvas context not available");
|
||||
return;
|
||||
}
|
||||
context.drawImage(videoElement, 0, 0, 335, 270);
|
||||
//ไฟล์รูป
|
||||
const dataURL = canvasElement.toDataURL(".image/.png");
|
||||
img.value = dataURL;
|
||||
console.log(img.value);
|
||||
|
||||
if (mediaStream.value) {
|
||||
mediaStream.value.getTracks().forEach((track) => track.stop());
|
||||
videoElement.srcObject = null;
|
||||
hasPhoto.value = false;
|
||||
}
|
||||
}
|
||||
const setupCamera = async () => {
|
||||
try {
|
||||
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
|
||||
if (video.value) {
|
||||
video.value.srcObject = stream;
|
||||
}
|
||||
mediaStream.value = stream;
|
||||
} catch (error) {
|
||||
console.error("Error accessing camera:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// const time = new Date().toLocaleTimeString();
|
||||
const formattedS = ref();
|
||||
const formattedM = ref();
|
||||
const formattedH = ref();
|
||||
|
||||
onMounted(() => {
|
||||
updateClock();
|
||||
});
|
||||
|
||||
function updateClock() {
|
||||
const date = Date.now();
|
||||
let hh = moment(date).format("HH");
|
||||
let mm = moment(date).format("mm");
|
||||
let ss = moment(date).format("ss");
|
||||
formattedS.value = ss;
|
||||
formattedM.value = mm;
|
||||
formattedH.value = hh;
|
||||
}
|
||||
setInterval(updateClock, 1000);
|
||||
|
||||
const getClass = (val: boolean) => {
|
||||
return {
|
||||
"bg-primary text-white col-12 row items-center q-px-md q-py-sm": val,
|
||||
"bg-red-9 text-white col-12 row items-center q-px-md q-py-sm": !val,
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
.q-card.cardImg:hover {
|
||||
border: 1px solid #02a998 !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue