提交demo
This commit is contained in:
@@ -0,0 +1,422 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- <uni-nav-bar leftText=" " @clickLeft="leftClick" leftIcon="back" :fixed="true" :border="false" color="#fff" backgroundColor="#3F435B" :statusBar="true" title="车辆编辑"></uni-nav-bar> -->
|
||||
<view class="content">
|
||||
<view class="cell">
|
||||
<view>产品名称 <text class="red">*</text></view>
|
||||
<view class="right">
|
||||
<input placeholder="请输入产品名称" v-model="carinfo.product_name" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view>车辆识别码</view>
|
||||
<view class="right">
|
||||
<input placeholder="请输入车架号/VIN码" v-model="carinfo.vin" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view>车价(¥)</view>
|
||||
<view class="right">
|
||||
<input placeholder="请输入车价" v-model="carinfo.price" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view>车源地</view>
|
||||
<view class="right">
|
||||
<input placeholder="请输入车源地" v-model="carinfo.source_place" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view>上牌地</view>
|
||||
<view class="right">
|
||||
<input placeholder="请输入上牌地" v-model="carinfo.plate_place" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view>上牌时间</view>
|
||||
<view class="right">
|
||||
<uni-datetime-picker
|
||||
ref="borrowTimePicker"
|
||||
type="date"
|
||||
v-model="carinfo.plate_time"
|
||||
placeholder="请选择时间"
|
||||
:border="false"
|
||||
:clear-icon="false"
|
||||
@change="onBorrowTimeChange"
|
||||
>
|
||||
<view class="custom-datetime-input">
|
||||
<text class="custom-datetime-text" :class="{ 'placeholder': !carinfo.plate_time }">
|
||||
{{ carinfo.plate_time || '请选择时间' }}
|
||||
</text>
|
||||
<uni-icons type="calendar" size="16" color="#999"></uni-icons>
|
||||
</view>
|
||||
</uni-datetime-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view>排量</view>
|
||||
<view class="right">
|
||||
<input placeholder="请输入排量" v-model="carinfo.displacement" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view>里程</view>
|
||||
<view class="right">
|
||||
<input placeholder="请输入里程" v-model="carinfo.mileage" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell">
|
||||
<view>车身颜色</view>
|
||||
<view class="right">
|
||||
<input placeholder="请输入车身颜色" v-model="carinfo.body_color" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="cont">
|
||||
<view class="conts">产品图</view>
|
||||
<view class="media-upload-wrapper">
|
||||
<uni-file-picker
|
||||
ref="mediaPicker"
|
||||
v-model="fileList"
|
||||
:limit="maxMedia"
|
||||
file-mediatype="image"
|
||||
mode="grid"
|
||||
:auto-upload="false"
|
||||
@select="selectMedia"
|
||||
@delete="delfn"
|
||||
>
|
||||
<view class="upload-icon-wrapper">
|
||||
<image src="/static/image/img.png" mode="" class="addimg"></image>
|
||||
</view>
|
||||
</uni-file-picker>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cont">
|
||||
<view class="conts">车况介绍</view>
|
||||
<view class="">
|
||||
<textarea auto-height v-model="carinfo.condition_desc" placeholder="请输入车况介绍"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="zw">
|
||||
<button class="btn" @click="draftadd">提交</button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script>
|
||||
import { request,showToast } from '@/api/apiT.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
maxMedia:20,
|
||||
// uni-file-picker 回显/展示用(url/name/extname)
|
||||
fileList: [],
|
||||
id:'',
|
||||
_uploading:false,
|
||||
carinfo:{
|
||||
id:'',
|
||||
product_name:'',
|
||||
vin:'',
|
||||
price:'',
|
||||
source_place:'',
|
||||
plate_place:'',
|
||||
plate_time:'',
|
||||
displacement:'',
|
||||
body_color:'',
|
||||
// 提交给后端用:相对路径数组(最终 join(','))
|
||||
images:[],
|
||||
condition_desc:'',
|
||||
mileage:''
|
||||
}
|
||||
}
|
||||
},
|
||||
onLoad(options) {
|
||||
this.id = options?.id || ''
|
||||
this.getshows()
|
||||
},
|
||||
methods: {
|
||||
leftClick() {
|
||||
uni.navigateBack()
|
||||
},
|
||||
getshows(){
|
||||
let that = this;
|
||||
request({
|
||||
url:'common/usedcar/show',
|
||||
method:'GET',
|
||||
data:{
|
||||
id:that.id
|
||||
}
|
||||
}).then(res => {
|
||||
if (res.data.code == 200) {
|
||||
const d = res.data.data || {}
|
||||
// 1) images:后端返回的是逗号字符串,这里转成数组(用于编辑提交)
|
||||
const keys = String(d.images || '')
|
||||
.split(',')
|
||||
.map(s => String(s || '').trim())
|
||||
.filter(Boolean)
|
||||
|
||||
// 2) 表单字段
|
||||
this.carinfo = {
|
||||
...this.carinfo,
|
||||
...d,
|
||||
images: keys
|
||||
}
|
||||
|
||||
// 3) 图片回显:优先用 images_pull(签名URL用于显示)
|
||||
const pulls = Array.isArray(d.images_pull) && d.images_pull.length
|
||||
? d.images_pull
|
||||
: keys
|
||||
this.fileList = pulls.map((u, idx) => {
|
||||
const raw = String(u || '')
|
||||
const filename = raw.split('?')[0].split('/').pop() || `img_${idx + 1}`
|
||||
const ext = filename.includes('.') ? filename.split('.').pop() : ''
|
||||
return { url: raw, name: filename, extname: ext }
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
onBorrowTimeChange(e) {
|
||||
this.carinfo.plate_time = e
|
||||
},
|
||||
uploadfn(imgUrl){
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: 'https://usedcar.dev.hnxinyouhe.com/upload/image?scene=usedcarimg',
|
||||
filePath: imgUrl,
|
||||
name: 'image',
|
||||
header:{'Fdesk-Auth-Token': uni.getStorageSync('token'),'Fdesk-Login-Type': 'feishu','Fdesk-System-Code':'fdesk'},
|
||||
success: (uploadFileRes) => {
|
||||
const res = JSON.parse(uploadFileRes.data || '{}')
|
||||
if(res && res.data && res.data.href){
|
||||
resolve(res.data.href)
|
||||
}else{
|
||||
reject('上传失败')
|
||||
}
|
||||
},
|
||||
fail: (err) => reject(err)
|
||||
});
|
||||
})
|
||||
},
|
||||
selectMedia(e){
|
||||
const allowCount = this.maxMedia - (this.carinfo.images?.length || 0)
|
||||
if(allowCount <= 0){
|
||||
uni.showToast({
|
||||
title:`最多只能上传${this.maxMedia}张图片`,
|
||||
icon:'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const tempFiles = e.tempFiles || []
|
||||
const tempFilePaths = (tempFiles.length
|
||||
? tempFiles.map(f => f.path || f.url).filter(Boolean)
|
||||
: (e.tempFilePaths || [])
|
||||
)
|
||||
const paths = tempFilePaths.slice(0, allowCount)
|
||||
if(paths.length === 0) return
|
||||
if(this._uploading) return
|
||||
this._uploading = true
|
||||
|
||||
// 先占位,保证 delete 的 index 与 images 数组对得上
|
||||
const startAt = this.carinfo.images.length
|
||||
for(let i=0;i<paths.length;i++){
|
||||
this.carinfo.images.push('__PENDING__')
|
||||
}
|
||||
|
||||
Promise.all(paths.map(p => this.uploadfn(p)))
|
||||
.then(keys => {
|
||||
keys.forEach((key, i) => {
|
||||
// 替换占位
|
||||
this.$set(this.carinfo.images, startAt + i, String(key))
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
// 失败:移除占位,同时把 fileList 对应项删掉(避免页面“假回显”)
|
||||
this.carinfo.images.splice(startAt, paths.length)
|
||||
if(Array.isArray(this.fileList) && this.fileList.length >= startAt + paths.length){
|
||||
this.fileList.splice(startAt, paths.length)
|
||||
}
|
||||
uni.showToast({
|
||||
title:'图片上传失败,请重试',
|
||||
icon:'none'
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
this._uploading = false
|
||||
})
|
||||
},
|
||||
delfn(e){
|
||||
// fileList 会由 uni-file-picker 自己维护;这里同步删除提交用的 images
|
||||
this.carinfo.images.splice(e.index, 1)
|
||||
},
|
||||
draftadd(){
|
||||
const payload = {
|
||||
...this.carinfo,
|
||||
// images 数组 => "url1,url2,url3"
|
||||
images: (this.carinfo.images || [])
|
||||
.map(s => String(s || '').trim())
|
||||
.filter(s => !!s && s !== '__PENDING__')
|
||||
.join(',')
|
||||
}
|
||||
request({
|
||||
url:'common/usedcar/update',
|
||||
method:'post',
|
||||
data:{
|
||||
id:payload.id,
|
||||
product_name:payload.product_name,
|
||||
vin:payload.vin,
|
||||
price:payload.price,
|
||||
source_place:payload.source_place,
|
||||
plate_place:payload.plate_place,
|
||||
plate_time:payload.plate_time,
|
||||
displacement:payload.displacement,
|
||||
body_color:payload.body_color,
|
||||
images:payload.images,
|
||||
condition_desc:payload.condition_desc,
|
||||
mileage:payload.mileage
|
||||
}
|
||||
}).then(res => {
|
||||
uni.showToast({
|
||||
title: res.data.message,
|
||||
icon: 'none'
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.reLaunch({
|
||||
url: '/pages/index/mine',// 替换为你要跳转的页面路径
|
||||
});
|
||||
}, 1000);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.uniui-right{
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
}
|
||||
.red{
|
||||
color: red;
|
||||
}
|
||||
.content{
|
||||
margin: 20px 12px;
|
||||
background: #FFFFFF;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.zw{
|
||||
height: 120px;
|
||||
}
|
||||
.cont{
|
||||
position: relative;
|
||||
padding: 18px 20px;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
.conts{
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.media-upload-wrapper{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
}
|
||||
.cell{
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content:space-between;
|
||||
padding: 18px 20px;
|
||||
/* border-bottom: 1px solid #C3C3C3; */
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
.cont::after,.cell::after{
|
||||
content : '';
|
||||
position : absolute;
|
||||
width : 200%;
|
||||
height : 200%;
|
||||
top : 0;
|
||||
left : 0;
|
||||
transform-origin: 0 0;
|
||||
border-width: 0;
|
||||
border-bottom-width:1px;
|
||||
border-style : solid;
|
||||
transform : scale(0.5, 0.5);
|
||||
border-radius : 1px;
|
||||
box-sizing : border-box;
|
||||
pointer-events : none;
|
||||
border-color:#C3C3C3;
|
||||
}
|
||||
.cell1{
|
||||
display: flex;
|
||||
justify-content:space-between;
|
||||
padding: 18px 20px;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
}
|
||||
.right{
|
||||
text-align: right;
|
||||
}
|
||||
.select{
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.foot{
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 120px;
|
||||
background: #FFFFFF;
|
||||
z-index: 2;
|
||||
}
|
||||
.btn{
|
||||
background-color: #3F435B;
|
||||
color: white;
|
||||
border-radius: 50px;
|
||||
width: 92%;
|
||||
margin-bottom: 40px;
|
||||
margin: 15px 4%;
|
||||
}
|
||||
|
||||
.actives{
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
.text{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
line-height: 30px;
|
||||
padding: 10px 15px 0px;
|
||||
.qd{
|
||||
color: #3471FF;
|
||||
}
|
||||
}
|
||||
.popup-content {
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.option-list {
|
||||
max-height: 400rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.option-item {
|
||||
padding: 20rpx;
|
||||
border-bottom: 1rpx solid #eee;
|
||||
}
|
||||
|
||||
.option-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
text-align: center;
|
||||
padding: 20rpx;
|
||||
color: #999;
|
||||
}
|
||||
.addimg{
|
||||
width: 215rpx;
|
||||
height: 215rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user