Files
product-uniapp/pages/publish/index.vue
T
2025-12-12 18:34:44 +08:00

727 lines
16 KiB
Vue

<template>
<view class="publish-page">
<uni-nav-bar leftText=" " :fixed="true" :border="false" @clickLeft="leftClick" color="#000000" backgroundColor="#fff" :statusBar="true" title="样机发布"></uni-nav-bar>
<view class="form-card">
<view class="select-input gradient-bg" @click="showSelect1 = true">
<view class="category-content">
<text class="category-text">{{form.category || '请输入/选择型号'}}</text>
</view>
<u-icon name="arrow-down" color="#3BC8BE" size="20"></u-icon>
</view>
<view class="conts mag-top">
<view class="">
<textarea v-model="form.content" class="content-textarea" placeholder="请输入文字内容"
:maxlength="maxWords" @input="handleContentInput" />
</view>
<view class="media-upload-wrapper">
<uni-file-picker fileMediatype="image" limit="9" @select="selectMedia" @delete="delfn" :imageStyles="imageStyles">
<view class="upload-icon-wrapper">
<image src="/static/image/photo.png" mode="" class="addimg"></image>
</view>
</uni-file-picker>
</view>
<view class="help-text">
<u-icon name="info-circle" size="18" color="#A6ABB7"></u-icon>
<text>文字不多于2000字,图片不多于9张</text>
</view>
</view>
<view class="mag-top">
<picker mode="selector" :range="conditionOptions" range-key="name" @change="onCategoryChange">
<view class="select-input gradient-bg">
<view class="category-content">
<text class="category-text">{{form.agename || '请选择样机新旧程度'}}</text>
</view>
<u-icon name="arrow-down" color="#3BC8BE" size="20"></u-icon>
</view>
</picker>
</view>
<view class="mag-top">
<input class="uni-input" focus v-model="form.price" placeholder="请输入折扣价格" />
</view>
<view class="detils">
<view v-html="productcontents">
</view>
</view>
</view>
<!-- 型号选择弹层 -->
<view v-if="showSelect1" class="select-popup">
<view class="popup-mask" @click="showSelect1=false"></view>
<view class="popup-panel">
<view class="popup-header">
<input class="popup-search" v-model="searchKey1" placeholder="搜索型号" />
<text class="popup-close" @click="showSelect1=false">取消</text>
</view>
<scroll-view scroll-y class="popup-list">
<view
v-for="item in filteredCategories"
:key="item.id"
class="popup-item"
@click="selectCategory(item)"
>
{{ item.model }}
</view>
<view v-if="!filteredCategories.length" class="popup-empty">暂无数据</view>
</scroll-view>
</view>
</view>
<view class="foot">
<view class="agreement">
<label class="agree-label" @click="toggleAgreement">
<checkbox :checked="agree" style="transform:scale(0.8)"></checkbox>
<text>我已阅读并同意</text>
<text class="link" @click.stop="viewAgreement">《发布协议》</text>
</label>
<button class="primary-btn gradient-btn" @click="submitForm">立即发布</button>
</view>
</view>
<u-popup :show="show" :closeOnClickOverlay="false" :round="10" mode="center">
<view class="cont-text" >
<rich-text :nodes="viewAgreementcont"></rich-text>
</view>
<view class="cent">
<button class="btn1" @click="show = !show">取消</button>
<button class="btn" @click="agreementbtn">确定</button>
</view>
</u-popup>
<u-popup :show="showlogin" :closeOnClickOverlay="false" :round="20" mode="center">
<view class="popupcontent">
<image class="log1" src="/static/image/log1.png"></image>
<view class="title">{{$t('home.loginmsg')}}</view>
<view class="yhxy">
<checkbox-group name="" style="width: 28px;display: inline-block;">
<label @tap="selfChangde()">
<checkbox :checked="selfChecked" activeBackgroundColor="#3F435B"
style="transform:scale(0.7);border-radius: 50%" />
</label>
</checkbox-group>
{{$t('home.argin')}}<text class="xy" @click="gouser">{{$t('home.UserAgreement')}}</text>{{$t('home.and')}}<text
class="xy" @click="goprivacy">{{$t('home.Privacy')}}</text>
</view>
</view>
<view class="cent">
<button class="btn1" @click="showlogin = !showlogin">{{$t('cancel')}}</button>
<button v-if="selfChecked" class="btn" open-type="getPhoneNumber" @click="showlogin = !showlogin"
@getphonenumber="getPhoneNumber">{{$t('login')}}</button>
<button v-else class="btn" @click="loginbtn">{{$t('login')}}</button>
</view>
</u-popup>
</view>
</template>
<script>
import { request,showToast } from '@/api/apiT.js'
export default {
name: 'PublishPage',
data(){
return {
showSelect1:false,
showSelect2:false,
searchKey1:'',
productcontents:'',
categoryOptions:[],
conditionOptions:[
{name:'全新',value:'10'},
{name:'9成新',value:'9'},
{name:'8成新',value:'8'},
{name:'7成新',value:'7'},
{name:'6成新',value:'6'},
{name:'5成新',value:'5'},
{name:'4成新',value:'4'},
{name:'3成新',value:'3'},
{name:'2成新',value:'2'},
{name:'1成新',value:'1'},
],
form:{
agename:'',
age:'',
category:'',
sku_id:'',
content:'',
media:[],
price:''
},
selfChecked: false,
showlogin:false,
viewAgreementcont:'',
iconurl:'',
maxWords:2000,
maxMedia:9,
agree:false,
show:false,
}
},
computed:{
canSubmit(){
return this.agree && this.form.content.trim().length>0 && this.form.media.length>0
},
filteredCategories(){
if(!this.searchKey1) return this.categoryOptions
return this.categoryOptions.filter(i => (i.model || '').toLowerCase().includes(this.searchKey1.toLowerCase()))
}
},
onLoad() {
this.getcategory()
},
onShow() {
// this.getset()
// this.syncTabbar()
},
methods:{
getlocation(){
wx.getFuzzyLocation({
type: 'wgs84',
success(res) {
console.log("模糊定位:", res)
},
fail(err) {
console.log("模糊定位失败:", err)
}
})
},
selectCategory(item){
this.form.category = item.model || ''
this.form.sku_id = item.id || ''
this.productcontents = item.desc || ''
console.log(this.productcontents)
this.showSelect1 = false
},
goprivacy(){
uni.navigateTo({
url: '/pages/login/agreement',// 替换为你要跳转的页面路径
});
},
gouser(){
uni.navigateTo({
url: '/pages/login/agreementuser',// 替换为你要跳转的页面路径
});
},
selfChangde(e) {
this.selfChecked = !this.selfChecked;
},
loginbtn(){
if(!this.selfChecked){
uni.showToast({
title:this.$t('home.arginimg'),
icon: 'none'
});
return false
}
},
getPhoneNumber(e) {
let that = this;
request({
url:'miniapp/phone',
method:'POST',
data:{
phone_code: e.detail.code,
}
}).then(res => {
if (res.data.code == -1) {
uni.showToast({
title: res.data.msg,
icon: 'none'
});
} else if (res.data.code == 200) {
uni.showToast({
title: '登录成功',
icon: 'none'
});
//返回数据接收成功
uni.setStorageSync('is_login', true);
}
})
},
//商品下拉
getcategory(){
request({
url:'common/sku/preset',
method:'GET'
}).then(res => {
if (res.data.code == 200) {
this.categoryOptions = res.data.data|| [];
}
})
},
syncTabbar(){
uni.setTabBarItem({ index:0, text:this.$t('tabbar.home') })
uni.setTabBarItem({ index:1, text:this.$t('tabbar.square') })
uni.setTabBarItem({ index:2, text:this.$t('tabbar.publish') })
uni.setTabBarItem({ index:3, text:this.$t('tabbar.mine') })
},
goBack(){
uni.navigateBack()
},
onCategoryChange(e){
console.log(e)
const index = e.detail.value; // picker 返回的 index
const selectCity = this.conditionOptions[index]; // 直接取整条数据
this.form.agename = selectCity.name
this.form.age = selectCity.name
},
handleContentInput(e){
if(e.detail.value.length>this.maxWords){
this.form.content = e.detail.value.slice(0,this.maxWords)
}
},
uploadfn(imgUrl){
return new Promise((resolve, reject) => {
uni.uploadFile({
url: 'https://cb.hnxinyouhe.com/upload/image?scene=postlist',
filePath: imgUrl,
name: 'image',
header:{'content-type': 'application/x-www-form-urlencoded','Fdesk-Auth-Token': 'Bearer ' + uni.getStorageSync('token'),'Fdesk-Language': uni.getStorageSync('i18locale')?uni.getStorageSync('i18locale'):'zh','Fdesk-Login-Type': 'wechat','Fdesk-System-Code':'wechat'},
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.form.media.length
if(allowCount <= 0){
uni.showToast({
title:`最多只能上传${this.maxMedia}张图片`,
icon:'none'
})
return
}
const tempFilePaths = e.tempFilePaths || (e.tempFiles || []).map(item => item.path || item.url)
const paths = tempFilePaths.slice(0, allowCount)
if(paths.length === 0){
return
}
Promise.all(paths.map(p => this.uploadfn(p))).then(urls => {
urls.forEach(url => {
this.form.media.push(url)
})
}).catch(() => {
uni.showToast({
title:'图片上传失败,请重试',
icon:'none'
})
})
},
delfn(e){
this.form.media.splice(e.index, 1)
},
deleteMedia(index){
this.form.media.splice(index, 1)
},
toggleAgreement(){
this.agree = !this.agree
},
viewAgreement(){
request({
url:'common/agreement?type=release_agreement',
method:'GET'
}).then(res => {
if (res.data.code == 200) {
this.viewAgreementcont = res.data.data.content
this.show = true
}
})
},
agreementbtn(){
this.agree = true
this.show = false
},
submitForm(){
if(!this.agree){
uni.showToast({
title: '请先同意发布协议!',
icon: 'none'
});
return
}
if(uni.getStorageSync('is_login')){
request({
url:'common/post/store',
method:'post',
data:this.form
}).then(res => {
uni.showToast({
title: res.data.message,
icon: 'none'
});
if(res.data.code ==200){
setTimeout(() => {
uni.reLaunch({
url: '/pages/square/index',// 替换为你要跳转的页面路径
});
}, 1000);
}
})
}else{
this.showlogin = true
}
}
}
}
</script>
<style lang="scss">
.detils{
margin-top: 40rpx;
}
.cent{
display: flex;
align-items: center;
justify-content: space-around;
padding: 0px 10px 20px;
.btn1{
background-color: #fff;
border: 1px solid #206ff4;
color: #206ff4;
border-radius: 50px;
width: 46%;
margin: 10px 0px 20px;
height: 40px;
line-height: 40px;
}
.btn{
background-color: #206ff4;
color: white;
border-radius: 50px;
width: 46%;
margin: 10px 0px 20px;
height: 40px;
line-height: 40px;
}
}
.custom-navbar{
position: fixed;
top: 0;
left: 0;
right: 0;
height: calc(var(--status-bar-height) + 88rpx);
background: #fff;
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--status-bar-height) 30rpx 0;
z-index: 999;
border-bottom: 1rpx solid #F0F0F0;
}
.form-card{
background: #fff;
padding: 30rpx;
margin-bottom: 400rpx;
box-shadow: 0 12rpx 30rpx rgba(0,0,0,0.04);
}
.section-label{
font-size: 30rpx;
color: #2F323A;
margin-bottom: 20rpx;
font-weight: 500;
}
.select-input{
height: 88rpx;
border-radius: 12rpx;
padding: 0 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
}
.gradient-bg{
background: #F4F4F4;
color: #999999;
}
.conts{
background: #F4F4F4;
color: #999999;
padding: 20rpx;
border-radius: 10rpx;
}
.uni-input{
background: #F4F4F4;
padding: 20rpx 25rpx;
border-radius: 10rpx;
}
.category-content{
display: flex;
align-items: center;
flex: 1;
}
.fridge-icon{
width: 48rpx;
height: 48rpx;
margin-right: 16rpx;
position: relative;
}
.fridge-icon image{
width: 20px;
height: 25px;
}
.fridge-body{
width: 32rpx;
height: 40rpx;
border: 2rpx solid #fff;
border-radius: 4rpx;
position: absolute;
left: 8rpx;
top: 4rpx;
}
.fridge-line{
width: 28rpx;
height: 2rpx;
background: #fff;
position: absolute;
left: 10rpx;
top: 18rpx;
}
.fridge-line2{
width: 28rpx;
height: 2rpx;
background: #fff;
position: absolute;
left: 10rpx;
top: 28rpx;
}
.category-text{
font-size: 28rpx;
color: #999999;
font-weight: 500;
}
.mag-top{
margin-top: 15px;
}
.content-textarea{
width: 100%;
// background: #F7F8FB;
border-radius: 16rpx;
max-height: 160rpx;
padding: 24rpx 0px;
font-size: 28rpx;
color: #2F323A;
box-sizing: border-box;
}
.media-upload-wrapper{
display: flex;
flex-wrap: wrap;
gap: 16rpx;
}
.upload-area{
width: 200rpx;
height: 200rpx;
background: #F7F8FB;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
}
.upload-icon-wrapper{
display: flex;
flex-direction: column;
align-items: center;
}
.camera-icon{
position: relative;
margin-bottom: 12rpx;
}
.addimg{
width: 215rpx;
height: 215rpx;
}
.upload-text{
font-size: 26rpx;
color: #3F75FF;
}
.media-preview{
width: 200rpx;
height: 200rpx;
border-radius: 16rpx;
overflow: hidden;
position: relative;
}
.preview-image{
width: 100%;
height: 100%;
}
.delete-btn{
position: absolute;
top: 8rpx;
right: 8rpx;
width: 48rpx;
height: 48rpx;
background: rgba(0,0,0,0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.help-text{
font-size: 24rpx;
color: #A6ABB7;
margin-top: 40rpx;
display: flex;
align-items: center;
gap: 8rpx;
}
.foot{
background: #fff;
position: fixed;
bottom: 1rpx;
width: 100%;
}
.agreement{
margin: 20px 12px;
}
.agree-label{
display: flex;
align-items: center;
font-size: 26rpx;
color: #6A6E7F;
}
.agree-label text{
margin-right: 6rpx;
}
.agree-label .link{
color: #51B6FF;
}
.primary-btn{
color: #fff;
border-radius: 20rpx;
height: 88rpx;
line-height: 88rpx;
font-size: 32rpx;
border: none;
}
.gradient-btn{
background: #3BC8BE;
margin-top: 20rpx;
}
.select-popup{
position: fixed;
inset: 0;
z-index: 999;
}
.popup-mask{
position: absolute;
inset: 0;
background: rgba(0,0,0,0.35);
}
.popup-panel{
position: absolute;
left: 0;
right: 0;
bottom: 0;
background: #fff;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
max-height: 40vh; /* 控制整体可视高度 */
display: flex;
flex-direction: column;
padding: 20rpx;
box-sizing: border-box;
}
.popup-header{
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16rpx;
}
.popup-search{
flex: 1;
height: 72rpx;
border-radius: 10rpx;
background: #f4f4f4;
padding: 0 20rpx;
font-size: 28rpx;
color: #333;
margin-right: 12rpx;
box-sizing: border-box;
}
.popup-title{
font-size: 28rpx;
color: #333;
}
.popup-close{
font-size: 28rpx;
color: #3BC8BE;
}
.popup-list{
flex: 1;
max-height: calc(40vh - 140rpx); /* 预留头部高度,保证可滚动 */
}
.popup-item{
padding: 20rpx 12rpx;
border-bottom: 1px solid #f0f0f0;
font-size: 28rpx;
color: #333;
}
.popup-item:last-child{
border-bottom: none;
}
.popup-empty{
text-align: center;
color: #999;
font-size: 26rpx;
padding: 30rpx 0;
}
.cont-text{
max-width: 350px;
max-height: 450px;
overflow: scroll;
padding: 10px;
}
.popupcontent{
background-size: 100% 100%;
padding: 26px 15px;
text-align: center;
background-repeat: no-repeat;
.title{
color: #333333;
font-size: 15px;
margin-bottom: 15px;
}
}
.log1{
width: 180px;
height: 180px;
}
.yhxy{
color: #999999;
font-size: 12px;
margin-bottom: 5px;
.xy{
color: #297EFF;
}
}
.cent{
display: flex;
align-items: center;
justify-content: space-around;
padding: 0px 10px 20px;
.btn1{
background-color: #fff;
border: 1px solid #206ff4;
color: #206ff4;
border-radius: 50px;
width: 46%;
margin: 10px 0px 20px;
height: 50px;
line-height: 50px;
}
.btn{
background-color: #206ff4;
color: white;
border-radius: 50px;
width: 46%;
margin: 10px 0px 20px;
height: 50px;
line-height: 50px;
}
}
</style>