|
|
@@ -1,33 +1,33 @@
|
|
|
<template>
|
|
|
<ele-modal :width="680" v-model="visible" :title="dialogTitle" :append-to-body="true" :close-on-click-modal="false">
|
|
|
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px" @submit.prevent>
|
|
|
- <el-form-item label="红包名称" prop="name">
|
|
|
- <el-input v-model="form.name" placeholder="请输入红包名称" maxlength="20" show-word-limit
|
|
|
+ <el-form-item label="红包名称" prop="couponName">
|
|
|
+ <el-input v-model="form.couponName" placeholder="请输入红包名称" maxlength="20" show-word-limit
|
|
|
:disabled="isEditActive" />
|
|
|
</el-form-item>
|
|
|
|
|
|
- <el-form-item label="红包数量" prop="quantity">
|
|
|
- <el-input-number v-model="form.quantity" :min="1" :max="100000" placeholder="请输入" class="!w-[200px]" />
|
|
|
+ <el-form-item label="红包数量" prop="totalNum">
|
|
|
+ <el-input-number v-model="form.totalNum" :min="1" :max="100000" placeholder="请输入" class="!w-[200px]" />
|
|
|
<span class="ml-2 text-gray-500">张</span>
|
|
|
</el-form-item>
|
|
|
|
|
|
<el-form-item label="红包面额" required>
|
|
|
<div class="flex items-center space-x-2">
|
|
|
- <template v-if="type === 'surprise'">
|
|
|
- <el-form-item prop="minAmount" class="mb-0 !mr-0">
|
|
|
- <el-input-number v-model="form.minAmount" :min="0.01" :precision="2" :controls="false"
|
|
|
+ <template v-if="type === '2'">
|
|
|
+ <el-form-item prop="minMoney" class="mb-0 !mr-0">
|
|
|
+ <el-input-number v-model="form.minMoney" :min="0.01" :precision="2" :controls="false"
|
|
|
placeholder="请输入" class="!w-[100px]" :disabled="isEditActive" />
|
|
|
</el-form-item>
|
|
|
<span>-</span>
|
|
|
- <el-form-item prop="maxAmount" class="mb-0 !mr-0">
|
|
|
- <el-input-number v-model="form.maxAmount" :min="0.01" :precision="2" :controls="false"
|
|
|
+ <el-form-item prop="maxMoney" class="mb-0 !mr-0">
|
|
|
+ <el-input-number v-model="form.maxMoney" :min="0.01" :precision="2" :controls="false"
|
|
|
placeholder="请输入" class="!w-[100px]" :disabled="isEditActive" />
|
|
|
</el-form-item>
|
|
|
<span class="text-gray-500">元随机数字</span>
|
|
|
</template>
|
|
|
<template v-else>
|
|
|
- <el-form-item prop="amount" class="mb-0 !mr-0">
|
|
|
- <el-input-number v-model="form.amount" :min="0.01" :precision="2" :controls="false"
|
|
|
+ <el-form-item prop="faceMoney" class="mb-0 !mr-0">
|
|
|
+ <el-input-number v-model="form.faceMoney" :min="0.01" :precision="2" :controls="false"
|
|
|
placeholder="请输入" class="!w-[150px]" :disabled="isEditActive" />
|
|
|
</el-form-item>
|
|
|
<span class="text-gray-500">元</span>
|
|
|
@@ -40,22 +40,29 @@
|
|
|
<el-radio label="none">无门槛</el-radio>
|
|
|
<el-radio label="full">满</el-radio>
|
|
|
</el-radio-group>
|
|
|
- <el-form-item v-if="form.thresholdType === 'full'" prop="thresholdAmount"
|
|
|
+ <el-form-item v-if="form.thresholdType === 'full'" prop="thresholdMoney"
|
|
|
class="inline-block ml-2 mb-0 !mr-0">
|
|
|
- <el-input-number v-model="form.thresholdAmount" :min="0.01" :precision="2" :controls="false"
|
|
|
+ <el-input-number v-model="form.thresholdMoney" :min="0.01" :precision="2" :controls="false"
|
|
|
placeholder="请输入" class="!w-[100px]" :disabled="isEditActive" />
|
|
|
<span class="ml-2 text-gray-500">元 可用</span>
|
|
|
</el-form-item>
|
|
|
</el-form-item>
|
|
|
|
|
|
- <el-form-item label="使用商品" prop="productType">
|
|
|
- <el-radio-group v-model="form.productType" :disabled="isEditActive">
|
|
|
- <el-radio label="all">所有商品</el-radio>
|
|
|
- <el-radio label="specific">指定商品</el-radio>
|
|
|
+ <el-form-item label="可否叠加使用" prop="stackType">
|
|
|
+ <el-radio-group v-model="form.stackType" :disabled="isEditActive">
|
|
|
+ <el-radio label="0">否</el-radio>
|
|
|
+ <el-radio label="1">是</el-radio>
|
|
|
</el-radio-group>
|
|
|
- <div v-if="form.productType === 'specific'" class="mt-2">
|
|
|
+ </el-form-item>
|
|
|
+
|
|
|
+ <el-form-item label="使用商品" prop="scope">
|
|
|
+ <el-radio-group v-model="form.scope" :disabled="isEditActive">
|
|
|
+ <el-radio :label="'1'">所有商品</el-radio>
|
|
|
+ <el-radio :label="'2'">指定商品</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ <div v-if="form.scope === '2'" class="mt-2">
|
|
|
<el-button type="primary" link @click="openProductSelect" :disabled="isEditActive">
|
|
|
- 已选择 {{ form.products.length }} 个商品
|
|
|
+ 已选择 {{ form.products ? form.products.length : 0 }} 个商品
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
@@ -63,31 +70,22 @@
|
|
|
<el-form-item label="有效期" required>
|
|
|
<div class="flex flex-col space-y-4 w-full">
|
|
|
<div class="flex items-center">
|
|
|
- <el-radio v-model="form.validityType" label="range" :disabled="isEditActive" class="!mr-4">日期范围</el-radio>
|
|
|
+ <el-radio v-model="form.validityType" label="range" :disabled="isEditActive" @change="handleValidityTypeChange"
|
|
|
+ class="!mr-4">日期范围</el-radio>
|
|
|
<el-form-item prop="validityRange" class="mb-0">
|
|
|
- <el-date-picker
|
|
|
- v-model="form.validityRange"
|
|
|
- type="daterange"
|
|
|
- range-separator="至"
|
|
|
- start-placeholder="开始日期"
|
|
|
- end-placeholder="结束日期"
|
|
|
- value-format="YYYY-MM-DD"
|
|
|
- :disabled="isEditActive || form.validityType !== 'range'"
|
|
|
- style="width: 320px;"
|
|
|
- />
|
|
|
+ <el-date-picker v-model="form.validityRange" type="daterange" range-separator="至"
|
|
|
+ start-placeholder="开始日期" end-placeholder="结束日期" value-format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ :disabled="isEditActive || form.validityType !== 'range'" style="width: 320px;" />
|
|
|
</el-form-item>
|
|
|
</div>
|
|
|
-
|
|
|
+
|
|
|
<div class="flex items-center">
|
|
|
- <el-radio v-model="form.validityType" label="days" :disabled="isEditActive" class="!mr-4">有效日期</el-radio>
|
|
|
+ <el-radio v-model="form.validityType" label="days" :disabled="isEditActive" @change="handleValidityTypeChange"
|
|
|
+ class="!mr-4">有效日期</el-radio>
|
|
|
<div class="flex items-center">
|
|
|
- <el-form-item prop="validityDays" class="mb-0 !mr-2">
|
|
|
- <el-input
|
|
|
- v-model="form.validityDays"
|
|
|
- placeholder="请输入"
|
|
|
- style="width: 200px;"
|
|
|
- :disabled="isEditActive || form.validityType !== 'days'"
|
|
|
- />
|
|
|
+ <el-form-item prop="effectDays" class="mb-0 !mr-2">
|
|
|
+ <el-input-number v-model="form.effectDays" placeholder="请输入" style="width: 200px;"
|
|
|
+ :min="1" :disabled="isEditActive || form.validityType !== 'days'" />
|
|
|
</el-form-item>
|
|
|
<span>天</span>
|
|
|
</div>
|
|
|
@@ -95,20 +93,21 @@
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
|
|
|
- <el-form-item label="每人限领" prop="limit">
|
|
|
- <el-input-number v-model="form.limit" :min="1" placeholder="请输入" class="!w-[200px]"
|
|
|
+ <el-form-item label="每人限领" prop="limitedPerUser">
|
|
|
+ <el-input-number v-model="form.limitedPerUser" :min="1" placeholder="请输入" class="!w-[200px]"
|
|
|
:disabled="isEditActive" />
|
|
|
<span class="ml-2 text-gray-500">张</span>
|
|
|
</el-form-item>
|
|
|
|
|
|
- <el-form-item v-if="type === 'surprise'" label="口令" prop="password">
|
|
|
- <el-input v-model="form.password" placeholder="请输入口令" :disabled="isEditActive" />
|
|
|
+ <el-form-item v-if="type === '2'" label="口令" prop="commandWord">
|
|
|
+ <el-input v-model="form.commandWord" placeholder="请输入口令" :disabled="isEditActive" />
|
|
|
<div class="text-gray-400 text-xs mt-1">
|
|
|
用户搜索后弹出惊喜红包
|
|
|
</div>
|
|
|
</el-form-item>
|
|
|
</el-form>
|
|
|
|
|
|
+
|
|
|
<template #footer>
|
|
|
<div class="flex justify-end items-center">
|
|
|
<el-button @click="visible = false">取消</el-button>
|
|
|
@@ -125,130 +124,201 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { ref, computed, reactive, watch } from 'vue';
|
|
|
-import { EleMessage } from 'ele-admin-plus/es';
|
|
|
-import GoodsSelectDialog from '@/views/salesOps/components/GoodsSelectDialog.vue';
|
|
|
-
|
|
|
-const props = defineProps({
|
|
|
- modelValue: Boolean,
|
|
|
- type: {
|
|
|
- type: String,
|
|
|
- default: 'ordinary', // 'ordinary' | 'surprise'
|
|
|
- },
|
|
|
- data: Object,
|
|
|
-});
|
|
|
-
|
|
|
-const emit = defineEmits(['update:modelValue', 'success']);
|
|
|
-
|
|
|
-const visible = computed({
|
|
|
- get: () => props.modelValue,
|
|
|
- set: (val) => emit('update:modelValue', val),
|
|
|
-});
|
|
|
-
|
|
|
-const formRef = ref(null);
|
|
|
-const loading = ref(false);
|
|
|
-const productDialogVisible = ref(false);
|
|
|
-
|
|
|
-const isEdit = computed(() => !!props.data?.id);
|
|
|
-const isEditActive = computed(() => !!props.data?.isActive); // Assuming 'isActive' flag passed if active
|
|
|
-
|
|
|
-const dialogTitle = computed(() => {
|
|
|
- const typeName = props.type === 'surprise' ? '惊喜红包' : '普通红包';
|
|
|
- return isEdit.value ? `编辑${typeName}` : `新建${typeName}`;
|
|
|
-});
|
|
|
-
|
|
|
-const form = reactive({
|
|
|
- name: '',
|
|
|
- quantity: undefined,
|
|
|
- minAmount: undefined,
|
|
|
- maxAmount: undefined,
|
|
|
- amount: undefined,
|
|
|
- thresholdType: 'none',
|
|
|
- thresholdAmount: undefined,
|
|
|
- productType: 'all',
|
|
|
- products: [],
|
|
|
- validityType: 'range',
|
|
|
- validityRange: [],
|
|
|
- validityDays: undefined,
|
|
|
- limit: 1,
|
|
|
- password: '',
|
|
|
-});
|
|
|
-
|
|
|
-const rules = {
|
|
|
- name: [{ required: true, message: '请输入红包名称', trigger: 'blur' }],
|
|
|
- quantity: [{ required: true, message: '请输入红包数量', trigger: 'blur' }],
|
|
|
- amount: [{ required: true, message: '请输入红包面额', trigger: 'blur' }],
|
|
|
- minAmount: [{ required: true, message: '请输入最小面额', trigger: 'blur' }],
|
|
|
- maxAmount: [{ required: true, message: '请输入最大面额', trigger: 'blur' }],
|
|
|
- thresholdAmount: [{ required: true, message: '请输入门槛金额', trigger: 'blur' }],
|
|
|
- validityRange: [{ required: true, message: '请选择有效期范围', trigger: 'change' }],
|
|
|
- validityDays: [{ required: true, message: '请输入有效天数', trigger: 'blur' }],
|
|
|
- limit: [{ required: true, message: '请输入限领数量', trigger: 'blur' }],
|
|
|
- password: [{ required: true, message: '请输入口令', trigger: 'blur' }],
|
|
|
-};
|
|
|
-
|
|
|
-watch(
|
|
|
- () => props.modelValue,
|
|
|
- (val) => {
|
|
|
- if (val) {
|
|
|
- resetForm();
|
|
|
- if (props.data) {
|
|
|
- Object.assign(form, props.data);
|
|
|
- // Handle complex types mapping if needed
|
|
|
+ import { ref, computed, reactive, nextTick } from 'vue';
|
|
|
+ import { EleMessage } from 'ele-admin-plus/es';
|
|
|
+ import GoodsSelectDialog from '@/views/salesOps/components/GoodsSelectDialog.vue';
|
|
|
+ import request from '@/utils/request';
|
|
|
+
|
|
|
+ const emit = defineEmits(['success']);
|
|
|
+
|
|
|
+ const visible = ref(false);
|
|
|
+ const type = ref('1'); // '1' (Common) | '2' (Surprise)
|
|
|
+ const dialogData = ref(null);
|
|
|
+
|
|
|
+ const formRef = ref(null);
|
|
|
+ const loading = ref(false);
|
|
|
+ const productDialogVisible = ref(false);
|
|
|
+
|
|
|
+ const isEdit = computed(() => !!dialogData.value?.id);
|
|
|
+ const isEditActive = computed(() => dialogData.value?.status === 1); // Status 1 is Normal/Active
|
|
|
+
|
|
|
+ const dialogTitle = computed(() => {
|
|
|
+ const typeName = (type.value === '2') ? '惊喜红包' : '普通红包';
|
|
|
+ return isEdit.value ? `编辑${typeName}` : `新建${typeName}`;
|
|
|
+ });
|
|
|
+
|
|
|
+ const form = reactive({
|
|
|
+ id: undefined,
|
|
|
+ couponName: '',
|
|
|
+ totalNum: undefined,
|
|
|
+ minMoney: undefined,
|
|
|
+ maxMoney: undefined,
|
|
|
+ faceMoney: undefined,
|
|
|
+ thresholdType: 'none',
|
|
|
+ thresholdMoney: undefined,
|
|
|
+ stackType: '0',
|
|
|
+ scope: '1', // 1: All, 2: Specific
|
|
|
+ products: [],
|
|
|
+ validityType: 'range',
|
|
|
+ validityRange: [],
|
|
|
+ effectDays: undefined,
|
|
|
+ limitedPerUser: 1,
|
|
|
+ commandWord: '',
|
|
|
+ });
|
|
|
+
|
|
|
+ const rules = computed(() => ({
|
|
|
+ couponName: [{ required: true, message: '请输入红包名称', trigger: 'blur' }],
|
|
|
+ totalNum: [{ required: true, message: '请输入红包数量', trigger: 'blur' }],
|
|
|
+ faceMoney: [{ required: true, message: '请输入红包面额', trigger: 'blur' }],
|
|
|
+ minMoney: [{ required: true, message: '请输入最小面额', trigger: 'blur' }],
|
|
|
+ maxMoney: [{ required: true, message: '请输入最大面额', trigger: 'blur' }],
|
|
|
+ thresholdMoney: [{ required: true, message: '请输入门槛金额', trigger: 'blur' }],
|
|
|
+ validityRange: [{ required: form.validityType === 'range', message: '请选择有效期范围', trigger: 'change' }],
|
|
|
+ effectDays: [{ required: form.validityType === 'days', message: '请输入有效天数', trigger: 'blur' }],
|
|
|
+ limitedPerUser: [{ required: true, message: '请输入限领数量', trigger: 'blur' }],
|
|
|
+ commandWord: [{ required: true, message: '请输入口令', trigger: 'blur' }],
|
|
|
+ }));
|
|
|
+
|
|
|
+ const handleValidityTypeChange = () => {
|
|
|
+ if (formRef.value) {
|
|
|
+ formRef.value.clearValidate(['validityRange', 'effectDays']);
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const open = (newType, data) => {
|
|
|
+ type.value = newType;
|
|
|
+ dialogData.value = data;
|
|
|
+ visible.value = true;
|
|
|
+
|
|
|
+ resetForm();
|
|
|
+ if (data) {
|
|
|
+ Object.assign(form, data);
|
|
|
+
|
|
|
+ // Handle threshold type
|
|
|
+ form.thresholdType = (form.thresholdMoney && form.thresholdMoney > 0) ? 'full' : 'none';
|
|
|
+
|
|
|
+ // Handle validity type
|
|
|
+ if (form.effectDays && form.effectDays > 0) {
|
|
|
+ form.validityType = 'days';
|
|
|
} else {
|
|
|
- // Default values based on type
|
|
|
- if (props.type === 'surprise') {
|
|
|
- form.validityType = 'days';
|
|
|
- } else {
|
|
|
- form.validityType = 'range';
|
|
|
+ form.validityType = 'range';
|
|
|
+ if (form.effectStartTime && form.effectEndTime) {
|
|
|
+ form.validityRange = [form.effectStartTime, form.effectEndTime];
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // Handle scope and products (if data contains product info)
|
|
|
+ form.scope = String(form.scope || '1');
|
|
|
+ form.stackType = String(form.stackType || '0');
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // Default values based on type
|
|
|
+ if (type.value === '2') {
|
|
|
+ form.validityType = 'days';
|
|
|
+ } else {
|
|
|
+ form.validityType = 'range';
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
-);
|
|
|
-
|
|
|
-const resetForm = () => {
|
|
|
- if (formRef.value) formRef.value.resetFields();
|
|
|
- form.products = [];
|
|
|
- form.thresholdType = 'none';
|
|
|
- form.productType = 'all';
|
|
|
- form.validityType = 'range';
|
|
|
- form.limit = 1;
|
|
|
-};
|
|
|
-
|
|
|
-const openProductSelect = () => {
|
|
|
- productDialogVisible.value = true;
|
|
|
-};
|
|
|
-
|
|
|
-const handleProductConfirm = (selected) => {
|
|
|
- form.products = selected;
|
|
|
- productDialogVisible.value = false;
|
|
|
-};
|
|
|
-
|
|
|
-const handleSubmit = async () => {
|
|
|
- if (!formRef.value) return;
|
|
|
-
|
|
|
- await formRef.value.validate((valid, fields) => {
|
|
|
- if (valid) {
|
|
|
- if (props.type === 'surprise') {
|
|
|
- if (form.minAmount > form.maxAmount) {
|
|
|
- EleMessage.error('最小面额不能大于最大面额');
|
|
|
+ };
|
|
|
+
|
|
|
+ const resetForm = () => {
|
|
|
+ if (formRef.value) formRef.value.resetFields();
|
|
|
+ form.id = undefined;
|
|
|
+ form.couponName = '';
|
|
|
+ form.totalNum = undefined;
|
|
|
+ form.minMoney = undefined;
|
|
|
+ form.maxMoney = undefined;
|
|
|
+ form.faceMoney = undefined;
|
|
|
+ form.thresholdType = 'none';
|
|
|
+ form.thresholdMoney = undefined;
|
|
|
+ form.stackType = '0';
|
|
|
+ form.scope = '1';
|
|
|
+ form.products = [];
|
|
|
+ form.validityType = 'range';
|
|
|
+ form.validityRange = [];
|
|
|
+ form.effectDays = undefined;
|
|
|
+ form.limitedPerUser = 1;
|
|
|
+ form.commandWord = '';
|
|
|
+ };
|
|
|
+
|
|
|
+ const openProductSelect = () => {
|
|
|
+ productDialogVisible.value = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleProductConfirm = (selected) => {
|
|
|
+ form.products = selected; // selected should be array of objects or IDs?
|
|
|
+ // Assuming selected is array of objects, and we need ISBNs for API
|
|
|
+ productDialogVisible.value = false;
|
|
|
+ };
|
|
|
+
|
|
|
+ const handleSubmit = async () => {
|
|
|
+ if (!formRef.value) return;
|
|
|
+
|
|
|
+ await formRef.value.validate(async (valid) => {
|
|
|
+ if (valid) {
|
|
|
+ if (type.value === '2' || type.value === 2) {
|
|
|
+ if (parseFloat(form.minMoney) > parseFloat(form.maxMoney)) {
|
|
|
+ EleMessage.error('最小面额不能大于最大面额');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (form.scope === '2' && (!form.products || form.products.length === 0)) {
|
|
|
+ EleMessage.error('请选择适用商品');
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const payload = {
|
|
|
+ type: String(type.value),
|
|
|
+ couponName: form.couponName,
|
|
|
+ totalNum: form.totalNum,
|
|
|
+ faceMoney: form.faceMoney,
|
|
|
+ minMoney: form.minMoney,
|
|
|
+ maxMoney: form.maxMoney,
|
|
|
+ thresholdMoney: form.thresholdType === 'none' ? 0 : form.thresholdMoney,
|
|
|
+ stackType: form.stackType,
|
|
|
+ scope: form.scope,
|
|
|
+ isbnList: form.products.map(p => p.isbn || p.id), // Adjust based on product object structure
|
|
|
+ scenario: '3', // Default to All
|
|
|
+ effectDays: form.validityType === 'days' ? form.effectDays : 0,
|
|
|
+ effectStartTime: form.validityType === 'range' ? form.validityRange[0] : null,
|
|
|
+ effectEndTime: form.validityType === 'range' ? form.validityRange[1] : null,
|
|
|
+ limitedPerUser: form.limitedPerUser,
|
|
|
+ commandWord: form.commandWord,
|
|
|
+ };
|
|
|
+
|
|
|
+ let res;
|
|
|
+ if (isEdit.value) {
|
|
|
+ // Update
|
|
|
+ res = await request.post('/shop/couponInfo/update', {
|
|
|
+ id: form.id,
|
|
|
+ totalNum: form.totalNum,
|
|
|
+ // Add other fields if update supports them
|
|
|
+ couponName: form.couponName,
|
|
|
+ // ...
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // Add
|
|
|
+ res = await request.post('/shop/couponInfo/add', payload);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (res.data.code === 200) {
|
|
|
+ EleMessage.success(isEdit.value ? '修改成功' : '添加成功');
|
|
|
+ emit('success');
|
|
|
+ visible.value = false;
|
|
|
+ } else {
|
|
|
+ EleMessage.error(res.data.msg || (isEdit.value ? '修改失败' : '添加失败'));
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error(error);
|
|
|
+ EleMessage.error(isEdit.value ? '修改失败' : '添加失败');
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
}
|
|
|
- if (form.productType === 'specific' && form.products.length === 0) {
|
|
|
- EleMessage.error('请选择适用商品');
|
|
|
- return;
|
|
|
- }
|
|
|
+ });
|
|
|
+ };
|
|
|
|
|
|
- loading.value = true;
|
|
|
- setTimeout(() => {
|
|
|
- loading.value = false;
|
|
|
- EleMessage.success('保存成功');
|
|
|
- emit('success', { ...form, type: props.type });
|
|
|
- visible.value = false;
|
|
|
- }, 500);
|
|
|
- }
|
|
|
- });
|
|
|
-};
|
|
|
+ defineExpose({ open });
|
|
|
</script>
|