优化资产编辑表单,移除第三方资产和无库存限制选项,新增配送方式选项,优化图片URL处理逻辑

This commit is contained in:
WUSIJIAN
2025-12-22 17:57:15 +08:00
parent 4fedcd16df
commit 7b8e9f40cc

View File

@@ -19,14 +19,7 @@
</el-select>
</el-form-item>
</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-cascader
v-model="ruleForm.categoryId"
@@ -35,10 +28,14 @@
placeholder="请选择资产分类"
clearable
class="w100"
:disabled="isEdit"
@change="onCategoryChange"
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="上线时间">
<el-date-picker
@@ -188,71 +185,15 @@
<template v-if="ruleForm.type === 'physical'">
<el-divider content-position="left">实物资产配置</el-divider>
<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-form-item label="配送方式">
<el-select v-model="ruleForm.physicalAssetConfig.shipping.deliveryMethod" placeholder="请选择配送方式" class="w100">
<el-option label="快递" value="express" />
<el-option label="自提" value="self_pickup" />
<el-option label="同城配送" value="city_delivery" disabled />
</el-select>
</el-form-item>
</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>
</template>
@@ -280,12 +221,6 @@
<span class="unit-text">分钟</span>
</el-form-item>
</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>
<!-- 时间段配置 -->
@@ -301,7 +236,15 @@
<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)" />
</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>
</el-form-item>
@@ -351,8 +294,9 @@ export default {
</script>
<script setup lang="ts">
import { ref, reactive, watch } from 'vue';
import { ref, reactive, watch, computed } from 'vue';
import { ElMessage } from 'element-plus';
import type { FormInstance, FormRules } from 'element-plus';
import { Plus, Delete } from '@element-plus/icons-vue';
import { getAsset, createAsset, updateAsset } from '/@/api/assets/asset';
import { getCategoryTree, getCategory } from '/@/api/assets/category';
@@ -385,14 +329,12 @@ interface CategoryAttr {
interface RuleForm {
id: string;
name: string;
sourceType: boolean;
type: string;
categoryId: string;
description: string;
onlineTime: string;
offlineTime: string;
physicalAssetConfig: {
unlimitedStock: boolean;
shipping: {
deliveryMethod: string;
deliveryTime: number;
@@ -423,13 +365,16 @@ interface RuleForm {
const emit = defineEmits(['getAssetList']);
const formRef = ref();
const formRef = ref<FormInstance>();
const editAssetRef = ref();
const MAX_TIME_SLOTS = 7;
const isShowDialog = ref(false);
const isEdit = ref(false);
const submitLoading = ref(false);
const formLoading = ref(false);
const categoryOptions = ref<any[]>([]);
const categoryAttrs = ref<CategoryAttr[]>([]);
const isTimeSlotLimitReached = computed(() => ruleForm.serviceAssetConfig.schedule.timeSlots.length >= MAX_TIME_SLOTS);
// 获取属性的key
const getAttrKey = (attr: CategoryAttr): string => {
@@ -447,19 +392,38 @@ const mainImagePreview = ref('');
const imageFileList = ref<UploadUserFile[]>([]);
const dialogVisible = ref(false);
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 => ({
id: '',
name: '',
sourceType: false,
type: 'physical',
categoryId: '',
description: '',
onlineTime: '',
offlineTime: '',
physicalAssetConfig: {
unlimitedStock: false,
shipping: {
deliveryMethod: 'express',
deliveryTime: 24,
@@ -473,7 +437,7 @@ const getInitialForm = (): RuleForm => ({
},
serviceAssetConfig: {
schedule: {
timeSlots: [],
timeSlots: createDefaultTimeSlots(),
exceptions: [],
},
booking: {
@@ -490,10 +454,19 @@ const getInitialForm = (): RuleForm => ({
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' }],
type: [{ 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) => {
console.log(file,'111');
dialogImageUrl.value = file.url || '';
dialogVisible.value = true;
};
@@ -564,6 +539,7 @@ const resetForm = () => {
mainImagePreview.value = '';
imageFileList.value = [];
categoryAttrs.value = [];
imgAddressPrefix.value = '';
};
// 获取分类数据
@@ -608,9 +584,9 @@ const openDialog = (row?: any, edit?: boolean) => {
getAsset(row.id)
.then((res: any) => {
const data = res.data;
imgAddressPrefix.value = data.imgAddressPrefix || '';
ruleForm.id = data.id || '';
ruleForm.name = data.name || '';
ruleForm.sourceType = data.sourceType || false;
ruleForm.type = data.type || 'physical';
ruleForm.categoryId = data.categoryId || '';
ruleForm.description = data.description || '';
@@ -619,14 +595,14 @@ const openDialog = (row?: any, edit?: boolean) => {
// 主图预览
if (data.imageUrl) {
mainImagePreview.value = data.imageUrl;
mainImagePreview.value = formatImageUrl(data.imageUrl);
}
// 图片列表
if (data.images && Array.isArray(data.images)) {
imageFileList.value = data.images.map((url: string, index: number) => ({
name: `image-${index}`,
url: url,
url: formatImageUrl(url),
}));
}
@@ -687,7 +663,6 @@ const buildFormData = (): FormData => {
formData.append('id', ruleForm.id);
}
formData.append('name', ruleForm.name);
formData.append('sourceType', String(ruleForm.sourceType));
formData.append('type', ruleForm.type);
formData.append('categoryId', ruleForm.categoryId);
formData.append('description', ruleForm.description || '');
@@ -729,7 +704,9 @@ const buildFormData = (): FormData => {
// 提交
const onSubmit = () => {
formRef.value.validate((valid: boolean) => {
const form = formRef.value;
if (!form) return;
form.validate((valid: boolean) => {
if (valid) {
submitLoading.value = true;
const formData = buildFormData();