This commit is contained in:
Viet An
2026-06-11 11:50:11 +07:00
parent a5a88b3b1c
commit 069ea1002c
20 changed files with 112 additions and 474 deletions

View File

@@ -128,6 +128,7 @@ const emit = defineEmits(["changeTab"]);
const { $find, $filter, $store, $snackbar } = useNuxtApp();
const lang = computed(() => $store.lang);
const menu = $filter($store.common, { category: "topmenu" });
const submenus = $filter($store.common, { category: "submenu" });
// if($store.rights.length>0) {
// menu = menu.filter(v=>$findIndex($store.rights, {setting: v.id})>=0)
// }
@@ -185,8 +186,9 @@ function openProfile() {
title: $store.lang === "vi" ? "Thông tin cá nhân" : "User profile",
});
}
const found = route.query.tab && $find(menu, { code: route.query.tab });
if (found || currentTab.value) changeTab(found || currentTab.value);
const foundTab = route.query.tab && $find(menu, { code: route.query.tab });
const foundSub = route.query.subtab && $find(submenus, { code: route.query.subtab });
if (foundTab || currentTab.value) changeTab(foundTab || currentTab.value, foundSub);
onMounted(() => {
if (!$store.login) return;

View File

@@ -1,20 +0,0 @@
<template>
<ImageGallery
v-bind="{ row, pagename, show, api: 'applicationfile' }"
@remove="emit('remove')"
@update="update"
></ImageGallery>
</template>
<script setup>
import ImageGallery from "../media/ImageGallery.vue";
import { defineProps, defineEmits } from "vue";
const props = defineProps({
row: Object,
pagename: String,
api: String,
});
const emit = defineEmits(["remove"]);
</script>

View File

@@ -1,5 +1,5 @@
<template>
<div class="field has-addons is-justify-content-center">
<div class="toolbar field has-addons is-justify-content-center">
<!-- <div class="control">
<button
class="button is-light is-primary"
@@ -431,6 +431,7 @@
<script setup>
import { useStore } from "~/stores/index";
import ScrollBox from "~/components/datatable/ScrollBox.vue";
import { cloneDeep, isEqual } from "es-toolkit";
const props = defineProps({
pagename: String,
@@ -439,7 +440,7 @@ const props = defineProps({
filterData: Object,
width: String,
});
const { $copy, $stripHtml, $clone, $arrayMove, $snackbar, $copyToClipboard } = useNuxtApp();
const { $copy, $stripHtml, $arrayMove, $snackbar, $copyToClipboard } = useNuxtApp();
const emit = defineEmits(["modalevent", "changepos", "close"]);
const store = useStore();
const { colorchoice } = store;
@@ -504,7 +505,7 @@ var search = undefined;
// }
//==============================================================
function moveLeft() {
let copy = $clone(pagedata);
const copy = cloneDeep(pagedata);
let i = copy.fields.findIndex((v) => v.name === props.field.name);
let idx = i - 1 >= 0 ? i - 1 : copy.fields.length - 1;
$arrayMove(copy.fields, i, idx);
@@ -513,7 +514,7 @@ function moveLeft() {
emit("changepos");
}
function moveRight() {
let copy = $clone(pagedata);
const copy = cloneDeep(pagedata);
let i = copy.fields.findIndex((v) => v.name === props.field.name);
let idx = copy.fields.length - 1 > i ? i + 1 : 0;
$arrayMove(copy.fields, i, idx);
@@ -522,7 +523,7 @@ function moveRight() {
emit("changepos");
}
function hideField() {
let copy = $clone(store[props.pagename]);
const copy = cloneDeep(store[props.pagename]);
let found = copy.fields.find((v) => v.name === props.field.name);
found.show = false;
copy.update = { fields: copy.fields };
@@ -530,7 +531,7 @@ function hideField() {
emit("close");
}
function doRemove() {
let copy = $clone(store[props.pagename]);
const copy = cloneDeep(store[props.pagename]);
let idx = copy.fields.findIndex((v) => v.name === props.field.name);
copy.fields.splice(idx, 1);
copy.update = { fields: copy.fields };
@@ -593,7 +594,7 @@ function close() {
showmodal.value = undefined;
}
const updateFields = function (field, type) {
let copy = $clone(store[props.pagename]);
let copy = cloneDeep(store[props.pagename]);
let idx = copy.fields.findIndex((v) => v.name === field.name);
copy.fields[idx] = field;
store.commit(props.pagename, copy);
@@ -619,14 +620,14 @@ const showSidebar = function () {
else if (event.name === "template") title = `Định dạng nâng cao: ${$stripHtml(event.field.label, 30)}`;
showmodal.value = {
component: "datatable/FormatOption",
width: "850px",
height: "500px",
title,
vbind: {
event: event,
currentField: currentField,
event,
currentField,
pagename: props.pagename,
},
width: "850px",
height: "600px",
title: title,
};
};
function resizeWidth(minus) {
@@ -644,7 +645,7 @@ function resizeWidth(minus) {
}
</script>
<style lang="css" scoped>
.control {
.toolbar .control {
flex-grow: 1;
> button {

View File

@@ -93,11 +93,11 @@
v-if="type.code === 'tag'"
>
<a
:class="getClass(v)"
v-for="(v, i) in colorscheme"
:key="i"
@click="doSelect(v)"
:ref="'tag' + i"
:class="getClass(v)"
@click="doSelect(v)"
>
{{ v.name }}
</a>
@@ -117,15 +117,15 @@
{{ v.name }}
</a>
</div>
<div :class="`tabs is-boxed mt-5 mb-5 ${tab.code === 'template' ? '' : 'pb-2'}`">
<div :class="['tabs is-boxed', tab.code !== 'template' && 'pb-2']">
<ul>
<li
:class="tab.code === v.code ? 'is-active' : ''"
v-for="(v, i) in tabs"
:key="i"
:class="tab.code === v.code && 'is-active'"
@click="changeTab(v)"
>
<a class="">{{ v.name }}</a>
<a class="has-text-inherit">{{ v.name }}</a>
</li>
</ul>
</div>
@@ -151,14 +151,21 @@
</p>
<p class="control">
<a @click="remove(i)">
<SvgIcon v-bind="{ name: 'close.svg', type: 'danger', size: 22 }"></SvgIcon>
<Icon
name="material-symbols:close-rounded"
:size="20"
class="has-text-danger"
/>
</a>
</p>
<p
class="control has-text-right ml-5"
v-if="selected ? selected.id === v.id : false"
v-if="selected?.id === v.id"
class="control has-text-right"
>
<SvgIcon v-bind="{ name: 'tick.svg', type: 'primary', size: 22 }"></SvgIcon>
<Icon
name="material-symbols:check-rounded"
:size="20"
/>
</p>
</div>
</a>
@@ -166,18 +173,23 @@
<template v-else-if="tab.code === 'condition'">
<div
class="mb-5"
v-if="selected"
class="mb-5 control"
>
<b-radio
<label
v-for="(v, i) in conditions"
:key="i"
v-model="condition"
:native-value="v"
@input="changeCondition(v)"
class="radio is-block"
>
<input
type="radio"
name="condition"
:value="v"
v-model="condition"
@change="changeCondition(v)"
/>
{{ v.name }}
</b-radio>
</label>
</div>
<template v-if="condition ? condition.code === 'yes' : false">
@@ -482,7 +494,7 @@ var conditions = [
{ code: "yes", name: "Có áp dụng" },
];
var condition = undefined;
var tags = [];
const tags = ref([]);
var selected = undefined;
var tabs = [
{ code: "selected", name: "Bước 1: Tạo nội dung" },
@@ -623,17 +635,17 @@ const checkExpression = function () {
};
const changeType = function (v) {};
const doSelect = function (v) {
tags.push({ id: $id(), name: v.name, class: getClass(v) });
tab = tabs.find((v) => v.code === "selected");
selected = tags[tags.length - 1];
tags.value.push({ id: $id(), name: v.name, class: getClass(v) });
tab.value = tabs.find((v) => v.code === "selected");
selected = tags.value[tags.value.length - 1];
};
const doSelectSpan = function (v) {
tags.push({ id: $id(), name: v.name, class: getSpanClass(v) });
tab = tabs.find((v) => v.code === "selected");
selected = tags[tags.length - 1];
tags.value.push({ id: $id(), name: v.name, class: getSpanClass(v) });
tab.value = tabs.find((v) => v.code === "selected");
selected = tags.value[tags.value.length - 1];
};
const remove = function (i) {
$remove(tags, i);
tags.value.splice(i, 1);
};
const getClass = function (v) {
let value = type.code + " " + v.code + " " + size.code + (shape.code === "default" ? "" : " " + shape.code);

View File

@@ -51,7 +51,7 @@
</div>
</div>
<div
class="table-container rounded mb-0"
class="table-container mb-0"
ref="container"
id="docid"
>
@@ -239,7 +239,7 @@ const updateShow = function (full_data) {
showPagination();
};
function confirmRemove() {
$deleterow(pagedata.api.name, currentRow.id, props.pagename, true);
$deleterow(pagedata.api.name, currentRow.id, props.pagename);
}
const clickEvent = function (event, row, field) {
const name = typeof event === "string" ? event : event.name;
@@ -280,9 +280,7 @@ const showField = async function (field) {
};
const getStyle = function (field, record) {
let stop = false;
let val = tablesetting.find((v) => v.code === "td-border")
? tablesetting.find((v) => v.code === "td-border").detail
: "border: solid 1px rgb(44, 44, 44); ";
let val = getDetail("td-border");
val = val.indexOf(";") >= 0 ? val : val + ";";
if (field.bgcolor ? !Array.isArray(field.bgcolor) : false) {
val += ` background-color:${field.bgcolor}; `;

View File

@@ -38,6 +38,7 @@ import { useStore } from "~/stores/index";
// [FIX] Thêm onActivated, onDeactivated để xử lý KeepAlive
import { ref, watch, onBeforeUnmount, onActivated, onDeactivated } from "vue";
import DataTable from "~/components/datatable/DataTable.vue";
import { cloneDeep } from "es-toolkit";
const emit = defineEmits(["modalevent", "dataevent", "dataUpdated"]);
const store = useStore();
@@ -55,7 +56,7 @@ const props = defineProps({
importdata: Object,
});
const { $copy, $find, $findapi, $getapi, $setpage, $clone, $stripHtml, $snackbar, $dayjs } = useNuxtApp();
const { $copy, $find, $findapi, $getapi, $setpage, $stripHtml, $snackbar, $dayjs } = useNuxtApp();
const showmodal = ref();
const pagedata = ref();
@@ -235,7 +236,7 @@ const openImportModal = () => {
};
const updateDataDisplay = (newData) => {
const copy = $clone(store[vpagename]);
const copy = cloneDeep(store[vpagename]);
copy.data = newData;
copy.update = { data: newData };
store.commit(vpagename, copy);
@@ -406,7 +407,7 @@ const getApi = async () => {
}
pagedata.value = $setpage(vpagename, row, obj);
const copy = $clone(pagedata.value);
const copy = cloneDeep(pagedata.value);
copy.data = data;
copy.update = { data };
store.commit(vpagename, copy);

View File

@@ -230,39 +230,37 @@
</CreateTemplate>
</template>
<script setup>
// FilterOption: () => import("~/components/datatable/FilterOption"),
// TableOption: () => import("~/components/datatable/TableOption"),
// CreateTemplate: () => import("~/components/datatable/CreateTemplate")
import CreateTemplate from "~/components/datatable/CreateTemplate";
import FilterOption from "~/components/datatable/FilterOption.vue";
import TableOption from "~/components/datatable/TableOption.vue";
const { $id, $copy, $empty, $stripHtml } = useNuxtApp();
var props = defineProps({
const props = defineProps({
event: Object,
currentField: Object,
pagename: String,
});
var currentField = props.currentField;
var event = props.event;
var openField = {};
var bgcolorFilter = [];
var colorFilter = [];
var sizeFilter = [];
var sideBar = undefined;
var sideBar = ref();
var script = undefined;
var radio = undefined;
var tabs = [
{ code: "expression", name: "Biểu thức" },
{ code: "script", name: "Mã lệnh" },
];
var tab = { code: "expression", name: "Biểu thức" };
const tab = ref({ code: "expression", name: "Biểu thức" });
var source = undefined;
var target = $copy(currentField.name);
const initData = function () {
openField = event.field;
sideBar = event.name;
script = event.script;
radio = event.radio;
let field = event.field;
openField = props.event.field;
sideBar.value = props.event.name;
script = props.event.script;
radio = props.event.radio;
let field = props.event.field;
bgcolorFilter = [{ id: $id() }];
if (field.bgcolor) {
if (Array.isArray(field.bgcolor)) bgcolorFilter = $copy(field.bgcolor);
@@ -310,7 +308,7 @@ const checkScript = function () {
const changeScript = function () {
if (!checkScript()) return;
let copy = $copy(openField);
copy[sideBar] = JSON.parse(script);
copy[sideBar.value] = JSON.parse(script);
$emit("modalevent", { name: "updatefields", data: copy });
};
const doConditionFilter = function (v, type, id) {

View File

@@ -1,221 +0,0 @@
<template>
<div class="tabs">
<ul>
<li
:class="`${v.code === tab ? 'is-active has-text-weight-bold fs-18' : 'fs-18'}`"
v-for="v in tabs"
>
<a @click="changeTab(v)">{{ v.name }}</a>
</li>
</ul>
</div>
<template v-if="tab === 'datatype'">
<Caption
class="mb-3"
v-bind="{ title: 'Kiểu dữ liệu (type)', type: 'has-text-warning' }"
></Caption>
<div
class="py-1 border-bottom is-clickable"
v-for="x in current.fields"
>
{{ x.name }}
<span class="ml-6 has-text-grey">{{ x.type }}</span>
<a
class="ml-6 has-text-primary"
v-if="x.model"
@click="openModel(x)"
>{{ x.model }}</a
>
</div>
</template>
<template v-else>
<div class="columns mx-0 mb-0 pb-0">
<div class="column is-7">
<Caption
class="mb-2"
v-bind="{ title: 'Values', type: 'has-text-warning' }"
></Caption>
<input
class="input"
rows="1"
v-model="values"
/>
</div>
<div class="column is-4s">
<Caption
class="mb-2"
v-bind="{ title: 'Filter', type: 'has-text-warning' }"
></Caption>
<input
class="input"
rows="1"
v-model="filter"
/>
</div>
<div class="column is-1">
<Caption
class="mb-2"
v-bind="{ title: 'Load', type: 'has-text-warning' }"
></Caption>
<div>
<button
class="button is-primary has-text-white"
@click="loadData()"
>
Load
</button>
</div>
</div>
</div>
<Caption
class="mb-2"
v-bind="{ title: 'Query', type: 'has-text-warning' }"
></Caption>
<div class="mb-4">
{{ query }}
<a
class="has-text-primary ml-5"
@click="copy()"
>copy</a
>
<p>
{{ apiUrl }}
<a
class="has-text-primary ml-5"
@click="$copyToClipboard(apiUrl)"
>copy</a
>
<a
class="has-text-primary ml-5"
target="_blank"
:href="apiUrl"
>open</a
>
</p>
</div>
<div>
<Caption
class="mb-2"
v-bind="{ title: 'Data', type: 'has-text-warning' }"
></Caption>
<DataTable
v-bind="{ pagename: pagename }"
v-if="pagedata"
/>
</div>
</template>
<Modal
@close="showmodal = undefined"
v-bind="showmodal"
v-if="showmodal"
></Modal>
</template>
<script setup>
import { useStore } from "~/stores/index";
var props = defineProps({
data: Array,
info: Object,
});
const { $getdata, $getapi, $createField, $clone, $getpage, $empty, $copyToClipboard, $find } = useNuxtApp();
const store = useStore();
var pagename = "pagedata99";
var pagedata = ref();
pagedata.value = $getpage();
store.commit(pagename, pagedata);
let list = ["LogEntry", "Permission", "ContentType", "Session", "Group"];
var current = ref({ fields: [] });
var tabs = [
{ code: "datatype", name: "Kiểu dữ liệu" },
{ code: "table", name: "Dữ liệu" },
];
var tab = ref("datatype");
var datatable = ref();
var query = ref();
var values, filter;
var apiUrl = ref();
var showmodal = ref();
var data = props.data;
current.value = props.info;
function changeMenu(v) {
values = undefined;
filter = undefined;
current.value = v;
if (tab.value === "table") loadData();
}
async function changeTab(v) {
tab.value = v.code;
if (v.code === "table") loadData();
}
async function loadData() {
let vfilter = filter ? filter.trim() : undefined;
if (vfilter) {
try {
vfilter = JSON.parse(vfilter);
} catch (error) {
alert("Cấu trúc filter có lỗi");
vfilter = undefined;
}
}
let params = { values: values ? values.trim() : undefined, filter: filter };
let modelName = current.value.model;
let found = {
name: modelName.toLowerCase().replace("_", ""),
url: `data/${modelName}/`,
url_detail: `data-detail/${modelName}/`,
params: params,
};
query.value = $clone(found);
let rs = await $getapi([found]);
if (rs === "error") return alert("Đã xảy ra lỗi, hãy xem lại câu lệnh.");
datatable.value = rs[0].data.rows;
showData();
// api query
const baseUrl = "https://api.y99.vn/" + `${query.value.url}`;
apiUrl.value = baseUrl;
let vparams = !$empty(values) ? { values: values } : null;
if (!$empty(filter)) {
vparams = vparams ? { values: values, filter: filter } : { filter: filter };
}
if (vparams) {
let url = new URL(baseUrl);
let searchParams = new URLSearchParams(vparams);
url.search = searchParams.toString();
apiUrl.value = baseUrl + url.search;
}
}
function showData() {
let arr = [];
if (!$empty(values)) {
let arr1 = values.trim().split(",");
arr1.map((v) => {
let val = v.trim();
let field = $createField(val, val, "string", true);
arr.push(field);
});
} else {
current.value.fields.map((v) => {
let field = $createField(v.name, v.name, "string", true);
arr.push(field);
});
}
let clone = $clone(pagedata.value);
clone.fields = arr;
clone.data = datatable.value;
pagedata.value = undefined;
setTimeout(() => (pagedata.value = clone));
}
function copy() {
$copyToClipboard(JSON.stringify(query.value));
}
function openModel(x) {
showmodal.value = {
component: "datatable/ModelInfo",
title: x.model,
width: "70%",
height: "600px",
vbind: { data: data, info: $find(data, { model: x.model }) },
};
}
</script>
s

View File

@@ -257,10 +257,11 @@
/>
</template>
<script setup>
import { cloneDeep } from "es-toolkit";
import { useStore } from "~/stores/index";
const emit = defineEmits(["modalevent"]);
const store = useStore();
const { $id, $copy, $clone, $empty, $stripHtml, $createField, $calc, $isNumber } = useNuxtApp();
const { $id, $copy, $empty, $stripHtml, $createField, $calc, $isNumber } = useNuxtApp();
var props = defineProps({
pagename: String,
field: Object,
@@ -460,7 +461,7 @@ function createEmptyField() {
if (errors.value.length > 0) return;
let field = $createField(name.trim(), label.trim(), radioType.value.code, true);
if (selectType.code === "chart") field = createChartField();
let copy = $clone(pagedata);
let copy = cloneDeep(pagedata);
copy.fields.push(field);
copy.update = { fields: copy.fields };
store.commit(props.pagename, copy);

View File

@@ -193,6 +193,7 @@
import TimeOption from "~/components/datatable/TimeOption";
import { ref, computed, watch, onMounted, onBeforeUnmount, defineComponent } from "vue";
import { useStore } from "~/stores/index";
import { cloneDeep } from "es-toolkit";
const emit = defineEmits(["modalevent", "dataevent", "dataUpdated", "edit", "insert"]);
const store = useStore();
@@ -217,7 +218,6 @@ const {
$findapi,
$getapi,
$setpage,
$clone,
$stripHtml,
$snackbar,
$dayjs,
@@ -897,7 +897,7 @@ const loadFullDataAsync = async () => {
};
const updateDataDisplay = (newData) => {
const copy = $clone(store[vpagename]);
const copy = cloneDeep(store[vpagename]);
copy.data = newData;
copy.update = { data: newData };
store.commit(vpagename, copy);
@@ -1023,7 +1023,7 @@ const getApi = async () => {
}
pagedata.value = $setpage(vpagename, row, obj);
const copy = $clone(pagedata.value);
const copy = cloneDeep(pagedata.value);
copy.data = data;
copy.update = { data: data };
store.commit(vpagename, copy);

View File

@@ -27,64 +27,6 @@
/>
</span>
</td>
<p
class="control py-0"
v-if="show"
>
<span
class="icon-text has-text-grey mr-2 fs-13"
v-if="show.author"
>
<SvgIcon v-bind="{ name: 'user.svg', type: 'gray', size: 15 }"></SvgIcon>
<span>{{ v[show.author] }}</span>
</span>
<span
class="icon-text has-text-grey mr-2 fs-13"
v-if="show.view"
>
<SvgIcon v-bind="{ name: 'view.svg', type: 'gray', size: 15 }"></SvgIcon>
<span>{{ v[show.view] }}</span>
</span>
<span
class="fs-13 has-text-grey"
v-if="show.time"
>{{ $dayjs(v["create_time"]).fromNow(true) }}</span
>
<span class="tooltip">
<a
class="icon ml-1"
v-if="show.link"
@click="doClick(v, i, 'newtab')"
>
<SvgIcon v-bind="{ name: 'opennew.svg', type: 'gray', size: 15 }"></SvgIcon>
</a>
<span class="tooltiptext">Mở trong tab mới</span>
</span>
<span
class="tooltip"
v-if="show.rename"
>
<a
class="icon ml-1"
@click="$emit('rename', v, i)"
>
<SvgIcon v-bind="{ name: 'pen1.svg', type: 'gray', size: 15 }"></SvgIcon>
</a>
<span class="tooltiptext">Đổi tên</span>
</span>
<span
class="tooltip"
v-if="show.rename"
>
<a
class="icon has-text-danger ml-1"
@click="$emit('remove', v, i)"
>
<SvgIcon v-bind="{ name: 'bin1.svg', type: 'gray', size: 15 }"></SvgIcon>
</a>
<span class="tooltiptext">Xóa</span>
</span>
</p>
</tr>
</tbody>
</table>
@@ -110,64 +52,6 @@
/>
</span>
</button>
<p
class="control py-0"
v-if="show"
>
<span
class="icon-text has-text-grey mr-2 fs-13"
v-if="show.author"
>
<SvgIcon v-bind="{ name: 'user.svg', type: 'gray', size: 15 }"></SvgIcon>
<span>{{ v[show.author] }}</span>
</span>
<span
class="icon-text has-text-grey mr-2 fs-13"
v-if="show.view"
>
<SvgIcon v-bind="{ name: 'view.svg', type: 'gray', size: 15 }"></SvgIcon>
<span>{{ v[show.view] }}</span>
</span>
<span
class="fs-13 has-text-grey"
v-if="show.time"
>{{ $dayjs(v["create_time"]).fromNow(true) }}</span
>
<span class="tooltip">
<a
class="icon ml-1"
v-if="show.link"
@click="doClick(v, i, 'newtab')"
>
<SvgIcon v-bind="{ name: 'opennew.svg', type: 'gray', size: 15 }"></SvgIcon>
</a>
<span class="tooltiptext">Mở trong tab mớ</span>
</span>
<span
class="tooltip"
v-if="show.rename"
>
<a
class="icon ml-1"
@click="$emit('rename', v, i)"
>
<SvgIcon v-bind="{ name: 'pen1.svg', type: 'gray', size: 15 }"></SvgIcon>
</a>
<span class="tooltiptext">Đổi tên</span>
</span>
<span
class="tooltip"
v-if="show.rename"
>
<a
class="icon has-text-danger ml-1"
@click="$emit('remove', v, i)"
>
<SvgIcon v-bind="{ name: 'bin1.svg', type: 'gray', size: 15 }"></SvgIcon>
</a>
<span class="tooltiptext">Xóa</span>
</span>
</p>
</div>
</div>
</template>
@@ -180,7 +64,6 @@ const props = defineProps({
sort: String,
selects: String,
keyval: String,
show: Object,
notick: Boolean,
inContext: Boolean,
clearTrigger: Number,
@@ -224,9 +107,6 @@ function getdata() {
array.value = $copy(props.data);
if (props.sort) {
const f = {};
if (props.show?.time) {
f.create_time = "desc";
}
if (props.sort.startsWith("-")) {
f[props.sort.slice(1)] = "desc";

View File

@@ -77,9 +77,10 @@
></Modal>
</template>
<script setup>
import { cloneDeep } from "es-toolkit";
import { useStore } from "~/stores/index";
const emit = defineEmits(["close"]);
const { $stripHtml, $clone, $arrayMove, $remove } = useNuxtApp();
const { $stripHtml, $arrayMove, $remove } = useNuxtApp();
const store = useStore();
var props = defineProps({
pagename: String,
@@ -100,7 +101,7 @@ function openField(v, i) {
}
function update(data) {
fields.value[current.i] = data;
let copy = $clone(pagedata);
let copy = cloneDeep(pagedata);
copy.fields = fields.value;
copy.update = { fields: fields.value };
store.commit(props.pagename, copy);
@@ -108,7 +109,7 @@ function update(data) {
emit("close");
}
function updateField() {
let copy = $clone(pagedata);
let copy = cloneDeep(pagedata);
copy.fields = fields.value;
copy.update = { fields: fields.value };
store.commit(props.pagename, copy);

View File

@@ -166,12 +166,14 @@
</button>
</template>
<script setup>
import { cloneDeep } from "es-toolkit";
const props = defineProps({
pagename: String,
});
const emit = defineEmits(["close"]);
const { $copy, $clone, $empty, $store } = useNuxtApp();
let pagedata = $clone($store[props.pagename]);
const { $copy, $empty, $store } = useNuxtApp();
let pagedata = cloneDeep($store[props.pagename]);
if (!pagedata.tablesetting) {
pagedata.tablesetting = [];
}

View File

@@ -128,6 +128,8 @@
</template>
<script>
import { cloneDeep } from "es-toolkit";
export default {
props: ["code"],
data() {
@@ -347,7 +349,7 @@ export default {
field.color = "red";
let fields = this.$copy(this.pagedata.fields);
fields = [field].concat(fields);
const copy = this.$clone(this.pagedata);
const copy = cloneDeep(this.pagedata);
copy.data = data;
copy.fields = fields;
copy.update = { data, fields };
@@ -511,7 +513,7 @@ export default {
key: "data",
data,
});
const copy = this.$clone(this.pagedata);
const copy = cloneDeep(this.pagedata);
this.pagedata = undefined;
setTimeout(() => (this.pagedata = copy), 10);
},

View File

@@ -36,14 +36,14 @@ function getViewport() {
// Follow Bulma's breakpoints: https://bulma.io/documentation/start/responsiveness/#breakpoints
if (width <= 768)
viewport = 1; // 'mobile'
viewport = 1; // mobile
else if (width <= 1023)
viewport = 2; // 'tablet'
viewport = 2; // tablet
else if (width <= 1215)
viewport = 3; // 'desktop'
viewport = 3; // desktop
else if (width <= 1407)
viewport = 4; // 'widescreen'
else viewport = 5; // 'fullhd'
viewport = 4; // widescreen
else viewport = 5; // fullhd
if (viewport !== $store.viewport) {
$store.commit("viewport", viewport);

View File

@@ -91,22 +91,6 @@ export default defineNuxtPlugin(() => {
return structuredClone(toRawDeep(val));
};
const clone = function (obj) {
if (obj === null || typeof obj !== "object" || "isActiveClone" in obj) return obj;
let temp;
if (obj instanceof Date)
temp = new obj.constructor(); //or new Date(obj);
else temp = obj.constructor();
for (let key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
obj["isActiveClone"] = null;
temp[key] = clone(obj[key]);
delete obj["isActiveClone"];
}
}
return temp;
};
const remove = function (arr, idx) {
arr.splice(idx, 1);
};
@@ -459,7 +443,6 @@ export default defineNuxtPlugin(() => {
empty,
toRawDeep,
copy,
clone,
remove,
stripHtml,
isNumber,

View File

@@ -1,5 +1,7 @@
/** @typedef {import('~/utils/apis').ApiName} ApiName */
import { cloneDeep } from "es-toolkit";
export default defineNuxtPlugin((nuxtApp) => {
const module = "application";
const mode = "dev";
@@ -9,7 +11,7 @@ export default defineNuxtPlugin((nuxtApp) => {
{ name: "prod", url: "https://erpapi.bigdatatech.vn/" },
];
const path = paths.find((v) => v.name === mode).url;
const { $copy, $clone, $updateSeriesFields, $snackbar, $store, $remove, $dialog } = nuxtApp;
const { $copy, $updateSeriesFields, $snackbar, $store, $remove, $dialog } = nuxtApp;
const requestLogin = function () {
$store.commit("login", undefined);
@@ -274,7 +276,7 @@ export default defineNuxtPlugin((nuxtApp) => {
return;
}
const params = $clone(apiConfig.params) || {};
const params = cloneDeep(apiConfig.params) || {};
// List of parameters that need to be stringified if they are objects
const paramsToJSONify = ["filter_or", "exclude", "distinct_values", "calculation", "final_filter", "final_exclude"];
@@ -302,7 +304,7 @@ export default defineNuxtPlugin((nuxtApp) => {
const insertrow = async function (name, data, values, pagename, notify) {
let result = await insertapi(name, { data, values, notify });
if (result === "error" || !pagename || !$store[pagename]) return result;
let copy = $clone($store[pagename]);
let copy = cloneDeep($store[pagename]);
copy.update = { refresh: true };
$store.commit(pagename, copy);
return result;
@@ -311,7 +313,7 @@ export default defineNuxtPlugin((nuxtApp) => {
const updaterow = async function (name, data, values, pagename, notify) {
let result = await patchapi(name, data, values, notify);
if (result === "error" || !pagename || !$store[pagename]) return result;
let copy = $clone($store[pagename]);
let copy = cloneDeep($store[pagename]);
copy.update = { refresh: true };
$store.commit(pagename, copy);
return result;
@@ -374,7 +376,7 @@ export default defineNuxtPlugin((nuxtApp) => {
const deleterow = async function (name, id, pagename) {
const result = await deleteapi(name, id);
if (result === "error" || !pagename || !$store[pagename]) return result;
const copy = $clone($store[pagename]);
const copy = cloneDeep($store[pagename]);
copy.update = { refresh: true };
$store.commit(pagename, copy);
return result;
@@ -382,7 +384,7 @@ export default defineNuxtPlugin((nuxtApp) => {
// update page
const updatepage = function (pagename, row, action) {
let copy = $clone($store[pagename]);
let copy = cloneDeep($store[pagename]);
let rows = Array.isArray(row) ? row : [row];
rows.map((x) => {
let idx = copy.data.findIndex((v) => v.id === x.id);

View File

@@ -1,22 +1,21 @@
export default defineNuxtPlugin(async (nuxtApp) => {
const { $getapi, $readyapi } = nuxtApp;
const connlist = $readyapi([
"datatype",
"common",
"tablesetting",
"datatype",
"filtertype",
"sorttype",
"settingtype",
"settingclass",
"settingchoice",
"filterchoice",
"colorchoice",
"sharechoice",
"menuchoice",
"textalign",
"placement",
"colorscheme",
"filtertype",
"sorttype",
"tablesetting",
"settingchoice",
"sharechoice",
"menuchoice",
"settingtype",
"settingclass",
"sex",
]);
const notReadyConns = connlist.filter((v) => !v.ready);
if (notReadyConns.length > 0) await $getapi(notReadyConns);

View File

@@ -1,4 +1,3 @@
import SvgIcon from "~/components/SvgIcon.vue";
import Datepicker from "~/components/datepicker/Datepicker.vue";
import DataTable from "~/components/datatable/DataTable.vue";
@@ -90,7 +89,6 @@ const components = {
CountWithAdd,
MenuAction,
Email,
SvgIcon,
Datepicker,
ImageGallery,
FileGallery,

View File

@@ -14,7 +14,6 @@ export const useStore = defineStore("maindev", {
branch: {},
rights: [],
product: [],
customer: undefined,
}),
actions: {
commit(name, data) {
@@ -24,7 +23,7 @@ export const useStore = defineStore("maindev", {
},
persist: {
pick: ["token", "login", "lang", "customer"],
pick: ["token", "login", "lang"],
storage: piniaPluginPersistedstate.localStorage(),
},
});