changes
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="fixed-grid has-3-cols">
|
||||
<div class="grid">
|
||||
<div
|
||||
class="cell"
|
||||
v-for="rule in recordRules"
|
||||
:key="rule.code"
|
||||
>
|
||||
<label class="radio">
|
||||
<input
|
||||
type="radio"
|
||||
name="answer"
|
||||
:value="rule.code"
|
||||
v-model="recordCurrent"
|
||||
/>
|
||||
{{ isVietnamese ? rule.vi : rule.en }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const { $updateapi, $snackbar, $getdata, $store } = useNuxtApp();
|
||||
var props = defineProps({
|
||||
api: String,
|
||||
pagename: String,
|
||||
row: Object,
|
||||
prefix: String,
|
||||
});
|
||||
|
||||
const isVietnamese = computed(() => $store.lang.toLowerCase() === "vi");
|
||||
|
||||
const recordRules = ref([]);
|
||||
const recordCurrent = ref({});
|
||||
let current = {};
|
||||
|
||||
let foundCurrent = await $getdata(props.api, {
|
||||
category: "system",
|
||||
classify: "current",
|
||||
code: "rule",
|
||||
});
|
||||
|
||||
if (foundCurrent !== "error" && foundCurrent.length > 0) {
|
||||
recordCurrent.value = foundCurrent[0].detail;
|
||||
current.value = foundCurrent[0];
|
||||
}
|
||||
|
||||
let foundRules = await $getdata(props.api, {
|
||||
category: "system",
|
||||
classify: "rules",
|
||||
});
|
||||
if (foundRules !== "error" && foundRules.length > 0) {
|
||||
recordRules.value = foundRules;
|
||||
}
|
||||
|
||||
watch(recordCurrent, async (newVal) => {
|
||||
current.value.detail = newVal;
|
||||
let rs = await $updateapi(props.api, current.value, null);
|
||||
if (rs === "error") return $snackbar(rs);
|
||||
});
|
||||
</script>
|
||||
@@ -1,107 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<label class="label">Mã <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.code"
|
||||
id="code"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Tên <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.name"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal mt-5">
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<label class="label">Điện thoại <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.phone"
|
||||
id="code"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Email <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.email"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-horizontal mt-5">
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<label class="label">Địa chỉ <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.address"
|
||||
id="code"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<button
|
||||
class="button is-primary has-text-white"
|
||||
@click="update()"
|
||||
>
|
||||
Lưu lại
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
const { $copy, $resetNull, $insertrow, $updaterow, $snackbar, $updatepage } = useNuxtApp();
|
||||
var props = defineProps({
|
||||
api: String,
|
||||
pagename: String,
|
||||
row: Object,
|
||||
prefix: String,
|
||||
});
|
||||
const emit = defineEmits(["close", "modalevent"]);
|
||||
var record = $copy(props.row || {});
|
||||
async function update() {
|
||||
let data = $resetNull(record);
|
||||
let rs = data.id
|
||||
? await $updaterow(props.api, data, undefined, props.pagename)
|
||||
: await $insertrow(props.api, data, undefined, props.pagename);
|
||||
$updatepage(props.pagename, rs);
|
||||
if (rs === "error") return $snackbar(rs);
|
||||
emit("modalevent", { name: "dataevent", data: rs });
|
||||
emit("close");
|
||||
}
|
||||
onMounted(() => {
|
||||
document.getElementById("code").focus();
|
||||
});
|
||||
</script>
|
||||
@@ -1,62 +0,0 @@
|
||||
<template>
|
||||
<div class="content-delete-cart">
|
||||
<div class="container is-fluid px-4">
|
||||
<div v-if="productRes.length">
|
||||
<p>
|
||||
Không thể thực hiện thao tác vì giỏ hàng vẫn còn sản phẩm. Vui lòng xóa toàn bộ sản phẩm trong giỏ hàng trước
|
||||
khi tiếp tục.
|
||||
</p>
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>
|
||||
Bạn có chắc chắn muốn xóa giỏ hàng [{{ props.row.code.toUpperCase() }} – {{ props.row.name.toUpperCase() }}]
|
||||
không?
|
||||
</p>
|
||||
<div class="action mt-3">
|
||||
<button
|
||||
class="button is-light"
|
||||
@click="handleCancel"
|
||||
>
|
||||
Hủy
|
||||
</button>
|
||||
<button
|
||||
class="button is-primary"
|
||||
@click="handleDeleteCart"
|
||||
>
|
||||
Đồng ý
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const { $snackbar, $getdata, $deleteapi, $copy } = useNuxtApp();
|
||||
|
||||
const emit = defineEmits(["close"]);
|
||||
const props = defineProps({
|
||||
row: Object,
|
||||
});
|
||||
|
||||
const productRes = await $getdata("product", { cart: props.row.id });
|
||||
const cartRes = await $getdata("cart");
|
||||
$copy("cart", cartRes);
|
||||
const handleDeleteCart = async () => {
|
||||
const res = await $deleteapi("cart", props.row.id);
|
||||
if (res) {
|
||||
emit("close");
|
||||
$snackbar("Xóa giỏ hàng thành công");
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit("close");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.content-delete-cart .action .button + .button {
|
||||
margin-left: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,55 +0,0 @@
|
||||
<template>
|
||||
<div class="content-delete-cart">
|
||||
<div class="container is-fluid px-4">
|
||||
<div>
|
||||
<p>
|
||||
Bạn có chắc chắn muốn xóa lịch công nợ thời gian:
|
||||
{{ detail.time }} ngày - mẫu: [{{ detail.name?.toUpperCase() }}] không?
|
||||
</p>
|
||||
<div class="action mt-3">
|
||||
<button
|
||||
class="button is-light"
|
||||
@click="handleCancel"
|
||||
>
|
||||
Hủy
|
||||
</button>
|
||||
<button
|
||||
class="button is-primary"
|
||||
@click="handleDeleteCart"
|
||||
>
|
||||
Đồng ý
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const { $snackbar, $deleteapi } = useNuxtApp();
|
||||
|
||||
const emit = defineEmits(["close"]);
|
||||
const props = defineProps({
|
||||
row: Object,
|
||||
});
|
||||
|
||||
const detail = JSON.parse(props.row?.detail || null);
|
||||
|
||||
const handleDeleteCart = async () => {
|
||||
const res = await $deleteapi("bizsetting", props.row.id);
|
||||
if (res) {
|
||||
emit("close");
|
||||
$snackbar("Xóa lịch công nợ thành công");
|
||||
}
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
emit("close");
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.content-delete-cart .action .button + .button {
|
||||
margin-left: 20px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,114 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<label class="label">Mã chiết khấu <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.code"
|
||||
id="code"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Tên chiết khấu<span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.name"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 columns">
|
||||
<div class="column">
|
||||
<label class="label">Giá trị chiết khấu <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.value"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="column">
|
||||
<label class="label">Loại chiết khấu <span class="has-text-danger"> * </span> </label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'valuetype',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
optionid: record.type,
|
||||
}"
|
||||
:disabled="record.type"
|
||||
@option="documentSelected('type', $event)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
<div class="column">
|
||||
<label class="label">Phương thức chiết khấu<span class="has-text-danger"> * </span> </label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'discountmethod',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
optionid: record.method,
|
||||
}"
|
||||
:disabled="record.method"
|
||||
@option="documentSelected('method', $event)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<button
|
||||
class="button is-primary has-text-white"
|
||||
@click="update()"
|
||||
>
|
||||
{{ record.id ? "Cập nhật" : "Tạo mới" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
const { $copy, $resetNull, $insertrow, $updaterow, $snackbar, $getdata } = useNuxtApp();
|
||||
var props = defineProps({
|
||||
api: String,
|
||||
pagename: String,
|
||||
row: Object,
|
||||
prefix: String,
|
||||
});
|
||||
const emit = defineEmits(["close", "modalevent"]);
|
||||
|
||||
var record = $copy(props.row || {});
|
||||
console.log("record", record);
|
||||
function documentSelected(attr, obj, v) {
|
||||
record[attr] = obj.id;
|
||||
}
|
||||
|
||||
async function update() {
|
||||
let data = $resetNull(record);
|
||||
let rs = data.id
|
||||
? await $updaterow(props.api, data, undefined, props.pagename)
|
||||
: await $insertrow(props.api, data, undefined, props.pagename);
|
||||
if (rs === "error") return $snackbar(rs);
|
||||
emit("modalevent", { name: "dataevent", data: rs });
|
||||
emit("close");
|
||||
}
|
||||
onMounted(() => {
|
||||
document.getElementById("code").focus();
|
||||
});
|
||||
</script>
|
||||
@@ -1,111 +0,0 @@
|
||||
<template>
|
||||
<div class="due-payable">
|
||||
<div class="mt-5 columns">
|
||||
<div class="column is-2">
|
||||
<label class="label"
|
||||
>{{ isVietnamese ? "Thời gian (ngày)" : "Duration (Days)" }}
|
||||
<span class="has-text-danger"> * </span>
|
||||
</label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="number"
|
||||
placeholder="15,30,60"
|
||||
v-model="record.time"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="column is-2">
|
||||
<label class="label"
|
||||
>{{ isVietnamese ? "So sánh" : "Lookup Field" }}
|
||||
<span class="has-text-danger"> * </span>
|
||||
</label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
placeholder="gt,lt,gte,lte"
|
||||
v-model="record.lookup"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="column">
|
||||
<label class="label"
|
||||
>{{ isVietnamese ? "Mẫu email" : "Email Template" }}
|
||||
<span class="has-text-danger"> * </span>
|
||||
</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Email_Template',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
optionid: Number(record.emailTemplate),
|
||||
}"
|
||||
@option="documentSelected('emailTemplate', $event)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<button
|
||||
class="button is-primary has-text-white"
|
||||
@click="update()"
|
||||
>
|
||||
{{ dataTemp.id ? "Cập nhật" : "Tạo mới" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const { $copy, $insertrow, $updaterow, $snackbar, $store } = useNuxtApp();
|
||||
|
||||
const isVietnamese = computed(() => $store.lang.toLowerCase() === "vi");
|
||||
|
||||
var props = defineProps({
|
||||
api: String,
|
||||
pagename: String,
|
||||
row: Object,
|
||||
prefix: String,
|
||||
});
|
||||
const emit = defineEmits(["close", "modalevent"]);
|
||||
const dataTemp = $copy(props.row || {});
|
||||
let record = $copy(props.row?.detail || {});
|
||||
|
||||
function documentSelected(attr, obj, v) {
|
||||
record[attr] = obj.id;
|
||||
record.name = obj.name;
|
||||
}
|
||||
|
||||
async function update() {
|
||||
const detail = record;
|
||||
let rs;
|
||||
if (dataTemp.id) {
|
||||
const dataUpdate = {
|
||||
...dataTemp,
|
||||
detail,
|
||||
};
|
||||
|
||||
console.log("detail", detail);
|
||||
console.log("dataTemp", dataTemp);
|
||||
console.log("dataUpdate", dataUpdate);
|
||||
rs = await $updaterow(props.api, dataUpdate, undefined, props.pagename);
|
||||
} else {
|
||||
const dataInsert = {
|
||||
detail,
|
||||
category: "system",
|
||||
classify: "duepayables",
|
||||
code: `due-${record.lookup}-${record.time}d-${record.emailTemplate}`,
|
||||
vi: "Lịch đến hạn thanh toán",
|
||||
};
|
||||
rs = await $insertrow(props.api, dataInsert, undefined, props.pagename);
|
||||
}
|
||||
|
||||
if (rs === "error") return $snackbar(rs);
|
||||
emit("modalevent", { name: "dataevent", data: rs });
|
||||
emit("close");
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- <div>{{ row.detail ? JSON.parse(row.detail)?.time : '' }}</div>
|
||||
<div>{{ await $getdata('Email_Template', {id:JSON.parse(row.detail)?.emailTemplate})}}</div> -->
|
||||
@@ -1,82 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<label class="label">Mã quà tặng <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.code"
|
||||
id="code"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Tên quà tặng<span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.name"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 columns">
|
||||
<div class="column">
|
||||
<label class="label">Chi tiết quà tặng<span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.detail"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-5">
|
||||
<button
|
||||
class="button is-primary has-text-white"
|
||||
@click="update()"
|
||||
>
|
||||
{{ record.id ? "Cập nhật" : "Tạo mới" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
const { $copy, $resetNull, $insertrow, $updaterow, $snackbar, $getdata } = useNuxtApp();
|
||||
var props = defineProps({
|
||||
api: String,
|
||||
pagename: String,
|
||||
row: Object,
|
||||
prefix: String,
|
||||
});
|
||||
const emit = defineEmits(["close", "modalevent"]);
|
||||
|
||||
var record = $copy(props.row || {});
|
||||
|
||||
async function update() {
|
||||
let data = $resetNull(record);
|
||||
let rs = data.id
|
||||
? await $updaterow(props.api, data, undefined, props.pagename)
|
||||
: await $insertrow(props.api, data, undefined, props.pagename);
|
||||
if (rs === "error") return $snackbar(rs);
|
||||
emit("modalevent", { name: "dataevent", data: rs });
|
||||
emit("close");
|
||||
}
|
||||
onMounted(() => {
|
||||
document.getElementById("code").focus();
|
||||
});
|
||||
</script>
|
||||
@@ -163,7 +163,7 @@ export default {
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
this.setting = await this.$getdata("importsetting", { code: this.code }, undefined, true);
|
||||
this.setting = await this.$getdata("importsetting", { first: true, filter: { code: this.code } });
|
||||
this.requireFields = this.setting.detail;
|
||||
},
|
||||
beforeUnmount() {
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
<template>
|
||||
<div class="container is-fluid px-4">
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-body">
|
||||
<!-- Mã giỏ hàng -->
|
||||
<div class="field is-narrow">
|
||||
<label class="label"> Mã <span class="has-text-danger">*</span> </label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="Nhập mã"
|
||||
v-model="record.code"
|
||||
id="code"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tên giỏ hàng -->
|
||||
<div class="field">
|
||||
<label class="label"> Tên giỏ hàng <span class="has-text-danger">*</span> </label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder="Nhập tên giỏ hàng"
|
||||
v-model="record.name"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Index -->
|
||||
<div
|
||||
class="field"
|
||||
style="width: 120px"
|
||||
>
|
||||
<label class="label"> Index <span class="has-text-danger">*</span> </label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="number"
|
||||
placeholder="0"
|
||||
v-model.number="record.index"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Đại lý -->
|
||||
<div class="field mt-5">
|
||||
<label class="label">Đại lý</label>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'dealer',
|
||||
field: 'code',
|
||||
column: 'code',
|
||||
optionid: record.dealer || null,
|
||||
first: true,
|
||||
viewaddon: viewAddon,
|
||||
addon: newAddon,
|
||||
}"
|
||||
@option="dealerSelected"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Nút lưu -->
|
||||
<div class="field is-grouped is-grouped-right mt-6">
|
||||
<div class="control">
|
||||
<button
|
||||
class="button is-primary has-text-white"
|
||||
@click="update"
|
||||
>
|
||||
{{ record.id ? "Cập nhật" : "Thêm mới" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, nextTick } from "vue";
|
||||
const { $copy, $resetNull, $snackbar, $getdata, $insertapi, $updateapi } = useNuxtApp();
|
||||
|
||||
// Chỉ nhận id (không nhận row)
|
||||
const props = defineProps({
|
||||
prefix: String,
|
||||
id: [Number, String, null],
|
||||
});
|
||||
|
||||
const emit = defineEmits(["close", "modalevent"]);
|
||||
|
||||
const record = ref({
|
||||
code: "",
|
||||
name: "",
|
||||
index: 0,
|
||||
dealer: null,
|
||||
});
|
||||
|
||||
const viewAddon = {};
|
||||
const newAddon = {};
|
||||
|
||||
function dealerSelected(obj) {
|
||||
record.value.dealer = obj ? obj.id : null;
|
||||
}
|
||||
|
||||
async function loadCart() {
|
||||
if (!props.id) {
|
||||
record.value = {
|
||||
code: "",
|
||||
name: "",
|
||||
index: 0,
|
||||
dealer: null,
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const row = await $getdata("cart", { id: props.id }, null, true);
|
||||
|
||||
if (row) {
|
||||
record.value = $copy(row);
|
||||
} else {
|
||||
$snackbar("Không tìm thấy giỏ hàng này");
|
||||
emit("close");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Lỗi khi tải dữ liệu giỏ hàng:", error);
|
||||
$snackbar("Lỗi tải dữ liệu");
|
||||
emit("close");
|
||||
}
|
||||
}
|
||||
|
||||
// Lưu dữ liệu
|
||||
async function update() {
|
||||
const data = $resetNull(record.value);
|
||||
|
||||
try {
|
||||
let rs;
|
||||
if (data.id) {
|
||||
rs = await $updateapi("cart", data);
|
||||
} else {
|
||||
rs = await $insertapi("cart", data);
|
||||
}
|
||||
|
||||
if (rs === "error") {
|
||||
$snackbar("Lỗi khi lưu dữ liệu");
|
||||
return;
|
||||
}
|
||||
|
||||
$snackbar("Lưu thành công!");
|
||||
emit("modalevent", { name: "dataevent", data: rs });
|
||||
emit("close");
|
||||
} catch (err) {
|
||||
$snackbar("Có lỗi xảy ra khi lưu");
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Khởi tạo khi mở modal
|
||||
onMounted(async () => {
|
||||
await loadCart();
|
||||
await nextTick();
|
||||
document.getElementById("code")?.focus();
|
||||
});
|
||||
</script>
|
||||
@@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="over-due-payable">
|
||||
<div class="mt-5 columns">
|
||||
<div class="column">
|
||||
<label class="label"
|
||||
>{{ isVietnamese ? "Thời gian (ngày)" : "Duration (Days)" }}
|
||||
<span class="has-text-danger"> * </span>
|
||||
</label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="number"
|
||||
placeholder=""
|
||||
v-model="record.time"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="column">
|
||||
<label class="label"
|
||||
>{{ isVietnamese ? "Mẫu email" : "Email Template" }}
|
||||
<span class="has-text-danger"> * </span>
|
||||
</label>
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'Email_Template',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
optionid: Number(record.emailTemplate),
|
||||
}"
|
||||
@option="documentSelected('emailTemplate', $event)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<button
|
||||
class="button is-primary has-text-white"
|
||||
@click="update()"
|
||||
>
|
||||
{{ dataTemp.id ? "Cập nhật" : "Tạo mới" }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
const { $copy, $insertrow, $updaterow, $snackbar, $store } = useNuxtApp();
|
||||
|
||||
const isVietnamese = computed(() => $store.lang.toLowerCase() === "vi");
|
||||
|
||||
var props = defineProps({
|
||||
api: String,
|
||||
pagename: String,
|
||||
row: Object,
|
||||
prefix: String,
|
||||
});
|
||||
const emit = defineEmits(["close", "modalevent"]);
|
||||
const dataTemp = $copy(props.row || {});
|
||||
let record = $copy(props.row?.detail || {});
|
||||
|
||||
function documentSelected(attr, obj, v) {
|
||||
record[attr] = obj.id;
|
||||
record.name = obj.name;
|
||||
}
|
||||
|
||||
async function update() {
|
||||
const detail = record;
|
||||
let rs;
|
||||
if (dataTemp.id) {
|
||||
const dataUpdate = {
|
||||
...dataTemp,
|
||||
detail,
|
||||
};
|
||||
rs = await $updaterow(props.api, dataUpdate, undefined, props.pagename);
|
||||
} else {
|
||||
const dataInsert = {
|
||||
detail,
|
||||
category: "system",
|
||||
classify: "overduepayables",
|
||||
code: `overdue-${record.lookup}-${record.time}-${record.emailTemplate}`,
|
||||
vi: "Lịch quá hạn thanh toán",
|
||||
};
|
||||
rs = await $insertrow(props.api, dataInsert, undefined, props.pagename);
|
||||
}
|
||||
|
||||
if (rs === "error") return $snackbar(rs);
|
||||
emit("modalevent", { name: "dataevent", data: rs });
|
||||
emit("close");
|
||||
}
|
||||
</script>
|
||||
@@ -1,471 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- Thông tin Sale Policy -->
|
||||
<div class="m-0">
|
||||
<Caption v-bind="{ title: 'Thông tin chính sách', type: 'has-text-warning' }"></Caption>
|
||||
</div>
|
||||
|
||||
<div class="columns is-multiline">
|
||||
<div class="column is-1">
|
||||
<div class="field">
|
||||
<label class="label">Thứ tự</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="number"
|
||||
v-model.number="record.index"
|
||||
placeholder="Thứ tự"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-5">
|
||||
<div class="field">
|
||||
<label class="label">Mã <span class="has-text-danger">*</span></label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
v-model="record.code"
|
||||
id="code"
|
||||
placeholder="Mã CS"
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
class="help is-danger"
|
||||
v-if="errors.code"
|
||||
>
|
||||
{{ errors.code }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-6">
|
||||
<div class="field">
|
||||
<label class="label">Tên chính sách <span class="has-text-danger">*</span></label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
v-model="record.name"
|
||||
placeholder="Tên"
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
class="help is-danger"
|
||||
v-if="errors.name"
|
||||
>
|
||||
{{ errors.name }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">Đặt cọc <span class="has-text-danger">*</span></label>
|
||||
<div class="control">
|
||||
<InputNumber
|
||||
v-bind="{
|
||||
record: record,
|
||||
attr: 'deposit',
|
||||
defaultValue: true,
|
||||
}"
|
||||
@number="selected('deposit', $event)"
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
class="help is-danger"
|
||||
v-if="errors.deposit"
|
||||
>
|
||||
{{ errors.deposit }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-4">
|
||||
<div class="field">
|
||||
<label class="label">PT thanh toán <span class="has-text-danger">*</span></label>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'paymentmethod',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
optionid: record.method,
|
||||
}"
|
||||
@option="selected('method', $event)"
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
class="help is-danger"
|
||||
v-if="errors.method"
|
||||
>
|
||||
{{ errors.method }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-3">
|
||||
<div class="field">
|
||||
<label class="label">% Phân bổ HĐ</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="number"
|
||||
v-model.number="record.contract_allocation_percentage"
|
||||
placeholder="%"
|
||||
min="0"
|
||||
max="100"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="column is-1">
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
Kích hoạt
|
||||
<span class="has-text-danger">*</span>
|
||||
</label>
|
||||
<div class="control">
|
||||
<div
|
||||
class="is-flex is-align-items-center is-clickable is-gap-2"
|
||||
@click="record.enable = !record.enable"
|
||||
>
|
||||
<SvgIcon
|
||||
v-bind="{
|
||||
name: record.enable ? 'checked.svg' : 'uncheck.svg',
|
||||
type: record.enable ? 'primary' : 'twitter',
|
||||
size: 22,
|
||||
}"
|
||||
/>
|
||||
<span>Cho phép</span>
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
class="help is-danger"
|
||||
v-if="errors.enable"
|
||||
>
|
||||
{{ errors.enable }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Plan -->
|
||||
<div class="m-0">
|
||||
<Caption v-bind="{ title: 'Kế hoạch thanh toán', type: 'has-text-warning' }"></Caption>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="p-3"
|
||||
v-for="(plan, i) in paymentPlans"
|
||||
:key="i"
|
||||
style="position: relative"
|
||||
>
|
||||
<a
|
||||
v-if="paymentPlans.length > 1"
|
||||
class="has-text-danger is-size-7"
|
||||
style="position: absolute; top: 0.5rem; right: 0.75rem; cursor: pointer"
|
||||
@click="removePlan(plan, i)"
|
||||
>
|
||||
Xóa
|
||||
</a>
|
||||
<div
|
||||
class="columns is-multiline is-mobile mb-0"
|
||||
style="border-top: 1px solid #dbdbdb"
|
||||
>
|
||||
<!-- Đợt -->
|
||||
<div class="column is-3-desktop is-2-mobile pb-0">
|
||||
<div class="field">
|
||||
<label class="label">Đợt</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input has-text-centered has-text-weight-bold"
|
||||
type="text"
|
||||
:value="i + 1"
|
||||
disabled
|
||||
style="background-color: #f5f5f5"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Value -->
|
||||
<div class="column is-3-desktop is-5-mobile pb-0">
|
||||
<div class="field">
|
||||
<label class="label">Giá trị <span class="has-text-danger">*</span></label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="number"
|
||||
v-model.number="plan.value"
|
||||
placeholder="Giá trị"
|
||||
min="0"
|
||||
step="0.01"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Type -->
|
||||
<div class="column is-3-desktop is-5-mobile pb-0">
|
||||
<div class="field">
|
||||
<label class="label">Loại <span class="has-text-danger">*</span></label>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'valuetype',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
optionid: plan.type,
|
||||
}"
|
||||
@option="planSelected('type', $event, plan)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Days -->
|
||||
<div class="column is-3-desktop is-4-mobile pb-0">
|
||||
<div class="field">
|
||||
<label class="label">Số ngày</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="number"
|
||||
v-model.number="plan.days"
|
||||
placeholder="Ngày"
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Payment Note -->
|
||||
<div class="column is-6-desktop is-6-mobile pb-0">
|
||||
<div class="field">
|
||||
<label class="label">Ghi chú TT</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
v-model="plan.payment_note"
|
||||
placeholder="Ghi chú thanh toán"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Due Note -->
|
||||
<div class="column is-6-desktop is-10-mobile pb-0">
|
||||
<div class="field mb-0">
|
||||
<label class="label">Ghi chú hạn</label>
|
||||
<div class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
v-model="plan.due_note"
|
||||
placeholder="Ghi chú hạn thanh toán"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Nút thêm -->
|
||||
<button
|
||||
class="button is-pulled-right is-info is-light mb-4"
|
||||
@click="addPlan"
|
||||
>
|
||||
<span class="icon">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
height="12"
|
||||
width="12"
|
||||
viewBox="0 0 448 512"
|
||||
>
|
||||
<path
|
||||
d="M256 80c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 144L48 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l144 0 0 144c0 17.7 14.3 32 32 32s32-14.3 32-32l0-144 144 0c17.7 0 32-14.3 32-32s-14.3-32-32-32l-144 0 0-144z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Action buttons -->
|
||||
<div class="buttons">
|
||||
<button
|
||||
:class="`button has-text-white is-primary ${isSubmitting ? 'is-loading' : ''}`"
|
||||
@click="update()"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span>Lưu</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="button has-text-white is-danger"
|
||||
@click="emit('close')"
|
||||
:disabled="isSubmitting"
|
||||
>
|
||||
<span>Hủy</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
|
||||
const { $getdata, $copy, $resetNull, $insertapi, $updateapi, $snackbar, $remove, $deleteapi, $empty } = useNuxtApp();
|
||||
|
||||
const props = defineProps({
|
||||
api: String,
|
||||
pagename: String,
|
||||
row: Object,
|
||||
prefix: String,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["close", "modalevent"]);
|
||||
|
||||
const record = ref($copy(props.row || { enable: true }));
|
||||
const paymentPlans = ref([{}]);
|
||||
const errors = ref({});
|
||||
const isSubmitting = ref(false);
|
||||
|
||||
if (props.row?.id) {
|
||||
const plans = await $getdata("paymentplan", { policy: props.row.id });
|
||||
if (plans && plans.length > 0) {
|
||||
paymentPlans.value = plans;
|
||||
}
|
||||
}
|
||||
|
||||
function validateForm() {
|
||||
errors.value = {};
|
||||
|
||||
if ($empty(record.value.code)) {
|
||||
errors.value.code = "Mã không được để trống";
|
||||
}
|
||||
|
||||
if ($empty(record.value.name)) {
|
||||
errors.value.name = "Tên không được để trống";
|
||||
}
|
||||
|
||||
if ($empty(record.value.deposit)) {
|
||||
errors.value.deposit = "Tiền đặt cọc không được để trống";
|
||||
}
|
||||
|
||||
if ($empty(record.value.method)) {
|
||||
errors.value.method = "Phương thức thanh toán không được để trống";
|
||||
}
|
||||
|
||||
return Object.keys(errors.value).length === 0;
|
||||
}
|
||||
|
||||
async function update() {
|
||||
if (isSubmitting.value) return;
|
||||
|
||||
if (!validateForm()) {
|
||||
$snackbar("Vui lòng kiểm tra lại dữ liệu");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
isSubmitting.value = true;
|
||||
|
||||
let policyData = $resetNull(record.value);
|
||||
if (policyData.method && typeof policyData.method === "object") {
|
||||
policyData.method = policyData.method.id;
|
||||
}
|
||||
|
||||
const policyResult = policyData.id
|
||||
? await $updateapi("salepolicy", policyData, undefined, false)
|
||||
: await $insertapi("salepolicy", policyData, undefined, false);
|
||||
|
||||
if (policyResult === "error") {
|
||||
throw new Error("Failed to save policy");
|
||||
}
|
||||
|
||||
const plans = paymentPlans.value.filter((v) => {
|
||||
return !$empty(v.value) && !$empty(v.type);
|
||||
});
|
||||
|
||||
plans.forEach((plan, index) => {
|
||||
plan.policy = policyResult.id;
|
||||
plan.cycle = index + 1;
|
||||
if (plan.type) {
|
||||
plan.type = Number(plan.type);
|
||||
}
|
||||
});
|
||||
|
||||
if (plans.length > 0) {
|
||||
if (props.row?.id) {
|
||||
const oldPlans = await $getdata("paymentplan", {
|
||||
policy: policyResult.id,
|
||||
});
|
||||
|
||||
if (oldPlans && oldPlans.length > 0) {
|
||||
for (const oldPlan of oldPlans) {
|
||||
await $deleteapi("paymentplan", oldPlan.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await $insertapi("paymentplan", plans, undefined, false);
|
||||
}
|
||||
|
||||
$snackbar("Lưu dữ liệu thành công!");
|
||||
|
||||
emit("modalevent", { name: "dataevent", data: policyResult });
|
||||
emit("close");
|
||||
} catch (error) {
|
||||
$snackbar("Lưu dữ liệu thất bại");
|
||||
} finally {
|
||||
isSubmitting.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function selected(attr, obj) {
|
||||
if (obj !== null && typeof obj === "object") {
|
||||
record.value[attr] = obj.id || obj;
|
||||
} else {
|
||||
record.value[attr] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
function planSelected(attr, obj, plan) {
|
||||
if (attr === "type") {
|
||||
if (obj && typeof obj === "object") {
|
||||
plan.type = obj.id;
|
||||
plan._type = obj;
|
||||
} else {
|
||||
plan.type = obj;
|
||||
}
|
||||
} else if (attr === "value") {
|
||||
plan.value = Number(obj);
|
||||
} else {
|
||||
plan[attr] = obj;
|
||||
}
|
||||
}
|
||||
|
||||
function addPlan() {
|
||||
paymentPlans.value.push({});
|
||||
}
|
||||
|
||||
async function removePlan(plan, index) {
|
||||
if (plan.id) {
|
||||
await $deleteapi("paymentplan", plan.id);
|
||||
}
|
||||
$remove(paymentPlans.value, index);
|
||||
if (paymentPlans.value.length === 0) {
|
||||
paymentPlans.value = [{}];
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
document.getElementById("code")?.focus();
|
||||
});
|
||||
</script>
|
||||
@@ -1,120 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="field is-horizontal mt-6 pt-4">
|
||||
<div class="field-body">
|
||||
<div class="field is-narrow">
|
||||
<label class="label">Code <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.code"
|
||||
id="code"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field is-narrow">
|
||||
<label class="label">Name <span class="has-text-danger"> * </span> </label>
|
||||
<p class="control">
|
||||
<input
|
||||
class="input"
|
||||
type="text"
|
||||
placeholder=""
|
||||
v-model="record.name"
|
||||
id="code"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="columns mx-0">
|
||||
<div class="column is-8">
|
||||
<div class="mt-5 mb-3">
|
||||
<Caption v-bind="{ title: 'Required documents', type: 'has-text-primary' }"></Caption>
|
||||
</div>
|
||||
<div
|
||||
class="field is-grouped"
|
||||
v-for="(v, i) in array"
|
||||
>
|
||||
<div class="control">
|
||||
<SearchBox
|
||||
v-bind="{
|
||||
api: 'documenttype',
|
||||
field: 'name',
|
||||
column: ['name'],
|
||||
first: true,
|
||||
optionid: v.doctype,
|
||||
position: 'is-top-left',
|
||||
}"
|
||||
@option="documentSelected('_doctype', $event, v)"
|
||||
></SearchBox>
|
||||
</div>
|
||||
<div class="control pl-5">
|
||||
<a
|
||||
class="mr-4"
|
||||
@click="add()"
|
||||
>
|
||||
<SvgIcon v-bind="{ name: 'add1.png', type: 'dark', size: 20 }"></SvgIcon>
|
||||
</a>
|
||||
<a @click="remove(v, i)">
|
||||
<SvgIcon v-bind="{ name: 'bin1.svg', type: 'dark', size: 20 }"></SvgIcon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5">
|
||||
<button
|
||||
class="button is-primary has-text-white"
|
||||
@click="update()"
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
const { $getdata, $copy, $resetNull, $insertrow, $updaterow, $snackbar, $remove, $deleteapi } = useNuxtApp();
|
||||
var props = defineProps({
|
||||
api: String,
|
||||
pagename: String,
|
||||
row: Object,
|
||||
prefix: String,
|
||||
});
|
||||
const emit = defineEmits(["close", "modalevent"]);
|
||||
var array = ref([{}]);
|
||||
var record = $copy(props.row || {});
|
||||
if (props.row) {
|
||||
let arr = await $getdata("phasedoctype", { phase: props.row.id });
|
||||
if (arr.length > 0) array.value = arr;
|
||||
}
|
||||
async function update() {
|
||||
let data = $resetNull(record);
|
||||
let rs = data.id
|
||||
? await $updaterow(props.api, data, undefined, props.pagename)
|
||||
: await $insertrow(props.api, data, undefined, props.pagename);
|
||||
if (rs === "error") return $snackbar(rs);
|
||||
let arr = array.value.filter((v) => v.doctype);
|
||||
arr.map((v) => (v.phase = rs.id));
|
||||
await $insertrow("phasedoctype", arr);
|
||||
emit("modalevent", { name: "dataevent", data: rs });
|
||||
emit("close");
|
||||
}
|
||||
function documentSelected(attr, obj, v) {
|
||||
v[attr] = obj;
|
||||
if (obj) v.doctype = obj.id;
|
||||
}
|
||||
function add() {
|
||||
array.value.push({});
|
||||
}
|
||||
async function remove(v, i) {
|
||||
if (v.id) await $deleteapi("phasedoctype", v.id);
|
||||
$remove(array.value, i);
|
||||
if (array.value.length === 0) array.value = [{}];
|
||||
}
|
||||
onMounted(() => {
|
||||
document.getElementById("code").focus();
|
||||
});
|
||||
</script>
|
||||
Reference in New Issue
Block a user