From e56792f78e4df0df2f12552d1a61dd8ca1db5c67 Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期一, 27 四月 2026 22:26:28 +0800
Subject: [PATCH] app
---
app/pages/order/order.vue | 932 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 926 insertions(+), 6 deletions(-)
diff --git a/app/pages/order/order.vue b/app/pages/order/order.vue
index 94d9b9c..faa455c 100644
--- a/app/pages/order/order.vue
+++ b/app/pages/order/order.vue
@@ -1,6 +1,146 @@
<template>
- <view>
-
+ <view class="order-page">
+ <view class="order-page__nav" :style="{ paddingTop: statusBarHeight + 'px' }">
+ <view class="order-page__nav-inner">
+ <text class="order-page__nav-title">鎴戠殑璁㈠崟</text>
+ </view>
+ </view>
+
+ <view class="order-page__tabs" :style="{ top: navHeight + 'px' }">
+ <view v-for="tab in displayTabs" :key="tab.value" class="order-page__tab" :class="{ 'order-page__tab--active': activeTab === tab.value }" @click="activeTab = tab.value">
+ <text class="order-page__tab-text">{{ tab.label }}</text>
+ <view v-if="activeTab === tab.value" class="order-page__tab-line"></view>
+ </view>
+ </view>
+
+ <scroll-view class="order-page__body" scroll-y :style="bodyStyle">
+ <view class="order-page__list">
+ <view v-for="(item, index) in orders" :key="item.id" class="order-card" @click="goToOrderDetail(item, index)">
+ <view class="order-card__head">
+ <view class="order-card__head-left">
+ <image class="order-card__badge-icon" :src="getBadgeIcon(item)" mode="widthFix"></image>
+ <text class="order-card__time-text">涓嬪崟鏃堕棿锛歿{ item.createTime }}</text>
+ </view>
+ <text class="order-card__status" :class="{ 'order-card__status--highlight': item.status === 3 || item.status === 4 }">{{ getStatusText(item.status) }}</text>
+ </view>
+
+ <view class="order-card__route-item">
+ <view class="order-card__point order-card__point--pickup">鍙�</view>
+ <view class="order-card__route-texts">
+ <text class="order-card__route-title">{{ item.takeName }}</text>
+ <text class="order-card__route-desc">{{ item.takeAddress }}</text>
+ </view>
+ </view>
+
+ <view class="order-card__route-item order-card__route-item--delivery">
+ <view class="order-card__point order-card__point--delivery">閫�</view>
+ <view class="order-card__route-texts">
+ <text class="order-card__route-title">{{ item.depositShopName }}</text>
+ <text class="order-card__route-desc">{{ item.depositShopAddress }}</text>
+ </view>
+ </view>
+
+ <view class="order-card__footer">
+ <view class="order-card__arrival">
+ <image class="order-card__clock" src="/static/image/ic_clock@2x.png" mode="aspectFit"></image>
+ <text class="order-card__arrival-text">鍓╀綑{{ item.remainMinutes }}鍒嗛挓</text>
+ </view>
+ <view class="order-card__price-wrap">
+ <text class="order-card__price">楼{{ (item.driverFee / 100).toFixed(2) }}</text>
+ </view>
+ </view>
+
+ <view v-if="getActions(item).length" class="order-card__actions">
+ <view></view>
+ <view style="display: flex;flex-wrap: wrap;gap: 20rpx;">
+ <button
+ v-for="action in getActions(item)"
+ :key="action.text"
+ class="order-card__action-btn"
+ :class="['order-card__action-btn--' + action.type, { 'order-card__action-btn--primary-fill': action.fill }]"
+ hover-class="order-card__action-btn--hover"
+ @click.stop="handleAction(item, action)"
+ >
+ {{ action.text }}
+ </button>
+ </view>
+
+ </view>
+ </view>
+
+ <view v-if="orders.length === 0 && !loading" class="order-page__empty">
+ <image class="order-page__empty-icon" src="/static/image/default_nodata@2x.png" mode="aspectFit"></image>
+ </view>
+
+ <view v-if="loading" class="order-page__loading">
+ <text>鍔犺浇涓�...</text>
+ </view>
+ </view>
+ </scroll-view>
+
+ <u-modal
+ :show="showCancelModal"
+ showCancelButton
+ @cancel="showCancelModal = false"
+ cancelColor="#666666"
+ confirmColor="#0055FF"
+ title="鍙栨秷璁㈠崟纭"
+ @confirm="confirmCancelOrder">
+ <view style="text-align: center;color: #333333;font-size: 28rpx;font-weight: 400;">
+ 鎮ㄤ粖鏃ヨ繕鍙彇娑� {{ cancelRemain }} 娆¤鍗曪紝娆℃暟鐢ㄥ敖鍚庝粖鏃ュ皢鏃犳硶鎺ュ崟锛屾槸鍚︾‘璁ゅ彇娑堬紵
+ </view>
+ </u-modal>
+
+ <u-popup :show="showQRPopup" round="20" mode="bottom">
+ <view class="qrcode">
+ <view class="qrcode-title">
+ <image src="/static/image/ic_close@2x.png" mode="widthFix" style="opacity: 0;"></image>
+ <text>{{ selectedOrder && selectedOrder.status === 4 ? '瀛樹欢鐮�' : '鍙栬揣鐮�' }}</text>
+ <image src="/static/image/ic_close@2x.png" mode="widthFix" @click="showQRPopup = false"></image>
+ </view>
+ <view class="qrcode-image">
+ <image v-if="selectedOrder && selectedOrder.driverVerifyCode" :src="'https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=' + selectedOrder.driverVerifyCode" mode="widthFix"></image>
+ </view>
+ <view class="qrcode-btn" hover-class="qrcode-btn--hover" @click="showQRPopup = false">鍏抽棴</view>
+ </view>
+ </u-popup>
+
+ <u-popup :show="showPhotoPopup" round="20" mode="bottom">
+ <view class="photo-popup">
+ <view class="photo-popup__header">
+ <view class="photo-popup__placeholder"></view>
+ <text class="photo-popup__title">{{ photoPopupTitle }}</text>
+ <image class="photo-popup__close" src="/static/image/ic_close2@2x.png" mode="aspectFit" @click="closePhotoPopup"></image>
+ </view>
+
+ <view class="photo-popup__section">
+ <view class="photo-popup__label-row">
+ <text class="photo-popup__label">{{ photoPopupLabel }}</text>
+ <text class="photo-popup__required">*</text>
+ <text class="photo-popup__hint">鏈�澶�3寮犵収鐗�</text>
+ </view>
+
+ <view class="photo-popup__photos">
+ <view v-for="(photo, index) in uploadedPhotos" :key="index" class="photo-popup__preview-card">
+ <image class="photo-popup__preview-image" :src="photo" mode="aspectFill"></image>
+ <view class="photo-popup__preview-mask" @click="deletePhoto(index)">
+ <text class="photo-popup__preview-delete">鍒犻櫎</text>
+ </view>
+ </view>
+ <view v-if="uploadedPhotos.length < 3" class="photo-popup__upload-btn" @click="choosePhoto">
+ <image src="/static/image/btn_upload2@2x.png" mode="aspectFit"></image>
+ </view>
+ </view>
+ </view>
+
+ <view class="photo-popup__section photo-popup__section--remark">
+ <text class="photo-popup__remark-title">澶囨敞淇℃伅</text>
+ <textarea v-model="photoRemark" class="photo-popup__textarea" maxlength="200" placeholder="璇疯緭鍏�" placeholder-style="color: #c7cbd3;" />
+ </view>
+
+ <button class="photo-popup__submit" hover-class="photo-popup__submit--hover" @click="submitPhotoPopup">{{ photoPopupSubmitText }}</button>
+ </view>
+ </u-popup>
</view>
</template>
@@ -8,12 +148,792 @@
export default {
data() {
return {
-
- };
+ statusBarHeight: 0,
+ navHeight: 0,
+ activeTab: null,
+ tabs: [
+ { label: '鍏ㄩ儴', value: null },
+ { label: '寰呭彇璐�', value: 3 },
+ { label: '閰嶉�佷腑', value: 4 },
+ { label: '宸插畬鎴�', value: 7 }
+ ],
+ orders: [],
+ page: 1,
+ hasMore: true,
+ loading: false,
+ showCancelModal: false,
+ showQRPopup: false,
+ showPhotoPopup: false,
+ selectedOrder: null,
+ cancelRemain: 0,
+ photoPopupMode: '',
+ photoRemark: '',
+ uploadedPhotos: [],
+ activeOrderCount: null
+ }
+ },
+ computed: {
+ displayTabs() {
+ return this.tabs.map((tab) => {
+ let count = null
+ if (tab.value === 3) {
+ count = this.activeOrderCount?.grabbedCount
+ } else if (tab.value === 4) {
+ count = this.activeOrderCount?.deliveringCount
+ }
+ if (count) {
+ return {
+ ...tab,
+ label: `${tab.label} ${count}`
+ }
+ }
+ return tab
+ })
+ },
+
+ bodyStyle() {
+ return {
+ marginTop: this.navHeight + uni.upx2px(88) + 'px',
+ height: `calc(100vh - ${this.navHeight + uni.upx2px(88)}px)`
+ }
+ },
+ photoPopupTitle() {
+ return this.photoPopupMode === 'deliver' ? '鎷嶇収閫佽揪' : '鎷嶇収鍙栬揣'
+ },
+ photoPopupLabel() {
+ return this.photoPopupMode === 'deliver' ? '鎷嶆憚閫佽揪鐓х墖' : '鎷嶆憚鍙栬揣鐓х墖'
+ },
+ photoPopupSubmitText() {
+ return this.photoPopupMode === 'deliver' ? '纭閫佽揪' : '纭鍙栬揣'
+ }
+ },
+ onLoad() {
+ const systemInfo = uni.getSystemInfoSync()
+ this.statusBarHeight = systemInfo.statusBarHeight || 0
+ this.navHeight = this.statusBarHeight + uni.upx2px(88)
+ this.getOrderList()
+ },
+ onShow() {
+ this.getActiveOrderCount()
+ },
+ onReachBottom() {
+ if (!this.hasMore || this.loading) return
+ this.page++
+ this.getOrderList()
+ },
+ watch: {
+ activeTab() {
+ this.page = 1
+ this.hasMore = true
+ this.orders = []
+ this.getOrderList()
+ }
+ },
+ methods: {
+ getActiveOrderCount() {
+ this.$u.api.activeOrderCount().then(res => {
+ if (res.code === 200) {
+ this.activeOrderCount = res.data
+ } else {
+ this.activeOrderCount = null
+ }
+ }).catch(() => {
+ this.activeOrderCount = null
+ })
+ },
+ getBadgeIcon(item) {
+ return item.isUrgent ? '/static/image/ic_jisuda@2x.png' : '/static/image/ic_biaosuda@2x.png'
+ },
+ getStatusText(status) {
+ const map = {
+ 2: '寰呮帴鍗�',
+ 3: '寰呭彇璐�',
+ 4: '閰嶉�佷腑',
+ 5: '宸插畬鎴�',
+ 7: '宸插畬鎴�',
+ 99: '宸插彇娑�'
+ }
+ return map[status] || ''
+ },
+ getActions(item) {
+ if (item.status === 3) {
+ return [
+ { text: '鍙栨秷璁㈠崟', type: 'light', fill: false },
+ { text: '鍙栬揣鐮�', type: 'primary', fill: false },
+ { text: '鎷嶇収鍙栬揣', type: 'primary', fill: true }
+ ]
+ }
+ if (item.status === 4 && item.takeShopId) {
+ return [
+ { text: '瀛樹欢鐮�', type: 'primary', fill: false }
+ ]
+ }
+ if (item.status === 4 && !item.takeShopId) {
+ return [
+ { text: '鎷嶇収閫佽揪', type: 'primary', fill: true }
+ ]
+ }
+ return []
+ },
+ getOrderList() {
+ if (this.loading) return
+ this.loading = true
+ this.$u.api.orderPage({
+ capacity: 10,
+ page: this.page,
+ model: {
+ status: this.activeTab
+ }
+ }).then(res => {
+ if (res.code === 200) {
+ const list = res.data.records || []
+ if (this.page === 1) {
+ this.orders = list
+ } else {
+ this.orders = [...this.orders, ...list]
+ }
+ this.hasMore = list.length >= 10
+ }
+ }).finally(() => {
+ this.loading = false
+ })
+ },
+ goToOrderDetail(item, index) {
+ uni.navigateTo({
+ url: `/pages/order-detail/order-detail?id=${item.id}`
+ })
+ },
+ handleAction(item, action) {
+ const text = action.text
+ if (text === '鍙栨秷璁㈠崟') {
+ this.handleCancelOrder(item)
+ } else if (text === '鍙栬揣鐮�' || text === '瀛樹欢鐮�') {
+ this.handleShowQRCode(item)
+ } else if (text === '鎷嶇収鍙栬揣') {
+ this.handlePhotoPickup(item)
+ } else if (text === '鎷嶇収閫佽揪') {
+ this.handlePhotoDeliver(item)
+ }
+ },
+ handleCancelOrder(item) {
+ this.selectedOrder = item
+ this.$u.api.cancelLimit().then(res => {
+ if (res.code === 200) {
+ this.cancelRemain = res.data.remain
+ }
+ }).finally(() => {
+ this.showCancelModal = true
+ })
+ },
+ confirmCancelOrder() {
+ if (!this.selectedOrder) return
+ this.$u.api.cancelOrder({ orderId: this.selectedOrder.id }).then(res => {
+ this.showCancelModal = false
+ if (res.code === 200) {
+ uni.showToast({ title: '鍙栨秷鎴愬姛', icon: 'success' })
+ this.getOrderList()
+ this.getActiveOrderCount()
+ } else {
+ uni.showToast({ title: res.message || '鍙栨秷澶辫触', icon: 'none' })
+ }
+ }).catch(() => {
+ this.showCancelModal = false
+ })
+ },
+ handleShowQRCode(item) {
+ this.selectedOrder = item
+ this.showQRPopup = true
+ },
+ handlePhotoPickup(item) {
+ this.selectedOrder = item
+ this.photoPopupMode = 'pickup'
+ this.uploadedPhotos = []
+ this.photoRemark = ''
+ this.showPhotoPopup = true
+ },
+ handlePhotoDeliver(item) {
+ this.selectedOrder = item
+ this.photoPopupMode = 'deliver'
+ this.uploadedPhotos = []
+ this.photoRemark = ''
+ this.showPhotoPopup = true
+ },
+ closePhotoPopup() {
+ this.showPhotoPopup = false
+ },
+ choosePhoto() {
+ if (this.uploadedPhotos.length >= 3) {
+ uni.showToast({ title: '鏈�澶氫笂浼�3寮犵収鐗�', icon: 'none' })
+ return
+ }
+ uni.chooseImage({
+ count: 3 - this.uploadedPhotos.length,
+ sourceType: ['camera', 'album'],
+ success: (res) => {
+ this.uploadedPhotos = [...this.uploadedPhotos, ...res.tempFilePaths]
+ }
+ })
+ },
+ deletePhoto(index) {
+ this.uploadedPhotos.splice(index, 1)
+ },
+ submitPhotoPopup() {
+ if (this.uploadedPhotos.length === 0) {
+ uni.showToast({ title: '璇蜂笂浼犵収鐗�', icon: 'none' })
+ return
+ }
+ uni.showLoading({ title: '涓婁紶涓�...' })
+ const uploadTasks = this.uploadedPhotos.map(path => {
+ return new Promise((resolve, reject) => {
+ uni.uploadFile({
+ url: this.$baseUrl + 'web/public/upload',
+ filePath: path,
+ name: 'file',
+ formData: {
+ folder: 'order'
+ },
+ success: (uploadRes) => {
+ const data = JSON.parse(uploadRes.data)
+ if (data.code === 200) {
+ resolve(data.data)
+ } else {
+ reject(new Error(data.msg))
+ }
+ },
+ fail: (err) => {
+ reject(err)
+ }
+ })
+ })
+ })
+
+ Promise.all(uploadTasks).then(images => {
+ const api = this.photoPopupMode === 'deliver' ? 'confirmDeliver' : 'confirmPickup'
+ const params = {
+ images: images.map(img => img.imgaddr),
+ orderId: this.selectedOrder.id,
+ remark: this.photoRemark
+ }
+ return this.$u.api[api](params)
+ }).then(res => {
+ uni.hideLoading()
+ if (res.code === 200) {
+ uni.showToast({ title: '鎻愪氦鎴愬姛', icon: 'success' })
+ this.showPhotoPopup = false
+ this.getOrderList()
+ this.getActiveOrderCount()
+ } else {
+ uni.showToast({ title: res.msg || '鎻愪氦澶辫触', icon: 'none' })
+ }
+ }).catch(err => {
+ uni.hideLoading()
+ uni.showToast({ title: err.message || '涓婁紶澶辫触', icon: 'none' })
+ })
+ }
}
}
</script>
-<style lang="scss">
+<style lang="scss" scoped>
+ .order-page {
+ height: 100vh;
+ background: #f5f7fb;
+ overflow: hidden;
-</style>
\ No newline at end of file
+ &__nav {
+ position: fixed;
+ left: 0;
+ top: 0;
+ right: 0;
+ z-index: 10;
+ background: linear-gradient(180deg, #1f73f6 0%, #1b6cf2 100%);
+ }
+
+ &__nav-inner {
+ height: 88rpx;
+ display: flex;
+ align-items: center;
+ padding: 0 28rpx;
+ }
+
+ &__nav-title {
+ font-size: 38rpx;
+ font-weight: 700;
+ color: #ffffff;
+ }
+
+ &__tabs {
+ position: fixed;
+ left: 0;
+ right: 0;
+ z-index: 9;
+ height: 88rpx;
+ display: flex;
+ align-items: center;
+ background: #ffffff;
+ box-shadow: 0 10rpx 20rpx rgba(40, 72, 128, 0.04);
+ }
+
+ &__tab {
+ position: relative;
+ flex: 1;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &--active {
+ .order-page__tab-text {
+ color: #272b33;
+ font-weight: 700;
+ }
+ }
+ }
+
+ &__tab-text {
+ font-size: 30rpx;
+ color: #8f96a3;
+ }
+
+ &__tab-line {
+ position: absolute;
+ left: 26rpx;
+ right: 26rpx;
+ bottom: 0;
+ height: 4rpx;
+ border-radius: 999rpx;
+ background: #1a73f8;
+ }
+
+ &__body {
+ box-sizing: border-box;
+ }
+
+ &__list {
+ padding: 18rpx 22rpx calc(env(safe-area-inset-bottom) + 26rpx);
+ }
+
+ &__empty {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding-top: 200rpx;
+ }
+
+ &__empty-icon {
+ width: 320rpx;
+ height: 320rpx;
+ }
+
+ &__loading {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 30rpx 0;
+ color: #8f96a3;
+ font-size: 26rpx;
+ }
+ }
+
+ .order-card {
+ margin-bottom: 18rpx;
+ padding: 20rpx 18rpx 18rpx;
+ border-radius: 20rpx;
+ background: #ffffff;
+ box-shadow: 0 8rpx 20rpx rgba(43, 65, 106, 0.05);
+
+ &__head {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ }
+
+ &__head-left {
+ display: flex;
+ align-items: center;
+ gap: 12rpx;
+ min-width: 0;
+ }
+
+ &__badge {
+ padding: 4rpx 10rpx;
+ border-radius: 10rpx;
+ font-size: 22rpx;
+ line-height: 1.2;
+ font-weight: 600;
+
+ &--blue {
+ border: 1rpx solid #75cfff;
+ color: #27a8f8;
+ background: #eefaff;
+ }
+
+ &--red {
+ border: 1rpx solid #ff8f8f;
+ color: #ff5d5d;
+ background: #fff1f1;
+ }
+ }
+
+ &__badge-icon {
+ width: 108rpx;
+ height: 40rpx;
+ flex-shrink: 0;
+ }
+
+ &__time-text,
+ &__status,
+ &__route-desc,
+ &__arrival-text {
+ font-size: 24rpx;
+ color: #a1a7b2;
+ }
+
+ &__status {
+ flex-shrink: 0;
+
+ &--highlight {
+ color: #ff4a3d;
+ font-weight: 700;
+ }
+ }
+
+ &__route-item {
+ display: flex;
+ align-items: flex-start;
+ margin-top: 22rpx;
+
+ &--delivery {
+ margin-top: 20rpx;
+ }
+ }
+
+ &__point {
+ width: 34rpx;
+ height: 34rpx;
+ line-height: 34rpx;
+ text-align: center;
+ border-radius: 50%;
+ font-size: 22rpx;
+ font-weight: 700;
+ color: #ffffff;
+ flex-shrink: 0;
+ margin-right: 16rpx;
+
+ &--pickup {
+ background: #2ab8ff;
+ }
+
+ &--delivery {
+ background: #ff9d2e;
+ }
+ }
+
+ &__route-texts {
+ flex: 1;
+ min-width: 0;
+ }
+
+ &__route-title {
+ display: block;
+ font-size: 34rpx;
+ font-weight: 700;
+ color: #2d3139;
+ line-height: 1.3;
+ }
+
+ &__route-desc {
+ display: block;
+ margin-top: 8rpx;
+ line-height: 1.4;
+ }
+
+ &__footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 22rpx;
+ padding-top: 16rpx;
+ border-top: 1rpx solid #f0f2f6;
+ }
+
+ &__arrival {
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+ }
+
+ &__clock {
+ width: 24rpx;
+ height: 24rpx;
+ flex-shrink: 0;
+ }
+
+ &__price-wrap {
+ display: flex;
+ align-items: center;
+ gap: 10rpx;
+ }
+
+ &__price-tag {
+ padding: 3rpx 8rpx;
+ border-radius: 8rpx;
+ border: 1rpx solid #ff8f8f;
+ font-size: 22rpx;
+ font-weight: 600;
+ color: #ff6a6a;
+ background: #fff4f4;
+ }
+
+ &__price {
+ font-size: 40rpx;
+ font-weight: 700;
+ color: #ff4030;
+ }
+
+ &__actions {
+ display: flex;
+ justify-content: space-between;
+ margin-top: 18rpx;
+ padding-top: 18rpx;
+ border-top: 1rpx solid #f0f2f6;
+ }
+
+ &__action-btn {
+ width: 160rpx;
+ height: 64rpx;
+ line-height: 64rpx;
+ padding: 0;
+ border-radius: 34rpx;
+ font-size: 28rpx;
+ font-weight: 500;
+ border: 1rpx solid transparent;
+ background: #ffffff;
+ box-sizing: border-box;
+
+ &::after {
+ border: 0;
+ }
+
+ &--light {
+ border-color: #d7dbe3;
+ color: #8f96a3;
+ }
+
+ &--primary {
+ border-color: #2c7cff;
+ color: #2c7cff;
+ }
+
+ &--primary-fill {
+ background: #2c7cff;
+ color: #ffffff;
+ }
+
+ &--hover {
+ opacity: 0.92;
+ }
+ }
+ }
+
+.qrcode {
+ padding: 30rpx 40rpx 50rpx;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ &-title {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 40rpx;
+
+ image {
+ width: 40rpx;
+ height: 40rpx;
+ }
+
+ text {
+ font-size: 34rpx;
+ font-weight: 700;
+ color: #2d3139;
+ }
+ }
+
+ &-image {
+ width: 400rpx;
+ height: 400rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: #f5f7fb;
+ border-radius: 16rpx;
+
+ image {
+ width: 360rpx;
+ height: 360rpx;
+ }
+ }
+
+ &-btn {
+ width: 100%;
+ height: 88rpx;
+ line-height: 88rpx;
+ text-align: center;
+ background: #106EFA;
+ border-radius: 44rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ margin-top: 40rpx;
+
+ &--hover {
+ background: #0d5fc7;
+ }
+ }
+}
+
+.photo-popup {
+ padding: 30rpx 30rpx calc(env(safe-area-inset-bottom) + 30rpx);
+
+ &__header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 40rpx;
+ }
+
+ &__placeholder {
+ width: 40rpx;
+ height: 40rpx;
+ }
+
+ &__title {
+ font-size: 34rpx;
+ font-weight: 700;
+ color: #2d3139;
+ }
+
+ &__close {
+ width: 40rpx;
+ height: 40rpx;
+ }
+
+ &__section {
+ margin-bottom: 30rpx;
+
+ &--remark {
+ margin-top: 30rpx;
+ }
+ }
+
+ &__label-row {
+ display: flex;
+ align-items: center;
+ margin-bottom: 20rpx;
+ }
+
+ &__label {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: #2d3139;
+ }
+
+ &__required {
+ color: #ff4030;
+ margin-left: 8rpx;
+ }
+
+ &__hint {
+ font-size: 24rpx;
+ color: #8f96a3;
+ margin-left: auto;
+ }
+
+ &__photos {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 20rpx;
+ }
+
+ &__preview-card {
+ position: relative;
+ width: 144rpx;
+ height: 144rpx;
+ border-radius: 12rpx;
+ overflow: hidden;
+ }
+
+ &__preview-image {
+ width: 100%;
+ height: 100%;
+ }
+
+ &__preview-mask {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ height: 56rpx;
+ background: rgba(0, 0, 0, 0.5);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ &__preview-delete {
+ font-size: 26rpx;
+ color: #ffffff;
+ }
+
+ &__upload-btn {
+ width: 144rpx;
+ height: 144rpx;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ image {
+ width: 100%;
+ height: 100%;
+ }
+ }
+
+ &__remark-title {
+ font-size: 30rpx;
+ font-weight: 600;
+ color: #2d3139;
+ margin-bottom: 20rpx;
+ display: block;
+ }
+
+ &__textarea {
+ width: 100%;
+ height: 160rpx;
+ padding: 20rpx;
+ background: #f5f7fb;
+ border-radius: 12rpx;
+ font-size: 28rpx;
+ color: #2d3139;
+ box-sizing: border-box;
+ }
+
+ &__submit {
+ width: 100%;
+ height: 88rpx;
+ line-height: 88rpx;
+ background: #2c7cff;
+ border-radius: 44rpx;
+ font-size: 32rpx;
+ font-weight: 600;
+ color: #ffffff;
+ margin-top: 40rpx;
+
+ &--hover {
+ background: #2678e8;
+ }
+ }
+}
+</style>
--
Gitblit v1.9.3