feat: 报告填写页新增服务过程中区块,支持照片+视频上传;报告展示页新增过程中媒体展示;前后端mediaType字段支持
This commit is contained in:
parent
a1b3780ab9
commit
525223be7f
@ -142,6 +142,53 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 服务过程中(照片+视频) -->
|
||||||
|
<view v-if="duringMedia.length > 0" class="section-gap">
|
||||||
|
<view class="during-section">
|
||||||
|
<view class="during-title">
|
||||||
|
<view class="during-title-dot"></view>
|
||||||
|
<text>服务过程中</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 照片 -->
|
||||||
|
<view v-if="duringPhotoItems.length > 0" class="during-group">
|
||||||
|
<view class="during-group-label">照片 {{ duringPhotoItems.length }} 张</view>
|
||||||
|
<view class="during-grid">
|
||||||
|
<view
|
||||||
|
v-for="(url, idx) in duringPhotoItems"
|
||||||
|
:key="'dp-' + idx"
|
||||||
|
class="during-thumb"
|
||||||
|
@click="previewPhotos('during-photo', idx)"
|
||||||
|
>
|
||||||
|
<image :src="imgUrl(url)" class="during-thumb-img" mode="aspectFill" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 视频 -->
|
||||||
|
<view v-if="duringVideoItems.length > 0" class="during-group">
|
||||||
|
<view class="during-group-label">视频 {{ duringVideoItems.length }} 个</view>
|
||||||
|
<view class="during-grid">
|
||||||
|
<view
|
||||||
|
v-for="(url, idx) in duringVideoItems"
|
||||||
|
:key="'dv-' + idx"
|
||||||
|
class="during-thumb during-thumb--video"
|
||||||
|
@click="playVideo(imgUrl(url))"
|
||||||
|
>
|
||||||
|
<video
|
||||||
|
:src="imgUrl(url)"
|
||||||
|
class="during-thumb-img"
|
||||||
|
:show-center-play-btn="true"
|
||||||
|
:show-play-btn="true"
|
||||||
|
objectFit="cover"
|
||||||
|
:enable-progress-gesture="false"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 宠主问候 -->
|
<!-- 宠主问候 -->
|
||||||
<view v-if="!isStaff" class="greeting-card">
|
<view v-if="!isStaff" class="greeting-card">
|
||||||
<text class="greeting-text">
|
<text class="greeting-text">
|
||||||
@ -235,12 +282,24 @@ const isStaff = computed(() => isLoggedIn())
|
|||||||
|
|
||||||
const beforePhotos = computed(() => {
|
const beforePhotos = computed(() => {
|
||||||
if (!reportData.value?.beforePhotos) return []
|
if (!reportData.value?.beforePhotos) return []
|
||||||
return reportData.value.beforePhotos
|
// 支持新旧两种格式:旧版是 string[],新版是 {url, mediaType}[]
|
||||||
|
const raw = reportData.value.beforePhotos
|
||||||
|
if (raw.length === 0) return []
|
||||||
|
if (typeof raw[0] === 'string') return raw
|
||||||
|
return raw.map(item => item.url)
|
||||||
})
|
})
|
||||||
const afterPhotos = computed(() => {
|
const afterPhotos = computed(() => {
|
||||||
if (!reportData.value?.afterPhotos) return []
|
if (!reportData.value?.afterPhotos) return []
|
||||||
return reportData.value.afterPhotos
|
const raw = reportData.value.afterPhotos
|
||||||
|
if (raw.length === 0) return []
|
||||||
|
if (typeof raw[0] === 'string') return raw
|
||||||
|
return raw.map(item => item.url)
|
||||||
})
|
})
|
||||||
|
const duringMedia = computed(() => {
|
||||||
|
return reportData.value?.duringMedia || []
|
||||||
|
})
|
||||||
|
const duringPhotoItems = computed(() => duringMedia.value.filter(i => i.mediaType !== 'video').map(i => i.url))
|
||||||
|
const duringVideoItems = computed(() => duringMedia.value.filter(i => i.mediaType === 'video').map(i => i.url))
|
||||||
const beforePhotoUrls = computed(() => beforePhotos.value.map((item) => imgUrl(item)))
|
const beforePhotoUrls = computed(() => beforePhotos.value.map((item) => imgUrl(item)))
|
||||||
const afterPhotoUrls = computed(() => afterPhotos.value.map((item) => imgUrl(item)))
|
const afterPhotoUrls = computed(() => afterPhotos.value.map((item) => imgUrl(item)))
|
||||||
const beforeMorePhotos = computed(() => beforePhotos.value.slice(1))
|
const beforeMorePhotos = computed(() => beforePhotos.value.slice(1))
|
||||||
@ -282,6 +341,13 @@ const loadReport = async () => {
|
|||||||
else notFound.value = true
|
else notFound.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const playVideo = (url) => {
|
||||||
|
if (!url) return
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/video-player/videoPlayer?url=${encodeURIComponent(url)}`}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const goHome = () => uni.reLaunch({ url: '/pages/home/Home' })
|
const goHome = () => uni.reLaunch({ url: '/pages/home/Home' })
|
||||||
|
|
||||||
const callStore = () => {
|
const callStore = () => {
|
||||||
@ -304,8 +370,12 @@ const navToStore = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const previewPhotos = (group, index = 0) => {
|
const previewPhotos = (group, index = 0) => {
|
||||||
const urls = group === 'before' ? beforePhotoUrls.value : afterPhotoUrls.value
|
let urls
|
||||||
if (!urls.length) return
|
if (group === 'before') urls = beforePhotoUrls.value
|
||||||
|
else if (group === 'after') urls = afterPhotoUrls.value
|
||||||
|
else if (group === 'during-photo') urls = duringPhotoItems.value.map(imgUrl)
|
||||||
|
else if (group === 'during-video') urls = duringVideoItems.value.map(imgUrl)
|
||||||
|
if (!urls || !urls.length) return
|
||||||
const current = urls[Math.max(0, Math.min(index, urls.length - 1))]
|
const current = urls[Math.max(0, Math.min(index, urls.length - 1))]
|
||||||
uni.previewImage({
|
uni.previewImage({
|
||||||
urls,
|
urls,
|
||||||
@ -993,4 +1063,55 @@ onMounted(() => loadReport())
|
|||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
letter-spacing: 0.5px;
|
letter-spacing: 0.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 过程中区块 */
|
||||||
|
.section-gap {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
.during-section {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 18px 18px 4px;
|
||||||
|
}
|
||||||
|
.during-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #1a1a1a;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
.during-title-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #7c5ce9;
|
||||||
|
}
|
||||||
|
.during-group {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
.during-group-label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #999993;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
.during-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.during-thumb {
|
||||||
|
position: relative;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f0f0ee;
|
||||||
|
}
|
||||||
|
.during-thumb-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -62,11 +62,11 @@
|
|||||||
<text>服务前</text>
|
<text>服务前</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="photo-grid">
|
<view class="photo-grid">
|
||||||
<view v-for="(img, idx) in report.before" :key="'b'+idx" class="photo-thumb">
|
<view v-for="(item, idx) in report.beforeMedia" :key="'b'+idx" class="photo-thumb">
|
||||||
<image :src="img" class="thumb-img" mode="aspectFill" />
|
<image :src="item.url" class="thumb-img" mode="aspectFill" />
|
||||||
<view class="thumb-del" @click="removePhoto('before', idx)">✕</view>
|
<view class="thumb-del" @click="removeMedia('beforeMedia', idx)">✕</view>
|
||||||
</view>
|
</view>
|
||||||
<view v-if="report.before.length < 4" class="photo-add" @click="uploadPhoto('before')">
|
<view v-if="report.beforeMedia.length < 4" class="photo-add" @click="uploadMedia('beforeMedia', 'photo')">
|
||||||
<AppIcon name="camera" :size="20" color="#bbbbb5" />
|
<AppIcon name="camera" :size="20" color="#bbbbb5" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -80,11 +80,11 @@
|
|||||||
<text>服务后</text>
|
<text>服务后</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="photo-grid">
|
<view class="photo-grid">
|
||||||
<view v-for="(img, idx) in report.after" :key="'a'+idx" class="photo-thumb">
|
<view v-for="(item, idx) in report.afterMedia" :key="'a'+idx" class="photo-thumb">
|
||||||
<image :src="img" class="thumb-img" mode="aspectFill" />
|
<image :src="item.url" class="thumb-img" mode="aspectFill" />
|
||||||
<view class="thumb-del" @click="removePhoto('after', idx)">✕</view>
|
<view class="thumb-del" @click="removeMedia('afterMedia', idx)">✕</view>
|
||||||
</view>
|
</view>
|
||||||
<view v-if="report.after.length < 4" class="photo-add" @click="uploadPhoto('after')">
|
<view v-if="report.afterMedia.length < 4" class="photo-add" @click="uploadMedia('afterMedia', 'photo')">
|
||||||
<AppIcon name="camera" :size="20" color="#bbbbb5" />
|
<AppIcon name="camera" :size="20" color="#bbbbb5" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -92,6 +92,48 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 服务过程中 -->
|
||||||
|
<view class="section">
|
||||||
|
<view class="section-head">
|
||||||
|
<text class="section-label">服务过程中</text>
|
||||||
|
<text class="section-hint">照片或视频,记录服务细节</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="during-actions">
|
||||||
|
<view class="during-action-btn" @click="uploadMedia('duringMedia', 'photo')">
|
||||||
|
<AppIcon name="camera" :size="18" color="#666660" />
|
||||||
|
<text>上传照片</text>
|
||||||
|
</view>
|
||||||
|
<view class="during-action-btn during-action-btn--video" @click="uploadMedia('duringMedia', 'video')">
|
||||||
|
<AppIcon name="video" :size="18" color="#666660" />
|
||||||
|
<text>拍摄视频</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="report.duringMedia.length > 0" class="during-grid">
|
||||||
|
<view v-for="(item, idx) in report.duringMedia" :key="'d'+idx" class="photo-thumb">
|
||||||
|
<image v-if="item.mediaType === 'photo'" :src="item.url" class="thumb-img" mode="aspectFill" />
|
||||||
|
<video
|
||||||
|
v-else
|
||||||
|
:src="item.url"
|
||||||
|
class="thumb-img"
|
||||||
|
:show-center-play-btn="false"
|
||||||
|
:show-play-btn="false"
|
||||||
|
objectFit="cover"
|
||||||
|
/>
|
||||||
|
<!-- 视频角标 -->
|
||||||
|
<view v-if="item.mediaType === 'video'" class="video-badge">
|
||||||
|
<text>视频</text>
|
||||||
|
</view>
|
||||||
|
<view class="thumb-del" @click="removeMedia('duringMedia', idx)">✕</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view v-if="report.duringMedia.length === 0" class="during-empty">
|
||||||
|
<text>暂无过程中记录</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 备注 -->
|
<!-- 备注 -->
|
||||||
<view class="section">
|
<view class="section">
|
||||||
<view class="section-head">
|
<view class="section-head">
|
||||||
@ -145,7 +187,17 @@ const navSafeStyle = (() => {
|
|||||||
return `padding-top:${statusBarHeight}px;height:${navHeight}px;`
|
return `padding-top:${statusBarHeight}px;height:${navHeight}px;`
|
||||||
})()
|
})()
|
||||||
|
|
||||||
const report = ref({ petName: '', serviceType: '', appointmentTime: '', before: [], after: [], remark: '' })
|
// beforeMedia / afterMedia: [{url, mediaType}] mediaType 固定为 "photo"
|
||||||
|
// duringMedia: [{url, mediaType}] mediaType 可以是 "photo" 或 "video"
|
||||||
|
const report = ref({
|
||||||
|
petName: '',
|
||||||
|
serviceType: '',
|
||||||
|
appointmentTime: '',
|
||||||
|
beforeMedia: [],
|
||||||
|
afterMedia: [],
|
||||||
|
duringMedia: [],
|
||||||
|
remark: ''
|
||||||
|
})
|
||||||
const serviceTypes = ref([])
|
const serviceTypes = ref([])
|
||||||
const currentAppointmentId = ref(null)
|
const currentAppointmentId = ref(null)
|
||||||
const submitting = ref(false)
|
const submitting = ref(false)
|
||||||
@ -160,43 +212,103 @@ const loadServiceTypes = async () => {
|
|||||||
if (res.code === 200) serviceTypes.value = res.data
|
if (res.code === 200) serviceTypes.value = res.data
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadPhoto = (field) => {
|
/**
|
||||||
const currentCount = report.value[field].length
|
* 上传媒体文件
|
||||||
if (currentCount >= 4) return uni.showToast({ title: '最多上传4张', icon: 'none' })
|
* @param {string} field - beforeMedia | afterMedia | duringMedia
|
||||||
uni.chooseImage({
|
* @param {string} mediaType - photo | video
|
||||||
count: 4 - currentCount,
|
*/
|
||||||
success: (res) => {
|
const uploadMedia = (field, mediaType) => {
|
||||||
const tempPaths = res.tempFilePaths
|
const maxTotal = 12 // 全局最多12条
|
||||||
uni.showLoading({ title: '上传中...' })
|
if (report.value[field].length >= maxTotal) {
|
||||||
let failCount = 0
|
return uni.showToast({ title: `最多上传${maxTotal}个`, icon: 'none' })
|
||||||
const tasks = tempPaths.map(tempPath => {
|
}
|
||||||
return new Promise((resolve) => {
|
const remain = maxTotal - report.value[field].length
|
||||||
uni.uploadFile({
|
|
||||||
url: `${BASE_URL}/upload/image`,
|
if (mediaType === 'video') {
|
||||||
filePath: tempPath,
|
// 拍摄/选择视频
|
||||||
name: 'file',
|
uni.chooseMedia({
|
||||||
success: (uploadRes) => {
|
count: Math.min(remain, 4),
|
||||||
try {
|
mediaType: ['video'],
|
||||||
const data = JSON.parse(uploadRes.data)
|
success: (res) => {
|
||||||
if (data.code === 200) {
|
const tempFiles = res.tempFiles
|
||||||
report.value[field].push(imgUrl(data.data.url))
|
uni.showLoading({ title: '上传中...' })
|
||||||
} else { failCount++ }
|
let failCount = 0
|
||||||
} catch (e) { failCount++ }
|
const tasks = tempFiles.map(f => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const sizeMB = (f.size || 0) / 1024 / 1024
|
||||||
|
if (sizeMB > 100) {
|
||||||
|
failCount++
|
||||||
|
uni.showToast({ title: '视频不能超过100MB', icon: 'none' })
|
||||||
resolve()
|
resolve()
|
||||||
},
|
return
|
||||||
fail: () => { failCount++; resolve() }
|
}
|
||||||
|
uni.uploadFile({
|
||||||
|
url: `${BASE_URL}/upload/image`,
|
||||||
|
filePath: f.tempFilePath,
|
||||||
|
name: 'file',
|
||||||
|
success: (uploadRes) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(uploadRes.data)
|
||||||
|
if (data.code === 200) {
|
||||||
|
report.value[field].push({ url: imgUrl(data.data.url), mediaType: 'video' })
|
||||||
|
} else {
|
||||||
|
failCount++
|
||||||
|
}
|
||||||
|
} catch (e) { failCount++ }
|
||||||
|
resolve()
|
||||||
|
},
|
||||||
|
fail: () => { failCount++; resolve() }
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
Promise.all(tasks).then(() => {
|
||||||
Promise.all(tasks).then(() => {
|
uni.hideLoading()
|
||||||
uni.hideLoading()
|
if (failCount > 0) uni.showToast({ title: `${failCount}个上传失败`, icon: 'none' })
|
||||||
if (failCount > 0) uni.showToast({ title: `${failCount}张上传失败`, icon: 'none' })
|
})
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 上传照片
|
||||||
|
const fieldMax = 4
|
||||||
|
if (report.value[field].length >= fieldMax) {
|
||||||
|
return uni.showToast({ title: '最多上传4张', icon: 'none' })
|
||||||
}
|
}
|
||||||
})
|
const count = Math.min(fieldMax - report.value[field].length, remain, 4)
|
||||||
|
uni.chooseImage({
|
||||||
|
count,
|
||||||
|
success: (res) => {
|
||||||
|
const tempPaths = res.tempFilePaths
|
||||||
|
uni.showLoading({ title: '上传中...' })
|
||||||
|
let failCount = 0
|
||||||
|
const tasks = tempPaths.map(tempPath => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
uni.uploadFile({
|
||||||
|
url: `${BASE_URL}/upload/image`,
|
||||||
|
filePath: tempPath,
|
||||||
|
name: 'file',
|
||||||
|
success: (uploadRes) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(uploadRes.data)
|
||||||
|
if (data.code === 200) {
|
||||||
|
report.value[field].push({ url: imgUrl(data.data.url), mediaType: 'photo' })
|
||||||
|
} else { failCount++ }
|
||||||
|
} catch (e) { failCount++ }
|
||||||
|
resolve()
|
||||||
|
},
|
||||||
|
fail: () => { failCount++; resolve() }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Promise.all(tasks).then(() => {
|
||||||
|
uni.hideLoading()
|
||||||
|
if (failCount > 0) uni.showToast({ title: `${failCount}张上传失败`, icon: 'none' })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const removePhoto = (field, idx) => { report.value[field].splice(idx, 1) }
|
const removeMedia = (field, idx) => { report.value[field].splice(idx, 1) }
|
||||||
|
|
||||||
const onServiceConfirm = (e) => {
|
const onServiceConfirm = (e) => {
|
||||||
report.value.serviceType = serviceColumns.value[e.detail.value].value
|
report.value.serviceType = serviceColumns.value[e.detail.value].value
|
||||||
@ -238,14 +350,19 @@ const submitReport = async () => {
|
|||||||
if (!report.value.serviceType) return uni.showToast({ title: '请选择服务类型', icon: 'none' })
|
if (!report.value.serviceType) return uni.showToast({ title: '请选择服务类型', icon: 'none' })
|
||||||
if (!report.value.appointmentTime) return uni.showToast({ title: '请选择服务时间', icon: 'none' })
|
if (!report.value.appointmentTime) return uni.showToast({ title: '请选择服务时间', icon: 'none' })
|
||||||
submitting.value = true
|
submitting.value = true
|
||||||
|
|
||||||
// 构建图片列表
|
// 构建图片列表
|
||||||
const images = []
|
const images = []
|
||||||
report.value.before.forEach((url, i) => {
|
report.value.beforeMedia.forEach((item, i) => {
|
||||||
images.push({ photoUrl: url, photoType: 'before', sortOrder: i })
|
images.push({ photoUrl: item.url, photoType: 'before', mediaType: item.mediaType || 'photo', sortOrder: i })
|
||||||
})
|
})
|
||||||
report.value.after.forEach((url, i) => {
|
report.value.afterMedia.forEach((item, i) => {
|
||||||
images.push({ photoUrl: url, photoType: 'after', sortOrder: i })
|
images.push({ photoUrl: item.url, photoType: 'after', mediaType: item.mediaType || 'photo', sortOrder: i })
|
||||||
})
|
})
|
||||||
|
report.value.duringMedia.forEach((item, i) => {
|
||||||
|
images.push({ photoUrl: item.url, photoType: 'during', mediaType: item.mediaType || 'photo', sortOrder: i })
|
||||||
|
})
|
||||||
|
|
||||||
const payload = {
|
const payload = {
|
||||||
appointmentId: currentAppointmentId.value || null,
|
appointmentId: currentAppointmentId.value || null,
|
||||||
userId: userInfo.id,
|
userId: userInfo.id,
|
||||||
@ -255,13 +372,14 @@ const submitReport = async () => {
|
|||||||
remark: report.value.remark,
|
remark: report.value.remark,
|
||||||
images
|
images
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await createReport(payload)
|
const res = await createReport(payload)
|
||||||
submitting.value = false
|
submitting.value = false
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
const token = res.data.reportToken
|
const token = res.data.reportToken
|
||||||
uni.showToast({ title: '已生成报告', icon: 'success' })
|
uni.showToast({ title: '已生成报告', icon: 'success' })
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
report.value = { petName: '', serviceType: '', appointmentTime: '', before: [], after: [], remark: '' }
|
report.value = { petName: '', serviceType: '', appointmentTime: '', beforeMedia: [], afterMedia: [], duringMedia: [], remark: '' }
|
||||||
currentAppointmentId.value = null
|
currentAppointmentId.value = null
|
||||||
uni.navigateTo({ url: `/pages/report-view/reportView?token=${token}` })
|
uni.navigateTo({ url: `/pages/report-view/reportView?token=${token}` })
|
||||||
}, 800)
|
}, 800)
|
||||||
@ -423,6 +541,7 @@ onMounted(async () => {
|
|||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background: #f0f0ee;
|
||||||
}
|
}
|
||||||
.thumb-img {
|
.thumb-img {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -453,6 +572,69 @@ onMounted(async () => {
|
|||||||
background: #fafaf8;
|
background: #fafaf8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 过程中区块 */
|
||||||
|
.during-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
.during-action-btn {
|
||||||
|
flex: 1;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 12px;
|
||||||
|
border: 1.5px solid #ebebea;
|
||||||
|
background: #fafaf8;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #666660;
|
||||||
|
}
|
||||||
|
.during-action-btn:active {
|
||||||
|
background: #f0f0ee;
|
||||||
|
}
|
||||||
|
.during-action-btn--video {
|
||||||
|
border-color: #e0d8f5;
|
||||||
|
background: #f8f5ff;
|
||||||
|
}
|
||||||
|
.during-action-btn--video:active {
|
||||||
|
background: #f0ecff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.during-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-badge {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
left: 5px;
|
||||||
|
height: 18px;
|
||||||
|
padding: 0 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: rgba(0,0,0,0.55);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.video-badge text {
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #fff;
|
||||||
|
letter-spacing: 0.3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.during-empty {
|
||||||
|
padding: 16px 0 4px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #bbbbb5;
|
||||||
|
}
|
||||||
|
|
||||||
/* 备注 */
|
/* 备注 */
|
||||||
.form-textarea {
|
.form-textarea {
|
||||||
background: #f5f5f2;
|
background: #f5f5f2;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user