feat: 新增工单中心、房间巡查、失物招领等业务模块

- 新增工单中心(ticket_center)与工单工作台(ticket_workbench)页面
- 新增房间巡查(room_inspection)与失物招领发布(lost_found_publish)页面
- 预约看样流程新增房型/楼栋/楼层选择器组件
- 新增工具模块: booking-entry、privacy、reservation-flow
- api/index.js 补充楼层列表、看样提交等接口
- locales/messages.js 补充多语言文案
- manifest.json 开启微信小程序隐私检查
- 完善登录、注册、申请详情、账单等相关页面交互
This commit is contained in:
liangjian
2026-07-24 09:35:46 +08:00
parent 9fea127de1
commit 445bd850f4
36 changed files with 9281 additions and 340 deletions

View File

@@ -109,14 +109,51 @@
</template>
<script>
import { applicationFormMePage } from '@/api/index.js'
import { applicationFormMePage, orderSearchedReservationFlow } from '@/api/index.js'
import { saveActiveApplicationCode, saveMyApplicationList } from '@/utils/app-state'
import {
attachReservationFlow,
buildReservationFlowMap,
getReservationOrderNo,
parseReservationFlowResponse
} from '@/utils/reservation-flow'
function formatPageResponse(response) {
const payload = response && response.data ? response.data : response
return payload && typeof payload === 'object' ? payload : {}
}
const VIEWING_APPLICATION_PATTERN = /预约看房申请|看房时间[::]|意向房型[::]|意向区域[::]|viewing request|viewing time[::]|preferred room type[::]|preferred area[::]/i
function isViewingApplicationRecord(item = {}) {
if (!item || typeof item !== 'object') {
return false
}
const typeText = [
item.businessType,
item.applicationType,
item.applicationTypeDesc,
item.formType,
item.bizType,
item.type,
item.typeDesc
]
.filter(value => value !== null && typeof value !== 'undefined' && String(value).trim())
.join(' ')
if (/viewing|看房|带看/i.test(typeText)) {
return true
}
if ([item.appointmentViewingTime, item.viewingTime, item.bookViewingTime].some(value => String(value || '').trim())) {
return true
}
const remark = item && item.remark ? String(item.remark) : ''
return VIEWING_APPLICATION_PATTERN.test(remark)
}
function normalizeApplicationList(list = []) {
if (!Array.isArray(list)) {
return []
@@ -124,11 +161,9 @@ function normalizeApplicationList(list = []) {
return list
.filter(item => item && typeof item === 'object')
.map((item) => {
const remark = item && item.remark ? String(item.remark) : ''
const isViewingApplication = /预约看房申请|看房时间[::]|意向房型[::]|意向区域[::]|viewing request|viewing time[::]|preferred room type[::]|preferred area[::]/i.test(remark)
return {
...item,
isViewingApplication
isViewingApplication: isViewingApplicationRecord(item)
}
})
}
@@ -349,7 +384,7 @@ export default {
}
await applicationFormMePage(params, this.language)
.then((response) => {
.then(async (response) => {
const pageData = formatPageResponse(response)
console.log('pageData', pageData)
const nextList = normalizeApplicationList(pageData.data || [])
@@ -358,12 +393,14 @@ export default {
this.total = total
this.list = normalizeApplicationList(isReload ? nextList : this.list.concat(nextList))
this.hasMore = this.list.length < total && nextList.length > 0
saveMyApplicationList(this.list)
const activeCode = this.resolvePreferredReferenceTypeNo(this.list)
if (activeCode) {
saveActiveApplicationCode(activeCode)
}
await this.loadReservationFlowsForList(this.list)
saveMyApplicationList(this.list)
})
.catch((error) => {
if (!isReload) {
@@ -416,6 +453,41 @@ export default {
const preferredItem = sortedList.find(item => Number(item.status) !== 99) || sortedList[0]
return this.resolveReferenceTypeNo(preferredItem)
},
async loadReservationFlowsForList(list = []) {
const baseList = Array.isArray(list) ? list : []
const orderNos = [...new Set(
baseList
.filter(item => item && !item.isViewingApplication)
.map(item => getReservationOrderNo(item))
.filter(Boolean)
)]
const requestToken = Date.now()
this._reservationFlowRequestToken = requestToken
const applyFlowMap = (flowMap = {}) => {
if (this._reservationFlowRequestToken !== requestToken) {
return
}
this.list = (Array.isArray(this.list) ? this.list : []).map(item => attachReservationFlow(item, flowMap))
}
if (!orderNos.length) {
applyFlowMap({})
return
}
try {
const response = await orderSearchedReservationFlow({
orderNos
}, this.language)
const flowMap = buildReservationFlowMap(parseReservationFlowResponse(response))
applyFlowMap(flowMap)
} catch (error) {
console.log('[my_application] load reservation flow failed', error)
applyFlowMap({})
}
},
goToBillPage(event) {
const dataset = event && event.currentTarget ? event.currentTarget.dataset || {} : {}
const referenceTypeNo = dataset.referenceTypeNo || dataset.referenceTypeNo === 0
@@ -437,10 +509,6 @@ export default {
goToApplicationDetail(item = {}) {
const code = item.detailCode || ''
if (!code) {
uni.showToast({
title: this.t('missingApplicationCode'),
icon: 'none'
})
return
}
uni.navigateTo({