394 lines
14 KiB
JavaScript
394 lines
14 KiB
JavaScript
import Vue from 'vue';
|
|
import { COMPANY } from '~/constants/company';
|
|
|
|
Vue.use({
|
|
install(Vue) {
|
|
Vue.prototype.$dialog = function (content, title, type, duration, width, height, vbind) {
|
|
if (typeof content == 'string') {
|
|
let vtitle = type === 'Success' ? `<span class="has-text-primary">${title}</span>` : title;
|
|
if (type === 'Error') vtitle = `<span class="has-text-danger">${title}</span>`;
|
|
let data = {
|
|
id: this.$id(),
|
|
component: `dialog/${type || 'Info'}`,
|
|
vbind: { content: content, duration: duration, vbind: vbind },
|
|
title: vtitle,
|
|
width: width || '500px',
|
|
height: height || '100px',
|
|
};
|
|
this.$store.commit('updateStore', { name: 'showmodal', data: data });
|
|
} else this.$store.commit('updateStore', { name: 'showmodal', data: content });
|
|
};
|
|
|
|
Vue.prototype.$snackbar = function (content, title, type, width, height) {
|
|
if (typeof content == 'string') {
|
|
let vtitle = type === 'Success' ? `<span class="has-text-primary">${title}</span>` : title;
|
|
if (type === 'Error') vtitle = `<span class="has-text-danger">${title}</span>`;
|
|
let data = {
|
|
id: this.$id(),
|
|
component: `snackbar/${type || 'Info'}`,
|
|
vbind: { content: content },
|
|
title: vtitle,
|
|
width: width || '400px',
|
|
height: height || '100px',
|
|
};
|
|
this.$store.commit('updateStore', { name: 'snackbar', data: data });
|
|
} else this.$store.commit('updateStore', { name: 'snackbar', data: content });
|
|
};
|
|
|
|
Vue.prototype.$pending = function () {
|
|
this.$dialog({
|
|
width: '500px',
|
|
icon: ' mdi mdi-wrench-clock',
|
|
content: '<p class="fs-16">Chức năng này đang được xây dựng, vui lòng trở lại sau</p>',
|
|
type: 'is-dark',
|
|
progress: true,
|
|
duration: 5,
|
|
});
|
|
};
|
|
|
|
Vue.prototype.$getLink = function (val) {
|
|
if (val === undefined || val === null || val === '' || val === '') return '';
|
|
let json = val.indexOf('{') >= 0 ? JSON.parse(val) : { path: val };
|
|
return json;
|
|
};
|
|
|
|
Vue.prototype.$timeFormat = function (startDate, endDate) {
|
|
let milliseconds = startDate - endDate;
|
|
let secs = Math.floor(Math.abs(milliseconds) / 1000);
|
|
let mins = Math.floor(secs / 60);
|
|
let hours = Math.floor(mins / 60);
|
|
let days = Math.floor(hours / 24);
|
|
const millisecs = Math.floor(Math.abs(milliseconds)) % 1000;
|
|
function pad2(n) {
|
|
return (n < 10 ? '0' : '') + n;
|
|
}
|
|
let display = undefined;
|
|
|
|
if (days >= 1) {
|
|
display =
|
|
pad2(startDate.getHours()) +
|
|
':' +
|
|
pad2(startDate.getMinutes()) +
|
|
' ' +
|
|
pad2(startDate.getDate()) +
|
|
'/' +
|
|
pad2(startDate.getMonth());
|
|
} else if (hours > 0) display = hours + 'h trước';
|
|
else if (mins > 0) display = mins + "' trước";
|
|
else if (secs > 0 || millisecs > 0) display = 'Vừa xong';
|
|
|
|
return {
|
|
days: days,
|
|
hours: hours % 24,
|
|
minutes: mins % 60,
|
|
seconds: secs % 60,
|
|
milliSeconds: millisecs,
|
|
display: display,
|
|
};
|
|
};
|
|
|
|
(Vue.prototype.$errPhone = function (phone) {
|
|
var text = undefined;
|
|
if (this.$empty(phone)) {
|
|
text = 'Số điện thoại di động không được bỏ trống.';
|
|
} else if (isNaN(phone)) {
|
|
text = 'Số điện thoại di động không hợp lệ.';
|
|
} else if (phone.length < 9 || phone.length > 11) {
|
|
text = 'Số điện thoại di động phải có từ 9-11 số.';
|
|
}
|
|
return text;
|
|
}),
|
|
(Vue.prototype.$errEmail = function (email) {
|
|
const re =
|
|
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
var text = undefined;
|
|
if (this.$empty(email)) {
|
|
text = 'Email không được bỏ trống.';
|
|
} else if (!re.test(String(email).toLowerCase())) {
|
|
text = 'Email không hợp lệ.';
|
|
}
|
|
return text;
|
|
});
|
|
|
|
Vue.prototype.$errPhoneEmail = function (contact) {
|
|
const re =
|
|
/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
|
var text = undefined;
|
|
|
|
if (this.$empty(contact)) {
|
|
text = 'Số điện thoại di động hoặc Email không được bỏ trống.';
|
|
} else if (!(re.test(String(contact).toLowerCase()) || !isNaN(contact))) {
|
|
text = 'Số điện thoại di động hoặc Email không hợp lệ.';
|
|
} else if (!isNaN(contact) && (contact.length < 9 || contact.length > 11)) {
|
|
text = 'Số điện thoại di động không hợp lệ.';
|
|
}
|
|
return text;
|
|
};
|
|
|
|
Vue.prototype.$dummy = function (data, count) {
|
|
let list = this.$copy(data);
|
|
for (let index = 0; index < count; index++) {
|
|
if (data.length < index + 1) list.push({ dummy: true });
|
|
}
|
|
return list;
|
|
};
|
|
|
|
Vue.prototype.$upload = function (file, type, user) {
|
|
var fileFormat = [
|
|
{ type: 'image', format: ['.png', '.jpg', 'jpeg', '.bmp', '.gif', '.svg'] },
|
|
{ type: 'video', format: ['.wmv', '.avi', '.mp4', '.flv', '.mov', '.mpg', '.amv', '.rm'] },
|
|
];
|
|
var valid = undefined;
|
|
if (type === 'image' || type === 'video') {
|
|
valid = false;
|
|
let found = fileFormat.find((v) => v.type === type);
|
|
found.format.map((x) => {
|
|
if (file.name.toLowerCase().indexOf(x) >= 0) valid = true;
|
|
});
|
|
}
|
|
|
|
if (valid === false) return { error: true, text: 'Định dạng file không hợp lệ' };
|
|
if ((type === 'image' || type === 'file') && file.size > 500 * 1024 * 1024) {
|
|
return { error: true, text: 'Kích thước ' + (type === 'image' ? 'hình ảnh' : 'tài liệu') + ' phải dưới 500MB' };
|
|
} else if (type === 'video' && file.size > 1073741274) {
|
|
return { error: true, text: 'Kích thước video phải dưới 1GB' };
|
|
}
|
|
|
|
let data = new FormData();
|
|
let fileName = this.$dayjs(new Date()).format('YYYYMMDDhhmmss') + '-' + file.name;
|
|
data.append('name', fileName);
|
|
data.append('file', file);
|
|
data.append('type', type);
|
|
data.append('size', file.size);
|
|
data.append('user', user);
|
|
return { form: data, name: fileName, type: type, size: file.size, file: file };
|
|
};
|
|
|
|
Vue.prototype.$change = function (obj1, obj2, list) {
|
|
var change = false;
|
|
if (list) {
|
|
list.map((v) => {
|
|
if (obj1[v] !== obj2[v]) change = true;
|
|
});
|
|
} else {
|
|
for (var k in obj1) {
|
|
if (obj1[k] !== obj2[k]) change = true;
|
|
}
|
|
}
|
|
return change;
|
|
};
|
|
|
|
Vue.prototype.$resetNull = function (obj) {
|
|
for (var key in obj) {
|
|
if (obj[key] === '' || obj[key] === '') obj[key] = null;
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
Vue.prototype.$responsiveMenu = function () {
|
|
// Get all "navbar-burger" elements
|
|
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
|
|
// Check if there are any navbar burgers
|
|
if ($navbarBurgers.length > 0) {
|
|
// Add a click event on each of them
|
|
$navbarBurgers.forEach((el) => {
|
|
// Get the target from the "data-target" attribute
|
|
const target = el.dataset.target;
|
|
const $target = document.getElementById(target);
|
|
|
|
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
|
|
el.classList.toggle('is-active');
|
|
$target.classList.toggle('is-active');
|
|
});
|
|
}
|
|
};
|
|
|
|
Vue.prototype.$copyToClipboard = function (text) {
|
|
if (window.clipboardData && window.clipboardData.setData) {
|
|
// IE specific code path to prevent textarea being shown while dialog is visible.
|
|
return clipboardData.setData('Text', text);
|
|
} else if (document.queryCommandSupported && document.queryCommandSupported('copy')) {
|
|
var textarea = document.createElement('textarea');
|
|
textarea.textContent = text;
|
|
textarea.style.position = 'fixed'; // Prevent scrolling to bottom of page in MS Edge.
|
|
document.body.appendChild(textarea);
|
|
textarea.select();
|
|
try {
|
|
return document.execCommand('copy'); // Security exception may be thrown by some browsers.
|
|
} catch (ex) {
|
|
console.warn('Copy to clipboard failed.', ex);
|
|
return false;
|
|
} finally {
|
|
document.body.removeChild(textarea);
|
|
}
|
|
}
|
|
};
|
|
|
|
Vue.prototype.$nonAccent = function (str) {
|
|
if (this.$empty(str)) return null;
|
|
str = str.replaceAll('/', '-').replaceAll('%', '-').replaceAll('?', '-');
|
|
str = str.toLowerCase();
|
|
str = str.replace(/à|á|ạ|ả|ã|â|ầ|ấ|ậ|ẩ|ẫ|ă|ằ|ắ|ặ|ẳ|ẵ/g, 'a');
|
|
str = str.replace(/è|é|ẹ|ẻ|ẽ|ê|ề|ế|ệ|ể|ễ/g, 'e');
|
|
str = str.replace(/ì|í|ị|ỉ|ĩ/g, 'i');
|
|
str = str.replace(/ò|ó|ọ|ỏ|õ|ô|ồ|ố|ộ|ổ|ỗ|ơ|ờ|ớ|ợ|ở|ỡ/g, 'o');
|
|
str = str.replace(/ù|ú|ụ|ủ|ũ|ư|ừ|ứ|ự|ử|ữ/g, 'u');
|
|
str = str.replace(/ỳ|ý|ỵ|ỷ|ỹ/g, 'y');
|
|
str = str.replace(/đ/g, 'd');
|
|
// Some system encode vietnamese combining accent as individual utf-8 characters
|
|
str = str.replace(/\u0300|\u0301|\u0303|\u0309|\u0323/g, ''); // Huyền sắc hỏi ngã nặng
|
|
str = str.replace(/\u02C6|\u0306|\u031B/g, ''); // Â, Ê, Ă, Ơ, Ư
|
|
str = str
|
|
.split(' ')
|
|
.filter((s) => s)
|
|
.join('-');
|
|
return str;
|
|
};
|
|
|
|
Vue.prototype.$linkID = function (link) {
|
|
link = link ? link : this.$route.params.slug;
|
|
if (this.$empty(link)) return;
|
|
let idx = link.lastIndexOf('-');
|
|
let id = idx > -1 && idx < link.length - 1 ? link.substring(idx + 1, link.length) : undefined;
|
|
return id;
|
|
};
|
|
|
|
Vue.prototype.$redirectWeb = function (ele) {
|
|
if (this.$store.state.iframe) {
|
|
let info = { id: ele.id, email: ele.email, fullname: ele.fullname, avatar: ele.avatar, token: ele.token };
|
|
if (window.parent) window.parent.postMessage(JSON.stringify(info), '*');
|
|
return;
|
|
}
|
|
let link = this.$store.state.link || COMPANY.website;
|
|
|
|
window.location.href =
|
|
link +
|
|
'?email=' +
|
|
ele.email +
|
|
'&userid=' +
|
|
ele.id +
|
|
'&fullname=' +
|
|
ele.fullname +
|
|
(ele.avatar ? '&avatar=' + ele.avatar : '') +
|
|
'&token=' +
|
|
ele.token;
|
|
};
|
|
|
|
Vue.prototype.$companyInfo = function () {
|
|
return COMPANY;
|
|
};
|
|
|
|
Vue.prototype.$regexEmail = function (email) {
|
|
const regexEmail = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
|
return regexEmail.test(email);
|
|
};
|
|
|
|
Vue.prototype.$regexPassword = function (password, length = 8) {
|
|
const regexPass = new RegExp(`^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[^A-Za-z\\d]).{${length},}$`);
|
|
return regexPass.test(password);
|
|
};
|
|
|
|
Vue.prototype.$regexPhone = function (phone) {
|
|
const regexPhone = /^(0|\+84)(3|5|7|8|9)[0-9]{8}$/;
|
|
return regexPhone.test(phone);
|
|
};
|
|
|
|
Vue.prototype.$regexFullName = function (fullName) {
|
|
const regexFullName = /^[A-Za-zÀ-ỹ]+(\s[A-Za-zÀ-ỹ]+)+$/;
|
|
return regexFullName.test(fullName);
|
|
};
|
|
|
|
Vue.prototype.$validateEmail = function (email, isNull = false) {
|
|
const value = (email || '').trim().toLowerCase();
|
|
|
|
if (!isNull && !value) {
|
|
return {
|
|
status: false,
|
|
message: 'Email không được bỏ trống.',
|
|
};
|
|
}
|
|
|
|
if (value && !this.$regexEmail(value)) {
|
|
return {
|
|
status: false,
|
|
message: 'Email không hợp lệ. Vui lòng nhập đúng định dạng (ví dụ: ex@gmail.com).',
|
|
};
|
|
}
|
|
|
|
return {
|
|
status: true,
|
|
message: '',
|
|
};
|
|
};
|
|
|
|
Vue.prototype.$validatePassword = function (password, isNull = false) {
|
|
const value = (password || '').trim();
|
|
|
|
if (!isNull && !value) {
|
|
return {
|
|
status: false,
|
|
message: 'Mật khẩu không được bỏ trống.',
|
|
};
|
|
}
|
|
|
|
if (value && !this.$regexPassword(value)) {
|
|
return {
|
|
status: false,
|
|
message: 'Mật khẩu không hợp lệ. Phải có ít nhất 8 ký tự, bao gồm chữ hoa, chữ thường, số và ký tự đặc biệt.',
|
|
};
|
|
}
|
|
|
|
return {
|
|
status: true,
|
|
message: '',
|
|
};
|
|
};
|
|
|
|
Vue.prototype.$validatePhone = function (phone, isNull = false) {
|
|
const value = (phone || '').trim();
|
|
|
|
if (!isNull && !value) {
|
|
return {
|
|
status: false,
|
|
message: 'Số điện thoại không được bỏ trống.',
|
|
};
|
|
}
|
|
|
|
if (value && !this.$regexPhone(value)) {
|
|
return {
|
|
status: false,
|
|
message: 'Số điện thoại không hợp lệ. Vui lòng nhập số điện thoại Việt Nam hợp lệ (ví dụ: 0912345678).',
|
|
};
|
|
}
|
|
|
|
return {
|
|
status: true,
|
|
message: '',
|
|
};
|
|
};
|
|
|
|
Vue.prototype.$validateFullName = function (fullName, isNull = false) {
|
|
const value = (fullName || '').trim();
|
|
|
|
if (!isNull && !value) {
|
|
return {
|
|
status: false,
|
|
message: 'Họ và tên không được bỏ trống.',
|
|
};
|
|
}
|
|
|
|
if (value && !this.$regexFullName(value)) {
|
|
return {
|
|
status: false,
|
|
message: 'Họ và tên không hợp lệ. Vui lòng nhập họ và tên đầy đủ.',
|
|
};
|
|
}
|
|
|
|
return {
|
|
status: true,
|
|
message: '',
|
|
};
|
|
};
|
|
},
|
|
});
|