Files
FE_CPONE/test/vuex/cpone-nonlab-upload-document/index.php
2026-04-27 10:13:31 +07:00

735 lines
35 KiB
PHP

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>CPONE</title>
<link rel="stylesheet" href="../../../libs/vendor/css/google-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/icomoon-fonts.css">
<link rel="stylesheet" href="../../../libs/vendor/css/vuetify.min.css">
</head>
<body>
<div v-cloak id="app">
<v-app id="smartApp">
<v-snackbar color="success" v-model="snackbarSuccess" right="right" :timeout="3000" top="top">
{{ successMsg }}
<v-btn color="white" flat @click="snackbarSuccess = false"> Close </v-btn>
</v-snackbar>
<v-snackbar color="error" v-model="snackbarError" right="right" :timeout="3000" top="top">
{{ errorMsg }}
<v-btn color="white" flat @click="snackbarError = false"> Close </v-btn>
</v-snackbar>
<v-dialog persistent v-model="dialogUpload" width="90%">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
Upload Dokumen
</v-card-title>
<v-card-text>
<v-progress-linear v-if="uploadLoading" :indeterminate="uploadLoading"></v-progress-linear>
<v-btn block :disabled="uploadLoading" color="blue-grey" class="white--text" @click='pickFile'>
Pilih Dokumen
<v-icon right dark>attach_file</v-icon>
</v-btn>
<!-- <v-text-field label=" Pilih Gambar" hide-details @click='pickFile' v-model='filesData' prepend-icon='attach_file' class="mt-2"></v-text-field> -->
<input type="file" style="display: none" ref="image" accept=".doc, .docx, .pdf, .xls, .xlsx, image/*" :value="filesData" multiple @change="onFilePicked">
<fieldset v-if="selectedFile.length > 0">
<legend class="px-3">
{{ selectedFile.length }} item terpilih
</legend>
<v-layout row wrap class="pa-2 text-wrap">
<!-- <v-btn small color="primary" v-for="(data, index) in selectedFile" :key="index" class="mr-2" dark>
<p class="text-truncate">{{ data.imageName }}</p>
</v-btn> -->
<v-chip v-for="(data, index) in selectedFile" @input="removeFile(data.imageName)" close :key="index" class="mr-2 text-truncate">
{{ data.imageName }}
</v-chip>
</v-layout>
</fieldset>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" :disabled="uploadLoading" flat @click="dialogUpload = false">
Tutup
</v-btn>
<v-btn color="primary" :disabled="uploadLoading" flat @click="uploadData()">
Simpan
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-dialog v-model="dialogPreview" width="90%">
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
Dokumen
</v-card-title>
<v-card-text>
<v-layout column wrap class="pa-2 text-wrap">
<P v-if="filePathList.length===0">Belum ada dokumen yang di upload</P>
<div v-for="(data, index) in filePathList">
<p class="mb-0 pb-0 font-weight-bold subheading text-wrap">{{ data.file }}</p>
<v-btn color="blue-grey" class="white--text" @click="download(data.file)">
Download
<v-icon class="ml-2" left dark>cloud_download</v-icon>
</v-btn>
<v-btn color="error" class="white--text" @click="deleteFile(data)">
Hapus
<v-icon class="ml-2" left dark>delete</v-icon>
</v-btn>
<!-- <v-chip @click="download(data.file)" :key="index" class="mr-2 text-truncate">
{{ data.file }}
</v-chip> -->
<img v-if="!['doc','docx','xls','xlsx','pdf'].includes(data.type)" width="100%" class="mb-2" height="400px" style="object-fit: cover;" :src="getDataPath(data.file)" alt="Dinosaur" />
<object v-if="['pdf'].includes(data.type)" :data="getDataPath(data.file)" class="mb-2" width="100%" height="300"></object>
<!-- <iframe v-if="data.type !== 'pdf'" width="100%" height="300" class="mb-2" :src="getDataPathNonPdf(data.file)"></iframe> -->
<iframe v-if="['doc','docx','xls','xlsx'].includes(data.type)" width="100%" height="300" class="mb-2" :src="getDataPathNonPdf(data.file)"></iframe>
</div>
</v-layout>
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error" flat @click="dialogPreview = false">
Tutup
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<one-navbar></one-navbar>
<v-dialog v-model="status_selesai" max-width="290" persistent>
<v-card>
<v-card-title class="headline">Selamat !</v-card-title>
<v-card-text>
Anda telah selesai melakukan seluruh pemeriksaan medical check up, silahkan mengisi survey
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="primary darken-1" flat="flat" @click="goToSurvey()">
Klik untuk isi surve
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-content style="background:#F5E8DF!important">
<v-container fluid>
<template>
<div id="e3" style="max-width: 400px; margin:auto" class="grey lighten-3">
<v-toolbar>
<v-btn icon>
<v-icon>assignment</v-icon>
</v-btn>
<v-toolbar-title>Upload Dokumen</v-toolbar-title>
<v-spacer></v-spacer>
<!--<v-btn icon>
<v-icon>search</v-icon>
</v-btn>-->
</v-toolbar>
<v-card>
<v-container fluid grid-list-lg>
<v-layout row wrap>
<v-flex xs12>
<!-- <v-card flat class="pb-4">
<v-img class="mt-2" :src="photo_qr" height="115px" contain></v-img>
</v-card> -->
<v-card color="primary" class="white--text">
<v-layout row>
<v-flex xs7>
<v-card-title primary-title>
<div>
<div class="headline mb-1">{{data_patient.labnumber}}</div>
<p class="mb-0">{{data_patient.patient_name}} <span v-if="data_patient.nip">/ {{data_patient.nip}}</span></p>
<p class="mb-0 caption">{{data_patient.patient_age}}</p>
<!--<div class="caption">{{data_patient.order_date}}</div>-->
<p class="mb-0 caption font-weight-bold">{{data_patient.corporate_name}}</p>
</div>
</v-card-title>
</v-flex>
<v-flex xs5>
<v-img class="mt-2" :src="data_patient.photo" height="115px" contain></v-img>
</v-flex>
</v-layout>
<v-divider light></v-divider>
<v-card-actions class="pa-3">
{{data_patient.gender}}
<v-spacer></v-spacer>
<p class="mb-0">{{data_patient.dob}}</p>
</v-card-actions>
</v-card>
<v-list class="mt-4" subheader>
<v-subheader>Pemeriksaan</v-subheader>
<v-list-group v-if="data_packet.length > 0" v-for="item in data_packet" :key="item.packet_name" v-model="item.active" :prepend-icon="item.action" no-action>
<template v-slot:activator>
<v-list-tile>
<v-list-tile-content>
<v-list-tile-title>{{ item.packet_name }}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</template>
<v-list-tile v-for="subItem in item.details" :key="subItem.test_name" @click="">
<v-list-tile-content>
<v-list-tile-title>{{ subItem.test_name }}</v-list-tile-title>
</v-list-tile-content>
<v-list-tile-action>
<v-icon>{{ subItem.action }}</v-icon>
</v-list-tile-action>
</v-list-tile>
</v-list-group>
<v-card v-if="data_tests.length > 0" flat>
<v-form>
<v-text-field v-for="(test,k_test) in data_tests" :key="test.test_name" label="" prepend-inner-icon="label_important" :value="test.test_name" single-line full-width hide-details></v-text-field>
<v-divider v-if="k_test <= data.tests.length - 1"></v-divider>
</v-form>
</v-card>
</v-list>
<v-subheader>Pemeriksaan / Pengambilan Sample</v-subheader>
<!--<v-subheader v-if="data_sample_lab.length > 0" inset>Laboratorium</v-subheader>-->
<!-- <v-list-tile v-if="data_sample_lab.length > 0" v-for="sample in data_sample_lab" :key="sample.barcode" avatar @click="" three-line class="mb-2">
<v-list-tile-avatar>
<v-icon class="blue white--text">colorize</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title>{{ sample.sampletype_name }}</v-list-tile-title>
<v-list-tile-sub-title class="font-weight-bold">{{sample.staff_name}}</v-list-tile-sub-title>
<v-list-tile-sub-title class="caption">{{ sample.receive_date }} {{ sample.receive_time }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple>
<v-icon v-if="sample.is_sampling == 'N' || sample.is_received == 'N'" color="grey lighten-1">info</v-icon>
<v-icon v-if="sample.is_sampling == 'Y' && sample.is_received == 'Y'" color="success lighten-1">check_circle</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile> -->
<!--<v-subheader v-if="data_sample_radiodiagnostic.length > 0" inset>Radiodiagnostik</v-subheader>-->
<v-list-tile v-if="data_sample_radiodiagnostic.length > 0" v-for="sample in data_sample_radiodiagnostic" :key="sample.barcode" avatar three-line class="mb-2">
<v-list-tile-avatar @click="openDialogUpload(sample)">
<v-icon class="amber white--text">assignment_ind</v-icon>
</v-list-tile-avatar>
<v-list-tile-content @click="openDialogUpload(sample)">
<v-list-tile-title>{{ sample.sampletype_name }}</v-list-tile-title>
<v-list-tile-sub-title class="font-weight-bold">{{sample.staff_name}}</v-list-tile-sub-title>
<v-list-tile-sub-title class="caption">{{ sample.receive_date }} {{ sample.receive_time }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple @click="openDialogPreview(sample)">
<v-icon v-if="sample.is_sampling == 'N' || sample.is_received == 'N'" color="grey lighten-1">info</v-icon>
<v-icon v-if="sample.is_sampling == 'Y' && sample.is_received == 'Y'" color="success lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile>
<!--<v-subheader v-if="data_sample_electromedic.length > 0" inset>Elektromedik</v-subheader>-->
<v-list-tile v-if="data_sample_electromedic.length > 0" v-for="sample in data_sample_electromedic" :key="sample.barcode" avatar three-line class="mb-2">
<v-list-tile-avatar @click="openDialogUpload(sample)">
<v-icon class="teal white--text">contacts</v-icon>
</v-list-tile-avatar>
<v-list-tile-content @click="openDialogUpload(sample)">
<v-list-tile-title>{{ sample.sampletype_name }}</v-list-tile-title>
<v-list-tile-sub-title class="font-weight-bold">{{sample.staff_name}}</v-list-tile-sub-title>
<v-list-tile-sub-title class="caption">{{ sample.receive_date }} {{ sample.receive_time }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple @click="openDialogPreview(sample)">
<v-icon v-if="sample.is_sampling == 'N' || sample.is_received == 'N'" color="grey lighten-1">info</v-icon>
<v-icon v-if="sample.is_sampling == 'Y' && sample.is_received == 'Y'" color="success lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile>
<v-list-tile v-if="data_sample_other.length > 0" v-for="sample in data_sample_other" :key="sample.barcode" avatar three-line class="mb-2">
<v-list-tile-avatar @click="openDialogUpload(sample)">
<v-icon class="teal white--text">contacts</v-icon>
</v-list-tile-avatar>
<v-list-tile-content @click="openDialogUpload(sample)">
<v-list-tile-title>{{ sample.sampletype_name }}</v-list-tile-title>
<v-list-tile-sub-title class="font-weight-bold">{{sample.staff_name}}</v-list-tile-sub-title>
<v-list-tile-sub-title class="caption">{{ sample.receive_date }} {{ sample.receive_time }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple @click="openDialogPreview(sample)">
<v-icon v-if="sample.is_sampling == 'N' || sample.is_received == 'N'" color="grey lighten-1">info</v-icon>
<v-icon v-if="sample.is_sampling == 'Y' && sample.is_received == 'Y'" color="success lighten-1">info</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile>
<!--<v-subheader v-if="data_sample_other.length > 0" inset>Layanan Klinik</v-subheader>-->
<!-- <v-list-tile v-if="data_sample_other.length > 0" v-for="sample in data_sample_other" :key="sample.barcode" avatar @click="" three-line class="mb-2">
<v-list-tile-avatar>
<v-icon class="orange darken-2 white--text">accessibility</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title>{{ sample.sampletype_name }}</v-list-tile-title>
<v-list-tile-sub-title class="font-weight-bold">{{sample.staff_name}}</v-list-tile-sub-title>
<v-list-tile-sub-title class="caption">{{ sample.receive_date }} {{ sample.receive_time }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple>
<v-icon v-if="sample.is_sampling == 'N' || sample.is_received == 'N'" color="grey lighten-1">info</v-icon>
<v-icon v-if="sample.is_sampling == 'Y' && sample.is_received == 'Y'" color="success lighten-1">check_circle</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile> -->
<!-- <v-list-tile avatar @click="goToSurvey()">
<v-list-tile-avatar>
<v-icon class="purple darken-2 white--text">assignment</v-icon>
</v-list-tile-avatar>
<v-list-tile-content>
<v-list-tile-title>{{ data_survey.sampletype_name }}</v-list-tile-title>
<v-list-tile-sub-title>{{ data_survey.receive_date }} {{ data_survey.receive_time }}</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-action>
<v-btn icon ripple>
<v-icon v-if="data_survey.is_sampling == 'N' || data_survey.is_received == 'N'" color="grey lighten-1">info</v-icon>
<v-icon v-if="data_survey.is_sampling == 'Y' && data_survey.is_received == 'Y'" color="success lighten-1">check_circle</v-icon>
</v-btn>
</v-list-tile-action>
</v-list-tile> -->
</v-list>
</v-flex>
</v-layout>
</v-container>
</v-card>
<v-card class="mt-1 pt-1 pa-2">
<v-btn block color="primary" @click="openscanner()">
Refresh
</v-btn>
<qr-scanner></qr-scanner>
</v-card>
</div>
</template>
</v-container>
</v-content>
<one-footer> </one-footer>
</v-app>
</div>
<!-- Vendor -->
<script src="../../../libs/vendor/html5-qrcode.min.js"></script>
<script src="../../../libs/vendor/moment.min.js"></script>
<script src="../../../libs/vendor/numeral.min.js"></script>
<script src="../../../libs/vendor/moment-locale-id.js"></script>
<script src="../../../libs/vendor/lodash.js"></script>
<script src="../../../libs/vendor/axios.min.js"></script>
<script src="../../../libs/vendor/vue.js"></script>
<script src="../../../libs/vendor/vuex.js"></script>
<script src="../../../libs/vendor/vuetify.js"></script>
<script src="../../../libs/vendor/httpVueLoader.js"></script>
<script src="../../../libs/one_global.js"></script>
<script src="../../../libs/one_print_barcode.js"></script>
<script src="../../../libs/one_print_robo.js"></script>
<!-- App Script -->
<?php
$ts = "?ts=" . Date("ymdhis");
?>
<script type="module">
window.calculate_age = function(inp_dob) {
var now = moment(new Date())
var dob = moment(new Date(inp_dob))
var year = now.diff(dob, 'years')
dob.add(year, 'years')
var month = now.diff(dob, 'months')
dob.add(month, 'months')
var day = now.diff(dob, 'days')
if (isNaN(year)) return ''
return `${year} tahun ${month} bulan ${day} hari`
}
import {
store
} from './store.js<?php echo $ts ?>';
//for testing
window.store = store;
new Vue({
store,
el: '#app',
components: {
'one-navbar': httpVueLoader('../../../apps/components/oneNavbarComponent.vue'),
'one-footer': httpVueLoader('../../../apps/components/oneFooter.vue'),
'one-patient-list': httpVueLoader('./components/onePatientList.vue'),
'qr-scanner': httpVueLoader('./components/oneQRscanner.vue')
},
mounted: function() {
var url_string = window.location.href
var url = new URL(url_string);
var id = url.searchParams.get("id");
var noreg = url.searchParams.get("noreg");
this.$store.commit('patient/update_order_id', id)
this.$store.commit('patient/update_noreg', noreg)
this.$store.dispatch('patient/load_data')
},
methods: {
deleteFile(data) {
let a = confirm("Apakah anda yakin menghapus dokumen" + data.file + " ?");
if (a) {
this.$store.dispatch('patient/deleteFile', data.documentID)
}
},
downloadFile(fileName) {
fetch(`download.php?file=${fileName}`)
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.blob();
})
.then(blob => {
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', fileName);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch(error => {
console.error('Error downloading file:', error);
});
},
download(name) {
// window.open("/one-api/mockup/cpone-nonlab-upload-document/patient/downloadfile/" + name, '_self')
// window.location = "/one-api/mockup/cpone-nonlab-upload-document/patient/downloadfile/" + name;
// `/one-api/mockup/cpone-nonlab-upload-document/patient/downloadfile/${name}`
fetch(this.filePath + name)
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.blob();
})
.then(blob => {
const url = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', name);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})
.catch(error => {
console.error('Error downloading file:', error);
});
},
getDataPath(name) {
return this.filePath + name;
},
getDataPathNonPdf(name) {
let link = window.location.protocol + "//" + window.location.hostname + this.filePath + name
let link2 = " https://view.officeapps.live.com/op/embed.aspx?src=" + link
return link2
// return "https://docs.google.com/viewer?url=" + link + "&embedded=true"
},
uploadData() {
this.$store.dispatch('patient/uploadDocument')
},
getBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
},
openDialogUpload(val) {
if (parseInt(val.soID) == 0) return;
this.selectedTest = val;
this.selectedFile = [];
this.dialogUpload = true;
},
openDialogPreview(val) {
if (parseInt(val.soID) == 0) return;
this.selectedTest = val;
this.$store.dispatch('patient/getdocument')
this.selectedFile = [];
this.dialogPreview = true;
},
removeFile(name) {
if (this.uploadLoading) return;
for (let i = 0; i < this.selectedFile.length; i++) {
const e = this.selectedFile[i];
if (e.imageName === name) {
this.selectedFile.splice(i, 1);
}
}
},
pickFile() {
this.$refs.image.click()
},
async onFilePicked(e) {
let a = [];
const files = e.target.files
console.log(files);
let validation = []
for (let i = 0; i < files.length; i++) {
const e = files[i];
let fileSize = (e.size / 1024 / 1024);
if (fileSize > 3) {
validation.push(e.name);
continue;
}
console.log(e);
let data = {}
data.imageName = e.name
if (data.imageName.lastIndexOf('.') <= 0) {
return
}
data.base64 = await this.getBase64(e);
console.log(data.base64);
data.imageFile = e // this is an image file that can be sent to server...
a.push(data);
}
this.selectedFile = a;
if (validation.length > 0) {
alert("File " + validation.join(", ") + " berukuran lebih besar dari 3 MB");
}
// if (files[0] !== undefined) {
// this.imageName = files[0].name
// if (this.imageName.lastIndexOf('.') <= 0) {
// return
// }
// const fr = new FileReader()
// fr.readAsDataURL(files[0])
// fr.addEventListener('load', () => {
// this.imageUrl = fr.result
// this.imageFile = files[0] // this is an image file that can be sent to server...
// })
// } else {
// this.imageName = ''
// this.imageFile = ''
// this.imageUrl = ''
// }
},
goToSurvey: function() {
console.log('aloha')
let order_id = this.$store.state.patient.order_id
let noreg = this.$store.state.patient.noreg
window.location = "/one-ui/test/vuex/cpone-control-card-survey/?noreg=" + noreg + "&id=" + order_id
},
openscanner() {
//this.dialog_scanner = true
location.reload()
}
},
computed: {
dialogUpload: {
get() {
return this.$store.state.patient.dialogUpload
},
set(val) {
this.$store.commit("patient/update_dialogUpload", val)
}
},
successMsg: {
get() {
return this.$store.state.patient.successMsg;
},
set(val) {
this.$store.commit("patient/update_successMsg", val);
},
},
errorMsg: {
get() {
return this.$store.state.patient.errorMsg;
},
set(val) {
this.$store.commit("patient/update_errorMsg", val);
},
},
snackbarError: {
get() {
return this.$store.state.patient.snackbarError;
},
set(val) {
this.$store.commit("patient/update_snackbarError", val);
},
},
snackbarSuccess: {
get() {
return this.$store.state.patient.snackbarSuccess;
},
set(val) {
this.$store.commit("patient/update_snackbarSuccess", val);
},
},
selectedFile: {
get() {
return this.$store.state.patient.selectedFile
},
set(val) {
this.$store.commit("patient/update_selectedFile", val)
}
},
dialogPreview: {
get() {
return this.$store.state.patient.dialogPreview
},
set(val) {
this.$store.commit("patient/update_dialogPreview", val)
}
},
uploadLoading() {
return this.$store.state.patient.uploadLoading
},
photo_qr() {
return this.$store.state.patient.photo_qr
},
status_selesai() {
return this.$store.state.patient.status_selesai
},
filePath() {
return this.$store.state.patient.filePath
},
filePathList() {
return this.$store.state.patient.filePathList
},
dialog_scanner: {
get() {
return this.$store.state.patient.dialog_scanner
},
set(val) {
this.$store.commit("patient/update_dialog_scanner", val)
}
},
selectedTest: {
get() {
return this.$store.state.patient.selectedTest
},
set(val) {
this.$store.commit("patient/update_selectedTest", val)
}
},
data_patient() {
return this.$store.state.patient.data_patient
},
data_packet() {
return this.$store.state.patient.data_packet
},
data_tests() {
return this.$store.state.patient.data_tests
},
data_sample_lab() {
return this.$store.state.patient.data_sample_lab
},
data_sample_radiodiagnostic() {
return this.$store.state.patient.data_sample_radiodiagnostic
},
data_sample_electromedic() {
return this.$store.state.patient.data_sample_electromedic
},
data_sample_other() {
return this.$store.state.patient.data_sample_other
},
data_survey() {
return this.$store.state.patient.data_survey
},
},
data() {
return {
filesData: [],
items2: [{
icon: 'assignment',
iconClass: 'blue white--text',
title: 'Vacation itinerary',
subtitle: 'Jan 20, 2014'
},
{
icon: 'call_to_action',
iconClass: 'amber white--text',
title: 'Kitchen remodel',
subtitle: 'Jan 10, 2014'
}
],
items: [{
action: 'healing',
title: 'Paket Pria 2024',
items: [{
title: 'List Item'
},
{
title: 'List Item'
},
{
title: 'List Item'
}
]
}]
}
}
})
</script>
<style>
[v-cloak] {
display: none
}
.left {}
.right {}
</style>
</body>
</html>