20260929
This commit is contained in:
@@ -0,0 +1,748 @@
|
||||
<template>
|
||||
<view class="visit-page">
|
||||
<view class="page-hero">
|
||||
<AppNavbar title="客户拜访" show-back/>
|
||||
<view class="intro-card">
|
||||
<view class="card-title">
|
||||
<view class="title-bar"></view>
|
||||
<text>培训拜访</text>
|
||||
</view>
|
||||
<text class="intro-text">记录培训拜访现场定位、沟通内容和照片,提交后可回看历史记录。</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card block">
|
||||
<view class="section-title">新增拜访</view>
|
||||
<view class="form">
|
||||
<view class="form-row location-row">
|
||||
<text>定位信息</text>
|
||||
<view class="location-box">
|
||||
<view class="picker-value location-text" :class="{placeholder: !visitForm.location}">
|
||||
{{ visitForm.location || '定位中,或点击右侧重新定位' }}
|
||||
</view>
|
||||
<view class="location-meta">
|
||||
<text>{{ formatCoordinate('纬度', visitForm.lat) }}</text>
|
||||
<text>{{ formatCoordinate('经度', visitForm.lng) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="refresh-btn" @tap="fetchLocation(false, true)">重新定位</view>
|
||||
</view>
|
||||
|
||||
<view class="form-row">
|
||||
<text>连锁</text>
|
||||
<view class="selector-picker" @tap="openChainPicker">
|
||||
<view class="picker-value" :class="{placeholder: !visitForm.chain}">
|
||||
{{ visitForm.chain || (chainLoading ? '连锁加载中...' : '请选择连锁') }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-row">
|
||||
<text>拜访人员</text>
|
||||
<input v-model="visitForm.name" maxlength="30" placeholder="请输入拜访人员"/>
|
||||
</view>
|
||||
|
||||
<view class="form-row textarea-row">
|
||||
<text>沟通内容</text>
|
||||
<textarea
|
||||
v-model="visitForm.content"
|
||||
class="textarea-input"
|
||||
maxlength="500"
|
||||
auto-height
|
||||
placeholder="请输入沟通内容"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="upload" @tap="uploadPhotos">
|
||||
<view>
|
||||
<view class="upload-title">拍照上传</view>
|
||||
<view class="upload-meta">{{ photos.length ? `已上传 ${photos.length} 张,点击继续拍照` : '点击拍照上传,最多 9 张' }}</view>
|
||||
</view>
|
||||
<view class="chip">必填</view>
|
||||
</view>
|
||||
|
||||
<view v-if="photos.length" class="photo-list">
|
||||
<view class="photo-item" v-for="(photo, index) in photos" :key="`${photo}-${index}`">
|
||||
<image class="photo-image" :src="photo" mode="aspectFill" @tap="previewPhoto(index)"/>
|
||||
<view class="photo-remove" @tap.stop="removePhoto(index)">x</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-row textarea-row">
|
||||
<text>活动小结</text>
|
||||
<textarea
|
||||
v-model="visitForm.summary"
|
||||
class="textarea-input"
|
||||
maxlength="300"
|
||||
auto-height
|
||||
placeholder="请输入活动小结"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<view class="primary-btn submit" @tap="submitVisit">提交拜访</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="card block">
|
||||
<view class="section-title">历史记录</view>
|
||||
<view v-if="loading" class="empty">加载中...</view>
|
||||
<view v-else-if="visitHistory.length === 0" class="empty">暂无记录</view>
|
||||
<view v-else>
|
||||
<view class="history" v-for="item in visitHistory" :key="item.id">
|
||||
<view class="history-head" @tap="toggleHistoryDetail(item.id)">
|
||||
<view class="history-main">
|
||||
<view class="history-title">{{ item.name || '未命名拜访' }}</view>
|
||||
<view class="history-meta">{{ item.createdAt || '暂无时间' }}</view>
|
||||
</view>
|
||||
<view class="history-side">
|
||||
<view class="history-status" :class="item.statusClass">{{ item.status }}</view>
|
||||
<u-icon name="arrow-right" size="24" color="#9ca3af" :class="['history-arrow', item.expanded ? 'open' : '']"/>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="item.expanded" class="history-detail">
|
||||
<view class="history-line">定位:{{ item.location || '-' }}</view>
|
||||
<view class="history-line">纬度:{{ item.lat || '-' }}</view>
|
||||
<view class="history-line">经度:{{ item.lng || '-' }}</view>
|
||||
<view class="history-line">连锁:{{ item.chain || '-' }}</view>
|
||||
<view class="history-line">沟通内容:{{ item.content || '-' }}</view>
|
||||
<view class="history-line">活动小结:{{ item.summary || '-' }}</view>
|
||||
<view class="history-line">照片:</view>
|
||||
<view v-if="item.photos.length" class="history-photo-list">
|
||||
<view class="history-photo-item" v-for="(photo, photoIndex) in item.photos" :key="`${item.id}-${photoIndex}`">
|
||||
<image
|
||||
class="history-photo-image"
|
||||
:src="photo"
|
||||
mode="aspectFill"
|
||||
@tap="previewHistoryPhoto(item.photos, photoIndex)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="history-line">-</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<u-picker
|
||||
:show="showChainPicker"
|
||||
:columns="[chainOptions]"
|
||||
:loading="chainLoading"
|
||||
:defaultIndex="chainPickerIndex"
|
||||
keyName="text"
|
||||
@confirm="onChainConfirm"
|
||||
@cancel="closeChainPicker"
|
||||
@close="closeChainPicker"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppNavbar from "@/components/AppNavbar.vue";
|
||||
import {chooseImg, getLocationOnly} from "@/util";
|
||||
import {visitAddReq, visitListReq} from "@/api/visit";
|
||||
import {merchantGroupByChainReq} from "@/api/shop";
|
||||
|
||||
export default {
|
||||
components: {AppNavbar},
|
||||
data() {
|
||||
return {
|
||||
visitForm: this.buildForm(),
|
||||
photos: [],
|
||||
visitHistory: [],
|
||||
chainOptions: [],
|
||||
chainLoading: false,
|
||||
showChainPicker: false,
|
||||
loading: false,
|
||||
locating: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
chainPickerIndex() {
|
||||
if (!this.chainOptions.length) return [0]
|
||||
const idx = this.chainOptions.findIndex(item => String(item.id) === String(this.visitForm.chainId))
|
||||
return [idx < 0 ? 0 : idx]
|
||||
}
|
||||
},
|
||||
async onShow() {
|
||||
await Promise.all([
|
||||
this.fetchLocation(true),
|
||||
this.fetchHistory(),
|
||||
this.fetchChainOptions()
|
||||
])
|
||||
},
|
||||
methods: {
|
||||
buildForm() {
|
||||
return {
|
||||
lat: '',
|
||||
lng: '',
|
||||
location: '',
|
||||
chainId: '',
|
||||
chain: '',
|
||||
name: '',
|
||||
content: '',
|
||||
summary: ''
|
||||
}
|
||||
},
|
||||
async fetchChainOptions() {
|
||||
this.chainLoading = true
|
||||
try {
|
||||
const {data} = await merchantGroupByChainReq()
|
||||
const list = this.unwrapList(data)
|
||||
this.chainOptions = list.map((item, index) => this.normalizeChainOption(item, index))
|
||||
.filter(item => item.id !== undefined && item.id !== null && String(item.id).trim() !== '')
|
||||
if (this.visitForm.chainId && !this.chainOptions.find(item => String(item.id) === String(this.visitForm.chainId))) {
|
||||
this.visitForm.chainId = ''
|
||||
this.visitForm.chain = ''
|
||||
}
|
||||
} catch (err) {
|
||||
this.chainOptions = []
|
||||
} finally {
|
||||
this.chainLoading = false
|
||||
}
|
||||
},
|
||||
openChainPicker() {
|
||||
this.showChainPicker = true
|
||||
},
|
||||
closeChainPicker() {
|
||||
this.showChainPicker = false
|
||||
},
|
||||
onChainConfirm(event) {
|
||||
const selected = event && event.value && event.value.length ? event.value[0] : null
|
||||
this.visitForm.chainId = selected ? selected.id : ''
|
||||
this.visitForm.chain = selected ? selected.text : ''
|
||||
this.showChainPicker = false
|
||||
},
|
||||
formatCoordinate(label, value) {
|
||||
if (value === '' || value === null || value === undefined) return `${label}:-`
|
||||
return `${label}:${value}`
|
||||
},
|
||||
async fetchLocation(silent = false, force = false) {
|
||||
if (this.locating) return
|
||||
if (!force && this.visitForm.location && this.visitForm.lat && this.visitForm.lng) return
|
||||
this.locating = true
|
||||
if (!silent) {
|
||||
uni.showLoading({
|
||||
title: '定位中'
|
||||
})
|
||||
}
|
||||
try {
|
||||
const res = await getLocationOnly()
|
||||
this.visitForm.lat = res.latitude
|
||||
this.visitForm.lng = res.longitude
|
||||
this.visitForm.location = res.full || [res.province_str, res.city_str, res.area_str].filter(Boolean).join(' ')
|
||||
} catch (err) {
|
||||
if (!silent) {
|
||||
uni.showToast({
|
||||
title: '定位失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
} finally {
|
||||
if (!silent) uni.hideLoading()
|
||||
this.locating = false
|
||||
}
|
||||
},
|
||||
async uploadPhotos() {
|
||||
const remain = 9 - this.photos.length
|
||||
if (remain <= 0) {
|
||||
uni.showToast({
|
||||
title: '最多上传9张',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
const res = await chooseImg(remain, ['camera'])
|
||||
this.photos = [
|
||||
...this.photos,
|
||||
...res.map(item => item.path).filter(Boolean)
|
||||
]
|
||||
},
|
||||
removePhoto(index) {
|
||||
this.photos.splice(index, 1)
|
||||
},
|
||||
previewPhoto(index) {
|
||||
if (!this.photos.length) return
|
||||
uni.previewImage({
|
||||
urls: this.photos,
|
||||
current: this.photos[index] || this.photos[0]
|
||||
})
|
||||
},
|
||||
async submitVisit() {
|
||||
if (!this.visitForm.lat || !this.visitForm.lng || !this.visitForm.location) {
|
||||
uni.showToast({
|
||||
title: '请先获取定位',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.visitForm.chainId || !this.visitForm.chain) {
|
||||
uni.showToast({
|
||||
title: '请选择连锁',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
if (!this.visitForm.name || !this.visitForm.content || !this.photos.length || !this.visitForm.summary) {
|
||||
uni.showToast({
|
||||
title: '请填写完整信息',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
try {
|
||||
await visitAddReq({
|
||||
lat: this.visitForm.lat,
|
||||
lng: this.visitForm.lng,
|
||||
location: this.visitForm.location,
|
||||
chainId: this.visitForm.chainId,
|
||||
chain: this.visitForm.chain,
|
||||
name: this.visitForm.name,
|
||||
content: this.visitForm.content,
|
||||
photos: JSON.stringify(this.photos),
|
||||
summary: this.visitForm.summary
|
||||
})
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
icon: 'success'
|
||||
})
|
||||
const locationSnapshot = {
|
||||
lat: this.visitForm.lat,
|
||||
lng: this.visitForm.lng,
|
||||
location: this.visitForm.location,
|
||||
chainId: this.visitForm.chainId,
|
||||
chain: this.visitForm.chain
|
||||
}
|
||||
this.visitForm = {
|
||||
...this.buildForm(),
|
||||
...locationSnapshot
|
||||
}
|
||||
this.photos = []
|
||||
await this.fetchHistory()
|
||||
} catch (err) {
|
||||
uni.showToast({
|
||||
title: '提交失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
},
|
||||
async fetchHistory() {
|
||||
this.loading = true
|
||||
try {
|
||||
const {data} = await visitListReq()
|
||||
const list = Array.isArray(data) ? data : (data && data.list ? data.list : [])
|
||||
this.visitHistory = list.map(this.normalizeHistory)
|
||||
} catch (err) {
|
||||
uni.showToast({
|
||||
title: '记录加载失败',
|
||||
icon: 'none'
|
||||
})
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
normalizeHistory(item) {
|
||||
const statusValue = Number(item.status)
|
||||
let status = '待处理'
|
||||
let statusClass = 'pending'
|
||||
if (statusValue === 0) {
|
||||
status = '审核中'
|
||||
statusClass = 'pending'
|
||||
} else if (statusValue === 1) {
|
||||
status = '已通过'
|
||||
statusClass = 'success'
|
||||
} else if (statusValue === 2 || statusValue === 3) {
|
||||
status = '已驳回'
|
||||
statusClass = 'reject'
|
||||
} else if (item.statusText || item.status_text) {
|
||||
status = item.statusText || item.status_text
|
||||
statusClass = ''
|
||||
}
|
||||
return {
|
||||
id: item.id,
|
||||
name: item.name || item.visitName || '',
|
||||
content: item.content || item.remark || '',
|
||||
summary: item.summary || item.result || '',
|
||||
location: item.location || item.address || '',
|
||||
lat: item.lat || item.latitude || '',
|
||||
lng: item.lng || item.longitude || '',
|
||||
chainId: item.chainId || item.chain_id || item.chainCode || item.chain_code || '',
|
||||
chain: item.chain || item.chain_name || item.chain || item.chainAbb || '',
|
||||
photos: this.parsePhotos(item.photos || item.images || item.image),
|
||||
createdAt: item.createTime || item.createdAt || item.create_date || '',
|
||||
status,
|
||||
statusClass,
|
||||
expanded: false
|
||||
}
|
||||
},
|
||||
parsePhotos(value) {
|
||||
if (value === null || value === undefined || value === '') return []
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(item => {
|
||||
if (!item) return ''
|
||||
if (typeof item === 'string') return item
|
||||
return item.url || item.path || item.image || item.img || ''
|
||||
}).filter(Boolean)
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
const url = value.url || value.path || value.image || value.img
|
||||
return url ? [url] : []
|
||||
}
|
||||
const text = String(value).trim()
|
||||
if (!text) return []
|
||||
if (text.startsWith('[') || text.startsWith('{')) {
|
||||
try {
|
||||
return this.parsePhotos(JSON.parse(text))
|
||||
} catch (err) {
|
||||
}
|
||||
}
|
||||
if (text.includes(',')) {
|
||||
return text.split(',').map(item => item.trim()).filter(Boolean)
|
||||
}
|
||||
return [text]
|
||||
},
|
||||
toggleHistoryDetail(id) {
|
||||
this.visitHistory = this.visitHistory.map(item => {
|
||||
if (item.id !== id) return item
|
||||
return {
|
||||
...item,
|
||||
expanded: !item.expanded
|
||||
}
|
||||
})
|
||||
},
|
||||
previewHistoryPhoto(list = [], index = 0) {
|
||||
if (!Array.isArray(list) || !list.length) return
|
||||
uni.previewImage({
|
||||
urls: list,
|
||||
current: list[index] || list[0]
|
||||
})
|
||||
},
|
||||
normalizeChainOption(item, index) {
|
||||
const text = item.chain || item.chain || item.chainAbb || item.name || item.title || item.text || `连锁${index + 1}`
|
||||
const rawId = item.chainId ?? item.chain_id ?? item.id ?? item.chainCode ?? item.chain_code ?? ''
|
||||
const id = rawId === undefined || rawId === null || String(rawId).trim() === ''
|
||||
? `chain_${index}`
|
||||
: rawId
|
||||
return {
|
||||
id,
|
||||
text
|
||||
}
|
||||
},
|
||||
unwrapList(data) {
|
||||
if (Array.isArray(data)) return data
|
||||
if (!data || typeof data !== 'object') return []
|
||||
const keys = ['list', 'records', 'rows', 'items', 'data', 'result', 'chainList']
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const value = data[keys[i]]
|
||||
if (Array.isArray(value)) return value
|
||||
if (value && typeof value === 'object') {
|
||||
const nested = this.unwrapList(value)
|
||||
if (nested.length) return nested
|
||||
}
|
||||
}
|
||||
return [data]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.visit-page {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.page-hero {
|
||||
background: url('https://yaodongxiao.oss-cn-guangzhou.aliyuncs.com/20260126/462bfa04cf0eff8698884c38b9d17519.png') no-repeat top center / 100% auto;
|
||||
}
|
||||
|
||||
.intro-card {
|
||||
margin: 18rpx 20rpx 0;
|
||||
padding: 20rpx 18rpx;
|
||||
border-radius: 20rpx;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
box-shadow: 0 10rpx 20rpx rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.card-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
font-size: 28rpx;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
width: 6rpx;
|
||||
height: 30rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #2f78ff;
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
margin-top: 12rpx;
|
||||
font-size: 26rpx;
|
||||
color: #6b7280;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.block {
|
||||
margin: 18rpx 20rpx 0;
|
||||
}
|
||||
|
||||
.form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
padding: 12rpx 0;
|
||||
border-bottom: 1rpx solid #edf1f7;
|
||||
}
|
||||
|
||||
.form-row input {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.selector-picker {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.selector-picker .picker-value {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.location-row {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.location-box {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.picker-value {
|
||||
color: var(--text-main);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.picker-value.placeholder {
|
||||
color: var(--text-sub);
|
||||
}
|
||||
|
||||
.location-text {
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
line-height: 1.5;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.location-meta {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 4rpx;
|
||||
font-size: 22rpx;
|
||||
color: var(--text-sub);
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
flex-shrink: 0;
|
||||
margin-top: 2rpx;
|
||||
padding: 8rpx 18rpx;
|
||||
border-radius: 999rpx;
|
||||
background: #eef4ff;
|
||||
color: #2f78ff;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.textarea-row {
|
||||
align-items: flex-start;
|
||||
padding-top: 16rpx;
|
||||
}
|
||||
|
||||
.textarea-input {
|
||||
flex: 1;
|
||||
min-height: 120rpx;
|
||||
text-align: right;
|
||||
font-size: 26rpx;
|
||||
color: var(--text-main);
|
||||
}
|
||||
|
||||
.upload {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12rpx 0;
|
||||
border-bottom: 1rpx solid #edf1f7;
|
||||
}
|
||||
|
||||
.upload-title {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.upload-meta {
|
||||
color: var(--text-sub);
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.photo-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.photo-item {
|
||||
position: relative;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.photo-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.photo-remove {
|
||||
position: absolute;
|
||||
top: 8rpx;
|
||||
right: 8rpx;
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: #ffffff;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 22rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.submit {
|
||||
margin-top: 12rpx;
|
||||
padding: 14rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.history {
|
||||
padding: 12rpx 0;
|
||||
border-bottom: 1rpx solid #edf1f7;
|
||||
}
|
||||
|
||||
.history:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.history-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.history-main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.history-title {
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
.history-meta {
|
||||
color: var(--text-sub);
|
||||
font-size: 24rpx;
|
||||
margin-top: 6rpx;
|
||||
}
|
||||
|
||||
.history-side {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.history-status {
|
||||
font-weight: 700;
|
||||
color: #ff8354;
|
||||
}
|
||||
|
||||
.history-status.success {
|
||||
color: #22c55e;
|
||||
}
|
||||
|
||||
.history-status.reject {
|
||||
color: #ff3b30;
|
||||
}
|
||||
|
||||
.history-arrow {
|
||||
transform: rotate(0deg);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.history-arrow.open {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.history-detail {
|
||||
margin-top: 10rpx;
|
||||
padding: 12rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.history-line {
|
||||
margin-top: 6rpx;
|
||||
font-size: 24rpx;
|
||||
color: #4b5563;
|
||||
line-height: 1.6;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.history-line:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.history-photo-list {
|
||||
margin-top: 10rpx;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10rpx;
|
||||
}
|
||||
|
||||
.history-photo-item {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.history-photo-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.empty {
|
||||
color: var(--text-sub);
|
||||
text-align: center;
|
||||
padding: 16rpx 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user