changes
This commit is contained in:
@@ -38,7 +38,7 @@
|
|||||||
z-index: 999;
|
z-index: 999;
|
||||||
bottom: 110%;
|
bottom: 110%;
|
||||||
transition: opacity 0.3s;
|
transition: opacity 0.3s;
|
||||||
padding: 6px 9px;
|
padding: 0.4rem 0.6rem;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
box-shadow: 2px 2px 1px rgba(0, 0, 0, 0.1);
|
box-shadow: 2px 2px 1px rgba(0, 0, 0, 0.1);
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
class="modal-card"
|
class="modal-card"
|
||||||
:id="docid"
|
:id="docid"
|
||||||
:style="{
|
:style="{
|
||||||
width: $store.viewport <= 2 ? 'calc(100% - 2rem)' : width || '60%',
|
width: $store.viewport <= 1 ? 'calc(100% - 2rem)' : width || '60%',
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<header
|
<header
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
@close="closeModal"
|
@close="closeModal"
|
||||||
/>
|
/>
|
||||||
</section>
|
</section>
|
||||||
<footer class="modal-card-foot pt-0 px-4 pb-4"></footer>
|
<footer class="modal-card-foot px-4 pb-4 pt-0"></footer>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
@@ -139,7 +139,11 @@ onUnmounted(() => {
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
footer:empty {
|
footer {
|
||||||
display: none;
|
background-color: var(--bulma-modal-card-body-background-color);
|
||||||
|
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -390,11 +390,14 @@ export default {
|
|||||||
.field:not(:last-child) {
|
.field:not(:last-child) {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
.button.is-light {
|
.button.is-success {
|
||||||
--bulma-button-background-l: 89%;
|
&.is-light {
|
||||||
}
|
--bulma-button-background-l: 89%;
|
||||||
.button:hover,
|
}
|
||||||
.button.is-hovered {
|
|
||||||
--bulma-button-background-l-delta: -10%;
|
&:hover,
|
||||||
|
&.is-hovered {
|
||||||
|
--bulma-button-background-l-delta: -10%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -174,7 +174,7 @@
|
|||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon
|
<Icon
|
||||||
name="material-symbols:menu-rounded"
|
name="material-symbols:view-column-outline-rounded"
|
||||||
:size="22"
|
:size="22"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
@@ -223,18 +223,18 @@
|
|||||||
</p>
|
</p>
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<button
|
<button
|
||||||
class="button is-light is-primary"
|
class="button is-primary"
|
||||||
@click="saveSetting()"
|
@click="saveSetting()"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon
|
<Icon
|
||||||
name="material-symbols:save-outline-rounded"
|
name="material-symbols:save-rounded"
|
||||||
:size="22"
|
:size="22"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<span
|
<span
|
||||||
class="tooltiptext"
|
class="tooltiptext has-background-primary has-text-white"
|
||||||
style="top: 110%; bottom: unset; min-width: max-content; left: -45px"
|
style="top: 110%; bottom: unset; min-width: max-content; left: -45px"
|
||||||
>Lưu thiết lập</span
|
>Lưu thiết lập</span
|
||||||
>
|
>
|
||||||
@@ -254,7 +254,7 @@
|
|||||||
:class="selectTab.code === v.code ? 'is-active' : 'has-text-primary'"
|
:class="selectTab.code === v.code ? 'is-active' : 'has-text-primary'"
|
||||||
@click="changeTab(v)"
|
@click="changeTab(v)"
|
||||||
>
|
>
|
||||||
<a class="px-8 py-1.5 fs-14">{{ v.name }}</a>
|
<a class="px-12 py-1.5 fs-14">{{ v.name }}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -387,21 +387,17 @@
|
|||||||
</span>
|
</span>
|
||||||
<span>{{ v.name }}</span>
|
<span>{{ v.name }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="radioTemplate === 'option'"
|
||||||
|
class="button is-primary is-light fs-14 ml-2"
|
||||||
|
@click="showSidebar()"
|
||||||
|
>
|
||||||
|
{{ currentField.template ? "Sửa" : "Tạo" }} định dạng
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p
|
|
||||||
class="mt-3"
|
|
||||||
v-if="radioTemplate === 'option'"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
class="button is-primary is-light fs-14"
|
|
||||||
@click="showSidebar()"
|
|
||||||
>
|
|
||||||
{{ `${currentField.template ? "Sửa" : "Tạo"} định dạng` }}
|
|
||||||
</button>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="currentTab === 'value'">
|
<div v-else-if="currentTab === 'value'">
|
||||||
<ScrollBox
|
<ScrollBox
|
||||||
@@ -563,7 +559,7 @@ function editLabel() {
|
|||||||
component: "datatable/EditLabel",
|
component: "datatable/EditLabel",
|
||||||
title: "Điều chỉnh tiêu đề",
|
title: "Điều chỉnh tiêu đề",
|
||||||
width: "500px",
|
width: "500px",
|
||||||
height: "300px",
|
height: "auto",
|
||||||
vbind: { label },
|
vbind: { label },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -621,7 +617,7 @@ const showSidebar = function () {
|
|||||||
pagename: props.pagename,
|
pagename: props.pagename,
|
||||||
},
|
},
|
||||||
width: "850px",
|
width: "850px",
|
||||||
height: "700px",
|
height: "600px",
|
||||||
title: title,
|
title: title,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="field is-grouped is-grouped-multiline is-gap-4 px-2"
|
class="field is-grouped is-grouped-multiline is-gap-4 px-2"
|
||||||
v-if="filters ? filters.length > 0 : false"
|
v-if="filters?.length > 0"
|
||||||
>
|
>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<a
|
<a
|
||||||
class="button is-primary is-light"
|
class="button is-primary is-light fs-14"
|
||||||
@click="updateData({ filters: [] })"
|
@click="updateData({ filters: [] })"
|
||||||
>
|
>
|
||||||
<span class="fs-14">Xóa lọc</span>
|
Xóa lọc
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="control">
|
<div class="control">
|
||||||
@@ -103,6 +103,7 @@
|
|||||||
:row="v"
|
:row="v"
|
||||||
v-if="field.template"
|
v-if="field.template"
|
||||||
@clickevent="clickEvent($event, v, field)"
|
@clickevent="clickEvent($event, v, field)"
|
||||||
|
@dynamicCompEvent="onDynamicCompEvent"
|
||||||
/>
|
/>
|
||||||
<span v-else>{{ v[field.name] }}</span>
|
<span v-else>{{ v[field.name] }}</span>
|
||||||
</td>
|
</td>
|
||||||
@@ -121,7 +122,7 @@
|
|||||||
@confirm="confirmRemove"
|
@confirm="confirmRemove"
|
||||||
v-bind="showmodal"
|
v-bind="showmodal"
|
||||||
v-if="showmodal"
|
v-if="showmodal"
|
||||||
></Modal>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { createApp } from "vue/dist/vue.esm-bundler.js";
|
import { createApp } from "vue/dist/vue.esm-bundler.js";
|
||||||
@@ -136,6 +137,7 @@ const {
|
|||||||
$deleterow,
|
$deleterow,
|
||||||
$empty,
|
$empty,
|
||||||
$find,
|
$find,
|
||||||
|
$getdata,
|
||||||
$getEditRights,
|
$getEditRights,
|
||||||
$formatNumber,
|
$formatNumber,
|
||||||
$multiSort,
|
$multiSort,
|
||||||
@@ -144,9 +146,10 @@ const {
|
|||||||
$unique,
|
$unique,
|
||||||
} = useNuxtApp();
|
} = useNuxtApp();
|
||||||
const store = useStore();
|
const store = useStore();
|
||||||
var props = defineProps({
|
const props = defineProps({
|
||||||
pagename: String,
|
pagename: String,
|
||||||
});
|
});
|
||||||
|
|
||||||
function dynamicComponent(htmlString) {
|
function dynamicComponent(htmlString) {
|
||||||
return defineComponent({
|
return defineComponent({
|
||||||
template: htmlString,
|
template: htmlString,
|
||||||
@@ -165,10 +168,14 @@ var currentPage = 1;
|
|||||||
var displayFields = ref([]);
|
var displayFields = ref([]);
|
||||||
var displayData = [];
|
var displayData = [];
|
||||||
var pagedata = store[props.pagename];
|
var pagedata = store[props.pagename];
|
||||||
var tablesetting = $copy(pagedata.tablesetting || store.tablesetting);
|
let tablesetting = $copy(pagedata.tablesetting || store.tablesetting);
|
||||||
if (!Array.isArray(tablesetting)) {
|
if (!Array.isArray(tablesetting)) {
|
||||||
tablesetting = Object.values(tablesetting);
|
tablesetting = Object.values(tablesetting);
|
||||||
}
|
}
|
||||||
|
// console.log("props.pagename", props.pagename);
|
||||||
|
// console.log("pagedata.tablesetting", pagedata.tablesetting);
|
||||||
|
// console.log("store.tablesetting", store.tablesetting);
|
||||||
|
// console.log("tablesetting", tablesetting);
|
||||||
// var tablesetting = $copy(store.tablesetting);
|
// var tablesetting = $copy(store.tablesetting);
|
||||||
// const tablesettingObj = Object.fromEntries(tablesetting.map((v) => [v.code, v]));
|
// const tablesettingObj = Object.fromEntries(tablesetting.map((v) => [v.code, v]));
|
||||||
var perPage = Number($find(tablesetting, { code: "per-page" }, "detail")) || 20;
|
var perPage = Number($find(tablesetting, { code: "per-page" }, "detail")) || 20;
|
||||||
@@ -183,7 +190,7 @@ var data = $copy(pagedata.data);
|
|||||||
var showmodal = ref();
|
var showmodal = ref();
|
||||||
watch(
|
watch(
|
||||||
() => store[props.pagename],
|
() => store[props.pagename],
|
||||||
(newVal, oldVal) => {
|
() => {
|
||||||
updateChange();
|
updateChange();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -204,7 +211,7 @@ const updateShow = function (full_data) {
|
|||||||
const allowedFns = {
|
const allowedFns = {
|
||||||
"$getEditRights()": $getEditRights,
|
"$getEditRights()": $getEditRights,
|
||||||
};
|
};
|
||||||
const arr = pagedata.fields.filter(({ show }) => {
|
const shownFields = pagedata.fields.filter(({ show }) => {
|
||||||
if (typeof show === "boolean") return show;
|
if (typeof show === "boolean") return show;
|
||||||
else {
|
else {
|
||||||
// show is a string
|
// show is a string
|
||||||
@@ -213,19 +220,20 @@ const updateShow = function (full_data) {
|
|||||||
return allowedFns[show]?.() || false;
|
return allowedFns[show]?.() || false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (full_data === false) displayData = $copy(data);
|
|
||||||
else
|
if (full_data === false) {
|
||||||
displayData = $copy(
|
displayData = $copy(data);
|
||||||
data.filter((ele, index) => index >= (currentPage - 1) * perPage && index < currentPage * perPage),
|
} else {
|
||||||
);
|
displayData = data.filter((ele, index) => index >= (currentPage - 1) * perPage && index < currentPage * perPage);
|
||||||
displayData.map((v) => {
|
}
|
||||||
arr.map((x) => (v[`${x.name}color`] = getStyle(x, v)));
|
displayData.forEach((v) => {
|
||||||
|
shownFields.forEach((x) => (v[`${x.name}color`] = getStyle(x, v)));
|
||||||
});
|
});
|
||||||
arr.map((v) => {
|
shownFields.forEach((v) => {
|
||||||
v.headerStyle = getSettingStyle("header", v);
|
v.headerStyle = getSettingStyle("header", v);
|
||||||
v.dropStyle = getSettingStyle("dropdown", v);
|
v.dropStyle = getSettingStyle("dropdown", v);
|
||||||
});
|
});
|
||||||
displayFields.value = arr;
|
displayFields.value = shownFields;
|
||||||
showPagination();
|
showPagination();
|
||||||
};
|
};
|
||||||
function confirmRemove() {
|
function confirmRemove() {
|
||||||
@@ -237,11 +245,11 @@ const clickEvent = function (event, row, field) {
|
|||||||
if (name === "remove") {
|
if (name === "remove") {
|
||||||
currentRow = row;
|
currentRow = row;
|
||||||
showmodal.value = {
|
showmodal.value = {
|
||||||
component: `dialog/Confirm`,
|
component: "dialog/Confirm",
|
||||||
vbind: { content: "Bạn có muốn xóa bản ghi này không?", duration: 10 },
|
vbind: { content: "Bạn có muốn xóa bản ghi này không?", duration: 10 },
|
||||||
title: "Xác nhận",
|
title: "Xác nhận",
|
||||||
width: "500px",
|
width: "500px",
|
||||||
height: "100px",
|
height: "auto",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
emit(name, row, field, data);
|
emit(name, row, field, data);
|
||||||
@@ -269,7 +277,7 @@ const showField = async function (field) {
|
|||||||
}; //$stripHtml(field.label)
|
}; //$stripHtml(field.label)
|
||||||
};
|
};
|
||||||
const getStyle = function (field, record) {
|
const getStyle = function (field, record) {
|
||||||
var stop = false;
|
let stop = false;
|
||||||
let val = tablesetting.find((v) => v.code === "td-border")
|
let val = tablesetting.find((v) => v.code === "td-border")
|
||||||
? tablesetting.find((v) => v.code === "td-border").detail
|
? tablesetting.find((v) => v.code === "td-border").detail
|
||||||
: "border: solid 1px rgb(44, 44, 44); ";
|
: "border: solid 1px rgb(44, 44, 44); ";
|
||||||
@@ -342,6 +350,117 @@ const getStyle = function (field, record) {
|
|||||||
return val;
|
return val;
|
||||||
};
|
};
|
||||||
const getSettingStyle = function (name, field) {
|
const getSettingStyle = function (name, field) {
|
||||||
|
if (name === "table") {
|
||||||
|
console.log("tablesetting", tablesetting);
|
||||||
|
}
|
||||||
|
if (!tablesetting || tablesetting.length === 0) {
|
||||||
|
// manual temp fix
|
||||||
|
tablesetting = [
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
code: "per-page",
|
||||||
|
name: "Số dòng trong 1 trang",
|
||||||
|
detail: "20",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
code: "header-filter-color",
|
||||||
|
name: "Màu chữ khi áp dụng Filter",
|
||||||
|
detail: "#00cc66",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
code: "background",
|
||||||
|
name: "Màu nền background",
|
||||||
|
detail: "#363636",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
code: "table-background",
|
||||||
|
name: "Màu nền của bảng",
|
||||||
|
detail: "#ffffff",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
code: "table-font-color",
|
||||||
|
name: "Mầu chữ trong bảng",
|
||||||
|
detail: "hsl(0, 0%, 14%)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 13,
|
||||||
|
code: "table-font-size",
|
||||||
|
name: "Cỡ chữ trong bảng",
|
||||||
|
detail: "12",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 14,
|
||||||
|
code: "header-background",
|
||||||
|
name: "Màu nền tiêu đề",
|
||||||
|
detail: "var(--bulma-primary-soft)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 15,
|
||||||
|
code: "header-font-color",
|
||||||
|
name: "Màu chữ tiêu đề",
|
||||||
|
detail: "var(--bulma-primary-40)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 16,
|
||||||
|
code: "header-font-size",
|
||||||
|
name: "Cỡ chữ tiêu đề",
|
||||||
|
detail: "12",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 17,
|
||||||
|
code: "container-height",
|
||||||
|
name: "Chiều cao container",
|
||||||
|
detail: "38",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 18,
|
||||||
|
code: "header-arrow",
|
||||||
|
name: "Mũi tên trỏ xuống",
|
||||||
|
detail: "no",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 19,
|
||||||
|
code: "menu-width",
|
||||||
|
name: "Chiều rộng menu",
|
||||||
|
detail: "20.6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 20,
|
||||||
|
code: "menu-min-height",
|
||||||
|
name: "Chiều cao menu (nhỏ nhất)",
|
||||||
|
detail: "32",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 21,
|
||||||
|
code: "menu-max-height",
|
||||||
|
name: "Chiều cao menu (lớn nhất)",
|
||||||
|
detail: "37",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 22,
|
||||||
|
code: "show-menu",
|
||||||
|
name: "Hiển thị menu",
|
||||||
|
detail: "yes",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 23,
|
||||||
|
code: "note",
|
||||||
|
name: "Ghi chú",
|
||||||
|
detail: "@",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 24,
|
||||||
|
code: "td-border",
|
||||||
|
name: "Đường viền",
|
||||||
|
detail: "border: 1px solid #dbdbdb;",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
let value = "";
|
let value = "";
|
||||||
if (name === "container") {
|
if (name === "container") {
|
||||||
value = "min-height:" + tablesetting.find((v) => v.code === "container-height").detail + "rem; ";
|
value = "min-height:" + tablesetting.find((v) => v.code === "container-height").detail + "rem; ";
|
||||||
@@ -550,8 +669,15 @@ const doubleClick = function (field, v) {
|
|||||||
currentField = field;
|
currentField = field;
|
||||||
doSelect(v[field.name]);
|
doSelect(v[field.name]);
|
||||||
};
|
};
|
||||||
var tableStyle = getSettingStyle("table");
|
const tableStyle = getSettingStyle("table");
|
||||||
setTimeout(() => updateShow(), 200);
|
setTimeout(() => updateShow(), 200);
|
||||||
|
|
||||||
|
async function onDynamicCompEvent(e) {
|
||||||
|
console.log("DataTable received dynamicCompEvent", e);
|
||||||
|
if (e.type === "refresh") {
|
||||||
|
updateShow(); // doesn't get new data
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
:deep(.table tbody tr:hover td, .table tbody tr:hover th) {
|
:deep(.table tbody tr:hover td, .table tbody tr:hover th) {
|
||||||
|
|||||||
@@ -219,20 +219,20 @@
|
|||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<TableOption
|
<TableOption
|
||||||
v-bind="{ pagename: pagename }"
|
v-bind="{ pagename }"
|
||||||
v-else-if="sideBar === 'option'"
|
v-else-if="sideBar === 'option'"
|
||||||
>
|
>
|
||||||
</TableOption>
|
</TableOption>
|
||||||
<CreateTemplate
|
<CreateTemplate
|
||||||
v-else-if="sideBar === 'template'"
|
v-else-if="sideBar === 'template'"
|
||||||
v-bind="{ pagename: pagename, field: openField }"
|
v-bind="{ pagename, field: openField }"
|
||||||
>
|
>
|
||||||
</CreateTemplate>
|
</CreateTemplate>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
// FilterOption: () => import("@/components/datatable/FilterOption"),
|
// FilterOption: () => import("@/components/datatable/FilterOption"),
|
||||||
// TableOption: () => import("@/components/datatable/TableOption"),
|
// TableOption: () => import("@/components/datatable/TableOption"),
|
||||||
//CreateTemplate: () => import("@/components/datatable/CreateTemplate")
|
// CreateTemplate: () => import("@/components/datatable/CreateTemplate")
|
||||||
import CreateTemplate from "~/components/datatable/CreateTemplate";
|
import CreateTemplate from "~/components/datatable/CreateTemplate";
|
||||||
const { $id, $copy, $empty, $stripHtml } = useNuxtApp();
|
const { $id, $copy, $empty, $stripHtml } = useNuxtApp();
|
||||||
var props = defineProps({
|
var props = defineProps({
|
||||||
@@ -323,5 +323,4 @@ const doConditionFilter = function (v, type, id) {
|
|||||||
$emit("modalevent", { name: "updatefields", data: copy });
|
$emit("modalevent", { name: "updatefields", data: copy });
|
||||||
};
|
};
|
||||||
initData();
|
initData();
|
||||||
console.log(sideBar);
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -14,22 +14,29 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="selectType.code === 'formula'">
|
<template v-if="selectType.code === 'formula'">
|
||||||
<b-radio
|
<div class="control is-flex is-gap-2">
|
||||||
:class="i === 1 ? 'ml-5' : null"
|
<label
|
||||||
v-model="choice"
|
v-for="(v, i) in choices"
|
||||||
v-for="(v, i) in choices"
|
:key="i"
|
||||||
:key="i"
|
class="radio"
|
||||||
:native-value="v.code"
|
>
|
||||||
>
|
<input
|
||||||
<span :class="v.code === choice ? 'fsb-16' : 'fs-16'">{{ v.name }}</span>
|
v-model="choice"
|
||||||
</b-radio>
|
:value="v.code"
|
||||||
<div class="has-background-light mt-3 px-3 py-3">
|
@input="changeType(v)"
|
||||||
|
type="radio"
|
||||||
|
name="choice"
|
||||||
|
/>
|
||||||
|
{{ v.name }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="has-background-white-bis mt-3 p-3 rounded-md">
|
||||||
<div
|
<div
|
||||||
class="tags are-medium mb-0"
|
class="tags mb-0"
|
||||||
v-if="choice === 'function'"
|
v-if="choice === 'function'"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
:class="`tag ${func === v.code ? 'is-primary' : 'is-dark'} is-rounded is-clickable`"
|
:class="`tag is-primary ${func !== v.code && 'is-light'} fs-13 is-rounded is-clickable`"
|
||||||
v-for="(v, i) in funcs"
|
v-for="(v, i) in funcs"
|
||||||
:key="i"
|
:key="i"
|
||||||
@click="changeFunc(v)"
|
@click="changeFunc(v)"
|
||||||
@@ -285,7 +292,7 @@ var choices = [
|
|||||||
{ code: "column", name: "Dùng cột dữ liệu" },
|
{ code: "column", name: "Dùng cột dữ liệu" },
|
||||||
{ code: "function", name: "Dùng hàm số" },
|
{ code: "function", name: "Dùng hàm số" },
|
||||||
];
|
];
|
||||||
var choice = "column";
|
const choice = ref("column");
|
||||||
var funcs = [
|
var funcs = [
|
||||||
{ code: "sum", name: "Sum" },
|
{ code: "sum", name: "Sum" },
|
||||||
{ code: "max", name: "Max" },
|
{ code: "max", name: "Max" },
|
||||||
@@ -363,7 +370,7 @@ function checkFunc() {
|
|||||||
}
|
}
|
||||||
function checkValid() {
|
function checkValid() {
|
||||||
errors.value = [];
|
errors.value = [];
|
||||||
if (tags.length === 0 && choice === "column") {
|
if (tags.length === 0 && choice.value === "column") {
|
||||||
errors.value.push({
|
errors.value.push({
|
||||||
name: "tags",
|
name: "tags",
|
||||||
message: "Chưa chọn trường xây dựng công thức.",
|
message: "Chưa chọn trường xây dựng công thức.",
|
||||||
@@ -382,7 +389,7 @@ function checkValid() {
|
|||||||
}
|
}
|
||||||
if (errors.value.length > 0) return false;
|
if (errors.value.length > 0) return false;
|
||||||
//check formula in case use column
|
//check formula in case use column
|
||||||
if (choice === "column") {
|
if (choice.value === "column") {
|
||||||
let val = $copy(formula);
|
let val = $copy(formula);
|
||||||
tags.forEach((v) => {
|
tags.forEach((v) => {
|
||||||
let myRegExp = new RegExp(v.name, "g");
|
let myRegExp = new RegExp(v.name, "g");
|
||||||
@@ -410,7 +417,7 @@ function createField() {
|
|||||||
if (!checkValid()) return;
|
if (!checkValid()) return;
|
||||||
let field = $createField(name.trim(), label.trim(), "number", true);
|
let field = $createField(name.trim(), label.trim(), "number", true);
|
||||||
field.formula = formula.trim().replaceAll(" ", "");
|
field.formula = formula.trim().replaceAll(" ", "");
|
||||||
if (choice === "function") {
|
if (choice.value === "function") {
|
||||||
field.func = func;
|
field.func = func;
|
||||||
field.vals = checkFunc();
|
field.vals = checkFunc();
|
||||||
} else field.tags = tags.map((v) => v.name);
|
} else field.tags = tags.map((v) => v.name);
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
<table class="table is-fullwidth">
|
<table class="table is-fullwidth">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="fs-14">
|
<tr class="fs-14">
|
||||||
<th>#</th>
|
<th class="is-narrow">#</th>
|
||||||
<th>Tên trường</th>
|
<th>Tên trường</th>
|
||||||
<th>Tên cột</th>
|
<th>Tên cột</th>
|
||||||
<th class="is-narrow">...</th>
|
<th class="is-narrow has-text-right">Thao tác</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -13,52 +13,52 @@
|
|||||||
class="fs-14"
|
class="fs-14"
|
||||||
v-for="(v, i) in fields"
|
v-for="(v, i) in fields"
|
||||||
>
|
>
|
||||||
<td>{{ i }}</td>
|
<td style="vertical-align: middle">{{ i }}</td>
|
||||||
<td>
|
<td style="vertical-align: middle">
|
||||||
<a
|
<a
|
||||||
class="has-text-primary"
|
class="has-text-primary"
|
||||||
@click="openField(v, i)"
|
@click="openField(v, i)"
|
||||||
>{{ v.name }}</a
|
>{{ v.name }}</a
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
<td>{{ $stripHtml(v.label, 50) }}</td>
|
<td style="vertical-align: middle">{{ $stripHtml(v.label, 50) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="field has-addons">
|
<div class="field has-addons">
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<button
|
<button
|
||||||
class="button is-primary is-light"
|
class="button is-primary is-light px-3.5 py-1.5"
|
||||||
@click="moveDown(v, i)"
|
@click="moveDown(v, i)"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon
|
<Icon
|
||||||
name="material-symbols:arrow-downward-rounded"
|
name="material-symbols:arrow-downward-rounded"
|
||||||
:size="19"
|
:size="18"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<button
|
<button
|
||||||
class="button is-primary is-light"
|
class="button is-primary is-light px-3.5 py-1.5"
|
||||||
@click="moveUp(v, i)"
|
@click="moveUp(v, i)"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon
|
<Icon
|
||||||
name="material-symbols:arrow-upward-rounded"
|
name="material-symbols:arrow-upward-rounded"
|
||||||
:size="19"
|
:size="18"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</p>
|
</p>
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<button
|
<button
|
||||||
class="button is-primary is-light"
|
class="button is-primary is-light px-3.5 py-1.5"
|
||||||
@click="askConfirm(v, i)"
|
@click="askConfirm(v, i)"
|
||||||
>
|
>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<Icon
|
<Icon
|
||||||
name="material-symbols:delete-outline-rounded"
|
name="material-symbols:delete-outline-rounded"
|
||||||
:size="19"
|
:size="18"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<div
|
<div
|
||||||
v-if="enableTime"
|
v-if="enableTime"
|
||||||
class="cell is-col-span-7 is-flex is-align-items-center is-flex-wrap-wrap"
|
class="cell is-col-span-7 is-flex is-align-items-center is-flex-wrap-wrap"
|
||||||
style="row-gap: 0.5rem; column-gap: 1rem"
|
style="row-gap: 0; column-gap: 1rem"
|
||||||
>
|
>
|
||||||
<Caption
|
<Caption
|
||||||
:title="lang === 'vi' ? 'Thời gian' : 'Time'"
|
:title="lang === 'vi' ? 'Thời gian' : 'Time'"
|
||||||
@@ -41,11 +41,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
v-if="newDataAvailable"
|
v-if="newDataAvailable"
|
||||||
class="has-text-danger is-italic is-size-6 ml-2"
|
class="has-text-danger is-italic fs-14 ml-2"
|
||||||
>Có dữ liệu mới, vui lòng làm mới.</span
|
>Có dữ liệu mới, vui lòng làm mới.</span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell is-col-span-5 is-flex is-align-items-center is-gap-1 is-flex-wrap-wrap">
|
<div
|
||||||
|
class="cell is-col-span-5 is-flex is-align-items-center is-flex-wrap-wrap"
|
||||||
|
style="row-gap: 0; column-gap: 1rem"
|
||||||
|
>
|
||||||
<Caption
|
<Caption
|
||||||
:title="lang === 'vi' ? `Tìm ${viewport === 1 ? '' : 'kiếm'}` : 'Search'"
|
:title="lang === 'vi' ? `Tìm ${viewport === 1 ? '' : 'kiếm'}` : 'Search'"
|
||||||
type="has-text-orange"
|
type="has-text-orange"
|
||||||
@@ -60,45 +63,50 @@
|
|||||||
:placeholder="lang === 'vi' ? 'Nhập từ khóa...' : 'Enter keyword...'"
|
:placeholder="lang === 'vi' ? 'Nhập từ khóa...' : 'Enter keyword...'"
|
||||||
/>
|
/>
|
||||||
<div class="field has-addons is-flex is-flex-wrap-wrap is-gap-0 is-align-items-center">
|
<div class="field has-addons is-flex is-flex-wrap-wrap is-gap-0 is-align-items-center">
|
||||||
<span
|
<p
|
||||||
class="tooltip"
|
|
||||||
v-if="importdata && $getEditRights()"
|
v-if="importdata && $getEditRights()"
|
||||||
|
class="control"
|
||||||
>
|
>
|
||||||
<a
|
<button
|
||||||
class="mr-2"
|
class="button is-ghost has-text-orange fs-14"
|
||||||
@click="openImport()"
|
@click="openImport()"
|
||||||
>
|
>
|
||||||
<SvgIcon
|
<span class="icon">
|
||||||
v-bind="{
|
<Icon
|
||||||
name: 'upload.svg',
|
name="material-symbols:upload-rounded"
|
||||||
type: 'findata',
|
:size="22"
|
||||||
size: 22,
|
/>
|
||||||
}"
|
</span>
|
||||||
></SvgIcon>
|
</button>
|
||||||
</a>
|
|
||||||
<span
|
<span
|
||||||
class="tooltiptext"
|
class="tooltiptext has-background-orange-soft has-text-orange-bold"
|
||||||
style="min-width: max-content"
|
style="top: 110%; bottom: unset; min-width: max-content; left: -45px"
|
||||||
>
|
>
|
||||||
{{ lang === "vi" ? "Nhập dữ liệu" : "Import data" }}
|
Nhập dữ liệu
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</p>
|
||||||
<span
|
<p
|
||||||
class="tooltip"
|
|
||||||
v-if="enableAdd && $getEditRights()"
|
v-if="enableAdd && $getEditRights()"
|
||||||
|
class="control"
|
||||||
>
|
>
|
||||||
<a
|
<button
|
||||||
class="mr-2"
|
class="button is-ghost has-text-orange fs-14"
|
||||||
@click="$emit('add')"
|
@click="$emit('add')"
|
||||||
>
|
>
|
||||||
<SvgIcon v-bind="{ name: 'add1.png', type: 'findata', size: 22 }"></SvgIcon>
|
<span class="icon">
|
||||||
</a>
|
<Icon
|
||||||
|
name="material-symbols:add-rounded"
|
||||||
|
:size="22"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
<span
|
<span
|
||||||
class="tooltiptext"
|
class="tooltiptext has-background-orange-soft has-text-orange-bold"
|
||||||
style="min-width: max-content"
|
style="top: 110%; bottom: unset; min-width: max-content; left: -45px"
|
||||||
>{{ lang === "vi" ? "Thêm mới" : "Add new" }}</span
|
|
||||||
>
|
>
|
||||||
</span>
|
Thêm mới
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<button
|
<button
|
||||||
class="button is-ghost has-text-orange fs-14"
|
class="button is-ghost has-text-orange fs-14"
|
||||||
@@ -110,8 +118,13 @@
|
|||||||
:size="22"
|
:size="22"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span>Xuất excel</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
<span
|
||||||
|
class="tooltiptext has-background-orange-soft has-text-orange-bold"
|
||||||
|
style="top: 110%; bottom: unset; min-width: max-content; left: -45px"
|
||||||
|
>
|
||||||
|
Xuất Excel
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p class="control">
|
<p class="control">
|
||||||
<button
|
<button
|
||||||
@@ -124,8 +137,13 @@
|
|||||||
:size="22"
|
:size="22"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<span>Làm mới</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
<span
|
||||||
|
class="tooltiptext has-background-orange-soft has-text-orange-bold"
|
||||||
|
style="top: 110%; bottom: unset; min-width: max-content; left: -45px"
|
||||||
|
>
|
||||||
|
Làm mới
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<Icon
|
<Icon
|
||||||
v-if="loading"
|
v-if="loading"
|
||||||
|
|||||||
@@ -5,37 +5,35 @@
|
|||||||
defer
|
defer
|
||||||
to=".modal-card:has(.confirm) .modal-card-foot"
|
to=".modal-card:has(.confirm) .modal-card-foot"
|
||||||
>
|
>
|
||||||
<div class="field is-grouped">
|
<div class="field is-grouped w-full is-align-items-center">
|
||||||
<div class="control is-expanded">
|
<div class="control is-expanded">
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button
|
<button
|
||||||
class="button is-primary has-text-white"
|
class="button is-primary has-text-white"
|
||||||
@click="confirm()"
|
@click="confirm"
|
||||||
>
|
>
|
||||||
Đồng ý
|
Đồng ý
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="button is-white"
|
class="button is-white"
|
||||||
@click="cancel()"
|
@click="cancel"
|
||||||
>
|
>
|
||||||
Hủy
|
Hủy
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<CountDown
|
||||||
class="control"
|
|
||||||
v-if="duration"
|
v-if="duration"
|
||||||
>
|
:duration="duration"
|
||||||
<CountDown
|
@close="cancel"
|
||||||
:duration="duration"
|
/>
|
||||||
@close="cancel()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</Teleport>
|
</Teleport>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import CountDown from "@/components/dialog/CountDown.vue";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
content: String,
|
content: String,
|
||||||
duration: Number,
|
duration: Number,
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="countdown">
|
<div id="countdown">
|
||||||
<div id="countdown-number"></div>
|
<div
|
||||||
|
ref="countdownNumber"
|
||||||
|
style="display: inline-block; line-height: 40px"
|
||||||
|
></div>
|
||||||
<svg>
|
<svg>
|
||||||
<circle
|
<circle
|
||||||
r="18"
|
r="18"
|
||||||
cx="20"
|
cx="20"
|
||||||
cy="20"
|
cy="20"
|
||||||
color="red"
|
|
||||||
></circle>
|
></circle>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
@@ -21,18 +23,19 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
var countdownNumberEl = document.getElementById("countdown-number");
|
this.$refs.countdownNumber.textContent = this.countdown;
|
||||||
countdownNumberEl.textContent = this.countdown;
|
|
||||||
this.timer = setInterval(() => this.startCount(), 1000);
|
this.timer = setInterval(() => this.startCount(), 1000);
|
||||||
},
|
},
|
||||||
|
unmounted() {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
clearInterval(this.timer);
|
clearInterval(this.timer);
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
startCount() {
|
startCount() {
|
||||||
this.countdown -= 1;
|
this.countdown -= 1;
|
||||||
var countdownNumberEl = document.getElementById("countdown-number");
|
this.$refs.countdownNumber.textContent = this.countdown;
|
||||||
countdownNumberEl.textContent = this.countdown;
|
|
||||||
if (this.countdown === 0) {
|
if (this.countdown === 0) {
|
||||||
clearInterval(this.timer);
|
clearInterval(this.timer);
|
||||||
this.$emit("close");
|
this.$emit("close");
|
||||||
@@ -49,12 +52,7 @@ export default {
|
|||||||
width: 40px;
|
width: 40px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
#countdown-number {
|
svg {
|
||||||
color: black;
|
|
||||||
display: inline-block;
|
|
||||||
line-height: 40px;
|
|
||||||
}
|
|
||||||
:deep(svg) {
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@@ -62,12 +60,12 @@ export default {
|
|||||||
height: 40px;
|
height: 40px;
|
||||||
transform: rotateY(-180deg) rotateZ(-90deg);
|
transform: rotateY(-180deg) rotateZ(-90deg);
|
||||||
}
|
}
|
||||||
:deep(svg circle) {
|
svg circle {
|
||||||
stroke-dasharray: 113px;
|
stroke-dasharray: 113px;
|
||||||
stroke-dashoffset: 0px;
|
stroke-dashoffset: 0px;
|
||||||
stroke-linecap: round;
|
stroke-linecap: round;
|
||||||
stroke-width: 2px;
|
stroke-width: 2px;
|
||||||
stroke: black;
|
stroke: var(--bulma-primary);
|
||||||
fill: none;
|
fill: none;
|
||||||
animation: countdown 10s linear infinite forwards;
|
animation: countdown 10s linear infinite forwards;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ watch(product, () => {
|
|||||||
<template>
|
<template>
|
||||||
<div class="fixed-grid has-12-cols">
|
<div class="fixed-grid has-12-cols">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<div class="cell is-col-span-6 is-col-start-4">
|
<div class="cell is-col-span-8 is-col-start-3">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label class="label">Sản phẩm</label>
|
<label class="label">Sản phẩm</label>
|
||||||
<SearchBox
|
<SearchBox
|
||||||
@@ -47,6 +47,7 @@ watch(product, () => {
|
|||||||
values:
|
values:
|
||||||
'id,code,product,product__name,color,color__code,color__name,color__hex_code,ram,ram__code,ram__capacity,internal_storage,internal_storage__code,internal_storage__capacity,image,price,note,create_time,update_time',
|
'id,code,product,product__name,color,color__code,color__name,color__hex_code,ram,ram__code,ram__capacity,internal_storage,internal_storage__code,internal_storage__capacity,image,price,note,create_time,update_time',
|
||||||
filter: { product: product.id },
|
filter: { product: product.id },
|
||||||
|
sort: 'id',
|
||||||
},
|
},
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const props = defineProps({
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="w-20 h-4"
|
class="w-full h-4"
|
||||||
:style="{ backgroundColor: color, outline: '1px solid var(--bulma-grey-85)' }"
|
:style="{ backgroundColor: color, outline: '1px solid var(--bulma-grey-85)' }"
|
||||||
></div>
|
></div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const activeMenu = ref(menus[1]);
|
|||||||
<template>
|
<template>
|
||||||
<div class="fixed-grid has-12-cols">
|
<div class="fixed-grid has-12-cols">
|
||||||
<div class="grid is-gap-4">
|
<div class="grid is-gap-4">
|
||||||
<div class="cell is-col-span-2">
|
<div class="cell is-col-span-3">
|
||||||
<aside class="menu">
|
<aside class="menu">
|
||||||
<ul class="menu-list">
|
<ul class="menu-list">
|
||||||
<li
|
<li
|
||||||
@@ -25,19 +25,36 @@ const activeMenu = ref(menus[1]);
|
|||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
@click="activeMenu = menu"
|
@click="activeMenu = menu"
|
||||||
:class="{
|
:class="[
|
||||||
'is-active': activeMenu.id === menu.id,
|
'fs-13',
|
||||||
}"
|
{
|
||||||
|
'is-active': activeMenu.id === menu.id,
|
||||||
|
},
|
||||||
|
]"
|
||||||
>{{ menu.name }}</a
|
>{{ menu.name }}</a
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
<div class="cell is-col-span-10">
|
<div class="cell is-col-span-9">
|
||||||
<AddProductForm v-if="activeMenu.id === 'add-product'" />
|
<AddProductForm v-if="activeMenu.id === 'add-product'" />
|
||||||
<AddProductVariant v-if="activeMenu.id === 'add-product-variant'" />
|
<AddProductVariant v-if="activeMenu.id === 'add-product-variant'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.menu-list a {
|
||||||
|
--bulma-menu-list-link-padding: 0.75em 1.25em;
|
||||||
|
|
||||||
|
&:not(.is-active) {
|
||||||
|
--bulma-menu-item-background-l: 95%;
|
||||||
|
}
|
||||||
|
&.is-active {
|
||||||
|
--bulma-menu-item-h: var(--bulma-menu-item-selected-h);
|
||||||
|
--bulma-menu-item-s: var(--bulma-menu-item-selected-s);
|
||||||
|
--bulma-menu-item-l: var(--bulma-menu-item-selected-l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
const { dealer } = useStore();
|
|
||||||
const { $buildFileUrl, $copyToClipboard, $getEditRights } = useNuxtApp();
|
const { $buildFileUrl, $copyToClipboard, $getEditRights } = useNuxtApp();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -24,7 +23,7 @@ const url = $buildFileUrl(props.image.file__file);
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="!dealer && $getEditRights()"
|
v-if="$getEditRights()"
|
||||||
class="button is-small is-white"
|
class="button is-small is-white"
|
||||||
@click="editImage(image)"
|
@click="editImage(image)"
|
||||||
title="Sửa"
|
title="Sửa"
|
||||||
@@ -43,7 +42,7 @@ const url = $buildFileUrl(props.image.file__file);
|
|||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
v-if="!dealer && $getEditRights()"
|
v-if="$getEditRights()"
|
||||||
class="button is-small is-white"
|
class="button is-small is-white"
|
||||||
@click="openDeleteImageConfirm(image)"
|
@click="openDeleteImageConfirm(image)"
|
||||||
title="Xóa"
|
title="Xóa"
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import FileUpload from "@/components/media/FileUpload.vue";
|
import FileUpload from "@/components/media/FileUpload.vue";
|
||||||
|
|
||||||
const { dealer } = useStore();
|
|
||||||
const { $buildFileUrl, $formatFileSize, $getdata, $insertapi, $patchapi, $snackbar } = useNuxtApp();
|
const { $buildFileUrl, $formatFileSize, $getdata, $insertapi, $patchapi, $snackbar } = useNuxtApp();
|
||||||
|
|
||||||
const project = await $getdata("project", undefined, undefined, true);
|
const project = await $getdata("project", undefined, undefined, true);
|
||||||
@@ -117,7 +116,7 @@ function cancelEditDocument() {
|
|||||||
<template>
|
<template>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<FileUpload
|
<FileUpload
|
||||||
v-if="!dealer && $getEditRights()"
|
v-if="$getEditRights()"
|
||||||
position="right"
|
position="right"
|
||||||
:type="['pdf', 'file']"
|
:type="['pdf', 'file']"
|
||||||
@files="onUploadedProjectDocs"
|
@files="onUploadedProjectDocs"
|
||||||
@@ -222,7 +221,7 @@ function cancelEditDocument() {
|
|||||||
<td>
|
<td>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a
|
<a
|
||||||
v-if="!dealer && $getEditRights()"
|
v-if="$getEditRights()"
|
||||||
@click="editDocument(doc)"
|
@click="editDocument(doc)"
|
||||||
title="Sửa"
|
title="Sửa"
|
||||||
>
|
>
|
||||||
@@ -252,7 +251,7 @@ function cancelEditDocument() {
|
|||||||
></span>
|
></span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
v-if="!dealer && $getEditRights()"
|
v-if="$getEditRights()"
|
||||||
@click="deleteDocument(doc)"
|
@click="deleteDocument(doc)"
|
||||||
title="Xóa"
|
title="Xóa"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -176,11 +176,9 @@ async function handleFileUpload(uploadedFiles) {
|
|||||||
@click.prevent="openModal"
|
@click.prevent="openModal"
|
||||||
>Hợp đồng</a
|
>Hợp đồng</a
|
||||||
>
|
>
|
||||||
<!-- <span v-if="!store.dealer" class="mx-1 has-text-grey-light">•</span> -->
|
|
||||||
<FileUpload
|
<FileUpload
|
||||||
v-if="
|
v-if="
|
||||||
txndetail.phase === 7 &&
|
txndetail.phase === 7 &&
|
||||||
!store.dealer &&
|
|
||||||
$getEditRights('edit', {
|
$getEditRights('edit', {
|
||||||
code: 'transaction',
|
code: 'transaction',
|
||||||
category: 'topmenu',
|
category: 'topmenu',
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ const props = defineProps({
|
|||||||
transaction__code: String,
|
transaction__code: String,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { $exportpdf, $getdata, $snackbar, $store } = useNuxtApp();
|
const { $exportpdf, $getdata, $snackbar } = useNuxtApp();
|
||||||
const { dealer } = $store;
|
|
||||||
const txn = ref(null);
|
const txn = ref(null);
|
||||||
const txndetails = ref(null);
|
const txndetails = ref(null);
|
||||||
const showModal = ref(null);
|
const showModal = ref(null);
|
||||||
@@ -83,7 +82,7 @@ onMounted(async () => {
|
|||||||
class="column is-narrow is-flex is-align-items-center is-gap-2"
|
class="column is-narrow is-flex is-align-items-center is-gap-2"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-if="txn?.phase === 4 && !dealer && $getEditRights('edit', { code: 'transaction', category: 'topmenu' })"
|
v-if="txn?.phase === 4 && $getEditRights('edit', { code: 'transaction', category: 'topmenu' })"
|
||||||
@click="openChangeCustomerModal"
|
@click="openChangeCustomerModal"
|
||||||
class="button is-link"
|
class="button is-link"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -36,16 +36,21 @@ const showmodal = ref(undefined);
|
|||||||
function getViewport() {
|
function getViewport() {
|
||||||
let viewport;
|
let viewport;
|
||||||
const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
||||||
|
|
||||||
|
// Follow Bulma's breakpoints: https://bulma.io/documentation/start/responsiveness/#breakpoints
|
||||||
if (width <= 768)
|
if (width <= 768)
|
||||||
viewport = 1; // 'mobile'
|
viewport = 1; // 'mobile'
|
||||||
else if (width >= 769 && width <= 1023)
|
else if (width <= 1023)
|
||||||
viewport = 2; // 'tablet'
|
viewport = 2; // 'tablet'
|
||||||
else if (width >= 1024 && width <= 1215)
|
else if (width <= 1215)
|
||||||
viewport = 3; // 'desktop'
|
viewport = 3; // 'desktop'
|
||||||
else if (width >= 1216 && width <= 1407)
|
else if (width <= 1407)
|
||||||
viewport = 4; // 'widescreen'
|
viewport = 4; // 'widescreen'
|
||||||
else if (width >= 1408) viewport = 5; // 'fullhd'
|
else viewport = 5; // 'fullhd'
|
||||||
$store.commit("viewport", viewport);
|
|
||||||
|
if (viewport !== $store.viewport) {
|
||||||
|
$store.commit("viewport", viewport);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
async function checkRedirect() {
|
async function checkRedirect() {
|
||||||
if (route.query.username && route.query.token) {
|
if (route.query.username && route.query.token) {
|
||||||
@@ -69,18 +74,6 @@ async function checkRedirect() {
|
|||||||
async function checkLogin() {
|
async function checkLogin() {
|
||||||
if ($store.login ? $store.login.token : false) {
|
if ($store.login ? $store.login.token : false) {
|
||||||
$store.commit("rights", await $getdata("grouprights", { group: $store.login.type }));
|
$store.commit("rights", await $getdata("grouprights", { group: $store.login.type }));
|
||||||
$store.commit(
|
|
||||||
"dealer",
|
|
||||||
await $getdata(
|
|
||||||
"dealer",
|
|
||||||
undefined,
|
|
||||||
{
|
|
||||||
filter: { user: $store.login.id },
|
|
||||||
values: "id,code,name,phone,email,create_time",
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
let authtoken = await $getdata("token", { token: $store.login.token }, undefined, true);
|
let authtoken = await $getdata("token", { token: $store.login.token }, undefined, true);
|
||||||
if (authtoken ? authtoken.expiry : true) return; /* $requestLogin(); */
|
if (authtoken ? authtoken.expiry : true) return; /* $requestLogin(); */
|
||||||
authorized.value = true;
|
authorized.value = true;
|
||||||
|
|||||||
@@ -403,7 +403,7 @@ export default defineNuxtPlugin(() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//======================Export===============================
|
//======================Export===============================
|
||||||
const exportExcel = function (data, filename, fields) {
|
const exportExcel = async function (data, filename, fields) {
|
||||||
var _filename = filename + ".xlsx";
|
var _filename = filename + ".xlsx";
|
||||||
let list = [];
|
let list = [];
|
||||||
data.map((v) => {
|
data.map((v) => {
|
||||||
@@ -414,8 +414,9 @@ export default defineNuxtPlugin(() => {
|
|||||||
});
|
});
|
||||||
list.push(ele);
|
list.push(ele);
|
||||||
});
|
});
|
||||||
var XLSX = require("xlsx");
|
|
||||||
//workBook class
|
const XLSX = await import("xlsx");
|
||||||
|
// WorkBook class
|
||||||
function Workbook() {
|
function Workbook() {
|
||||||
if (!(this instanceof Workbook)) return new Workbook();
|
if (!(this instanceof Workbook)) return new Workbook();
|
||||||
this.SheetNames = [];
|
this.SheetNames = [];
|
||||||
|
|||||||
@@ -20,12 +20,17 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
const { $id, $empty, $store } = nuxtApp;
|
const { $id, $empty, $store } = nuxtApp;
|
||||||
const dialog = function (content, title, type, duration, width, height, vbind) {
|
const dialog = function (content, title, type, duration, width, height, vbind) {
|
||||||
content = typeof content === "string" ? content : JSON.stringify(content);
|
content = typeof content === "string" ? content : JSON.stringify(content);
|
||||||
let vtitle = type === "Success" ? `<span class="has-text-primary">${title}</span>` : title;
|
const vtitle =
|
||||||
if (type === "Error") vtitle = `<span class="has-text-danger">${title}</span>`;
|
type === "Success"
|
||||||
|
? `<span class="has-text-primary">${title}</span>`
|
||||||
|
: type === "Error"
|
||||||
|
? `<span class="has-text-danger">${title}</span>`
|
||||||
|
: title;
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
id: $id(),
|
id: $id(),
|
||||||
component: `dialog/${type || "Info"}`,
|
component: `dialog/${type || "Info"}`,
|
||||||
vbind: { content: content, duration: duration, vbind: vbind },
|
vbind: { content, duration, vbind },
|
||||||
title: vtitle,
|
title: vtitle,
|
||||||
width: width || "600px",
|
width: width || "600px",
|
||||||
height: height || "100px",
|
height: height || "100px",
|
||||||
|
|||||||
@@ -1108,13 +1108,18 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
sort: "capacity",
|
sort: "capacity",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "IMEI",
|
||||||
|
url: "data/IMEI/",
|
||||||
|
url_detail: "data-detail/IMEI/",
|
||||||
|
params: {},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
const { $copy, $clone, $updateSeriesFields, $snackbar, $store, $remove, $dialog } = nuxtApp;
|
const { $copy, $clone, $updateSeriesFields, $snackbar, $store, $remove, $dialog } = nuxtApp;
|
||||||
|
|
||||||
const requestLogin = function () {
|
const requestLogin = function () {
|
||||||
$store.commit("login", undefined);
|
$store.commit("login", undefined);
|
||||||
$store.commit("layersetting", undefined);
|
$store.commit("layersetting", undefined);
|
||||||
$store.commit("lastlegendfiltertab", "Giỏ hàng");
|
|
||||||
window.location.href = `https://${mode === "dev" ? "dev." : ""}login.utopia.com.vn/signin?module=${module}&link=${window.location.origin}`;
|
window.location.href = `https://${mode === "dev" ? "dev." : ""}login.utopia.com.vn/signin?module=${module}&link=${window.location.origin}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1178,7 +1183,7 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
const insertapi = async function (name, data, values, notify) {
|
const insertapi = async function (name, data, values, notify) {
|
||||||
try {
|
try {
|
||||||
let found = findapi(name);
|
let found = findapi(name);
|
||||||
let curpath = found.path ? paths.find((x) => x.name === found.path).url : path;
|
const curpath = found.path ? paths.find((x) => x.name === found.path).url : path;
|
||||||
let rs;
|
let rs;
|
||||||
if (!Array.isArray(data)) {
|
if (!Array.isArray(data)) {
|
||||||
rs = await $fetch(`${curpath}${found.url}`, {
|
rs = await $fetch(`${curpath}${found.url}`, {
|
||||||
@@ -1190,15 +1195,15 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
rs = await $fetch(`${curpath}import-data/${found.url.substring(5, found.url.length - 1)}/`, {
|
rs = await $fetch(`${curpath}import-data/${found.url.substring(5, found.url.length - 1)}/`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: data,
|
body: data,
|
||||||
params: { action: "import", values },
|
params: { values, action: "import" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// update store
|
// update store
|
||||||
if (found.commit) {
|
if (found.commit) {
|
||||||
if ($store[found.commit]) {
|
if ($store[found.commit]) {
|
||||||
let copy = $copy($store[found.commit]);
|
const copy = $copy($store[found.commit]);
|
||||||
let rows = Array.isArray(rs) ? rs : [rs];
|
const rows = Array.isArray(rs) ? rs : [rs];
|
||||||
rows.map((v) => {
|
rows.forEach((v) => {
|
||||||
if (v.id && !v.error) {
|
if (v.id && !v.error) {
|
||||||
let idx = copy.findIndex((x) => x.id === v.id);
|
let idx = copy.findIndex((x) => x.id === v.id);
|
||||||
if (idx >= 0) copy[idx] = v;
|
if (idx >= 0) copy[idx] = v;
|
||||||
@@ -1441,16 +1446,15 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
// delete data
|
// delete data
|
||||||
const deleteapi = async function (name, id) {
|
const deleteapi = async function (name, id) {
|
||||||
try {
|
try {
|
||||||
var rs;
|
const found = findapi(name);
|
||||||
let found = findapi(name);
|
let rs;
|
||||||
if (!Array.isArray(id))
|
if (!Array.isArray(id)) {
|
||||||
rs = await $fetch(`${path}${found.url_detail}${id}`, {
|
rs = await $fetch(`${path}${found.url_detail}${id}`, {
|
||||||
method: "delete",
|
method: "delete",
|
||||||
});
|
});
|
||||||
else {
|
} else {
|
||||||
let params = { action: "delete" };
|
|
||||||
rs = await $fetch(`${path}import-data/${found.url.substring(5, found.url.length - 1)}/`, id, {
|
rs = await $fetch(`${path}import-data/${found.url.substring(5, found.url.length - 1)}/`, id, {
|
||||||
params,
|
params: { action: "delete" },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (found.commit) {
|
if (found.commit) {
|
||||||
@@ -1465,13 +1469,12 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
$store.commit(found.name, copy);
|
$store.commit(found.name, copy);
|
||||||
console.log("copy", copy);
|
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
if (err.response) {
|
if (err.response) {
|
||||||
let content = `<span class="has-text-danger">Đã xảy ra lỗi, xóa dữ liệu không thành công</span>`;
|
let content = `<span>Đã xảy ra lỗi, xóa dữ liệu không thành công</span>`;
|
||||||
if (err.response.data)
|
if (err.response.data)
|
||||||
content += `<p class="mt-2 has-text-grey-dark">
|
content += `<p class="mt-2 has-text-grey-dark">
|
||||||
<sapn class="icon-text">Chi tiết<SvgIcon class="ml-1" v-bind="{name: 'right.svg', type: 'dark', size: 20}"></SvgIcon></span></p>
|
<sapn class="icon-text">Chi tiết<SvgIcon class="ml-1" v-bind="{name: 'right.svg', type: 'dark', size: 20}"></SvgIcon></span></p>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ export const useStore = defineStore("maindev", {
|
|||||||
state: () => ({
|
state: () => ({
|
||||||
viewport: undefined,
|
viewport: undefined,
|
||||||
login: undefined,
|
login: undefined,
|
||||||
dealer: undefined,
|
|
||||||
token: undefined,
|
token: undefined,
|
||||||
common: undefined,
|
common: undefined,
|
||||||
settings: [],
|
settings: [],
|
||||||
@@ -18,15 +17,13 @@ export const useStore = defineStore("maindev", {
|
|||||||
branch: {},
|
branch: {},
|
||||||
rights: [],
|
rights: [],
|
||||||
product: [],
|
product: [],
|
||||||
cart: [],
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
commit(name, data) {
|
commit(name, data) {
|
||||||
// if (name === "common") {
|
// console.trace("commit", name, data);
|
||||||
// console.trace("commit", name, data);
|
|
||||||
// }
|
|
||||||
this[name] = data;
|
this[name] = data;
|
||||||
},
|
},
|
||||||
|
|
||||||
removeSnackbar() {
|
removeSnackbar() {
|
||||||
this.snackbar = undefined;
|
this.snackbar = undefined;
|
||||||
},
|
},
|
||||||
@@ -35,10 +32,6 @@ export const useStore = defineStore("maindev", {
|
|||||||
this.product = products;
|
this.product = products;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateCart(carts) {
|
|
||||||
this.cart = carts;
|
|
||||||
},
|
|
||||||
|
|
||||||
updateSingleProduct(updatedProduct) {
|
updateSingleProduct(updatedProduct) {
|
||||||
const index = this.product.findIndex((p) => p.id === updatedProduct.id);
|
const index = this.product.findIndex((p) => p.id === updatedProduct.id);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
@@ -54,7 +47,7 @@ export const useStore = defineStore("maindev", {
|
|||||||
},
|
},
|
||||||
|
|
||||||
persist: {
|
persist: {
|
||||||
pick: ["token", "login", "lang", "dealer", "lastlegendfiltertab", "layersetting"],
|
pick: ["token", "login", "lang"],
|
||||||
storage: piniaPluginPersistedstate.localStorage(),
|
storage: piniaPluginPersistedstate.localStorage(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
87
package-lock.json
generated
87
package-lock.json
generated
@@ -38,7 +38,8 @@
|
|||||||
"vue-pdf": "^4.3.0",
|
"vue-pdf": "^4.3.0",
|
||||||
"vue-router": "latest",
|
"vue-router": "latest",
|
||||||
"vue3-datepicker": "^0.4.0",
|
"vue3-datepicker": "^0.4.0",
|
||||||
"vue3-quill": "^0.3.1"
|
"vue3-quill": "^0.3.1",
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify-json/material-symbols": "^1.2.69",
|
"@iconify-json/material-symbols": "^1.2.69",
|
||||||
@@ -6010,6 +6011,14 @@
|
|||||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/adler-32": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/agent-base": {
|
"node_modules/agent-base": {
|
||||||
"version": "7.1.4",
|
"version": "7.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||||
@@ -7716,6 +7725,18 @@
|
|||||||
"url": "https://github.com/sponsors/wooorm"
|
"url": "https://github.com/sponsors/wooorm"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cfb": {
|
||||||
|
"version": "1.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
|
||||||
|
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"crc-32": "~1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/character-entities-html4": {
|
"node_modules/character-entities-html4": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
|
||||||
@@ -7968,6 +7989,14 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/codepage": {
|
||||||
|
"version": "1.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
|
||||||
|
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/collection-visit": {
|
"node_modules/collection-visit": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
|
||||||
@@ -8347,7 +8376,6 @@
|
|||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
|
||||||
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
"crc32": "bin/crc32.njs"
|
"crc32": "bin/crc32.njs"
|
||||||
@@ -10419,6 +10447,14 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/frac": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fraction.js": {
|
"node_modules/fraction.js": {
|
||||||
"version": "5.3.4",
|
"version": "5.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
|
||||||
@@ -17279,6 +17315,17 @@
|
|||||||
"node": ">=20.16.0"
|
"node": ">=20.16.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/ssf": {
|
||||||
|
"version": "0.11.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
|
||||||
|
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
|
||||||
|
"dependencies": {
|
||||||
|
"frac": "~1.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ssri": {
|
"node_modules/ssri": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
|
||||||
@@ -20361,6 +20408,22 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wmf": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/word": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/word-wrap": {
|
"node_modules/word-wrap": {
|
||||||
"version": "1.2.5",
|
"version": "1.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
|
||||||
@@ -20545,6 +20608,26 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/xlsx": {
|
||||||
|
"version": "0.18.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
|
||||||
|
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"adler-32": "~1.3.0",
|
||||||
|
"cfb": "~1.2.1",
|
||||||
|
"codepage": "~1.15.0",
|
||||||
|
"crc-32": "~1.2.1",
|
||||||
|
"ssf": "~0.11.2",
|
||||||
|
"wmf": "~1.0.1",
|
||||||
|
"word": "~0.3.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"xlsx": "bin/xlsx.njs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xmlbuilder": {
|
"node_modules/xmlbuilder": {
|
||||||
"version": "10.1.1",
|
"version": "10.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz",
|
||||||
|
|||||||
@@ -43,7 +43,8 @@
|
|||||||
"vue-pdf": "^4.3.0",
|
"vue-pdf": "^4.3.0",
|
||||||
"vue-router": "latest",
|
"vue-router": "latest",
|
||||||
"vue3-datepicker": "^0.4.0",
|
"vue3-datepicker": "^0.4.0",
|
||||||
"vue3-quill": "^0.3.1"
|
"vue3-quill": "^0.3.1",
|
||||||
|
"xlsx": "^0.18.5"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"vue": "latest"
|
"vue": "latest"
|
||||||
|
|||||||
Reference in New Issue
Block a user