Initial commit
This commit is contained in:
84
app/components/people/People.vue
Normal file
84
app/components/people/People.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<div class="columns mx-0 px-0 py-2">
|
||||
<div
|
||||
:class="`column is-narrow ${viewport === 1 ? 'px-0' : ''}`"
|
||||
:style="`${viewport === 1 ? '' : 'border-right: 1px solid #B0B0B0;'}`"
|
||||
>
|
||||
<template v-if="viewport > 1">
|
||||
<div
|
||||
v-for="(v, i) in tabs"
|
||||
:class="['is-clickable py-3 px-3', i !== 0 && 'mt-2', getStyle(v)]"
|
||||
style="width: 130px; border-radius: 4px"
|
||||
@click="changeTab(v)"
|
||||
>
|
||||
{{ v.name }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="field is-grouped is-grouped-multiline" v-else>
|
||||
<div class="control" v-for="(v, i) in tabs" :key="i" @click="changeTab(v)">
|
||||
<div style="width: 110px">
|
||||
<div :class="`py-3 px-3 ${getStyle(v)}`">{{ v.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column">
|
||||
<PeopleInfo
|
||||
v-if="tab === 'info' && record !== undefined"
|
||||
v-bind="{ row: record, pagename }"
|
||||
@update="update"
|
||||
></PeopleInfo>
|
||||
<template v-if="record">
|
||||
<ImageGallery
|
||||
v-if="tab === 'image'"
|
||||
v-bind="{ row: record, pagename, api: 'peoplefile', show: ['delete'] }"
|
||||
@update="update"
|
||||
></ImageGallery>
|
||||
</template>
|
||||
<PeopleView v-bind="{ row: record, pagename }" v-if="tab === 'summary'" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import PeopleInfo from "~/components/people/PeopleInfo";
|
||||
const { $dialog } = useNuxtApp()
|
||||
const props = defineProps({
|
||||
pagename: String,
|
||||
row: Object,
|
||||
});
|
||||
const emit = defineEmits(["modalevent", "close"]);
|
||||
const viewport = 5;
|
||||
const tabs = [
|
||||
{ code: "info", name: "1. Thông tin" },
|
||||
{ code: "image", name: "2. Hình ảnh" },
|
||||
{ code: "summary", name: "3. Bản in" },
|
||||
];
|
||||
const tab = ref("info");
|
||||
const record = ref(props.row || null);
|
||||
function getStyle(v) {
|
||||
let check = record.value ? record.value.id : false;
|
||||
if (v.tab === "info") check = true;
|
||||
return v.code === tab.value
|
||||
? "has-background-primary has-text-white"
|
||||
: `has-background-light ${check ? "" : "has-text-grey"}`;
|
||||
}
|
||||
function changeTab(v) {
|
||||
if (tab.value === v.code) return;
|
||||
if (!record.value)
|
||||
return $dialog(
|
||||
"Vui lòng <b>lưu dữ liệu</b> trước khi chuyển sang mục tiếp theo",
|
||||
"Thông báo"
|
||||
);
|
||||
|
||||
tab.value = v.code;
|
||||
}
|
||||
function update(v) {
|
||||
record.value = {
|
||||
...v,
|
||||
label: `${v.code} / ${v.fullname} / ${v.phone || ""}`
|
||||
}
|
||||
|
||||
emit("modalevent", { name: "dataevent", data: record.value });
|
||||
if (!props.row) emit("close");
|
||||
}
|
||||
</script>
|
||||
230
app/components/people/PeopleInfo.vue
Normal file
230
app/components/people/PeopleInfo.vue
Normal file
@@ -0,0 +1,230 @@
|
||||
<template>
|
||||
<div v-if="record">
|
||||
<div class="columns is-multiline mx-0 is-2">
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang('code') }}<b class="ml-1 has-text-danger">*</b></label>
|
||||
<div class="control">
|
||||
<input class="input has-text-black" disabled type="text" placeholder="" v-model="record.code">
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.code">{{ errors.code }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang('name') }}<b class="ml-1 has-text-danger">*</b></label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="" v-model="record.fullname">
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.fullname">{{ errors.fullname }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">Điện thoại<b class="ml-1 has-text-danger">*</b></label>
|
||||
<div class="control">
|
||||
<InputPhone v-bind="{ record: record, attr: 'phone', placeholder: '' }" @phone="selected('phone', $event)">
|
||||
</InputPhone>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.phone">{{ errors.phone }}
|
||||
<a class="has-text-primary" v-if="existedPeople" @click="showPeople()">Chi tiết</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">Email</label>
|
||||
<div class="control">
|
||||
<InputEmail v-bind="{ record: record, attr: 'email', placeholder: '' }" @email="selected('email', $event)">
|
||||
</InputEmail>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.email">{{ errors.email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang('gender') }}</label>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{ vdata: store.sex, api: 'sex', field: 'name', column: ['name'], first: true, optionid: record.sex }"
|
||||
@option="selected('_sex', $event)"></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang('dob') }}</label>
|
||||
<div class="control">
|
||||
<Datepicker v-bind="{ record: record, attr: 'dob', maxdate: new Date(), position: 'is-bottom-left' }"
|
||||
@date="selected('dob', $event)"></Datepicker>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.dob">{{ errors.dob }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-6">
|
||||
<div class="field">
|
||||
<label class="label">Địa chỉ liên hệ</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="" v-model="record.address" />
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.address"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-6">
|
||||
<div class="field">
|
||||
<label class="label">Địa chỉ thường trú</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="" v-model="record.contact_address" />
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.contact_address"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang('personal_id') }}</label>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{ api: 'legaltype', field: 'name', column: ['name'], first: true, optionid: record.legal_type, filter: { code__in: ['CCCD', 'CC'] } }"
|
||||
@option="selected('_legal_type', $event)"></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang('idnum') }}</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="" v-model="record.legal_code">
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.legal_code"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang('issued_date') }}</label>
|
||||
<div class="control">
|
||||
<Datepicker v-bind="{ record: record, attr: 'issued_date', maxdate: new Date(), position: 'is-top-left' }"
|
||||
@date="selected('issued_date', $event)"></Datepicker>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.issued_date">{{ errors.issued_date }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang('issued_place') }}</label>
|
||||
<div class="control">
|
||||
<SearchBox v-bind="{
|
||||
api: 'issuedplace',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
optionid: record.issued_place,
|
||||
filter: { code__in: ['BCA', 'XNC'] } // Bộ Công an, Cục Cảnh sát QLHC về TTXH
|
||||
}" @option="selected('_issued_place', $event)"></SearchBox>
|
||||
</div>
|
||||
<p class="help is-danger" v-if="errors.issued_place"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
<button class="button is-primary has-text-white" @click="update()">{{ findLang('save') }}</button>
|
||||
</div>
|
||||
<Modal @close="showmodal = undefined" v-bind="showmodal" v-if="showmodal"></Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import InputPhone from '~/components/common/InputPhone'
|
||||
import InputEmail from '~/components/common/InputEmail'
|
||||
import SearchBox from '~/components/SearchBox'
|
||||
import Datepicker from '~/components/datepicker/Datepicker'
|
||||
|
||||
import { useStore } from '~/stores/index'
|
||||
var props = defineProps({
|
||||
pagename: String,
|
||||
row: Object
|
||||
})
|
||||
const store = useStore()
|
||||
const { $find, $getdata, $updateapi, $findapi, $getapi, $empty, $errPhone, $errEmail, $resetNull, $snackbar, $insertapi, $updatepage } = useNuxtApp()
|
||||
const emit = defineEmits(['update'])
|
||||
var viewport = store.viewport
|
||||
var companyAddon = { component: 'customer/Company', with: '55%', height: '400px', title: findLang('company') }
|
||||
var companyviewAddon = { component: 'customer/Company', width: '50%', height: '400px', title: findLang('company') }
|
||||
var errors = ref({})
|
||||
var record = ref()
|
||||
var showmodal = ref()
|
||||
var existedPeople = undefined
|
||||
async function initData() {
|
||||
if (props.row) {
|
||||
let conn = $findapi('people')
|
||||
conn.params.filter = { id: props.row.customer || props.row.id }
|
||||
let rs = await $getapi([conn])
|
||||
let found = $find(rs, { name: 'people' })
|
||||
if (found.data.rows.length > 0) record.value = found.data.rows[0]
|
||||
} else {
|
||||
// let code = await $getdata('getcodepeople')
|
||||
record.value = {}
|
||||
}
|
||||
}
|
||||
function findLang(code) {
|
||||
let found = $find(store.common, { code: code })
|
||||
return found ? found[store.lang] : ''
|
||||
}
|
||||
function showPeople() {
|
||||
showmodal.value = {
|
||||
component: 'people/PeopleView', width: '60%', height: '600px', title: 'Người liên quan',
|
||||
vbind: { row: existedPeople }
|
||||
}
|
||||
}
|
||||
function selected(attr, obj) {
|
||||
record.value[attr] = obj
|
||||
if (obj === null) record.value[attr.replace('_', '')] = null
|
||||
}
|
||||
function checkError() {
|
||||
existedPeople = undefined
|
||||
errors.value = {}
|
||||
if ($empty(record.value.fullname)) errors.value.fullname = 'Họ tên không được bỏ trống'
|
||||
|
||||
const errPhone = $errPhone(record.value.phone)
|
||||
if (errPhone) errors.value.phone = errPhone
|
||||
|
||||
return Object.keys(errors.value).length > 0
|
||||
}
|
||||
async function update() {
|
||||
if (checkError()) return
|
||||
if (!record.value.id) {
|
||||
if (record.value.phone) {
|
||||
record.value.phone = record.value.phone.trim()
|
||||
let obj = await $getdata('people', { phone: record.value.phone }, undefined, true)
|
||||
if (obj) {
|
||||
existedPeople = obj
|
||||
errors.value.phone = 'Số điện thoại đã tồn tại.'
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
record.value = $resetNull(record.value)
|
||||
if (record.value._province) record.value.province = record.value._province.id
|
||||
if (record.value._company) record.value.company = record.value._company.id
|
||||
if (record.value._country) record.value.country = record.value._country.id
|
||||
if (record.value._sex) record.value.sex = record.value._sex.id
|
||||
if (record.value._legal_type) record.value.legal_type = record.value._legal_type.id
|
||||
if (record.value._issued_place) record.value.issued_place = record.value._issued_place.id
|
||||
if (!record.value.creator) record.value.creator = store.login.id
|
||||
record.value.updater = store.login.id
|
||||
record.value.updater_time = new Date()
|
||||
let rs = record.value.id ? await $updateapi('people', record.value)
|
||||
: await $insertapi('people', record.value, undefined, false)
|
||||
if (rs === 'error') return
|
||||
if (!record.value.id) $snackbar(`Người liên quan đã được khởi tạo với mã <b>${rs.code}</b>`, 'Thành công', 'Success')
|
||||
record.value.id = rs.id
|
||||
if (record.value.image ? record.value.image.length > 0 : false) {
|
||||
let arr = []
|
||||
record.image.map(v => arr.push({ ref: record.value.id, file: v }))
|
||||
await $insertapi('customerfile', arr, undefined, false)
|
||||
}
|
||||
let ele = await $getdata('people', { id: rs.id }, undefined, true)
|
||||
emit('update', ele)
|
||||
emit('modalevent', { name: 'dataevent', data: ele })
|
||||
if (props.pagename) $updatepage(props.pagename, ele)
|
||||
}
|
||||
initData()
|
||||
</script>
|
||||
217
app/components/people/PeopleView.vue
Normal file
217
app/components/people/PeopleView.vue
Normal file
@@ -0,0 +1,217 @@
|
||||
<template>
|
||||
<div :id="docid" v-if="record">
|
||||
<div>
|
||||
<Caption
|
||||
v-bind="{
|
||||
title: store.lang === 'en' ? 'Information' : 'Thông tin',
|
||||
type: 'has-text-primary',
|
||||
}"
|
||||
></Caption>
|
||||
<div class="columns is-multiline mx-0">
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">Mã</label>
|
||||
<div class="control">
|
||||
<span class="hyperlink" @click="$copyToClipboard(record.code)">{{
|
||||
record.code
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">Họ tên</label>
|
||||
<div class="control">{{ record.fullname }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">Điện thoại</label>
|
||||
<div class="control">
|
||||
<span class="hyperlink" @click="openPhone()">{{ record.phone }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">Email</label>
|
||||
<div class="control" style="word-break: break-all">
|
||||
{{ record.email || "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang("country") }}</label>
|
||||
<div class="control">
|
||||
{{ record.country__name || "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">Địa chỉ thường trú</label>
|
||||
<div class="control">
|
||||
{{ record.address || "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">Địa chỉ liên hệ</label>
|
||||
<div class="control">
|
||||
{{ record.contact_address || "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang("dob") }}</label>
|
||||
<div class="control">
|
||||
{{ record.dob ? $dayjs(record.dob).format("DD/MM/YYYY") : "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang("gender") }}</label>
|
||||
<div class="control">
|
||||
{{ record.sex__name || "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang("personal_id") }}</label>
|
||||
<div class="control">
|
||||
{{ record.legal_type__name || "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang("idnum") }}</label>
|
||||
<div class="control">
|
||||
{{ record.legal_code || "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang("issued_date") }}</label>
|
||||
<div class="control">
|
||||
{{ record.issued_date ? $dayjs(record.issued_date).format("DD/MM/YYYY") : "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang("issued_place") }}</label>
|
||||
<div class="control">
|
||||
{{ record.issued_place__name || "/" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column is-3 pb-1 px-0">
|
||||
<div class="field">
|
||||
<label class="label">{{ findLang("update") }}</label>
|
||||
<div class="control">
|
||||
<span class="hyperlink" @click="openUser()">
|
||||
{{ record.updater__fullname }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Caption
|
||||
class="mt-5"
|
||||
v-bind="{
|
||||
title: store.lang === 'en' ? 'Images' : 'Hình ảnh',
|
||||
type: 'has-text-primary',
|
||||
}"
|
||||
></Caption>
|
||||
<ImageGallery
|
||||
v-bind="{ row: record, api: 'peoplefile', hideopt: true }"
|
||||
></ImageGallery>
|
||||
<div class="mt-2 border-bottom" id="ignore"></div>
|
||||
<div class="buttons mt-3" id="ignore">
|
||||
<button v-if="$getEditRights('edit', { code: 'customer', category: 'topmenu' })" class="button is-primary has-text-white" @click="edit()">
|
||||
Chỉnh sửa
|
||||
</button>
|
||||
<button
|
||||
class="button is-light has-text-black"
|
||||
@click="$exportpdf(docid, record.code)"
|
||||
>
|
||||
{{ findLang("print") }}
|
||||
</button>
|
||||
</div>
|
||||
<Modal
|
||||
@close="showmodal = undefined"
|
||||
v-bind="showmodal"
|
||||
@dataevent="changeInfo"
|
||||
v-if="showmodal"
|
||||
></Modal>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { useStore } from "~/stores/index";
|
||||
export default {
|
||||
setup() {
|
||||
const store = useStore();
|
||||
return { store };
|
||||
},
|
||||
props: ["row", "pagename", "noheader"],
|
||||
data() {
|
||||
return {
|
||||
record: undefined,
|
||||
errors: {},
|
||||
showmodal: undefined,
|
||||
docid: this.$id(),
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
this.record = await this.$getdata(
|
||||
"people",
|
||||
{ id: this.row.people || this.row.id },
|
||||
undefined,
|
||||
true
|
||||
);
|
||||
},
|
||||
methods: {
|
||||
findLang(code) {
|
||||
let found = this.$find(this.store.common, { code: code });
|
||||
return found ? found[this.store.lang] : "";
|
||||
},
|
||||
copy(value) {
|
||||
this.$copyToClipboard(value);
|
||||
this.$snackbar("Đã copy vào clipboard.", "Copy", "Success");
|
||||
},
|
||||
openPhone() {
|
||||
this.showmodal = {
|
||||
title: this.findLang("phone"),
|
||||
height: "180px",
|
||||
width: "400px",
|
||||
component: "common/Phone",
|
||||
vbind: { row: this.row, pagename: this.pagename },
|
||||
};
|
||||
},
|
||||
selected(attr, obj) {
|
||||
this.record[attr] = obj;
|
||||
},
|
||||
edit() {
|
||||
this.showmodal = {
|
||||
component: "people/People",
|
||||
title: "Chỉnh sửa người liên quan",
|
||||
width: '65%',
|
||||
height: '400px',
|
||||
vbind: { row: this.record },
|
||||
};
|
||||
},
|
||||
changeInfo(v) {
|
||||
this.record = this.$copy(v);
|
||||
},
|
||||
openUser() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user