1426 lines
39 KiB
Vue
1426 lines
39 KiB
Vue
<template>
|
||
<view class="app-page">
|
||
<view class="page-bg">
|
||
<view class="bg-orb bg-orb--primary"></view>
|
||
<view class="bg-orb bg-orb--soft"></view>
|
||
</view>
|
||
|
||
<tn-nav-bar :isBack="true" :bottomShadow="false" backgroundColor="transparent">
|
||
<view class="nav-title">{{ $tr('验房') }}</view>
|
||
</tn-nav-bar>
|
||
|
||
<view class="page-shell" :style="{ paddingTop: vuex_custom_bar_height ? 'calc(' + vuex_custom_bar_height + 'px + 16rpx)' : '16rpx' }">
|
||
<view class="hero-panel">
|
||
<view class="hero-top">
|
||
<view class="hero-title-wrap">
|
||
<text class="hero-kicker">{{ $tr('交付检查') }}</text>
|
||
<text class="hero-title">{{ $tr('验房') }}</text>
|
||
</view>
|
||
<view v-if="activeInspection" class="hero-status">
|
||
{{ activeInspection.statusText }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="inspectionList.length > 1" class="tab-wrap">
|
||
<view class="section-head">
|
||
<text class="section-head__title">{{ $tr('验房单切换') }}</text>
|
||
<text class="section-head__meta">{{ inspectionList.length }} {{ $tr('份记录') }}</text>
|
||
</view>
|
||
<scroll-view scroll-x class="tab-scroll" :show-scrollbar="false">
|
||
<view class="tab-list">
|
||
<view
|
||
v-for="item in inspectionList"
|
||
:key="item.inspectionNo"
|
||
class="tab-item"
|
||
:class="{ 'tab-item--active': item.inspectionNo === activeInspectionNo }"
|
||
@click="switchInspection(item)"
|
||
>
|
||
<text class="tab-item__type">{{ item.typeText }}</text>
|
||
<text class="tab-item__room font-mono">{{ item.roomNo || '--' }}</text>
|
||
<text class="tab-item__time font-mono">{{ item.createTimeText }}</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
|
||
<view v-if="activeInspectionDetail" class="content-wrap">
|
||
<view v-if="activeInspectionDetail.items.length" class="items-wrap">
|
||
<view class="section-head section-head--main">
|
||
<view>
|
||
<text class="section-head__title">{{ $tr('检查项') }}</text>
|
||
<text class="section-head__desc">{{ $tr('建议逐项填写,异常情况请补充描述并上传照片。') }}</text>
|
||
</view>
|
||
<view class="section-head__actions">
|
||
<view class="section-action-btn" @click="markAllItemsNormal">
|
||
{{ $tr('全部正常') }}
|
||
</view>
|
||
<text class="section-head__meta">{{ activeInspectionDetail.items.length }} {{ $tr('项') }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="item-list">
|
||
<view
|
||
v-for="(item, index) in activeInspectionDetail.items"
|
||
:key="item.itemId || index"
|
||
class="inspect-item"
|
||
:class="{ 'inspect-item--expanded': shouldShowItemDetail(item) }"
|
||
>
|
||
<view class="inspect-item__glow"></view>
|
||
<view class="item-header">
|
||
<view class="item-order">{{ String(index + 1).padStart(2, '0') }}</view>
|
||
<view class="item-title-col">
|
||
<view class="item-title-row">
|
||
<text class="item-name">{{ getInspectionItemDisplayName(item) || $tr('未命名设备') }}</text>
|
||
<text v-if="item.isRequiredSnapshot" class="item-required">{{ $tr('必查') }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="item-header__right">
|
||
<view class="radio-group radio-group--compact">
|
||
<view
|
||
v-for="option in inspectionResultOptions"
|
||
:key="option.key"
|
||
class="radio-btn radio-btn--compact"
|
||
:class="{ 'radio-btn--active': String(item.resultDraft) === String(option.key) }"
|
||
@click="updateItemField(index, 'resultDraft', option.key)"
|
||
>
|
||
{{ option.value }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="shouldShowItemDetail(item)" class="item-body">
|
||
<text class="item-meta item-meta--detail" v-if="item.assetSourceText || item.brandSnapshot">
|
||
{{ [item.assetSourceText, item.brandSnapshot].filter(Boolean).join(' / ') }}
|
||
</text>
|
||
<view class="data-grid">
|
||
<view class="data-card">
|
||
<text class="field-label">{{ $tr('应有数量') }}</text>
|
||
<text class="field-value font-mono">{{ item.expectedQuantityText }}</text>
|
||
</view>
|
||
<view class="data-card data-card--input">
|
||
<text class="field-label">{{ $tr('实测数量') }}</text>
|
||
<input
|
||
class="field-input font-mono"
|
||
type="number"
|
||
:value="item.checkedQuantityDraft"
|
||
:placeholder="$tr('请输入数量')"
|
||
@input="updateItemField(index, 'checkedQuantityDraft', $event.detail.value)"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="field-block">
|
||
<view class="field-block__head">
|
||
<text class="field-block__title">{{ $tr('异常说明') }}</text>
|
||
<text class="field-block__hint">{{ $tr('缺失、损坏或无法使用时请补充描述') }}</text>
|
||
</view>
|
||
<textarea
|
||
class="field-textarea"
|
||
:value="item.problemDetailDraft"
|
||
:placeholder="$tr('请描述异常、缺失或损坏情况')"
|
||
maxlength="300"
|
||
auto-height
|
||
@input="updateItemField(index, 'problemDetailDraft', $event.detail.value)"
|
||
/>
|
||
</view>
|
||
|
||
<view class="field-block">
|
||
<view class="field-block__head">
|
||
<text class="field-block__title">{{ $tr('现场照片') }}</text>
|
||
<text class="field-block__hint">{{ $tr('建议上传关键部位照片,便于后续确认') }}</text>
|
||
</view>
|
||
<view class="photo-uploader">
|
||
<view
|
||
v-for="(url, imageIndex) in item.imageUrlsDraft"
|
||
:key="`${item.itemId || index}-${imageIndex}`"
|
||
class="photo-item"
|
||
>
|
||
<image
|
||
class="photo-img"
|
||
:src="resolveImageUrl(url)"
|
||
mode="aspectFill"
|
||
@click="previewImages(item.imageUrlsDraft, imageIndex)"
|
||
/>
|
||
<view class="photo-del" @click.stop="removeImage(index, imageIndex)">×</view>
|
||
</view>
|
||
<view class="photo-add" @click="chooseImages(index)">
|
||
<text class="photo-add-icon">+</text>
|
||
<text class="photo-add-text">{{ $tr('上传照片') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-else-if="!loading" class="empty-card">
|
||
<text class="empty-title">{{ $tr('暂无检查项') }}</text>
|
||
<text class="empty-desc">{{ $tr('当前验房单还没有检查项明细。') }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="!loading && !inspectionList.length" class="empty-card empty-card--page">
|
||
<text class="empty-title">{{ $tr('暂无验房单') }}</text>
|
||
<text class="empty-desc">{{ $tr('当前订单还没有可查看的验房记录。') }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="activeInspectionDetail" class="bottom-action">
|
||
<view class="btn-submit" @click="submitInspection">
|
||
{{ submitting ? $tr('提交中...') : $tr('提交验房') }}
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="remarksDialogVisible" class="remarks-dialog">
|
||
<view class="remarks-dialog__mask" @click="closeRemarksDialog"></view>
|
||
<view class="remarks-dialog__panel">
|
||
<view class="remarks-dialog__title">{{ $tr('提交前确认') }}</view>
|
||
<view class="remarks-dialog__desc">{{ $tr('如有交接备注、异常背景或补充情况,可在提交前补充说明。') }}</view>
|
||
<textarea
|
||
class="remarks-dialog__input"
|
||
:value="remarksDraft"
|
||
:placeholder="$tr('可填写本次验房的补充说明')"
|
||
maxlength="300"
|
||
auto-height
|
||
@input="handleRemarksInput"
|
||
/>
|
||
<view class="remarks-dialog__footer">
|
||
<view class="remarks-dialog__btn remarks-dialog__btn--ghost" @click="submitWithoutRemarks">
|
||
{{ $tr('暂不填写') }}
|
||
</view>
|
||
<view class="remarks-dialog__btn remarks-dialog__btn--primary" @click="confirmSubmitInspection">
|
||
{{ $tr('确认提交') }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-if="loading" class="global-loading">
|
||
<tn-loading mode="circle" color="#2B8EFF" size="48"></tn-loading>
|
||
<text class="loading-text">{{ $tr('正在同步验房数据...') }}</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import {
|
||
roomInspectionDetail,
|
||
roomInspectionMyPage,
|
||
roomInspectionSubmit,
|
||
uploadCommonFile
|
||
} from '@/api/index.js'
|
||
import { fetchEnums, getEnumLabel, getEnumOptions } from '@/utils/enum-store'
|
||
import { addFilePrefix } from '@/utils/common'
|
||
import { getAuthToken } from '@/utils/app-state'
|
||
|
||
function getResponsePayload(response) {
|
||
const payload = response && response.data ? response.data : response
|
||
if (typeof payload !== 'string') {
|
||
return payload
|
||
}
|
||
const text = payload.trim()
|
||
if (!text) {
|
||
return payload
|
||
}
|
||
if (!((text.startsWith('{') && text.endsWith('}')) || (text.startsWith('[') && text.endsWith(']')))) {
|
||
return payload
|
||
}
|
||
try {
|
||
return JSON.parse(text)
|
||
} catch (error) {
|
||
return payload
|
||
}
|
||
}
|
||
|
||
function getArrayPayload(response) {
|
||
const payload = getResponsePayload(response)
|
||
if (Array.isArray(payload)) {
|
||
return payload
|
||
}
|
||
if (payload && Array.isArray(payload.data)) {
|
||
return payload.data
|
||
}
|
||
if (payload && Array.isArray(payload.items)) {
|
||
return payload.items
|
||
}
|
||
return []
|
||
}
|
||
|
||
function getObjectPayload(response) {
|
||
const payload = getResponsePayload(response)
|
||
if (payload && typeof payload === 'object' && !Array.isArray(payload)) {
|
||
return payload
|
||
}
|
||
return {}
|
||
}
|
||
|
||
function formatDateTime(value) {
|
||
if (!value) {
|
||
return '--'
|
||
}
|
||
const text = String(value).replace('T', ' ')
|
||
return text.length > 16 ? text.slice(0, 16) : text
|
||
}
|
||
|
||
function resolveUploadedFileUrl(uploadResult) {
|
||
const candidates = [
|
||
uploadResult && uploadResult.data && uploadResult.data.url,
|
||
uploadResult && uploadResult.data && uploadResult.data.fileUrl,
|
||
uploadResult && uploadResult.data && uploadResult.data.path,
|
||
uploadResult && uploadResult.data && uploadResult.data.filePath,
|
||
uploadResult && uploadResult.data,
|
||
uploadResult && uploadResult.url,
|
||
uploadResult && uploadResult.fileUrl,
|
||
uploadResult && uploadResult.path,
|
||
uploadResult && uploadResult.filePath,
|
||
typeof uploadResult === 'string' ? uploadResult : ''
|
||
]
|
||
return candidates.find(item => typeof item === 'string' && item) || ''
|
||
}
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
loading: false,
|
||
submitting: false,
|
||
orderNo: '',
|
||
inspectionResultOptions: [],
|
||
inspectionList: [],
|
||
activeInspectionNo: '',
|
||
detailMap: {},
|
||
remarksDraft: '',
|
||
remarksDialogVisible: false
|
||
}
|
||
},
|
||
watch: {
|
||
language() {
|
||
this.detailMap = {}
|
||
this.loadPage(true)
|
||
}
|
||
},
|
||
computed: {
|
||
language() {
|
||
return this.$getLanguage()
|
||
},
|
||
activeInspection() {
|
||
return this.inspectionList.find(item => item.inspectionNo === this.activeInspectionNo) || null
|
||
},
|
||
activeInspectionDetail() {
|
||
return this.detailMap[this.activeInspectionNo] || null
|
||
},
|
||
},
|
||
onLoad(options = {}) {
|
||
this.orderNo = String(options.orderNo || '').trim()
|
||
this.activeInspectionNo = String(options.inspectionNo || '').trim()
|
||
this.loadPage(true)
|
||
},
|
||
onPullDownRefresh() {
|
||
this.loadPage(true).finally(() => {
|
||
uni.stopPullDownRefresh()
|
||
})
|
||
},
|
||
methods: {
|
||
syncInspectionResultOptions() {
|
||
this.inspectionResultOptions = this.getEnumOptionsWithAliases([
|
||
'InspectionItemResultEnum',
|
||
'INSPECTIONITEMRESULTENUM'
|
||
])
|
||
},
|
||
getCheckTypeLabel(value, fallback = '') {
|
||
return getEnumLabel('CheckTypeEnum', value, fallback, this.language)
|
||
},
|
||
getInspectionStatusLabel(value, fallback = '') {
|
||
return getEnumLabel('InspectionStatusEnum', value, fallback, this.language)
|
||
},
|
||
getInspectionItemResultLabel(value, fallback = '') {
|
||
return this.getEnumLabelWithAliases([
|
||
'InspectionItemResultEnum',
|
||
'INSPECTIONITEMRESULTENUM'
|
||
], value, fallback)
|
||
},
|
||
getAssetSourceLabel(value, fallback = '') {
|
||
return getEnumLabel('RoomAssetSourceTypeEnum', value, fallback, this.language)
|
||
},
|
||
getEnumOptionsWithAliases(codes = []) {
|
||
const codeList = Array.isArray(codes) ? codes : [codes]
|
||
for (let index = 0; index < codeList.length; index += 1) {
|
||
const code = String(codeList[index] || '').trim()
|
||
if (!code) {
|
||
continue
|
||
}
|
||
const options = getEnumOptions(code, this.language)
|
||
if (Array.isArray(options) && options.length) {
|
||
return options
|
||
}
|
||
}
|
||
return []
|
||
},
|
||
getEnumLabelWithAliases(codes = [], value = '', fallback = '') {
|
||
const codeList = Array.isArray(codes) ? codes : [codes]
|
||
for (let index = 0; index < codeList.length; index += 1) {
|
||
const code = String(codeList[index] || '').trim()
|
||
if (!code) {
|
||
continue
|
||
}
|
||
const label = getEnumLabel(code, value, '', this.language)
|
||
if (label !== '') {
|
||
return label
|
||
}
|
||
}
|
||
return fallback
|
||
},
|
||
normalizeListItem(item = {}) {
|
||
const inspectionNo = String(item.no || item.inspectionNo || '').trim()
|
||
return {
|
||
inspectionNo,
|
||
roomNo: item.roomNo || '',
|
||
type: item.type,
|
||
status: item.status,
|
||
createTime: item.createTime || '',
|
||
createTimeText: formatDateTime(item.createTime),
|
||
typeText: this.getCheckTypeLabel(item.type, item.typeDes || '--'),
|
||
statusText: this.getInspectionStatusLabel(item.status, item.statusDes || '--')
|
||
}
|
||
},
|
||
normalizeDetail(detail = {}) {
|
||
const inspectionNo = String(detail.no || detail.inspectionNo || '').trim()
|
||
const items = Array.isArray(detail.items)
|
||
? [...detail.items]
|
||
.sort((a, b) => Number(a.sort || 0) - Number(b.sort || 0))
|
||
.map(item => ({
|
||
itemId: item.id,
|
||
deviceName: item.deviceName || '',
|
||
assetNameEn: item.assetNameEn || item.deviceNameEn || '',
|
||
brandSnapshot: item.brandSnapshot || '',
|
||
isRequiredSnapshot: !!item.isRequiredSnapshot,
|
||
expectedQuantityText: item.expectedQuantity === null || item.expectedQuantity === undefined ? '--' : String(item.expectedQuantity),
|
||
checkedQuantityDraft: item.checkedQuantity === null || item.checkedQuantity === undefined ? '' : String(item.checkedQuantity),
|
||
resultDraft: item.result === null || item.result === undefined ? '' : String(item.result),
|
||
problemDetailDraft: item.problemDetail || '',
|
||
imageUrlsDraft: Array.isArray(item.imageUrls) ? item.imageUrls.filter(Boolean) : [],
|
||
assetSourceText: this.getAssetSourceLabel(item.assetSourceType, ''),
|
||
resultText: this.getInspectionItemResultLabel(item.result, item.resultDes || '')
|
||
}))
|
||
: []
|
||
|
||
return {
|
||
inspectionNo,
|
||
roomNo: detail.roomNo || '',
|
||
typeText: this.getCheckTypeLabel(detail.type, detail.typeDes || '--'),
|
||
statusText: this.getInspectionStatusLabel(detail.status, detail.statusDes || '--'),
|
||
createTimeText: formatDateTime(detail.createTime),
|
||
remarksDraft: detail.remarks || '',
|
||
items
|
||
}
|
||
},
|
||
getInspectionItemDisplayName(item = {}) {
|
||
if (this.language === 'en') {
|
||
return item.assetNameEn || item.deviceName || ''
|
||
}
|
||
return item.deviceName || item.assetNameEn || ''
|
||
},
|
||
async loadPage(force = false) {
|
||
this.loading = true
|
||
try {
|
||
await fetchEnums(force, this.language).catch(() => {})
|
||
this.syncInspectionResultOptions()
|
||
await this.fetchInspectionList()
|
||
if (!this.activeInspectionNo && this.inspectionList.length) {
|
||
this.activeInspectionNo = this.inspectionList[0].inspectionNo
|
||
}
|
||
if (this.activeInspectionNo) {
|
||
await this.fetchInspectionDetail(this.activeInspectionNo, force)
|
||
}
|
||
} finally {
|
||
this.loading = false
|
||
}
|
||
},
|
||
async fetchInspectionList() {
|
||
if (!this.orderNo) {
|
||
this.inspectionList = []
|
||
this.activeInspectionNo = ''
|
||
return
|
||
}
|
||
const response = await roomInspectionMyPage({
|
||
orderNo: this.orderNo
|
||
}, this.language)
|
||
const list = getArrayPayload(response)
|
||
.map(item => this.normalizeListItem(item))
|
||
.filter(item => item.inspectionNo)
|
||
.sort((prev, next) => new Date(next.createTime || 0).getTime() - new Date(prev.createTime || 0).getTime())
|
||
this.inspectionList = list
|
||
if (!list.some(item => item.inspectionNo === this.activeInspectionNo)) {
|
||
this.activeInspectionNo = list.length ? list[0].inspectionNo : ''
|
||
}
|
||
},
|
||
async fetchInspectionDetail(inspectionNo = '', force = false) {
|
||
const targetNo = String(inspectionNo || '').trim()
|
||
if (!targetNo) {
|
||
return
|
||
}
|
||
if (!force && this.detailMap[targetNo]) {
|
||
this.remarksDraft = this.detailMap[targetNo].remarksDraft || ''
|
||
return
|
||
}
|
||
const response = await roomInspectionDetail({
|
||
inspectionNo: targetNo
|
||
}, this.language)
|
||
const normalized = this.normalizeDetail(getObjectPayload(response))
|
||
this.$set(this.detailMap, targetNo, normalized)
|
||
this.remarksDraft = normalized.remarksDraft || ''
|
||
},
|
||
async switchInspection(item = {}) {
|
||
const inspectionNo = String(item.inspectionNo || '').trim()
|
||
if (!inspectionNo || inspectionNo === this.activeInspectionNo) {
|
||
return
|
||
}
|
||
this.activeInspectionNo = inspectionNo
|
||
await this.fetchInspectionDetail(inspectionNo)
|
||
},
|
||
handleRemarksInput(event) {
|
||
const value = event && event.detail ? event.detail.value : ''
|
||
this.remarksDraft = value
|
||
if (this.activeInspectionDetail) {
|
||
this.activeInspectionDetail.remarksDraft = value
|
||
}
|
||
},
|
||
updateItemField(index, field, value) {
|
||
const detail = this.activeInspectionDetail
|
||
if (!detail || !Array.isArray(detail.items) || !detail.items[index]) {
|
||
return
|
||
}
|
||
this.$set(detail.items[index], field, value)
|
||
},
|
||
getInspectionResultCategory(value = '') {
|
||
const result = String(value || '').trim()
|
||
if (!result) {
|
||
return 'pending'
|
||
}
|
||
const matchedOption = (Array.isArray(this.inspectionResultOptions) ? this.inspectionResultOptions : []).find((option) => {
|
||
return String(option && option.key) === result
|
||
}) || null
|
||
const candidateText = [
|
||
this.getInspectionItemResultLabel(result, ''),
|
||
matchedOption && matchedOption.value,
|
||
matchedOption && matchedOption.label,
|
||
result
|
||
].filter(value => value !== undefined && value !== null).join(' ')
|
||
|
||
if (/未检|待检|未查|unchecked|notchecked|pending|not checked|not inspected/i.test(candidateText)) {
|
||
return 'pending'
|
||
}
|
||
if (/问题|异常|损坏|缺失|故障|problem|issue|abnormal|damage|damaged|missing|fault|broken|unusable/i.test(candidateText)) {
|
||
return 'abnormal'
|
||
}
|
||
if (/正常|可用|完好|normal|available|good|intact|ok/i.test(candidateText)) {
|
||
return 'normal'
|
||
}
|
||
return 'done'
|
||
},
|
||
getNormalResultOption() {
|
||
return (Array.isArray(this.inspectionResultOptions) ? this.inspectionResultOptions : []).find((option) => {
|
||
return this.getInspectionResultCategory(option && option.key) === 'normal'
|
||
}) || null
|
||
},
|
||
shouldShowItemDetail(item = {}) {
|
||
return this.getInspectionResultCategory(item.resultDraft) === 'abnormal'
|
||
},
|
||
markAllItemsNormal() {
|
||
const detail = this.activeInspectionDetail
|
||
const normalOption = this.getNormalResultOption()
|
||
if (!detail || !Array.isArray(detail.items) || !detail.items.length || !normalOption) {
|
||
uni.showToast({
|
||
title: this.$tr('未找到正常结果选项'),
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
detail.items.forEach((item, index) => {
|
||
this.$set(detail.items[index], 'resultDraft', normalOption.key)
|
||
})
|
||
uni.showToast({
|
||
title: this.$tr('已全部勾选正常'),
|
||
icon: 'success'
|
||
})
|
||
},
|
||
buildSubmitItems() {
|
||
const detail = this.activeInspectionDetail
|
||
if (!detail) {
|
||
return []
|
||
}
|
||
return (Array.isArray(detail.items) ? detail.items : [])
|
||
.filter(item => item && item.itemId)
|
||
.map(item => {
|
||
const resultText = String(item.resultDraft || '').trim()
|
||
const checkedQuantityText = String(item.checkedQuantityDraft || '').trim()
|
||
return {
|
||
itemId: item.itemId,
|
||
result: resultText === '' ? null : Number(resultText),
|
||
checkedQuantity: checkedQuantityText === '' ? null : Number(checkedQuantityText),
|
||
problemDetail: String(item.problemDetailDraft || '').trim(),
|
||
imageUrls: Array.isArray(item.imageUrlsDraft) ? item.imageUrlsDraft.filter(Boolean) : []
|
||
}
|
||
})
|
||
},
|
||
validateBeforeSubmit() {
|
||
const items = this.buildSubmitItems()
|
||
const hasMissingResult = items.some(item => item.result === null || Number.isNaN(item.result))
|
||
if (hasMissingResult) {
|
||
uni.showToast({
|
||
title: this.$tr('请先完成所有检查项结果选择'),
|
||
icon: 'none'
|
||
})
|
||
return false
|
||
}
|
||
return true
|
||
},
|
||
closeRemarksDialog() {
|
||
this.remarksDialogVisible = false
|
||
},
|
||
submitInspection() {
|
||
const inspectionNo = String(this.activeInspectionNo || '').trim()
|
||
if (!inspectionNo || this.submitting) {
|
||
return
|
||
}
|
||
if (!this.validateBeforeSubmit()) {
|
||
return
|
||
}
|
||
this.remarksDialogVisible = true
|
||
},
|
||
submitWithoutRemarks() {
|
||
this.remarksDraft = ''
|
||
if (this.activeInspectionDetail) {
|
||
this.activeInspectionDetail.remarksDraft = ''
|
||
}
|
||
this.confirmSubmitInspection()
|
||
},
|
||
async confirmSubmitInspection() {
|
||
const inspectionNo = String(this.activeInspectionNo || '').trim()
|
||
if (!inspectionNo || this.submitting) {
|
||
return
|
||
}
|
||
this.remarksDialogVisible = false
|
||
this.submitting = true
|
||
try {
|
||
await roomInspectionSubmit({
|
||
inspectionNo,
|
||
remarks: this.remarksDraft,
|
||
items: this.buildSubmitItems()
|
||
}, this.language)
|
||
uni.showToast({
|
||
title: this.$tr('验房单已提交'),
|
||
icon: 'success'
|
||
})
|
||
setTimeout(() => {
|
||
uni.$emit('reservation-flow-force-refresh', {
|
||
source: 'room-inspection-submit',
|
||
orderNo: this.orderNo,
|
||
inspectionNo
|
||
})
|
||
uni.navigateBack()
|
||
}, 500)
|
||
} catch (error) {
|
||
uni.showToast({
|
||
title: (error && (error.message || error.msg)) || this.$tr('提交失败'),
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
this.submitting = false
|
||
}
|
||
},
|
||
chooseImages(index) {
|
||
uni.chooseImage({
|
||
count: 9,
|
||
sizeType: ['compressed'],
|
||
sourceType: ['album', 'camera'],
|
||
success: async (res) => {
|
||
const tempFilePaths = Array.isArray(res.tempFilePaths) ? res.tempFilePaths : []
|
||
if (!tempFilePaths.length) {
|
||
return
|
||
}
|
||
uni.showLoading({
|
||
title: this.$tr('正在同步验房数据...'),
|
||
mask: true
|
||
})
|
||
try {
|
||
const uploadedUrls = []
|
||
for (let fileIndex = 0; fileIndex < tempFilePaths.length; fileIndex += 1) {
|
||
const uploadResult = await uploadCommonFile(
|
||
tempFilePaths[fileIndex],
|
||
{},
|
||
'file',
|
||
{
|
||
...(getAuthToken() ? { Authorization: `Bearer ${getAuthToken()}` } : {})
|
||
}
|
||
)
|
||
const remoteUrl = resolveUploadedFileUrl(uploadResult)
|
||
if (!remoteUrl) {
|
||
throw new Error(this.$tr('图片上传失败'))
|
||
}
|
||
uploadedUrls.push(addFilePrefix(remoteUrl))
|
||
}
|
||
const detail = this.activeInspectionDetail
|
||
if (!detail || !Array.isArray(detail.items) || !detail.items[index]) {
|
||
return
|
||
}
|
||
const nextUrls = (detail.items[index].imageUrlsDraft || []).concat(uploadedUrls)
|
||
this.$set(detail.items[index], 'imageUrlsDraft', nextUrls)
|
||
} catch (error) {
|
||
uni.showToast({
|
||
title: (error && (error.message || error.msg)) || this.$tr('图片上传失败'),
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
uni.hideLoading()
|
||
}
|
||
},
|
||
fail: () => {
|
||
uni.showToast({
|
||
title: this.$tr('选择图片失败'),
|
||
icon: 'none'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
removeImage(itemIndex, imageIndex) {
|
||
const detail = this.activeInspectionDetail
|
||
if (!detail || !Array.isArray(detail.items) || !detail.items[itemIndex]) {
|
||
return
|
||
}
|
||
const nextUrls = (detail.items[itemIndex].imageUrlsDraft || []).filter((_, index) => index !== imageIndex)
|
||
this.$set(detail.items[itemIndex], 'imageUrlsDraft', nextUrls)
|
||
},
|
||
previewImages(urls, currentIndex = 0) {
|
||
const safeUrls = Array.isArray(urls) ? urls.filter(Boolean).map(item => this.resolveImageUrl(item)) : []
|
||
if (!safeUrls.length) {
|
||
return
|
||
}
|
||
uni.previewImage({
|
||
urls: safeUrls,
|
||
current: safeUrls[currentIndex] || safeUrls[0]
|
||
})
|
||
},
|
||
resolveImageUrl(url = '') {
|
||
return addFilePrefix(url)
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.app-page {
|
||
min-height: 100vh;
|
||
background: linear-gradient(180deg, #F2F5FC 0%, #F7F9FC 42%, #FBFCFE 100%);
|
||
padding-bottom: calc(188rpx + env(safe-area-inset-bottom));
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.page-bg {
|
||
position: fixed;
|
||
inset: 0;
|
||
pointer-events: none;
|
||
}
|
||
|
||
.bg-orb {
|
||
position: absolute;
|
||
border-radius: 999rpx;
|
||
filter: blur(12rpx);
|
||
}
|
||
|
||
.bg-orb--primary {
|
||
top: 120rpx;
|
||
right: -80rpx;
|
||
width: 320rpx;
|
||
height: 320rpx;
|
||
background: radial-gradient(circle, rgba(43, 142, 255, 0.18) 0%, rgba(43, 142, 255, 0.02) 72%, rgba(43, 142, 255, 0) 100%);
|
||
}
|
||
|
||
.bg-orb--soft {
|
||
top: 420rpx;
|
||
left: -120rpx;
|
||
width: 360rpx;
|
||
height: 360rpx;
|
||
background: radial-gradient(circle, rgba(133, 189, 255, 0.16) 0%, rgba(133, 189, 255, 0.02) 72%, rgba(133, 189, 255, 0) 100%);
|
||
}
|
||
|
||
.page-shell {
|
||
position: relative;
|
||
z-index: 1;
|
||
padding: 0 24rpx 24rpx;
|
||
}
|
||
|
||
.nav-title {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: #10213A;
|
||
}
|
||
|
||
.hero-panel {
|
||
padding: 24rpx 28rpx;
|
||
border-radius: 36rpx;
|
||
background: linear-gradient(180deg, rgba(255, 255, 255, 0.86) 0%, rgba(255, 255, 255, 0.97) 100%);
|
||
box-shadow: 0 18rpx 44rpx rgba(31, 80, 146, 0.08);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.85);
|
||
backdrop-filter: blur(18rpx);
|
||
}
|
||
|
||
.hero-top {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.hero-title-wrap {
|
||
min-width: 0;
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.hero-kicker {
|
||
font-size: 22rpx;
|
||
font-weight: 600;
|
||
color: #7E95B7;
|
||
letter-spacing: 8rpx;
|
||
}
|
||
|
||
.hero-title {
|
||
margin-top: 10rpx;
|
||
font-size: 52rpx;
|
||
line-height: 1.08;
|
||
font-weight: 700;
|
||
color: #12233C;
|
||
}
|
||
|
||
.hero-status {
|
||
padding: 12rpx 20rpx;
|
||
border-radius: 999rpx;
|
||
background: rgba(43, 142, 255, 0.1);
|
||
color: #2B8EFF;
|
||
font-size: 22rpx;
|
||
font-weight: 600;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.tab-wrap,
|
||
.empty-card {
|
||
margin-top: 24rpx;
|
||
border-radius: 30rpx;
|
||
background: rgba(255, 255, 255, 0.92);
|
||
box-shadow: 0 16rpx 36rpx rgba(31, 80, 146, 0.06);
|
||
border: 1rpx solid rgba(224, 233, 247, 0.95);
|
||
}
|
||
|
||
.section-head {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.section-head__title {
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: #14253F;
|
||
}
|
||
|
||
.section-head__meta {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: #6E83A6;
|
||
}
|
||
|
||
.section-head__actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 14rpx;
|
||
}
|
||
|
||
.section-action-btn {
|
||
height: 52rpx;
|
||
padding: 0 22rpx;
|
||
border-radius: 999rpx;
|
||
background: rgba(43, 142, 255, 0.1);
|
||
color: #2B8EFF;
|
||
font-size: 22rpx;
|
||
font-weight: 700;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.tab-wrap,
|
||
.empty-card {
|
||
padding: 24rpx;
|
||
}
|
||
|
||
.tab-scroll {
|
||
width: 100%;
|
||
margin-top: 18rpx;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.tab-list {
|
||
display: inline-flex;
|
||
gap: 18rpx;
|
||
padding-right: 8rpx;
|
||
}
|
||
|
||
.tab-item {
|
||
min-width: 220rpx;
|
||
padding: 22rpx 24rpx;
|
||
border-radius: 24rpx;
|
||
background: linear-gradient(180deg, #F8FBFF 0%, #FFFFFF 100%);
|
||
border: 1rpx solid rgba(221, 231, 246, 0.95);
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.tab-item--active {
|
||
background: linear-gradient(135deg, rgba(43, 142, 255, 0.14) 0%, rgba(255, 255, 255, 0.98) 100%);
|
||
border-color: rgba(43, 142, 255, 0.22);
|
||
box-shadow: 0 10rpx 24rpx rgba(43, 142, 255, 0.1);
|
||
}
|
||
|
||
.tab-item__type {
|
||
font-size: 26rpx;
|
||
font-weight: 700;
|
||
color: #1B2C46;
|
||
}
|
||
|
||
.tab-item__room {
|
||
margin-top: 10rpx;
|
||
font-size: 26rpx;
|
||
color: #4C6285;
|
||
}
|
||
|
||
.tab-item__time {
|
||
margin-top: 12rpx;
|
||
font-size: 20rpx;
|
||
color: #8A9AB4;
|
||
}
|
||
|
||
.content-wrap {
|
||
position: relative;
|
||
z-index: 1;
|
||
margin-top: 24rpx;
|
||
}
|
||
|
||
.section-head__desc {
|
||
display: block;
|
||
margin-top: 10rpx;
|
||
font-size: 22rpx;
|
||
line-height: 1.6;
|
||
color: #7B8EAA;
|
||
}
|
||
|
||
.items-wrap {
|
||
margin-top: 12rpx;
|
||
}
|
||
|
||
.section-head--main {
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.item-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.inspect-item {
|
||
position: relative;
|
||
overflow: hidden;
|
||
border-radius: 32rpx;
|
||
background: rgba(255, 255, 255, 0.95);
|
||
box-shadow: 0 16rpx 34rpx rgba(31, 80, 146, 0.07);
|
||
border: 1rpx solid rgba(224, 233, 247, 0.96);
|
||
}
|
||
|
||
.inspect-item__glow {
|
||
position: absolute;
|
||
top: -40rpx;
|
||
right: -30rpx;
|
||
width: 180rpx;
|
||
height: 180rpx;
|
||
border-radius: 999rpx;
|
||
background: radial-gradient(circle, rgba(43, 142, 255, 0.12) 0%, rgba(43, 142, 255, 0) 72%);
|
||
pointer-events: none;
|
||
}
|
||
|
||
.item-header {
|
||
position: relative;
|
||
z-index: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 18rpx;
|
||
padding: 22rpx 24rpx;
|
||
}
|
||
|
||
.item-order {
|
||
width: 56rpx;
|
||
height: 56rpx;
|
||
border-radius: 18rpx;
|
||
background: linear-gradient(180deg, #EAF4FF 0%, #F5FAFF 100%);
|
||
color: #2B8EFF;
|
||
font-size: 22rpx;
|
||
font-weight: 700;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.item-title-col {
|
||
min-width: 0;
|
||
flex: 1;
|
||
}
|
||
|
||
.item-title-row {
|
||
display: flex;
|
||
align-items: center;
|
||
flex-wrap: wrap;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.item-name {
|
||
font-size: 30rpx;
|
||
line-height: 1.35;
|
||
font-weight: 700;
|
||
color: #152742;
|
||
}
|
||
|
||
.item-meta {
|
||
display: block;
|
||
font-size: 22rpx;
|
||
color: #7E90AA;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
|
||
.item-meta--detail {
|
||
margin-bottom: 18rpx;
|
||
}
|
||
|
||
.item-required {
|
||
padding: 6rpx 14rpx;
|
||
border-radius: 999rpx;
|
||
background: rgba(255, 181, 72, 0.16);
|
||
color: #D47D17;
|
||
font-size: 20rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.item-header__right {
|
||
margin-left: auto;
|
||
flex-shrink: 0;
|
||
max-width: none;
|
||
}
|
||
|
||
.item-body {
|
||
position: relative;
|
||
z-index: 1;
|
||
padding: 0 24rpx 24rpx;
|
||
border-top: 1rpx solid rgba(224, 233, 247, 0.9);
|
||
}
|
||
|
||
.data-grid {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.data-card {
|
||
flex: 1;
|
||
padding: 22rpx;
|
||
border-radius: 24rpx;
|
||
background: linear-gradient(180deg, #F8FBFF 0%, #FFFFFF 100%);
|
||
border: 1rpx solid rgba(221, 231, 246, 0.95);
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.data-card--input {
|
||
background: linear-gradient(180deg, #F5FAFF 0%, #FFFFFF 100%);
|
||
}
|
||
|
||
.field-label {
|
||
display: block;
|
||
font-size: 22rpx;
|
||
color: #7D8FAC;
|
||
}
|
||
|
||
.field-value {
|
||
display: block;
|
||
margin-top: 12rpx;
|
||
font-size: 34rpx;
|
||
line-height: 1.2;
|
||
font-weight: 700;
|
||
color: #152742;
|
||
}
|
||
|
||
.field-input {
|
||
width: 100%;
|
||
height: 74rpx;
|
||
margin-top: 12rpx;
|
||
padding: 0 20rpx;
|
||
border-radius: 18rpx;
|
||
background: rgba(255, 255, 255, 0.96);
|
||
border: 1rpx solid rgba(205, 220, 241, 0.95);
|
||
box-sizing: border-box;
|
||
font-size: 30rpx;
|
||
color: #152742;
|
||
}
|
||
|
||
.field-block {
|
||
margin-top: 18rpx;
|
||
padding: 22rpx;
|
||
border-radius: 24rpx;
|
||
background: linear-gradient(180deg, rgba(248, 251, 255, 0.96) 0%, rgba(255, 255, 255, 0.98) 100%);
|
||
border: 1rpx solid rgba(221, 231, 246, 0.95);
|
||
}
|
||
|
||
.field-block__head {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: baseline;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.field-block__title {
|
||
font-size: 25rpx;
|
||
font-weight: 700;
|
||
color: #172944;
|
||
}
|
||
|
||
.field-block__hint {
|
||
font-size: 20rpx;
|
||
color: #8A9AB4;
|
||
text-align: right;
|
||
}
|
||
|
||
.radio-group {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
margin-top: 18rpx;
|
||
}
|
||
|
||
.radio-group--compact {
|
||
margin-top: 0;
|
||
justify-content: flex-end;
|
||
gap: 10rpx;
|
||
flex-wrap: nowrap;
|
||
}
|
||
|
||
.radio-btn {
|
||
min-width: 146rpx;
|
||
padding: 16rpx 24rpx;
|
||
border-radius: 18rpx;
|
||
background: #FFFFFF;
|
||
border: 1rpx solid rgba(205, 220, 241, 0.95);
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: #5A6F93;
|
||
text-align: center;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.radio-btn--compact {
|
||
min-width: auto;
|
||
padding: 12rpx 16rpx;
|
||
border-radius: 999rpx;
|
||
font-size: 22rpx;
|
||
line-height: 1.2;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.radio-btn--active {
|
||
background: linear-gradient(135deg, rgba(43, 142, 255, 0.12) 0%, rgba(255, 255, 255, 0.98) 100%);
|
||
border-color: rgba(43, 142, 255, 0.22);
|
||
color: #2B8EFF;
|
||
box-shadow: 0 10rpx 22rpx rgba(43, 142, 255, 0.08);
|
||
}
|
||
|
||
.field-textarea {
|
||
width: 100%;
|
||
min-height: 112rpx;
|
||
margin-top: 18rpx;
|
||
padding: 18rpx 20rpx;
|
||
border-radius: 20rpx;
|
||
background: rgba(255, 255, 255, 0.96);
|
||
border: 1rpx solid rgba(205, 220, 241, 0.95);
|
||
box-sizing: border-box;
|
||
font-size: 26rpx;
|
||
color: #152742;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.photo-uploader {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
margin-top: 18rpx;
|
||
}
|
||
|
||
.photo-item,
|
||
.photo-add {
|
||
width: 148rpx;
|
||
height: 148rpx;
|
||
border-radius: 24rpx;
|
||
overflow: hidden;
|
||
position: relative;
|
||
}
|
||
|
||
.photo-item {
|
||
background: #EFF5FD;
|
||
border: 1rpx solid rgba(221, 231, 246, 0.95);
|
||
}
|
||
|
||
.photo-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.photo-del {
|
||
position: absolute;
|
||
top: 8rpx;
|
||
right: 8rpx;
|
||
width: 34rpx;
|
||
height: 34rpx;
|
||
border-radius: 999rpx;
|
||
background: rgba(10, 24, 45, 0.55);
|
||
color: #FFFFFF;
|
||
font-size: 28rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
line-height: 1;
|
||
}
|
||
|
||
.photo-add {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: linear-gradient(180deg, #F9FBFF 0%, #FFFFFF 100%);
|
||
border: 1rpx dashed rgba(141, 179, 232, 0.95);
|
||
color: #7E95B7;
|
||
}
|
||
|
||
.photo-add-icon {
|
||
font-size: 44rpx;
|
||
line-height: 1;
|
||
}
|
||
|
||
.photo-add-text {
|
||
margin-top: 8rpx;
|
||
font-size: 20rpx;
|
||
}
|
||
|
||
.empty-card {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
text-align: center;
|
||
}
|
||
|
||
.empty-card--page {
|
||
margin: 24rpx;
|
||
min-height: 320rpx;
|
||
}
|
||
|
||
.empty-title {
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
color: #1A2D49;
|
||
}
|
||
|
||
.empty-desc {
|
||
margin-top: 12rpx;
|
||
font-size: 24rpx;
|
||
line-height: 1.7;
|
||
color: #8496B2;
|
||
}
|
||
|
||
.bottom-action {
|
||
position: fixed;
|
||
left: 24rpx;
|
||
right: 24rpx;
|
||
bottom: calc(20rpx + env(safe-area-inset-bottom));
|
||
z-index: 100;
|
||
padding: 18rpx;
|
||
border-radius: 28rpx;
|
||
background: rgba(255, 255, 255, 0.92);
|
||
box-shadow: 0 18rpx 40rpx rgba(31, 80, 146, 0.14);
|
||
backdrop-filter: blur(16rpx);
|
||
border: 1rpx solid rgba(224, 233, 247, 0.95);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.btn-submit {
|
||
width: 100%;
|
||
height: 92rpx;
|
||
border-radius: 22rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
color: #FFFFFF;
|
||
background: linear-gradient(135deg, #4AA2FF 0%, #2B8EFF 58%, #1E6FE0 100%);
|
||
box-shadow: 0 16rpx 32rpx rgba(43, 142, 255, 0.28);
|
||
}
|
||
|
||
.btn-submit:active {
|
||
transform: translateY(2rpx);
|
||
}
|
||
|
||
.remarks-dialog {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 260;
|
||
}
|
||
|
||
.remarks-dialog__mask {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: rgba(10, 24, 45, 0.28);
|
||
backdrop-filter: blur(8px);
|
||
}
|
||
|
||
.remarks-dialog__panel {
|
||
position: absolute;
|
||
left: 24rpx;
|
||
right: 24rpx;
|
||
bottom: calc(24rpx + env(safe-area-inset-bottom));
|
||
padding: 28rpx;
|
||
border-radius: 32rpx;
|
||
background: rgba(255, 255, 255, 0.98);
|
||
box-shadow: 0 20rpx 48rpx rgba(15, 37, 68, 0.18);
|
||
}
|
||
|
||
.remarks-dialog__title {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: #152742;
|
||
}
|
||
|
||
.remarks-dialog__desc {
|
||
margin-top: 12rpx;
|
||
font-size: 24rpx;
|
||
line-height: 1.7;
|
||
color: #7285A4;
|
||
}
|
||
|
||
.remarks-dialog__input {
|
||
width: 100%;
|
||
min-height: 160rpx;
|
||
margin-top: 24rpx;
|
||
padding: 22rpx 24rpx;
|
||
border-radius: 24rpx;
|
||
background: linear-gradient(180deg, #F7FAFF 0%, #FFFFFF 100%);
|
||
border: 1rpx solid rgba(221, 231, 246, 0.95);
|
||
box-sizing: border-box;
|
||
font-size: 26rpx;
|
||
line-height: 1.7;
|
||
color: #152742;
|
||
}
|
||
|
||
.remarks-dialog__footer {
|
||
margin-top: 24rpx;
|
||
display: flex;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.remarks-dialog__btn {
|
||
flex: 1;
|
||
height: 84rpx;
|
||
border-radius: 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.remarks-dialog__btn--ghost {
|
||
background: #F3F7FE;
|
||
color: #5E7397;
|
||
}
|
||
|
||
.remarks-dialog__btn--primary {
|
||
background: linear-gradient(135deg, #4AA2FF 0%, #2B8EFF 58%, #1E6FE0 100%);
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.global-loading {
|
||
position: fixed;
|
||
inset: 0;
|
||
background: rgba(247, 250, 255, 0.82);
|
||
backdrop-filter: blur(10px);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 999;
|
||
}
|
||
|
||
.loading-text {
|
||
margin-top: 24rpx;
|
||
font-size: 26rpx;
|
||
color: #5E7397;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.font-mono {
|
||
font-family: "DIN Alternate", "SF Pro Text", SFMono-Regular, Consolas, "Liberation Mono", Menlo, monospace;
|
||
}
|
||
|
||
@media screen and (max-width: 360px) {
|
||
.hero-top,
|
||
.field-block__head {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.data-grid,
|
||
.remarks-dialog__footer {
|
||
flex-direction: column;
|
||
}
|
||
|
||
.item-header {
|
||
align-items: flex-start;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.item-header__right {
|
||
max-width: 100%;
|
||
width: 100%;
|
||
}
|
||
|
||
.radio-group--compact {
|
||
justify-content: flex-start;
|
||
}
|
||
|
||
.section-head__actions {
|
||
width: 100%;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.btn-submit {
|
||
width: 100%;
|
||
}
|
||
}
|
||
</style>
|