优化资产编辑表单,移除第三方资产和无库存限制选项,新增配送方式选项,优化图片URL处理逻辑
This commit is contained in:
@@ -19,13 +19,6 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="第三方资产">
|
|
||||||
<el-switch v-model="ruleForm.sourceType" inline-prompt active-text="是" inactive-text="否" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="24">
|
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="资产分类" prop="categoryId">
|
<el-form-item label="资产分类" prop="categoryId">
|
||||||
<el-cascader
|
<el-cascader
|
||||||
@@ -35,10 +28,14 @@
|
|||||||
placeholder="请选择资产分类"
|
placeholder="请选择资产分类"
|
||||||
clearable
|
clearable
|
||||||
class="w100"
|
class="w100"
|
||||||
|
:disabled="isEdit"
|
||||||
@change="onCategoryChange"
|
@change="onCategoryChange"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="24">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="上线时间">
|
<el-form-item label="上线时间">
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
@@ -188,71 +185,15 @@
|
|||||||
<template v-if="ruleForm.type === 'physical'">
|
<template v-if="ruleForm.type === 'physical'">
|
||||||
<el-divider content-position="left">实物资产配置</el-divider>
|
<el-divider content-position="left">实物资产配置</el-divider>
|
||||||
<el-row :gutter="24">
|
<el-row :gutter="24">
|
||||||
<el-col :span="8">
|
|
||||||
<el-form-item label="无库存限制">
|
|
||||||
<el-switch v-model="ruleForm.physicalAssetConfig.unlimitedStock" inline-prompt active-text="是" inactive-text="否" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-form-item label="配送方式">
|
<el-form-item label="配送方式">
|
||||||
<el-select v-model="ruleForm.physicalAssetConfig.shipping.deliveryMethod" placeholder="请选择配送方式" class="w100">
|
<el-select v-model="ruleForm.physicalAssetConfig.shipping.deliveryMethod" placeholder="请选择配送方式" class="w100">
|
||||||
<el-option label="快递" value="express" />
|
<el-option label="快递" value="express" />
|
||||||
<el-option label="自提" value="self_pickup" />
|
<el-option label="自提" value="self_pickup" />
|
||||||
|
<el-option label="同城配送" value="city_delivery" disabled />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="8" v-if="ruleForm.physicalAssetConfig.shipping.deliveryMethod === 'express'">
|
|
||||||
<el-form-item label="发货周期">
|
|
||||||
<el-input-number v-model="ruleForm.physicalAssetConfig.shipping.deliveryTime" :min="1" :max="720" class="w100" />
|
|
||||||
<span class="unit-text">小时</span>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 虚拟资产配置 -->
|
|
||||||
<template v-if="ruleForm.type === 'virtual'">
|
|
||||||
<el-divider content-position="left">虚拟资产配置</el-divider>
|
|
||||||
<el-row :gutter="24">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="HTTP方法">
|
|
||||||
<el-select v-model="ruleForm.virtualAssetConfig.method" placeholder="请选择HTTP方法" class="w100">
|
|
||||||
<el-option label="GET" value="GET" />
|
|
||||||
<el-option label="POST" value="POST" />
|
|
||||||
<el-option label="PUT" value="PUT" />
|
|
||||||
<el-option label="DELETE" value="DELETE" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="24">
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="请求地址">
|
|
||||||
<el-input v-model="ruleForm.virtualAssetConfig.requestURL" placeholder="请输入请求地址" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="认证类型">
|
|
||||||
<el-select v-model="ruleForm.virtualAssetConfig.authType" placeholder="请选择认证类型" class="w100">
|
|
||||||
<el-option label="无认证" value="none" />
|
|
||||||
<el-option label="API Key" value="apikey" />
|
|
||||||
<el-option label="Bearer Token" value="bearer" />
|
|
||||||
<el-option label="OAuth" value="oauth" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="24" v-if="ruleForm.virtualAssetConfig.authType && ruleForm.virtualAssetConfig.authType !== 'none'">
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="认证配置">
|
|
||||||
<el-input
|
|
||||||
v-model="ruleForm.virtualAssetConfig.authConfig"
|
|
||||||
type="textarea"
|
|
||||||
:rows="4"
|
|
||||||
placeholder='请输入认证配置JSON,例如:{"api_key": "your_api_key"}'
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -280,12 +221,6 @@
|
|||||||
<span class="unit-text">分钟</span>
|
<span class="unit-text">分钟</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
|
||||||
<el-form-item label="最大用户">
|
|
||||||
<el-input-number v-model="ruleForm.serviceAssetConfig.capacity.maxUsers" :min="0" class="w100" />
|
|
||||||
<span class="unit-text">0=无限</span>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<!-- 时间段配置 -->
|
<!-- 时间段配置 -->
|
||||||
@@ -301,7 +236,15 @@
|
|||||||
<el-input-number v-model="slot.capacity" :min="1" placeholder="容量" style="width: 100px" controls-position="right" />
|
<el-input-number v-model="slot.capacity" :min="1" placeholder="容量" style="width: 100px" controls-position="right" />
|
||||||
<el-button type="danger" :icon="Delete" circle size="small" @click="removeTimeSlot(index)" />
|
<el-button type="danger" :icon="Delete" circle size="small" @click="removeTimeSlot(index)" />
|
||||||
</div>
|
</div>
|
||||||
<el-button type="primary" :icon="Plus" size="small" @click="addTimeSlot">添加时间段</el-button>
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
:icon="Plus"
|
||||||
|
size="small"
|
||||||
|
@click="addTimeSlot"
|
||||||
|
:disabled="isTimeSlotLimitReached"
|
||||||
|
>
|
||||||
|
添加时间段
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -351,8 +294,9 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, reactive, watch } from 'vue';
|
import { ref, reactive, watch, computed } from 'vue';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
import type { FormInstance, FormRules } from 'element-plus';
|
||||||
import { Plus, Delete } from '@element-plus/icons-vue';
|
import { Plus, Delete } from '@element-plus/icons-vue';
|
||||||
import { getAsset, createAsset, updateAsset } from '/@/api/assets/asset';
|
import { getAsset, createAsset, updateAsset } from '/@/api/assets/asset';
|
||||||
import { getCategoryTree, getCategory } from '/@/api/assets/category';
|
import { getCategoryTree, getCategory } from '/@/api/assets/category';
|
||||||
@@ -385,14 +329,12 @@ interface CategoryAttr {
|
|||||||
interface RuleForm {
|
interface RuleForm {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
sourceType: boolean;
|
|
||||||
type: string;
|
type: string;
|
||||||
categoryId: string;
|
categoryId: string;
|
||||||
description: string;
|
description: string;
|
||||||
onlineTime: string;
|
onlineTime: string;
|
||||||
offlineTime: string;
|
offlineTime: string;
|
||||||
physicalAssetConfig: {
|
physicalAssetConfig: {
|
||||||
unlimitedStock: boolean;
|
|
||||||
shipping: {
|
shipping: {
|
||||||
deliveryMethod: string;
|
deliveryMethod: string;
|
||||||
deliveryTime: number;
|
deliveryTime: number;
|
||||||
@@ -423,13 +365,16 @@ interface RuleForm {
|
|||||||
|
|
||||||
const emit = defineEmits(['getAssetList']);
|
const emit = defineEmits(['getAssetList']);
|
||||||
|
|
||||||
const formRef = ref();
|
const formRef = ref<FormInstance>();
|
||||||
|
const editAssetRef = ref();
|
||||||
|
const MAX_TIME_SLOTS = 7;
|
||||||
const isShowDialog = ref(false);
|
const isShowDialog = ref(false);
|
||||||
const isEdit = ref(false);
|
const isEdit = ref(false);
|
||||||
const submitLoading = ref(false);
|
const submitLoading = ref(false);
|
||||||
const formLoading = ref(false);
|
const formLoading = ref(false);
|
||||||
const categoryOptions = ref<any[]>([]);
|
const categoryOptions = ref<any[]>([]);
|
||||||
const categoryAttrs = ref<CategoryAttr[]>([]);
|
const categoryAttrs = ref<CategoryAttr[]>([]);
|
||||||
|
const isTimeSlotLimitReached = computed(() => ruleForm.serviceAssetConfig.schedule.timeSlots.length >= MAX_TIME_SLOTS);
|
||||||
|
|
||||||
// 获取属性的key
|
// 获取属性的key
|
||||||
const getAttrKey = (attr: CategoryAttr): string => {
|
const getAttrKey = (attr: CategoryAttr): string => {
|
||||||
@@ -447,19 +392,38 @@ const mainImagePreview = ref('');
|
|||||||
const imageFileList = ref<UploadUserFile[]>([]);
|
const imageFileList = ref<UploadUserFile[]>([]);
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
const dialogImageUrl = ref('');
|
const dialogImageUrl = ref('');
|
||||||
|
// 图片拼接
|
||||||
|
const imgAddressPrefix = ref('');
|
||||||
|
|
||||||
|
const formatImageUrl = (url?: string) => {
|
||||||
|
if (!url) return '';
|
||||||
|
if (/^https?:\/\//i.test(url)) return url;
|
||||||
|
return `${imgAddressPrefix.value || ''}${url}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createDefaultTimeSlots = (): TimeSlot[] => {
|
||||||
|
const slots: TimeSlot[] = [];
|
||||||
|
for (let i = 1; i <= MAX_TIME_SLOTS; i++) {
|
||||||
|
slots.push({
|
||||||
|
dayOfWeek: String(i),
|
||||||
|
startTime: '09:00',
|
||||||
|
endTime: '18:00',
|
||||||
|
capacity: 100,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return slots;
|
||||||
|
};
|
||||||
|
|
||||||
// 初始表单数据
|
// 初始表单数据
|
||||||
const getInitialForm = (): RuleForm => ({
|
const getInitialForm = (): RuleForm => ({
|
||||||
id: '',
|
id: '',
|
||||||
name: '',
|
name: '',
|
||||||
sourceType: false,
|
|
||||||
type: 'physical',
|
type: 'physical',
|
||||||
categoryId: '',
|
categoryId: '',
|
||||||
description: '',
|
description: '',
|
||||||
onlineTime: '',
|
onlineTime: '',
|
||||||
offlineTime: '',
|
offlineTime: '',
|
||||||
physicalAssetConfig: {
|
physicalAssetConfig: {
|
||||||
unlimitedStock: false,
|
|
||||||
shipping: {
|
shipping: {
|
||||||
deliveryMethod: 'express',
|
deliveryMethod: 'express',
|
||||||
deliveryTime: 24,
|
deliveryTime: 24,
|
||||||
@@ -473,7 +437,7 @@ const getInitialForm = (): RuleForm => ({
|
|||||||
},
|
},
|
||||||
serviceAssetConfig: {
|
serviceAssetConfig: {
|
||||||
schedule: {
|
schedule: {
|
||||||
timeSlots: [],
|
timeSlots: createDefaultTimeSlots(),
|
||||||
exceptions: [],
|
exceptions: [],
|
||||||
},
|
},
|
||||||
booking: {
|
booking: {
|
||||||
@@ -490,10 +454,19 @@ const getInitialForm = (): RuleForm => ({
|
|||||||
|
|
||||||
const ruleForm = reactive<RuleForm>(getInitialForm());
|
const ruleForm = reactive<RuleForm>(getInitialForm());
|
||||||
|
|
||||||
const rules = {
|
const validateOfflineTime = (_rule: any, value: string, callback: Function) => {
|
||||||
|
if (value && ruleForm.onlineTime && new Date(value).getTime() < new Date(ruleForm.onlineTime).getTime()) {
|
||||||
|
callback(new Error('下线时间不能早于上线时间'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const rules: FormRules = {
|
||||||
name: [{ required: true, message: '资产名称不能为空', trigger: 'blur' }],
|
name: [{ required: true, message: '资产名称不能为空', trigger: 'blur' }],
|
||||||
type: [{ required: true, message: '请选择资产类型', trigger: 'change' }],
|
type: [{ required: true, message: '请选择资产类型', trigger: 'change' }],
|
||||||
categoryId: [{ required: true, message: '请选择资产分类', trigger: 'change' }],
|
categoryId: [{ required: true, message: '请选择资产分类', trigger: 'change' }],
|
||||||
|
offlineTime: [{ validator: validateOfflineTime, trigger: 'change' }],
|
||||||
};
|
};
|
||||||
|
|
||||||
// 主图上传处理
|
// 主图上传处理
|
||||||
@@ -506,6 +479,8 @@ const handleMainImageChange = (file: UploadFile) => {
|
|||||||
|
|
||||||
// 图片列表预览
|
// 图片列表预览
|
||||||
const handlePictureCardPreview = (file: UploadFile) => {
|
const handlePictureCardPreview = (file: UploadFile) => {
|
||||||
|
console.log(file,'111');
|
||||||
|
|
||||||
dialogImageUrl.value = file.url || '';
|
dialogImageUrl.value = file.url || '';
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
};
|
};
|
||||||
@@ -564,6 +539,7 @@ const resetForm = () => {
|
|||||||
mainImagePreview.value = '';
|
mainImagePreview.value = '';
|
||||||
imageFileList.value = [];
|
imageFileList.value = [];
|
||||||
categoryAttrs.value = [];
|
categoryAttrs.value = [];
|
||||||
|
imgAddressPrefix.value = '';
|
||||||
};
|
};
|
||||||
|
|
||||||
// 获取分类数据
|
// 获取分类数据
|
||||||
@@ -608,9 +584,9 @@ const openDialog = (row?: any, edit?: boolean) => {
|
|||||||
getAsset(row.id)
|
getAsset(row.id)
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
const data = res.data;
|
const data = res.data;
|
||||||
|
imgAddressPrefix.value = data.imgAddressPrefix || '';
|
||||||
ruleForm.id = data.id || '';
|
ruleForm.id = data.id || '';
|
||||||
ruleForm.name = data.name || '';
|
ruleForm.name = data.name || '';
|
||||||
ruleForm.sourceType = data.sourceType || false;
|
|
||||||
ruleForm.type = data.type || 'physical';
|
ruleForm.type = data.type || 'physical';
|
||||||
ruleForm.categoryId = data.categoryId || '';
|
ruleForm.categoryId = data.categoryId || '';
|
||||||
ruleForm.description = data.description || '';
|
ruleForm.description = data.description || '';
|
||||||
@@ -619,14 +595,14 @@ const openDialog = (row?: any, edit?: boolean) => {
|
|||||||
|
|
||||||
// 主图预览
|
// 主图预览
|
||||||
if (data.imageUrl) {
|
if (data.imageUrl) {
|
||||||
mainImagePreview.value = data.imageUrl;
|
mainImagePreview.value = formatImageUrl(data.imageUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 图片列表
|
// 图片列表
|
||||||
if (data.images && Array.isArray(data.images)) {
|
if (data.images && Array.isArray(data.images)) {
|
||||||
imageFileList.value = data.images.map((url: string, index: number) => ({
|
imageFileList.value = data.images.map((url: string, index: number) => ({
|
||||||
name: `image-${index}`,
|
name: `image-${index}`,
|
||||||
url: url,
|
url: formatImageUrl(url),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,7 +663,6 @@ const buildFormData = (): FormData => {
|
|||||||
formData.append('id', ruleForm.id);
|
formData.append('id', ruleForm.id);
|
||||||
}
|
}
|
||||||
formData.append('name', ruleForm.name);
|
formData.append('name', ruleForm.name);
|
||||||
formData.append('sourceType', String(ruleForm.sourceType));
|
|
||||||
formData.append('type', ruleForm.type);
|
formData.append('type', ruleForm.type);
|
||||||
formData.append('categoryId', ruleForm.categoryId);
|
formData.append('categoryId', ruleForm.categoryId);
|
||||||
formData.append('description', ruleForm.description || '');
|
formData.append('description', ruleForm.description || '');
|
||||||
@@ -729,7 +704,9 @@ const buildFormData = (): FormData => {
|
|||||||
|
|
||||||
// 提交
|
// 提交
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
formRef.value.validate((valid: boolean) => {
|
const form = formRef.value;
|
||||||
|
if (!form) return;
|
||||||
|
form.validate((valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
submitLoading.value = true;
|
submitLoading.value = true;
|
||||||
const formData = buildFormData();
|
const formData = buildFormData();
|
||||||
|
|||||||
Reference in New Issue
Block a user