Merge branch 'master' of https://codeup.aliyun.com/bsdtec/biz-mobile-react-cloud
This commit is contained in:
commit
e237796840
6 files changed
+325
-127
No files matched your search
@@ -17,17 +17,17 @@ VITE_PWD_ENC_KEY='pigxpigxpigxpigx'
|
||||
VITE_OAUTH2_APP_CLIENT='mini:mini'
|
||||
|
||||
# --------------------------- 开发环境 api地址 ----------------------------------
|
||||
VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
|
||||
#VITE_APP_DEV_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
|
||||
#VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
|
||||
# VITE_APP_DEV_SERVICE = http://192.168.101.150:9999 # 邓-本地
|
||||
# VITE_APP_DEV_SERVICE = http://127.0.0.1:9999 # 邓-本地
|
||||
VITE_APP_DEV_SERVICE = http://127.0.0.1:9999 # 邓-本地
|
||||
# VITE_APP_DEV_SERVICE = http://123.157.250.162:8089/api # 测试线上
|
||||
|
||||
# --------------------------- 开发环境 图片访问基础地址 ---------------------------
|
||||
VITE_IMAGE_DEV_PATH = https://stgl.pj.gov.cn/api # 域名线上
|
||||
#VITE_IMAGE_DEV_PATH = https://stgl.pj.gov.cn/api # 域名线上
|
||||
#VITE_IMAGE_DEV_PATH = http://59.202.170.152:81/api # 信创线上
|
||||
# VITE_IMAGE_DEV_PATH = http://192.168.101.150:9999 # 邓-43本地
|
||||
# VITE_IMAGE_DEV_PATH = http://127.0.0.1:9999
|
||||
VITE_IMAGE_DEV_PATH = http://127.0.0.1:9999
|
||||
# VITE_IMAGE_DEV_PATH = http://123.157.250.162:8089/api # 测试线上
|
||||
|
||||
# --------------------------- 生产环境 api地址 ----------------------------------
|
||||
|
||||
@@ -464,6 +464,7 @@
|
||||
{
|
||||
"path": "feedback/index",
|
||||
"style": {
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationBarTitleText": "意见反馈"
|
||||
}
|
||||
},
|
||||
@@ -476,6 +477,7 @@
|
||||
{
|
||||
"path": "repair/index",
|
||||
"style": {
|
||||
"enablePullDownRefresh": true,
|
||||
"navigationBarTitleText": "维修上报"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,6 +6,15 @@
|
||||
</view>
|
||||
<view class="detail-content">
|
||||
<view class="content-text">{{ detail.description }}</view>
|
||||
<view v-if="imageList.length" class="image-list">
|
||||
<image
|
||||
v-for="(img, idx) in imageList"
|
||||
:key="idx"
|
||||
:src="img.startsWith('http') ? img : filePath(img)"
|
||||
class="feedback-img"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="detail-footer">
|
||||
<text class="create-time">提交时间:{{ formatTime(detail.createTime) }}</text>
|
||||
@@ -14,9 +23,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import meetingRoomApi from '@/sheep/api/meetingRoom'
|
||||
import { filePath } from '@/sheep/utils/file'
|
||||
|
||||
const detail = ref<any>({})
|
||||
const typeOptions = ref<{ value: string; label: string }[]>([])
|
||||
@@ -72,6 +82,12 @@ function formatTime(time: string) {
|
||||
return new Date(time).toLocaleString()
|
||||
}
|
||||
|
||||
// 计算图片数组
|
||||
const imageList = computed(() => {
|
||||
if (!detail.value.picUrl) return []
|
||||
return detail.value.picUrl.split(',').filter(Boolean)
|
||||
})
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
await loadTypeOptions()
|
||||
const id = options.id
|
||||
@@ -214,4 +230,18 @@ onLoad(async (options: any) => {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.image-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
.feedback-img {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border-radius: 8rpx;
|
||||
background: #f7f8fa;
|
||||
object-fit: cover;
|
||||
}
|
||||
</style>
|
||||
@@ -32,6 +32,19 @@
|
||||
<view class="label">联系方式</view>
|
||||
<input v-model="contact" placeholder="手机号或邮箱(选填)" class="contact-input" />
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<view class="label">图片上传</view>
|
||||
<tm-upload-photo
|
||||
v-model="uploadList"
|
||||
:maxCount="6"
|
||||
url="/api/admin/sys-file/upload"
|
||||
:header="uploadHeader"
|
||||
:show-upload-list="true"
|
||||
:width="180"
|
||||
:height="180"
|
||||
imgKey="url"
|
||||
/>
|
||||
</view>
|
||||
<button @click="submitFeedback" class="submit-btn" :disabled="!canSubmit">
|
||||
提交反馈
|
||||
</button>
|
||||
@@ -41,7 +54,10 @@
|
||||
<!-- 我的反馈列表 -->
|
||||
<view class="feedback-list">
|
||||
<view class="list-title">我的反馈</view>
|
||||
<view v-if="feedbackList.length === 0" class="empty-tip">
|
||||
<view v-if="error" class="error-tip">
|
||||
加载失败,请 <text class="retry-btn" @click="refreshList">重试</text>
|
||||
</view>
|
||||
<view v-else-if="feedbackList.length === 0" class="empty-tip">
|
||||
暂无反馈记录
|
||||
</view>
|
||||
<view v-else>
|
||||
@@ -58,7 +74,15 @@
|
||||
<view class="item-content">
|
||||
<view class="item-title">{{ item.title }}</view>
|
||||
<view class="item-desc">{{ item.description }}</view>
|
||||
<image v-if="item.picUrl" :src="item.picUrl" class="item-img" mode="aspectFill" />
|
||||
<view v-if="item.picUrl" class="image-list">
|
||||
<image
|
||||
v-for="(img, idx) in item.picUrl.split(',').filter(Boolean)"
|
||||
:key="idx"
|
||||
:src="filePath(img)"
|
||||
class="item-img"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item-footer">
|
||||
<text class="time">{{ formatTime(item.createTime) }}</text>
|
||||
@@ -72,8 +96,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { ref, onMounted, computed, watch, nextTick } from 'vue'
|
||||
import meetingRoomApi from '@/sheep/api/meetingRoom'
|
||||
import { onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'
|
||||
import { filePath } from '@/sheep/utils/file'
|
||||
import { useDefaultHeader } from '@/sheep/hooks/use-token'
|
||||
|
||||
const typeOptions = ref<{ value: string; label: string }[]>([])
|
||||
const typeIndex = ref(0)
|
||||
@@ -82,6 +109,13 @@ const description = ref('')
|
||||
const contact = ref('')
|
||||
const feedbackList = ref<any[]>([])
|
||||
const activeTab = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 5
|
||||
const hasMore = ref(true)
|
||||
const loading = ref(false)
|
||||
const error = ref(false)
|
||||
const uploadList = ref<any[]>([])
|
||||
const uploadHeader = ref({})
|
||||
|
||||
const canSubmit = computed(() => {
|
||||
return title.value.trim() && description.value.trim()
|
||||
@@ -92,7 +126,7 @@ async function loadTypeOptions() {
|
||||
const res: any = await meetingRoomApi.getFeedbackType()
|
||||
if (res.data && Array.isArray(res.data.data)) {
|
||||
typeOptions.value = res.data.data.map(item => ({
|
||||
value: item.id,
|
||||
value: item.value,
|
||||
label: item.label
|
||||
}))
|
||||
}
|
||||
@@ -120,24 +154,16 @@ function getTypeClass(type: string) {
|
||||
return classMap[type] || 'type-other'
|
||||
}
|
||||
|
||||
function getStatusText(status: string) {
|
||||
const statusMap: Record<string, string> = {
|
||||
'1': '待处理',
|
||||
'2': '处理中',
|
||||
'3': '已处理',
|
||||
'4': '已关闭'
|
||||
}
|
||||
return statusMap[status] || '未知'
|
||||
function getStatusText(status: string | number) {
|
||||
if (status === 1 || status === '1') return '已处理'
|
||||
// 只要不是1都显示未处理
|
||||
return '未处理'
|
||||
}
|
||||
|
||||
function getStatusClass(status: string) {
|
||||
const classMap: Record<string, string> = {
|
||||
'1': 'status-pending',
|
||||
'2': 'status-processing',
|
||||
'3': 'status-completed',
|
||||
'4': 'status-closed'
|
||||
}
|
||||
return classMap[status] || 'status-pending'
|
||||
function getStatusClass(status: string | number) {
|
||||
if (status === 1 || status === '1') return 'status-completed'
|
||||
// 只要不是1都用未处理样式
|
||||
return 'status-pending'
|
||||
}
|
||||
|
||||
function formatTime(time: string) {
|
||||
@@ -153,11 +179,23 @@ async function submitFeedback() {
|
||||
|
||||
try {
|
||||
uni.showLoading({ title: '提交中...' })
|
||||
let picUrlArr: any[] = []
|
||||
uploadList.value.forEach(item => {
|
||||
if (item.response) {
|
||||
try {
|
||||
const res = JSON.parse(item.response)
|
||||
if (res.code === 0 && res.data && res.data.url) {
|
||||
picUrlArr.push(res.data.url)
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
})
|
||||
const data = {
|
||||
title: title.value.trim(),
|
||||
type: typeOptions.value[typeIndex.value].value,
|
||||
description: description.value.trim(),
|
||||
contact: contact.value.trim()
|
||||
contact: contact.value.trim(),
|
||||
picUrl: picUrlArr.join(',')
|
||||
}
|
||||
const response: any = await meetingRoomApi.submitFeedback(data)
|
||||
uni.hideLoading()
|
||||
@@ -168,6 +206,7 @@ async function submitFeedback() {
|
||||
description.value = ''
|
||||
contact.value = ''
|
||||
typeIndex.value = 0
|
||||
uploadList.value = []
|
||||
// 刷新列表
|
||||
loadFeedbackList()
|
||||
} else {
|
||||
@@ -185,23 +224,86 @@ function viewDetail(item: any) {
|
||||
})
|
||||
}
|
||||
|
||||
async function loadFeedbackList() {
|
||||
async function loadFeedbackList(isLoadMore = false, autoFill = false) {
|
||||
if (loading.value || (!hasMore.value && isLoadMore)) return
|
||||
loading.value = true
|
||||
error.value = false
|
||||
try {
|
||||
const response: any = await meetingRoomApi.getFeedbackList({
|
||||
current: 1,
|
||||
size: 20
|
||||
current: page.value,
|
||||
size: pageSize
|
||||
})
|
||||
if (response.code === 0 && response.data) {
|
||||
feedbackList.value = response.data.records || []
|
||||
const records = response.data.records || []
|
||||
if (isLoadMore) {
|
||||
feedbackList.value = feedbackList.value.concat(records)
|
||||
} else {
|
||||
feedbackList.value = records
|
||||
}
|
||||
hasMore.value = records.length === pageSize
|
||||
if (hasMore.value) page.value += 1
|
||||
} else {
|
||||
error.value = true
|
||||
hasMore.value = false
|
||||
uni.showToast({ title: response.msg || '加载失败', icon: 'none' })
|
||||
}
|
||||
} catch (e) {
|
||||
error.value = true
|
||||
hasMore.value = false
|
||||
uni.showToast({ title: '加载失败', icon: 'none' })
|
||||
} finally {
|
||||
loading.value = false
|
||||
// H5端自动补齐:只有 autoFill=true 时才自动补齐
|
||||
if (autoFill) {
|
||||
await nextTick()
|
||||
if (hasMore.value) {
|
||||
const listDom = document.querySelector('.feedback-list')
|
||||
if (listDom && listDom.scrollHeight <= window.innerHeight) {
|
||||
await loadFeedbackList(true, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载反馈列表失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
function refreshList() {
|
||||
page.value = 1
|
||||
hasMore.value = true
|
||||
loadFeedbackList(false, true)
|
||||
}
|
||||
|
||||
// 监听页面触底事件,下拉加载更多
|
||||
onReachBottom(() => {
|
||||
if (activeTab.value === 1) {
|
||||
loadFeedbackList(true, false)
|
||||
}
|
||||
})
|
||||
|
||||
// 切换tab时重置分页并刷新
|
||||
watch(activeTab, (val) => {
|
||||
if (val === 1) {
|
||||
refreshList()
|
||||
}
|
||||
})
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
if (activeTab.value === 1) {
|
||||
page.value = 1
|
||||
hasMore.value = true
|
||||
loadFeedbackList(false, true).then(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
} else {
|
||||
uni.stopPullDownRefresh()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
uploadHeader.value = useDefaultHeader()
|
||||
loadTypeOptions().then(() => {
|
||||
loadFeedbackList()
|
||||
if (activeTab.value === 1) {
|
||||
refreshList()
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
@@ -315,6 +417,17 @@ onMounted(() => {
|
||||
font-weight: bold;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
.error-tip {
|
||||
text-align: center;
|
||||
color: #f56c6c;
|
||||
font-size: 28rpx;
|
||||
padding: 60rpx 0;
|
||||
}
|
||||
.retry-btn {
|
||||
color: #007aff;
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
@@ -396,12 +509,18 @@ onMounted(() => {
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.image-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
.item-img {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 8rpx;
|
||||
margin-top: 8rpx;
|
||||
background: #f7f8fa;
|
||||
object-fit: cover;
|
||||
}
|
||||
}
|
||||
.item-footer {
|
||||
|
||||
@@ -25,6 +25,15 @@
|
||||
<text class="label">故障描述:</text>
|
||||
<text class="description">{{ detail.description }}</text>
|
||||
</view>
|
||||
<view v-if="imageList.length" class="image-list">
|
||||
<image
|
||||
v-for="(img, idx) in imageList"
|
||||
:key="idx"
|
||||
:src="filePath(img)"
|
||||
class="repair-img"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="detail.repairResult" class="result-section">
|
||||
@@ -40,9 +49,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { ref, computed } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import meetingRoomApi from '@/sheep/api/meetingRoom'
|
||||
import { filePath } from "@/sheep/utils/file"
|
||||
|
||||
const detail = ref<any>({})
|
||||
|
||||
@@ -95,6 +105,12 @@ function formatTime(time: string) {
|
||||
return new Date(time).toLocaleString()
|
||||
}
|
||||
|
||||
// 计算图片数组
|
||||
const imageList = computed(() => {
|
||||
if (!detail.value.picUrl) return []
|
||||
return detail.value.picUrl.split(',').filter(Boolean)
|
||||
})
|
||||
|
||||
onLoad(async (options: any) => {
|
||||
const id = options.id
|
||||
if (!id) return
|
||||
@@ -249,4 +265,18 @@ onLoad(async (options: any) => {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.image-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
.repair-img {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
border-radius: 8rpx;
|
||||
background: #f7f8fa;
|
||||
object-fit: cover;
|
||||
}
|
||||
</style>
|
||||
@@ -30,10 +30,14 @@
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<view class="label">图片</view>
|
||||
<view class="image-upload">
|
||||
<image v-if="picUrl" :src="picUrl" class="feedback-img" mode="aspectFill" @click="previewImage" />
|
||||
<view v-else class="upload-btn" @click="chooseImage">上传图片</view>
|
||||
</view>
|
||||
<tm-upload-photo
|
||||
v-model="uploadFileUrl"
|
||||
:url="'/api/admin/sys-file/upload'"
|
||||
:maxCount="5"
|
||||
:maxFileSize="1024 * 1024"
|
||||
:beforeComplete="beforeComplete"
|
||||
:header="header"
|
||||
/>
|
||||
</view>
|
||||
<view class="form-item">
|
||||
<view class="label">故障描述</view>
|
||||
@@ -93,8 +97,11 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ref, computed, onMounted, watch, nextTick } from 'vue'
|
||||
import { onReachBottom, onPullDownRefresh } from '@dcloudio/uni-app'
|
||||
import meetingRoomApi from '@/sheep/api/meetingRoom'
|
||||
import { hooks } from '@@/index'
|
||||
import { filePath } from '@/sheep/utils/file'
|
||||
|
||||
const typeOptions = [
|
||||
{ value: 1, label: '电气设备' },
|
||||
@@ -116,9 +123,15 @@ const title = ref('')
|
||||
const location = ref('')
|
||||
const description = ref('')
|
||||
const dateFound = ref('')
|
||||
const picUrl = ref('')
|
||||
const uploadFileUrl = ref<any[]>([])
|
||||
const repairList = ref<any[]>([])
|
||||
const activeTab = ref(0)
|
||||
const page = ref(1)
|
||||
const pageSize = 5
|
||||
const hasMore = ref(true)
|
||||
const loading = ref(false)
|
||||
const repairForm = ref<any>(null)
|
||||
const header = ref({})
|
||||
|
||||
const canSubmit = computed(() => {
|
||||
return title.value.trim() && location.value.trim() && description.value.trim() && dateFound.value
|
||||
@@ -136,54 +149,9 @@ function onDateChange(e: any) {
|
||||
dateFound.value = e.detail.value
|
||||
}
|
||||
|
||||
function chooseImage() {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
success: (res) => {
|
||||
if (res.tempFilePaths && res.tempFilePaths.length > 0) {
|
||||
picUrl.value = res.tempFilePaths[0]
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function previewImage() {
|
||||
if (picUrl.value) {
|
||||
uni.previewImage({
|
||||
urls: [picUrl.value]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function uploadImageIfNeeded() {
|
||||
if (!picUrl.value || picUrl.value.startsWith('http')) {
|
||||
return picUrl.value
|
||||
}
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: '/file/upload',
|
||||
filePath: picUrl.value,
|
||||
name: 'file',
|
||||
success: (res) => {
|
||||
try {
|
||||
const data = JSON.parse(res.data)
|
||||
if (data.code === 0 && data.data && data.data.url) {
|
||||
resolve(data.data.url)
|
||||
} else {
|
||||
uni.showToast({ title: '图片上传失败', icon: 'none' })
|
||||
reject()
|
||||
}
|
||||
} catch {
|
||||
uni.showToast({ title: '图片上传失败', icon: 'none' })
|
||||
reject()
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '图片上传失败', icon: 'none' })
|
||||
reject()
|
||||
}
|
||||
})
|
||||
})
|
||||
function beforeComplete(uploadFile: any) {
|
||||
const res = JSON.parse(uploadFile.data)
|
||||
return res.code == 0
|
||||
}
|
||||
|
||||
function getTypeLabel(type: number) {
|
||||
@@ -202,24 +170,16 @@ function getTypeClass(type: number) {
|
||||
return classMap[type] || 'type-other'
|
||||
}
|
||||
|
||||
function getStatusText(status: string) {
|
||||
const statusMap: Record<string, string> = {
|
||||
'1': '待处理',
|
||||
'2': '处理中',
|
||||
'3': '已完成',
|
||||
'4': '已取消'
|
||||
}
|
||||
return statusMap[status] || '未知'
|
||||
function getStatusText(status: string | number) {
|
||||
if (status === 1 || status === '1') return '已处理'
|
||||
// 只要不是1都显示未处理
|
||||
return '未处理'
|
||||
}
|
||||
|
||||
function getStatusClass(status: string) {
|
||||
const classMap: Record<string, string> = {
|
||||
'1': 'status-pending',
|
||||
'2': 'status-processing',
|
||||
'3': 'status-completed',
|
||||
'4': 'status-cancelled'
|
||||
}
|
||||
return classMap[status] || 'status-pending'
|
||||
function getStatusClass(status: string | number) {
|
||||
if (status === 1 || status === '1') return 'status-completed'
|
||||
// 只要不是1都用未处理样式
|
||||
return 'status-pending'
|
||||
}
|
||||
|
||||
function formatTime(time: string) {
|
||||
@@ -232,41 +192,43 @@ async function submitRepair() {
|
||||
uni.showToast({ title: '请填写完整信息', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
// 收集所有上传成功图片的 url
|
||||
let picUrl: string[] = []
|
||||
if (uploadFileUrl.value.length > 0) {
|
||||
uploadFileUrl.value.forEach(item => {
|
||||
if (item.response) {
|
||||
try {
|
||||
const res = JSON.parse(item.response)
|
||||
if (res.code === 0 && res.data && res.data.url) {
|
||||
picUrl.push(res.data.url)
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
})
|
||||
}
|
||||
try {
|
||||
uni.showLoading({ title: '提交中...' })
|
||||
|
||||
let uploadedPicUrl = picUrl.value
|
||||
if (picUrl.value && !picUrl.value.startsWith('http')) {
|
||||
uploadedPicUrl = await uploadImageIfNeeded()
|
||||
}
|
||||
|
||||
const data = {
|
||||
title: title.value.trim(),
|
||||
picUrl: uploadedPicUrl,
|
||||
picUrl: picUrl.join(','),
|
||||
description: description.value.trim(),
|
||||
dateFound: dateFound.value,
|
||||
location: location.value.trim(),
|
||||
urgency: String(urgencyOptions[urgencyIndex.value].value),
|
||||
maintainType: typeOptions[typeIndex.value].value
|
||||
}
|
||||
|
||||
const response: any = await meetingRoomApi.submitRepair(data)
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
if (response.code === 0) {
|
||||
uni.showToast({ title: '提交成功', icon: 'success' })
|
||||
|
||||
// 清空表单
|
||||
title.value = ''
|
||||
location.value = ''
|
||||
description.value = ''
|
||||
dateFound.value = ''
|
||||
picUrl.value = ''
|
||||
uploadFileUrl.value = []
|
||||
typeIndex.value = 0
|
||||
urgencyIndex.value = 0
|
||||
|
||||
// 刷新列表
|
||||
loadRepairList()
|
||||
} else {
|
||||
@@ -284,23 +246,78 @@ function viewDetail(item: any) {
|
||||
})
|
||||
}
|
||||
|
||||
async function loadRepairList() {
|
||||
async function loadRepairList(isLoadMore = false, autoFill = false) {
|
||||
if (loading.value || (!hasMore.value && isLoadMore)) return
|
||||
loading.value = true
|
||||
let requestSuccess = false
|
||||
try {
|
||||
const response: any = await meetingRoomApi.getRepairList({
|
||||
current: 1,
|
||||
size: 20
|
||||
current: page.value,
|
||||
size: pageSize
|
||||
})
|
||||
|
||||
if (response.code === 0 && response.data) {
|
||||
repairList.value = response.data.records || []
|
||||
const records = response.data.records || []
|
||||
if (isLoadMore) {
|
||||
repairList.value = repairList.value.concat(records)
|
||||
} else {
|
||||
repairList.value = records
|
||||
}
|
||||
hasMore.value = records.length === pageSize
|
||||
if (hasMore.value) page.value += 1
|
||||
requestSuccess = true
|
||||
}
|
||||
} catch (e) {
|
||||
hasMore.value = false // 网络/接口异常,阻止递归
|
||||
} finally {
|
||||
loading.value = false
|
||||
// 只有请求成功时才自动补齐
|
||||
if (autoFill && requestSuccess) {
|
||||
await nextTick()
|
||||
if (hasMore.value) {
|
||||
const listDom = document.querySelector('.repair-list')
|
||||
if (listDom && listDom.scrollHeight <= window.innerHeight) {
|
||||
await loadRepairList(true, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载维修记录失败:', error)
|
||||
}
|
||||
}
|
||||
|
||||
function refreshRepairList() {
|
||||
page.value = 1
|
||||
hasMore.value = true
|
||||
loadRepairList(false, true)
|
||||
}
|
||||
|
||||
onReachBottom(() => {
|
||||
if (activeTab.value === 1) {
|
||||
loadRepairList(true, false)
|
||||
}
|
||||
})
|
||||
|
||||
onPullDownRefresh(() => {
|
||||
if (activeTab.value === 1) {
|
||||
page.value = 1
|
||||
hasMore.value = true
|
||||
loadRepairList(false, true).then(() => {
|
||||
uni.stopPullDownRefresh()
|
||||
})
|
||||
} else {
|
||||
uni.stopPullDownRefresh()
|
||||
}
|
||||
})
|
||||
|
||||
watch(activeTab, (val) => {
|
||||
if (val === 1) {
|
||||
refreshRepairList()
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadRepairList()
|
||||
header.value = hooks.useDefaultHeader()
|
||||
if (activeTab.value === 1) {
|
||||
refreshRepairList()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
Reference in new issue
Block a user