上传图片

This commit is contained in:
李远 2026-03-25 17:37:47 +08:00
parent fc2e3284b5
commit 7dbe351ac5
4 changed files with 101 additions and 25 deletions

View File

@ -5,7 +5,7 @@ import { request } from '@/api'; // 引入你已封装的request
* @param file * @param file
* @returns Promise<{ url: string }> URL * @returns Promise<{ url: string }> URL
*/ */
export const uploadImageApi = (file: File): Promise<{ url: string }> => { export const uploadImageApi = (file: any): Promise<{ url: string }> => {
// 构建FormData图片上传必须用FormData格式 // 构建FormData图片上传必须用FormData格式
const formData = new FormData(); const formData = new FormData();
formData.append('image', file); // 对应后端接收字段名image formData.append('image', file); // 对应后端接收字段名image

View File

@ -29,6 +29,18 @@
@cancel="handleCancel" @close="handleClose"> @cancel="handleCancel" @close="handleClose">
<VarietyForm :form-data="varietyForm" :form-rules="varietyFormRules" :form-items="dialogFormItemOptions" <VarietyForm :form-data="varietyForm" :form-rules="varietyFormRules" :form-items="dialogFormItemOptions"
:options-map="varietyFormOptionsMap" :row-gutter="rowGutter" :col-span="colSpan" ref="varietyFormRef"> :options-map="varietyFormOptionsMap" :row-gutter="rowGutter" :col-span="colSpan" ref="varietyFormRef">
<template #upload="{ formData }">
<el-upload v-model:file-list="fileList" class="upload-demo" :http-request="handleUpload"
:before-upload="beforeUpload" :limit="1">
<el-button type="primary">点击上传</el-button>
<template #tip>
<div class="el-upload__tip">
jpg/png格式 图片大小不能超过20KB
</div>
</template>
<img v-if="dialogType === 'edit'" :src="formData.imageUrl" alt="预览图片" style="width: 100px; height: 100px;">
</el-upload>
</template>
</VarietyForm> </VarietyForm>
</VarietyDialog> </VarietyDialog>
<!-- dialog表格 --> <!-- dialog表格 -->
@ -36,6 +48,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { UploadProps, UploadUserFile } from 'element-plus'
// //
import VarietySearch from '@/components/common/Search.vue' import VarietySearch from '@/components/common/Search.vue'
import VarietyTable from '@/components/common/Table.vue' import VarietyTable from '@/components/common/Table.vue'
@ -48,6 +61,8 @@ import { rules } from './rules'
// //
import { getVarietyListApi, getTradeGroupListApi, editVarietyApi, createVarietyApi } from '@/api/modules/trade/variety' import { getVarietyListApi, getTradeGroupListApi, editVarietyApi, createVarietyApi } from '@/api/modules/trade/variety'
//
import { uploadImageApi } from '@/api/modules/upload'
/** /**
* @description: 定义搜索数据 * @description: 定义搜索数据
@ -111,6 +126,10 @@ const varietyForm = ref({
decimalPlaces: '', decimalPlaces: '',
// //
pointDecimalPlaces: '', pointDecimalPlaces: '',
//
type: '',
//
imageUrl: '',
}) })
const varietyFormRef = ref<any>() const varietyFormRef = ref<any>()
const varietyFormRules = ref(rules()) const varietyFormRules = ref(rules())
@ -141,7 +160,9 @@ const selectedRow = ref<any>(null)
const rowGutter = ref(20) const rowGutter = ref(20)
const colSpan = ref(12) const colSpan = ref(12)
const typeMap:any = { const fileList = ref([])
const typeMap: any = {
1: '金属', 1: '金属',
2: '能源', 2: '能源',
3: '指数', 3: '指数',
@ -177,6 +198,7 @@ const getVarietyList = async () => {
shortStockFee: item.fee_inventory_short, shortStockFee: item.fee_inventory_short,
profitLevel: item.stop_loss_level, profitLevel: item.stop_loss_level,
type: typeMap[item.type], type: typeMap[item.type],
image: item.image,
})) }))
} }
@ -226,6 +248,7 @@ const handleEdit = () => {
decimalPlaces: row.decimal_place, decimalPlaces: row.decimal_place,
// //
pointDecimalPlaces: row.point_diff_decimal_place, pointDecimalPlaces: row.point_diff_decimal_place,
imageUrl: row.image,
} as any } as any
// //
dialogVisible.value = true dialogVisible.value = true
@ -239,31 +262,67 @@ const handleAdd = () => {
dialogTitle.value = '添加合约品种' dialogTitle.value = '添加合约品种'
dialogType.value = 'add' dialogType.value = 'add'
varietyForm.value = { varietyForm.value = {
varietyName: '', varietyName: '',
varietyCode: '', varietyCode: '',
onlineStatus: 1, onlineStatus: 1,
tradeStatus: 1, tradeStatus: 1,
minPoint: '', minPoint: '',
maxPoint: '', maxPoint: '',
contractSize: '', contractSize: '',
minFlux: '', minFlux: '',
unit: '', unit: '',
tradeGroup: '', tradeGroup: '',
longStockFee: '', longStockFee: '',
shortStockFee: '', shortStockFee: '',
profitLevel: '', profitLevel: '',
id: '', id: '',
groupId: '', groupId: '',
prepaymentHedge: '', prepaymentHedge: '',
prepaymentPercent: '', prepaymentPercent: '',
decimalPlaces: '', decimalPlaces: '',
pointDecimalPlaces: '', pointDecimalPlaces: '',
//
type: '',
//
imageUrl: '',
}
fileList.value = []
}
/**
* @description: 上传图片
*/
//
const handleUpload = async (options: any) => {
const { file } = options
try {
const data = await uploadImageApi(file)
varietyForm.value.imageUrl = data.url
// el-upload
options.onSuccess(data)
} catch (err) {
console.error('上传失败', err)
} }
} }
/**
* @description: 定义表格方法 // + 20KB = 20 * 1024
*/ const beforeUpload = (file: File) => {
const isTypeValid = file.type === 'image/jpeg' || file.type === 'image/png'
if (!isTypeValid) {
ElMessage.error('只能上传 JPG/PNG 格式!')
return false
}
const isSizeValid = file.size / 1024 < 20
if (!isSizeValid) {
ElMessage.error('图片大小不能超过 20KB')
return false
}
return true
}
/** /**
* @description: 定义弹窗方法 * @description: 定义弹窗方法
@ -289,13 +348,17 @@ const handleSubmit = async () => {
multiplier: varietyForm.value.contractSize, multiplier: varietyForm.value.contractSize,
undulate_min: varietyForm.value.minFlux, undulate_min: varietyForm.value.minFlux,
online_status: varietyForm.value.onlineStatus, online_status: varietyForm.value.onlineStatus,
type: Number(varietyForm.value.type),
image: varietyForm.value.imageUrl,
} }
console.log(params)
if (dialogType.value === 'edit') { if (dialogType.value === 'edit') {
console.log(params) console.log(params)
await editVarietyApi(params) await editVarietyApi(params)
getVarietyList() getVarietyList()
} else { } else {
await createVarietyApi({...params, group_id: varietyForm.value.tradeGroup}) await createVarietyApi({ ...params, group_id: varietyForm.value.tradeGroup })
getVarietyList() getVarietyList()
} }
dialogVisible.value = false dialogVisible.value = false
@ -328,4 +391,7 @@ const handleRowClick = (row: any) => {
} }
} }
} }
:deep(.el-upload){
flex-direction: column;
}
</style> </style>

View File

@ -78,6 +78,8 @@ export const editDialogFormItem = [
{ prop: 'minFlux', label: '最小波动', type: 'input' as const, placeholder: '请输入最小波动' }, { prop: 'minFlux', label: '最小波动', type: 'input' as const, placeholder: '请输入最小波动' },
// 类型 // 类型
{ prop: 'type', label: '类型', type: 'select' as const, placeholder: '请选择类型' }, { prop: 'type', label: '类型', type: 'select' as const, placeholder: '请选择类型' },
// 上传图片地址
{ prop: 'imageUrl', slotName: 'upload', label: '上传图片' ,type: 'upload' as const},
// 上下线状态 // 上下线状态
{ prop: 'onlineStatus', label: '上下线状态', type: 'switch' as const}, { prop: 'onlineStatus', label: '上下线状态', type: 'switch' as const},
// 交易状态 // 交易状态

View File

@ -110,5 +110,13 @@ export const rules = (): FormRules => {
{ required: true, message: '请输入最小波动', trigger: ['blur', 'change'] }, { required: true, message: '请输入最小波动', trigger: ['blur', 'change'] },
{ validator: validateMaxFiveDecimals('最小波动')} { validator: validateMaxFiveDecimals('最小波动')}
], ],
// 类型
type: [
{ required: true, message: '请选择类型', trigger: ['blur', 'change'] }
],
// 上传图片
imageUrl: [
{ required: true, message: '请上传图片', trigger: ['blur', 'change'] }
],
} }
} }