810 lines
18 KiB
Vue
810 lines
18 KiB
Vue
<template>
|
||
<view>
|
||
<scroll-view scroll-y class="page">
|
||
<cu-custom bgColor="bg-blue" :isBack="true">
|
||
<block slot="backText">返回</block>
|
||
<block slot="content">周转箱出库</block>
|
||
</cu-custom>
|
||
|
||
<view class="form-container">
|
||
<!-- 扫描周转箱 -->
|
||
<view class="scan-section">
|
||
<view class="scan-header">
|
||
<view class="scan-label">周转箱列表</view>
|
||
<button class="scan-btn" @click="scanBox">
|
||
<text class="cuIcon-scan"></text>
|
||
<text class="btn-text">扫描箱子</text>
|
||
</button>
|
||
</view>
|
||
|
||
<!-- 周转箱列表 -->
|
||
<view class="box-list">
|
||
<view v-if="boxList.length === 0" class="empty-tip">
|
||
<text class="cuIcon-info"></text>
|
||
<text>请扫描周转箱二维码添加</text>
|
||
</view>
|
||
<view class="box-item" v-for="(item, index) in boxList" :key="index">
|
||
<view class="box-info">
|
||
<view class="box-code">{{item.code}}</view>
|
||
<view class="box-detail">
|
||
<text class="box-bags">{{item.bagCount}}袋</text>
|
||
<text class="box-weight">{{item.totalWeight}}kg</text>
|
||
</view>
|
||
</view>
|
||
<view class="box-delete" @click="removeBox(index)">
|
||
<text class="cuIcon-delete"></text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 统计信息 -->
|
||
<view class="stats-section" v-if="boxList.length > 0">
|
||
<view class="stats-title">汇总统计</view>
|
||
<view class="stats-content">
|
||
<view class="stats-item">
|
||
<text class="stats-label">箱子数量:</text>
|
||
<text class="stats-value">{{boxList.length}}个</text>
|
||
</view>
|
||
<view class="stats-item">
|
||
<text class="stats-label">医废总袋数:</text>
|
||
<text class="stats-value">{{totalBagCount}}袋</text>
|
||
</view>
|
||
<view class="stats-item">
|
||
<text class="stats-label">医废总重量:</text>
|
||
<text class="stats-value highlight">{{totalWeight}}kg</text>
|
||
</view>
|
||
</view>
|
||
<view class="type-stats">
|
||
<view class="stats-title-sub">分类明细</view>
|
||
<view class="type-item" v-for="(stat, type) in typeStats" :key="type">
|
||
<text class="type-name">{{type}}</text>
|
||
<text class="type-info">{{stat.count}}袋 / {{stat.weight}}kg</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部按钮 -->
|
||
<view class="footer">
|
||
<button class="submit-btn" :disabled="boxList.length === 0" @click="submitOut">
|
||
周转箱出库
|
||
</button>
|
||
</view>
|
||
|
||
<view class="cu-tabbar-height"></view>
|
||
</scroll-view>
|
||
|
||
<!-- 出库确认弹窗 -->
|
||
<view class="modal" v-if="showModal" @click.self="closeModal">
|
||
<view class="modal-content">
|
||
<view class="modal-header">
|
||
<text class="modal-title">出库确认</text>
|
||
<text class="modal-close" @click="closeModal">✕</text>
|
||
</view>
|
||
<view class="modal-body">
|
||
<view class="confirm-section">
|
||
<view class="confirm-label">周转箱数量</view>
|
||
<view class="confirm-value highlight">{{boxList.length}}个</view>
|
||
</view>
|
||
<view class="confirm-section">
|
||
<view class="confirm-label">医废总袋数</view>
|
||
<view class="confirm-value">{{totalBagCount}}袋</view>
|
||
</view>
|
||
<view class="confirm-section">
|
||
<view class="confirm-label">医废总重量</view>
|
||
<view class="confirm-value highlight">{{totalWeight}}kg</view>
|
||
</view>
|
||
<view class="confirm-section type-detail">
|
||
<view class="confirm-label">分类医废明细</view>
|
||
<view class="type-list">
|
||
<view class="type-row" v-for="(stat, type) in typeStats" :key="type">
|
||
<text class="type-name">{{type}}</text>
|
||
<text class="type-info">{{stat.count}}袋 / {{stat.weight}}kg</text>
|
||
</view>
|
||
<view v-if="Object.keys(typeStats).length === 0" class="no-type-tip">
|
||
暂无分类数据
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="modal-footer">
|
||
<button class="btn-cancel" @click="closeModal">取消</button>
|
||
<button class="btn-confirm" @click="confirmOut">确认出库</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
boxList: [],
|
||
showModal: false,
|
||
isScanning: false, // 防抖
|
||
scanCodeBuffer: '',
|
||
scanTimer: null,
|
||
typeMap: {
|
||
'感染性废物': { code: 'infectious', color: '#e54d42' },
|
||
'损伤性废物': { code: 'injury', color: '#f37b1d' },
|
||
'病理性废物': { code: 'pathology', color: '#8dc63f' },
|
||
'化学性废物': { code: 'chemical', color: '#6739b6' },
|
||
'药物性废物': { code: 'pharmaceutical', color: '#279cff' }
|
||
}
|
||
}
|
||
},
|
||
computed: {
|
||
totalBagCount() {
|
||
return this.boxList.reduce((sum, item) => sum + (item.bagCount || 0), 0)
|
||
},
|
||
totalWeight() {
|
||
return this.boxList.reduce((sum, item) => sum + parseFloat(item.totalWeight || 0), 0).toFixed(2)
|
||
},
|
||
typeStats() {
|
||
const stats = {}
|
||
this.boxList.forEach(box => {
|
||
if (box.typeDetail) {
|
||
for (let type in box.typeDetail) {
|
||
if (!stats[type]) {
|
||
stats[type] = { count: 0, weight: 0 }
|
||
}
|
||
stats[type].count += box.typeDetail[type].count || 0
|
||
stats[type].weight += parseFloat(box.typeDetail[type].weight || 0)
|
||
}
|
||
}
|
||
})
|
||
// 格式化重量
|
||
for (let key in stats) {
|
||
stats[key].weight = parseFloat(stats[key].weight).toFixed(2)
|
||
}
|
||
return stats
|
||
}
|
||
},
|
||
onShow() {
|
||
this.initScanner()
|
||
},
|
||
onHide() {
|
||
this.destroyScanner()
|
||
},
|
||
onUnload() {
|
||
this.destroyScanner()
|
||
},
|
||
methods: {
|
||
// 初始化:同时开 广播+键盘监听(双保险)
|
||
initScanner() {
|
||
// #ifdef APP-PLUS
|
||
this.initBroadcast()
|
||
this.initKeyboard()
|
||
// #endif
|
||
},
|
||
|
||
// 1. 广播模式(scan.rcv.message / barcodeData)
|
||
initBroadcast() {
|
||
try {
|
||
const main = plus.android.runtimeMainActivity()
|
||
const IntentFilter = plus.android.importClass('android.content.IntentFilter')
|
||
const filter = new IntentFilter()
|
||
// 注册多个常见的扫码广播 action(含 PDA 实际使用的 scan.rcv.message)
|
||
const actions = [
|
||
'scan.rcv.message', // PDA 实际广播名
|
||
'com.android.scan.action.SCAN_RESULT',
|
||
'android.intent.action.DECODEDATA',
|
||
'com.barcode.send',
|
||
'com.ge.android.scanner.BARCODE_DATA'
|
||
]
|
||
actions.forEach(action => {
|
||
try {
|
||
filter.addAction(action)
|
||
} catch(e) {}
|
||
})
|
||
filter.addCategory('android.intent.category.DEFAULT')
|
||
|
||
this.scanReceiver = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
|
||
onReceive: (context, intent) => {
|
||
plus.android.importClass(intent)
|
||
// 尝试多种 extra 名称(含 PDA 实际键值名 barcodeData)
|
||
const extras = [
|
||
'barcodeData', // PDA 实际键值名
|
||
'data', 'BARCODE', 'barcode', 'scandata', 'code', 'content', 'string'
|
||
]
|
||
let code = null
|
||
for (let key of extras) {
|
||
try {
|
||
const val = intent.getStringExtra(key)
|
||
if (val && val.trim()) {
|
||
code = val.trim()
|
||
break
|
||
}
|
||
} catch(e) {}
|
||
}
|
||
if (code) {
|
||
this.handleScanCode(code)
|
||
}
|
||
}
|
||
})
|
||
main.registerReceiver(this.scanReceiver, filter)
|
||
} catch (e) {}
|
||
},
|
||
|
||
// 2. 键盘模式(兜底)
|
||
initKeyboard() {
|
||
document.addEventListener('keydown', this.onKeyDown, true)
|
||
window.addEventListener('keydown', this.onKeyDown, true)
|
||
},
|
||
|
||
// 键盘事件处理
|
||
onKeyDown(e) {
|
||
if (this.scanTimer) clearTimeout(this.scanTimer)
|
||
|
||
if (e.keyCode === 13) {
|
||
const code = this.scanCodeBuffer.trim()
|
||
this.scanCodeBuffer = ''
|
||
if (code) {
|
||
this.handleScanCode(code)
|
||
}
|
||
return
|
||
}
|
||
|
||
const char = e.key || String.fromCharCode(e.which)
|
||
if (char?.length === 1) this.scanCodeBuffer += char
|
||
|
||
this.scanTimer = setTimeout(() => { this.scanCodeBuffer = '' }, 200)
|
||
},
|
||
|
||
// 销毁监听
|
||
destroyScanner() {
|
||
// #ifdef APP-PLUS
|
||
try {
|
||
if (this.scanReceiver) {
|
||
const main = plus.android.runtimeMainActivity()
|
||
main.unregisterReceiver(this.scanReceiver)
|
||
this.scanReceiver = null
|
||
}
|
||
} catch (e) {}
|
||
document.removeEventListener('keydown', this.onKeyDown, true)
|
||
window.removeEventListener('keydown', this.onKeyDown, true)
|
||
// #endif
|
||
if (this.scanTimer) clearTimeout(this.scanTimer)
|
||
this.scanCodeBuffer = ''
|
||
},
|
||
|
||
// 统一处理扫码结果(防抖+去重)
|
||
handleScanCode(code) {
|
||
if (!code || this.isScanning) return
|
||
this.isScanning = true
|
||
setTimeout(() => { this.isScanning = false }, 500)
|
||
|
||
const exists = this.boxList.some(item => item.code === code)
|
||
if (exists) {
|
||
uni.showToast({ title: '该箱子已扫描', icon: 'none' })
|
||
return
|
||
}
|
||
this.getBoxInfo(code)
|
||
},
|
||
// 按钮扫码(备用)
|
||
scanBox() {
|
||
uni.scanCode({
|
||
success: (res) => this.handleScanCode(res.result),
|
||
fail: () => uni.showToast({ title: '扫描失败', icon: 'none' })
|
||
})
|
||
},
|
||
// 获取箱子信息(调用接口验证并获取箱子信息)
|
||
getBoxInfo(code) {
|
||
uni.showLoading({ title: '验证中...' })
|
||
|
||
uni.request({
|
||
url: 'https://lekapi.opmonitor.com/?c=app_api&a=box_verifyBox',
|
||
data: { code: code },
|
||
header: {
|
||
'Content-type': 'application/json'
|
||
},
|
||
success: (res) => {
|
||
uni.hideLoading()
|
||
console.log('箱子验证结果:', res.data)
|
||
|
||
// 处理 send_result 包装的情况
|
||
let resultData = res.data.data
|
||
console.log('resultData:', resultData)
|
||
console.log('bagCount:', resultData.bagCount, 'totalWeight:', resultData.totalWeight)
|
||
|
||
// 如果被包装了一层(data里有err_msg),取内层data
|
||
if (resultData && resultData.err_msg) {
|
||
if (resultData.err_msg !== 'success') {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: resultData.msg || '周转箱编码不存在',
|
||
showCancel: false
|
||
})
|
||
return
|
||
}
|
||
resultData = resultData.data
|
||
}
|
||
|
||
// 检查箱子是否可用(available 为 false 或 undefined/null 时不可用)
|
||
if (resultData && resultData.available === false) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: resultData.message || '该周转箱不可用',
|
||
showCancel: false
|
||
})
|
||
return
|
||
}
|
||
|
||
// 添加箱子到列表
|
||
this.boxList.push({
|
||
code: code,
|
||
bagCount: resultData.bagCount || 0,
|
||
totalWeight: resultData.totalWeight || '0',
|
||
typeDetail: resultData.typeDetail || {}
|
||
})
|
||
|
||
uni.showToast({
|
||
title: '添加成功',
|
||
icon: 'success'
|
||
})
|
||
},
|
||
fail: () => {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '网络错误',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 删除箱子
|
||
removeBox(index) {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '确定删除该周转箱?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
this.boxList.splice(index, 1)
|
||
}
|
||
}
|
||
})
|
||
},
|
||
// 提交出库
|
||
submitOut() {
|
||
if (this.boxList.length === 0) {
|
||
uni.showToast({
|
||
title: '请先扫描周转箱',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
this.showModal = true
|
||
},
|
||
// 关闭弹窗
|
||
closeModal() {
|
||
this.showModal = false
|
||
},
|
||
// 确认出库(调用接口)
|
||
confirmOut() {
|
||
const params = {
|
||
boxList: this.boxList.map(box => box.code),
|
||
hospital: getApp().globalData.hospital,
|
||
account: getApp().globalData.name || '暂存点管理员'
|
||
}
|
||
|
||
console.log('出库参数:', params)
|
||
uni.showLoading({ title: '出库中...' })
|
||
|
||
uni.request({
|
||
url: 'https://lekapi.opmonitor.com/?c=app_api&a=boxOut',
|
||
method: 'POST',
|
||
data: params,
|
||
header: {
|
||
'Content-type': 'application/json'
|
||
},
|
||
success: (res) => {
|
||
uni.hideLoading()
|
||
console.log('出库结果:', res.data)
|
||
|
||
// 处理 send_result 包装的情况
|
||
let resultData = res.data
|
||
if (res.data.data && res.data.data.code) {
|
||
resultData = res.data.data
|
||
}
|
||
|
||
if (resultData.code === 200) {
|
||
uni.showToast({
|
||
title: '出库成功',
|
||
icon: 'success'
|
||
})
|
||
this.resetData()
|
||
this.showModal = false
|
||
} else {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: resultData.msg || '出库失败',
|
||
showCancel: false
|
||
})
|
||
}
|
||
},
|
||
fail: () => {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '网络错误',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
})
|
||
},
|
||
// 重置数据
|
||
resetData() {
|
||
this.boxList = []
|
||
this.showModal = false
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style>
|
||
.page {
|
||
width: 100vw;
|
||
height: 100vh;
|
||
background: #f5f5f5;
|
||
}
|
||
|
||
.form-container {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.scan-section {
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.scan-label {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.scan-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.scan-btn {
|
||
height: 88rpx;
|
||
background: linear-gradient(135deg, #722ed1 0%, #5317ad 100%);
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 12rpx;
|
||
padding: 0 30rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8rpx;
|
||
box-shadow: 0 4rpx 12rpx rgba(114, 46, 209, 0.3);
|
||
}
|
||
|
||
.scan-btn::after {
|
||
border: none;
|
||
}
|
||
|
||
.scan-btn text {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.btn-text {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.box-list {
|
||
min-height: 200rpx;
|
||
}
|
||
|
||
.empty-tip {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 60rpx 0;
|
||
color: #999;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.empty-tip text {
|
||
margin-right: 8rpx;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.box-item {
|
||
display: flex;
|
||
align-items: center;
|
||
padding: 20rpx;
|
||
background: #f9f9f9;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.box-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.box-code {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.box-detail {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.box-bags {
|
||
font-size: 24rpx;
|
||
color: #722ed1;
|
||
padding: 4rpx 16rpx;
|
||
background: rgba(114, 46, 209, 0.1);
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
.box-weight {
|
||
font-size: 24rpx;
|
||
color: #52c41a;
|
||
}
|
||
|
||
.box-delete {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: #e54d42;
|
||
}
|
||
|
||
.box-delete text {
|
||
font-size: 36rpx;
|
||
}
|
||
|
||
.stats-section {
|
||
background: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.stats-title {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.stats-title-sub {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
margin-bottom: 16rpx;
|
||
margin-top: 20rpx;
|
||
padding-top: 20rpx;
|
||
border-top: 2rpx solid #f0f0f0;
|
||
}
|
||
|
||
.stats-content {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.stats-item {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.stats-label {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
width: 180rpx;
|
||
}
|
||
|
||
.stats-value {
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.stats-value.highlight {
|
||
color: #722ed1;
|
||
}
|
||
|
||
.type-stats {
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
.type-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 16rpx 20rpx;
|
||
background: #f9f9f9;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.type-item .type-name {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.type-item .type-info {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.footer {
|
||
padding: 20rpx 40rpx 40rpx;
|
||
}
|
||
|
||
.submit-btn {
|
||
height: 96rpx;
|
||
background: linear-gradient(135deg, #722ed1 0%, #5317ad 100%);
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 48rpx;
|
||
font-size: 32rpx;
|
||
font-weight: 500;
|
||
box-shadow: 0 8rpx 24rpx rgba(114, 46, 209, 0.3);
|
||
}
|
||
|
||
.submit-btn[disabled] {
|
||
background: #ccc;
|
||
box-shadow: none;
|
||
}
|
||
|
||
.submit-btn::after {
|
||
border: none;
|
||
}
|
||
|
||
/* 弹窗样式 */
|
||
.modal {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: rgba(0, 0, 0, 0.6);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
z-index: 999;
|
||
}
|
||
|
||
.modal-content {
|
||
width: 80%;
|
||
max-width: 600rpx;
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.modal-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 30rpx;
|
||
border-bottom: 2rpx solid #f0f0f0;
|
||
}
|
||
|
||
.modal-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
|
||
.modal-close {
|
||
font-size: 36rpx;
|
||
color: #999;
|
||
padding: 10rpx;
|
||
}
|
||
|
||
.modal-body {
|
||
padding: 30rpx;
|
||
}
|
||
|
||
.confirm-section {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.confirm-section.type-detail {
|
||
flex-direction: column;
|
||
align-items: flex-start;
|
||
margin-top: 30rpx;
|
||
padding-top: 20rpx;
|
||
border-top: 2rpx solid #f0f0f0;
|
||
}
|
||
|
||
.confirm-label {
|
||
font-size: 28rpx;
|
||
color: #666;
|
||
width: 160rpx;
|
||
}
|
||
|
||
.confirm-value {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.confirm-value.highlight {
|
||
color: #722ed1;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.type-list {
|
||
width: 100%;
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
.type-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 16rpx 20rpx;
|
||
background: #f9f9f9;
|
||
border-radius: 12rpx;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.type-row .type-name {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.type-row .type-info {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.no-type-tip {
|
||
text-align: center;
|
||
color: #999;
|
||
font-size: 26rpx;
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.modal-footer {
|
||
display: flex;
|
||
padding: 20rpx 30rpx 30rpx;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.btn-cancel,
|
||
.btn-confirm {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
border-radius: 40rpx;
|
||
font-size: 28rpx;
|
||
border: none;
|
||
}
|
||
|
||
.btn-cancel {
|
||
background: #f5f5f5;
|
||
color: #666;
|
||
}
|
||
|
||
.btn-confirm {
|
||
background: linear-gradient(135deg, #722ed1 0%, #5317ad 100%);
|
||
color: #fff;
|
||
}
|
||
|
||
.btn-cancel::after,
|
||
.btn-confirm::after {
|
||
border: none;
|
||
}
|
||
</style>
|