Files
property-resident-side/property-uniapp-project/pages/service-list/addComplaints.vue
2026-04-18 17:29:15 +08:00

579 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="contentStyle" style="">
<view class="status-bar"></view>
<uni-nav-bar title="投诉建议" backgroundColor="transparent" :border="false" left-icon="left" @clickLeft="goBack">
</uni-nav-bar>
<!-- 表单区域 -->
<scroll-view class="page" scroll-y="true">
<!-- 表单主体 -->
<view class="form-content">
<text class="form-tip">请填写反馈信息</text>
<!-- 1. 投诉类型点击弹出popup -->
<view class="form-row" @click="showTypePopup = true">
<view class="row-left">
<text class="required-star">*</text>
<text class="label-text">投诉类型</text>
</view>
<view class="row-right">
<text class="value-text"
:class="{placeholderStyle:selectedType}">{{ selectedType || '请选择投诉类型' }}</text>
<text class="arrow-icon">></text>
</view>
</view>
<!-- 2. 投诉物业选中物业服务时显示 -->
<view class="form-row" v-if="selectedType === '物业服务'" @click="showPropertyPopup = true">
<view class="row-left">
<text class="required-star">*</text>
<text class="label-text">投诉物业</text>
</view>
<view class="row-right">
<text class="value-text"
:class="{placeholderStyle:selectedProperty}">{{ selectedProperty || '请选择' }}</text>
<text class="arrow-icon">></text>
</view>
</view>
<!-- 3. 问题描述 -->
<view class="form-row desc-row" style="flex-direction: column;">
<view class="row-left">
<text class="required-star">*</text>
<text class="label-text">问题描述</text>
</view>
<view class="row-right desc-right">
<textarea v-model="description" placeholder="请描述您的问题" class="desc-input" auto-height
maxlength="500"></textarea>
</view>
</view>
<!-- 4. 投诉人姓名 -->
<view class="form-row">
<view class="row-left">
<text class="label-text">投诉人姓名</text>
</view>
<view class="row-right">
<input v-model="name" placeholder="请输入姓名" class="text-input" type="text" />
</view>
</view>
<!-- 5. 手机号码 -->
<view class="form-row">
<view class="row-left">
<text class="label-text">手机号码</text>
</view>
<view class="row-right">
<input v-model="phone" placeholder="请输入手机号" class="text-input" type="number" maxlength="11" />
</view>
</view>
<!-- 6. 相关照片多图上传+删除 -->
<view class="form-row photo-row">
<view class="row-left">
<text class="label-text">相关照片</text>
</view>
<view class="row-right photo-right">
<view class="photo-grid">
<!-- 已上传图片 -->
<view v-for="(img, index) in tempFilePaths" :key="index" class="photo-item">
<image :src="img" mode="aspectFill" class="photo-img"></image>
<view class="delete-btn" @click="deletePhoto(index)">
<text class="delete-icon">×</text>
</view>
</view>
<!-- 上传加号按钮 -->
<view class="add-btn" v-if="tempFilePaths.length < maxCount" @click="chooseImages">
<text class="add-icon">+</text>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<!-- 底部下一步按钮 -->
<view class="bottom-btn-wrap">
<button class="next-btn" @click="submitForm">提交</button>
</view>
<!-- ================== 自定义Popup弹窗纯view实现 ================== -->
<!-- 蒙层 -->
<view class="mask" v-if="showTypePopup || showPropertyPopup" @click="closeAllPopup"></view>
<!-- 投诉类型弹窗 -->
<view v-if="showTypePopup" class="mask" @click="showTypePopup=false"></view>
<view v-if="showTypePopup" class="popup">
<view class="popup-header">
<text class="title">选择投诉类型</text>
<text class="close" @click="showTypePopup = false"></text>
</view>
<view class="list">
<view :class="{ active: selectedType === item }" class="item" v-for="(item, index) in typeOptions"
:key="index" @click="selectType(item)">
{{ item }}
</view>
</view>
</view>
<!-- 投诉物业弹窗 -->
<view v-if="showPropertyPopup" class="mask" @click="showPropertyPopup=false"></view>
<view v-if="showPropertyPopup" class="popup">
<view class="popup-header">
<text class="title">选择投诉类型</text>
<text class="close" @click="showPropertyPopup = false"></text>
</view>
<view class="list">
<view :class="{ active: selectedProperty === item }" class="item"
v-for="(item, index) in propertyOptions" :key="index" @click="selectProperty(item)">
{{ item }}
</view>
</view>
</view>
</view>
</template>
<script>
export default {
onReady: function(e) {},
components: {
},
computed: {
},
created() {
},
onShow() {
},
mounted() {},
onReady() {
this.$nextTick(() => {
})
},
data() {
return {
/* 设定状态栏默认高度 */
statusBarHeight: 20,
// 弹窗控制
showTypePopup: false,
showPropertyPopup: false,
// 下拉选项
typeOptions: ['物业服务', '社区服务', '其他'],
propertyOptions: ['XX物业A', 'XX物业B', 'XX物业C'], // 替换为实际数据
// 表单数据
selectedType: '',
selectedProperty: '',
description: '',
name: '',
phone: '',
// 多图上传
tempFilePaths: [],
maxCount: 9 // 最大上传9张
}
},
methods: {
// 返回上一页
navigateBack() {
uni.navigateBack();
},
// 关闭所有弹窗
closeAllPopup() {
this.showTypePopup = false;
this.showPropertyPopup = false;
},
// 选择投诉类型
selectType(item) {
this.selectedType = item;
this.showTypePopup = false;
// 切换类型时清空物业选择
if (item !== '物业服务') {
this.selectedProperty = '';
}
},
// 选择物业
selectProperty(item) {
this.selectedProperty = item;
this.showPropertyPopup = false;
},
// 多图选择
chooseImages() {
uni.chooseImage({
count: this.maxCount - this.tempFilePaths.length,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
this.tempFilePaths = [...this.tempFilePaths, ...res.tempFilePaths];
}
});
},
// 删除图片
deletePhoto(index) {
this.tempFilePaths.splice(index, 1);
},
// 表单提交
submitForm() {
// 基础校验
if (!this.selectedType) {
return uni.showToast({
title: '请选择投诉类型',
icon: 'none'
});
}
if (this.selectedType === '物业服务' && !this.selectedProperty) {
return uni.showToast({
title: '请选择物业',
icon: 'none'
});
}
if (!this.description.trim()) {
return uni.showToast({
title: '请输入问题描述',
icon: 'none'
});
}
uni.showLoading({
title: '提交中...',
mask: true
});
setTimeout(() => {
uni.showToast({
title: '提交成功',
icon: 'success'
});
}, 1000);
setTimeout(() => {
// 提交成功后跳转列表页
uni.hideLoading();
this.goBack();
}, 2500);
},
goBack() {
uni.redirectTo({
url: '/pages/service-list/complaintsSuggestionsIndex',
success: res => {},
fail: () => {},
complete: () => {}
});
},
},
}
</script>
<style lang="scss">
page {
background: #fff;
}
</style>
<style scoped>
.contentStyle {
display: flex;
flex-direction: column;
height: 100vh;
/* 关键:占满屏幕高度 */
/* background: linear-gradient(to left bottom, #e2efff 0%, #f9f9f9 50%); */
}
.page {
flex: 1;
overflow-y: auto;
padding: 0px 40rpx;
box-sizing: border-box;
background-color: #fff;
}
/* 表单主体 */
.form-content {}
.form-tip {
display: block;
font-size: 32rpx;
color: #1D1D1D;
margin-bottom: 10rpx;
font-weight: 600;
}
/* 表单项:一行布局,不换行 */
.form-row {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1rpx solid #f0f0f0;
}
.row-left {
display: flex;
align-items: center;
width: 180rpx;
flex-shrink: 0;
}
.required-star {
color: #ff3b30;
font-size: 30rpx;
margin-right: 8rpx;
}
.label-text {
font-size: 28rpx;
color: #333;
}
.row-right {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
}
.value-text {
font-size: 30rpx;
color: grey;
}
.value-text.placeholderStyle {
color: #333;
}
.arrow-icon {
font-size: 28rpx;
color: #999;
}
/* 输入框样式 */
.text-input {
width: 100%;
font-size: 30rpx;
color: #333;
border: none;
outline: none;
background: transparent;
}
/* 问题描述行 */
.desc-row {
align-items: flex-start;
padding-top: 32rpx;
padding-bottom: 32rpx;
}
.desc-right {
flex: 1;
}
.desc-input {
width: calc(100vw - 84rpx);
min-height: 80px;
margin-top: 20rpx;
padding: 24rpx;
border: 1rpx solid #f0f0f0;
border-radius: 8rpx;
font-size: 30rpx;
color: #333;
line-height: 1.5;
box-sizing: border-box;
background: transparent;
}
/* 照片上传区域 */
.photo-row {
align-items: flex-start;
padding-top: 32rpx;
padding-bottom: 32rpx;
border-bottom: none;
}
.photo-right {
flex: 1;
}
.photo-grid {
display: flex;
flex-wrap: wrap;
gap: 24rpx;
}
.photo-item {
position: relative;
width: 120rpx;
height: 120rpx;
border-radius: 8rpx;
overflow: hidden;
}
.photo-img {
width: 100%;
height: 100%;
}
.delete-btn {
position: absolute;
top: -4rpx;
right: -4rpx;
width: 32rpx;
height: 32rpx;
background-color: rgba(0, 0, 0, 0.6);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.delete-icon {
color: #fff;
font-size: 24rpx;
line-height: 1;
}
.add-btn {
width: 120rpx;
height: 120rpx;
border: 1rpx solid #e5e5e5;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: center;
}
.add-icon {
font-size: 32rpx;
color: #999;
line-height: 1;
}
/* 底部按钮 */
.bottom-btn-wrap {
padding: 20rpx 30rpx 40rpx;
display: flex;
gap: 20rpx;
background-color: #fff;
}
.next-btn {
width: 100%;
height: 96rpx;
line-height: 96rpx;
background-color: #1677ff;
color: #fff;
font-size: 36rpx;
border-radius: 12rpx;
border: none;
}
/* 遮罩 */
.mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 99;
}
/* 底部弹出框 */
.popup {
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
border-radius: 20rpx 20rpx 0 0;
z-index: 100;
max-height: 60vh;
}
.popup-header {
padding: 30rpx;
text-align: center;
/* border-bottom: 1rpx solid #f0f0f0; */
position: relative;
}
.title {
font-size: 32rpx;
font-weight: 500;
}
.close {
position: absolute;
right: 30rpx;
top: 50%;
transform: translateY(-50%);
font-size: 36rpx;
color: #666;
}
/* 选项列表 */
.list {
padding: 0 30rpx;
}
.item {
padding: 30rpx 0;
text-align: center;
font-size: 28rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.item:last-child {
border-bottom: none;
}
.item.active {
color: #337eff;
font-weight: 600;
background-color: #f8f9fa;
}
.status-bar {
width: 100vw;
height: 46px;
}
</style>