|
@@ -1,81 +1,330 @@
|
|
|
<template>
|
|
<template>
|
|
|
- <ScreenLayout :show-back-btn="true" back-text="返回" back-target="/visitor/appointment">
|
|
|
|
|
- <div class="page-confirm">
|
|
|
|
|
- <h1 class="page-title">预约信息确认</h1>
|
|
|
|
|
-
|
|
|
|
|
- <div v-if="appointment" class="info-card">
|
|
|
|
|
- <div class="info-row">
|
|
|
|
|
- <span class="info-label">访客姓名</span>
|
|
|
|
|
- <span class="info-value">{{ appointment.visitorName }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-row">
|
|
|
|
|
- <span class="info-label">手机号码</span>
|
|
|
|
|
- <span class="info-value">{{ maskMobile(appointment.mobile) }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-row">
|
|
|
|
|
- <span class="info-label">身份证号</span>
|
|
|
|
|
- <span class="info-value">{{ maskIdCard(appointment.idCardNo) }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-row">
|
|
|
|
|
- <span class="info-label">被访人</span>
|
|
|
|
|
- <span class="info-value">{{ appointment.visitedPerson }}</span>
|
|
|
|
|
- </div>
|
|
|
|
|
- <div class="info-row">
|
|
|
|
|
- <span class="info-label">被访部门</span>
|
|
|
|
|
- <span class="info-value">{{ appointment.visitedDepartment }}</span>
|
|
|
|
|
|
|
+ <div class="confirm-layout">
|
|
|
|
|
+ <!-- 顶部状态栏 -->
|
|
|
|
|
+ <StatusBar :title="robotName" />
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 主内容区 -->
|
|
|
|
|
+ <div class="layout-main">
|
|
|
|
|
+ <div class="confirm-page">
|
|
|
|
|
+ <!-- 动态背景层 -->
|
|
|
|
|
+ <div class="bg-layer">
|
|
|
|
|
+ <div class="bg-orb orb-1"></div>
|
|
|
|
|
+ <div class="bg-orb orb-2"></div>
|
|
|
|
|
+ <div class="bg-orb orb-3"></div>
|
|
|
|
|
+ <div class="bg-grid-overlay"></div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="info-row">
|
|
|
|
|
- <span class="info-label">预约时间</span>
|
|
|
|
|
- <span class="info-value">{{ appointment.appointmentTime }}</span>
|
|
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 内容区 -->
|
|
|
|
|
+ <div class="confirm-content">
|
|
|
|
|
+ <!-- 标题区 -->
|
|
|
|
|
+ <div class="confirm-hero">
|
|
|
|
|
+ <h1 class="page-title">预约信息确认</h1>
|
|
|
|
|
+ <p class="page-subtitle">请核对预约信息,如需调整可修改被访人与来访事由</p>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 表单卡片 -->
|
|
|
|
|
+ <div class="form-card">
|
|
|
|
|
+ <!-- 预约单号:只读 -->
|
|
|
|
|
+ <div class="form-row form-row-readonly">
|
|
|
|
|
+ <span class="form-label">预约单号</span>
|
|
|
|
|
+ <span class="form-value">{{ form.appointmentNo || '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 访客姓名:只读 -->
|
|
|
|
|
+ <div class="form-row form-row-readonly">
|
|
|
|
|
+ <span class="form-label">访客姓名</span>
|
|
|
|
|
+ <span class="form-value">{{ form.visitorName }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 身份证号:只读 -->
|
|
|
|
|
+ <div class="form-row form-row-readonly">
|
|
|
|
|
+ <span class="form-label">身份证号</span>
|
|
|
|
|
+ <span class="form-value">{{ maskIdCard(form.idCardNo || appointment?.idCardNo) }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 手机号码:只读 -->
|
|
|
|
|
+ <div class="form-row form-row-readonly">
|
|
|
|
|
+ <span class="form-label">手机号码</span>
|
|
|
|
|
+ <span class="form-value">{{ form.mobile }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 被访人:可编辑 -->
|
|
|
|
|
+ <div class="form-row form-row-editable" @click="openTextModal('visitedPerson', '修改被访人', form.visitedPerson)">
|
|
|
|
|
+ <span class="form-label">被访人</span>
|
|
|
|
|
+ <div class="form-value-editable-wrapper">
|
|
|
|
|
+ <span v-if="form.visitedPerson" class="form-value form-value-editable">{{ form.visitedPerson }}</span>
|
|
|
|
|
+ <span v-else class="form-value form-value-placeholder">请输入被访人</span>
|
|
|
|
|
+ <svg class="edit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
|
|
|
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
|
|
|
|
+ <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
|
|
|
|
|
+ </svg>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 预约时间:只读 -->
|
|
|
|
|
+ <div class="form-row form-row-readonly">
|
|
|
|
|
+ <span class="form-label">预约时间</span>
|
|
|
|
|
+ <span class="form-value">{{ form.appointmentTime || '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 来访事由:可编辑 -->
|
|
|
|
|
+ <div class="form-row form-row-editable" @click="openReasonModal">
|
|
|
|
|
+ <span class="form-label">来访事由</span>
|
|
|
|
|
+ <div class="form-value-editable-wrapper">
|
|
|
|
|
+ <span v-if="currentReasonLabel" class="form-value form-value-editable">{{ currentReasonLabel }}</span>
|
|
|
|
|
+ <span v-else class="form-value form-value-placeholder">请选择来访事由</span>
|
|
|
|
|
+ <svg class="edit-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
|
|
|
+ <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
|
|
|
|
+ <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
|
|
|
|
|
+ </svg>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 表单卡片底部提示 -->
|
|
|
|
|
+ <div class="form-hint">蓝色标记项可点击修改</div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 底部按钮 -->
|
|
|
|
|
+ <div class="confirm-actions">
|
|
|
|
|
+ <button class="btn-back" @click="goBack">
|
|
|
|
|
+ <svg class="back-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
|
|
|
|
|
+ <path d="M15 18l-6-6 6-6" />
|
|
|
|
|
+ </svg>
|
|
|
|
|
+ <span>返回核验</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <button class="btn-confirm" :disabled="loading" @click="handleConfirm">
|
|
|
|
|
+ <span v-if="loading" class="loading-spinner"></span>
|
|
|
|
|
+ <span v-else>确认登记</span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
- <div class="info-row">
|
|
|
|
|
- <span class="info-label">来访事由</span>
|
|
|
|
|
- <span class="info-value">{{ appointment.visitPurpose }}</span>
|
|
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- ===== 文本编辑弹窗 ===== -->
|
|
|
|
|
+ <Teleport to="body">
|
|
|
|
|
+ <div v-if="showTextModal" class="modal-overlay" @click.self="closeTextModal">
|
|
|
|
|
+ <div class="modal-card">
|
|
|
|
|
+ <div class="modal-header">
|
|
|
|
|
+ <h2>{{ textModalTitle }}</h2>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="modal-input-wrapper">
|
|
|
|
|
+ <input
|
|
|
|
|
+ ref="textInputRef"
|
|
|
|
|
+ v-model="tempText"
|
|
|
|
|
+ class="modal-text-input"
|
|
|
|
|
+ type="text"
|
|
|
|
|
+ :placeholder="textModalPlaceholder"
|
|
|
|
|
+ @keydown.enter="confirmTextEdit"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="modal-text-actions">
|
|
|
|
|
+ <button class="btn-modal-cancel" @click="closeTextModal">取消</button>
|
|
|
|
|
+ <button class="btn-modal-save" @click="confirmTextEdit">保存</button>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ </Teleport>
|
|
|
|
|
|
|
|
- <div class="confirm-actions">
|
|
|
|
|
- <button class="btn-back" @click="goBack">信息有误</button>
|
|
|
|
|
- <button class="btn-confirm" @click="handleConfirm" :disabled="loading">
|
|
|
|
|
- <span v-if="loading" class="loading-spinner"></span>
|
|
|
|
|
- <span v-else>确认登记</span>
|
|
|
|
|
- </button>
|
|
|
|
|
|
|
+ <!-- ===== 来访事由选项弹窗 ===== -->
|
|
|
|
|
+ <Teleport to="body">
|
|
|
|
|
+ <div v-if="showReasonModal" class="modal-overlay" @click.self="closeReasonModal">
|
|
|
|
|
+ <div class="modal-card modal-reason-card">
|
|
|
|
|
+ <div class="modal-header">
|
|
|
|
|
+ <h2>选择来访事由</h2>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="reason-options">
|
|
|
|
|
+ <button
|
|
|
|
|
+ v-for="opt in visitReasonOptions"
|
|
|
|
|
+ :key="opt.value"
|
|
|
|
|
+ class="reason-btn"
|
|
|
|
|
+ :class="{ 'reason-btn-active': tempReason === opt.value }"
|
|
|
|
|
+ @click="tempReason = opt.value"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ opt.label }}
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="modal-reason-actions">
|
|
|
|
|
+ <button class="btn-modal-cancel" @click="closeReasonModal">取消</button>
|
|
|
|
|
+ <button class="btn-modal-save" @click="confirmReasonEdit">保存</button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
</div>
|
|
</div>
|
|
|
- </div>
|
|
|
|
|
- </ScreenLayout>
|
|
|
|
|
|
|
+ </Teleport>
|
|
|
|
|
+ </div>
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup>
|
|
<script setup>
|
|
|
-import { ref } from 'vue'
|
|
|
|
|
|
|
+import { ref, reactive, computed, nextTick } from 'vue'
|
|
|
import { useRouter } from 'vue-router'
|
|
import { useRouter } from 'vue-router'
|
|
|
|
|
+import StatusBar from '@/components/StatusBar.vue'
|
|
|
import { useScreenStore } from '@/stores/screen'
|
|
import { useScreenStore } from '@/stores/screen'
|
|
|
import { useVisitorStore } from '@/stores/visitor'
|
|
import { useVisitorStore } from '@/stores/visitor'
|
|
|
-import { maskMobile, maskIdCard } from '@/utils/device'
|
|
|
|
|
-import ScreenLayout from '@/layouts/ScreenLayout.vue'
|
|
|
|
|
|
|
+import { maskIdCard } from '@/utils/device'
|
|
|
|
|
|
|
|
const router = useRouter()
|
|
const router = useRouter()
|
|
|
const screenStore = useScreenStore()
|
|
const screenStore = useScreenStore()
|
|
|
const visitorStore = useVisitorStore()
|
|
const visitorStore = useVisitorStore()
|
|
|
|
|
|
|
|
|
|
+const robotName = computed(() => screenStore.screenTheme?.robotName || '迎宾巡逻机器人')
|
|
|
const loading = ref(false)
|
|
const loading = ref(false)
|
|
|
|
|
+const visitReasonOptions = visitorStore.visitReasonOptions
|
|
|
|
|
|
|
|
const appointment = visitorStore.appointmentInfo
|
|
const appointment = visitorStore.appointmentInfo
|
|
|
|
|
|
|
|
|
|
+// 表单数据
|
|
|
|
|
+const form = reactive({
|
|
|
|
|
+ appointmentNo: '',
|
|
|
|
|
+ visitorName: '',
|
|
|
|
|
+ idCardNo: '',
|
|
|
|
|
+ mobile: '',
|
|
|
|
|
+ visitedPerson: '',
|
|
|
|
|
+ appointmentTime: '',
|
|
|
|
|
+ visitPurpose: ''
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 初始化表单数据
|
|
|
|
|
+const initForm = () => {
|
|
|
|
|
+ if (appointment) {
|
|
|
|
|
+ form.appointmentNo = appointment.appointmentNo || ''
|
|
|
|
|
+ form.visitorName = appointment.visitorName || ''
|
|
|
|
|
+ form.idCardNo = appointment.idCardNo || ''
|
|
|
|
|
+ form.mobile = appointment.mobile || ''
|
|
|
|
|
+ form.visitedPerson = appointment.visitedPerson || ''
|
|
|
|
|
+ form.appointmentTime = appointment.appointmentTime || ''
|
|
|
|
|
+ form.visitPurpose = appointment.visitPurpose || appointment.visitReason || ''
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+initForm()
|
|
|
|
|
+
|
|
|
|
|
+// 来访事由标签
|
|
|
|
|
+const currentReasonLabel = computed(() => {
|
|
|
|
|
+ const found = visitReasonOptions.find(o => o.value === form.visitPurpose)
|
|
|
|
|
+ return found ? found.label : ''
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// ===== 文本编辑弹窗 =====
|
|
|
|
|
+const showTextModal = ref(false)
|
|
|
|
|
+const textModalField = ref('')
|
|
|
|
|
+const textModalTitle = ref('')
|
|
|
|
|
+const textModalPlaceholder = ref('')
|
|
|
|
|
+const tempText = ref('')
|
|
|
|
|
+const textInputRef = ref(null)
|
|
|
|
|
+
|
|
|
|
|
+const openTextModal = (field, title, currentValue) => {
|
|
|
|
|
+ textModalField.value = field
|
|
|
|
|
+ textModalTitle.value = title
|
|
|
|
|
+ textModalPlaceholder.value = title.replace('修改', '请输入')
|
|
|
|
|
+ tempText.value = currentValue
|
|
|
|
|
+ showTextModal.value = true
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ if (textInputRef.value) {
|
|
|
|
|
+ textInputRef.value.focus()
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const closeTextModal = () => {
|
|
|
|
|
+ showTextModal.value = false
|
|
|
|
|
+ textModalField.value = ''
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const confirmTextEdit = () => {
|
|
|
|
|
+ if (!tempText.value.trim()) {
|
|
|
|
|
+ screenStore.showAlert({
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ message: `${textModalTitle.value.replace('修改', '')}不能为空`,
|
|
|
|
|
+ duration: 3000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (textModalField.value === 'visitedPerson') {
|
|
|
|
|
+ form.visitedPerson = tempText.value
|
|
|
|
|
+ }
|
|
|
|
|
+ closeTextModal()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ===== 来访事由选项弹窗 =====
|
|
|
|
|
+const showReasonModal = ref(false)
|
|
|
|
|
+const tempReason = ref('')
|
|
|
|
|
+
|
|
|
|
|
+const openReasonModal = () => {
|
|
|
|
|
+ tempReason.value = form.visitPurpose
|
|
|
|
|
+ showReasonModal.value = true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const closeReasonModal = () => {
|
|
|
|
|
+ showReasonModal.value = false
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const confirmReasonEdit = () => {
|
|
|
|
|
+ if (!tempReason.value) {
|
|
|
|
|
+ screenStore.showAlert({
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ message: '请选择来访事由',
|
|
|
|
|
+ duration: 3000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ form.visitPurpose = tempReason.value
|
|
|
|
|
+ closeReasonModal()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ===== 导航 =====
|
|
|
const goBack = () => {
|
|
const goBack = () => {
|
|
|
- router.push('/visitor/walk-in')
|
|
|
|
|
|
|
+ router.push('/visitor/appointment')
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// ===== 确认登记 =====
|
|
|
const handleConfirm = async () => {
|
|
const handleConfirm = async () => {
|
|
|
if (loading.value) return
|
|
if (loading.value) return
|
|
|
|
|
+
|
|
|
|
|
+ // 手机号校验
|
|
|
|
|
+ if (!form.mobile || !/^1[3-9]\d{9}$/.test(form.mobile)) {
|
|
|
|
|
+ screenStore.showAlert({
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ message: '请输入正确的11位手机号',
|
|
|
|
|
+ duration: 3000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 被访人非空校验
|
|
|
|
|
+ if (!form.visitedPerson || !form.visitedPerson.trim()) {
|
|
|
|
|
+ screenStore.showAlert({
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ message: '请填写被访人姓名',
|
|
|
|
|
+ duration: 3000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 来访事由非空校验
|
|
|
|
|
+ if (!form.visitPurpose) {
|
|
|
|
|
+ screenStore.showAlert({
|
|
|
|
|
+ type: 'warning',
|
|
|
|
|
+ message: '请选择来访事由',
|
|
|
|
|
+ duration: 3000
|
|
|
|
|
+ })
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
loading.value = true
|
|
loading.value = true
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
|
|
+ visitorStore.appointmentInfo = {
|
|
|
|
|
+ ...visitorStore.appointmentInfo,
|
|
|
|
|
+ ...form,
|
|
|
|
|
+ visitReason: form.visitPurpose
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
await visitorStore.submitRegistration()
|
|
await visitorStore.submitRegistration()
|
|
|
router.push('/visitor/success')
|
|
router.push('/visitor/success')
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
screenStore.showAlert({
|
|
screenStore.showAlert({
|
|
|
type: 'error',
|
|
type: 'error',
|
|
|
- message: '登记失败,请重试'
|
|
|
|
|
|
|
+ message: '登记失败,请重试',
|
|
|
|
|
+ duration: 3000
|
|
|
})
|
|
})
|
|
|
} finally {
|
|
} finally {
|
|
|
loading.value = false
|
|
loading.value = false
|
|
@@ -84,116 +333,556 @@ const handleConfirm = async () => {
|
|
|
</script>
|
|
</script>
|
|
|
|
|
|
|
|
<style scoped>
|
|
<style scoped>
|
|
|
-.page-confirm {
|
|
|
|
|
- width: 100%;
|
|
|
|
|
- height: 100%;
|
|
|
|
|
|
|
+/* ===== 布局结构 ===== */
|
|
|
|
|
+.confirm-layout {
|
|
|
|
|
+ width: 100vw;
|
|
|
|
|
+ height: 100vh;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ background: linear-gradient(155deg, #e8f4fd 0%, #dbeafe 40%, #eff6ff 100%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.layout-main {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.confirm-page {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 动态背景层 ===== */
|
|
|
|
|
+.bg-layer {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ inset: 0;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ pointer-events: none;
|
|
|
|
|
+ z-index: 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.bg-orb {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ filter: blur(60px);
|
|
|
|
|
+ opacity: 0.45;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.orb-1 {
|
|
|
|
|
+ width: 380px;
|
|
|
|
|
+ height: 380px;
|
|
|
|
|
+ background: radial-gradient(circle, rgba(59, 130, 246, 0.35) 0%, transparent 70%);
|
|
|
|
|
+ top: -80px;
|
|
|
|
|
+ right: -80px;
|
|
|
|
|
+ animation: float1 18s ease-in-out infinite;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.orb-2 {
|
|
|
|
|
+ width: 300px;
|
|
|
|
|
+ height: 300px;
|
|
|
|
|
+ background: radial-gradient(circle, rgba(99, 102, 241, 0.30) 0%, transparent 70%);
|
|
|
|
|
+ bottom: -40px;
|
|
|
|
|
+ left: -60px;
|
|
|
|
|
+ animation: float2 22s ease-in-out infinite;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.orb-3 {
|
|
|
|
|
+ width: 240px;
|
|
|
|
|
+ height: 240px;
|
|
|
|
|
+ background: radial-gradient(circle, rgba(14, 165, 233, 0.28) 0%, transparent 70%);
|
|
|
|
|
+ top: 50%;
|
|
|
|
|
+ left: 50%;
|
|
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
|
|
+ animation: float3 16s ease-in-out infinite;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.bg-grid-overlay {
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ inset: 0;
|
|
|
|
|
+ background-image:
|
|
|
|
|
+ linear-gradient(rgba(147, 197, 253, 0.15) 1px, transparent 1px),
|
|
|
|
|
+ linear-gradient(90deg, rgba(147, 197, 253, 0.15) 1px, transparent 1px);
|
|
|
|
|
+ background-size: 48px 48px;
|
|
|
|
|
+ mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 40%, transparent 100%);
|
|
|
|
|
+ -webkit-mask-image: radial-gradient(ellipse 80% 80% at 50% 50%, black 40%, transparent 100%);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@keyframes float1 {
|
|
|
|
|
+ 0%, 100% { transform: translate(0, 0) scale(1); }
|
|
|
|
|
+ 33% { transform: translate(-20px, 25px) scale(1.05); }
|
|
|
|
|
+ 66% { transform: translate(15px, -15px) scale(0.96); }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@keyframes float2 {
|
|
|
|
|
+ 0%, 100% { transform: translate(0, 0) scale(1); }
|
|
|
|
|
+ 40% { transform: translate(25px, -20px) scale(1.08); }
|
|
|
|
|
+ 70% { transform: translate(-10px, 15px) scale(0.95); }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@keyframes float3 {
|
|
|
|
|
+ 0%, 100% { transform: translate(-50%, -50%) scale(1); }
|
|
|
|
|
+ 50% { transform: translate(-45%, -55%) scale(1.1); }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 内容区 ===== */
|
|
|
|
|
+.confirm-content {
|
|
|
|
|
+ flex: 1;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
- padding: 20px 0;
|
|
|
|
|
|
|
+ padding: 0 32px 32px;
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ z-index: 1;
|
|
|
|
|
+ overflow-y: auto;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 标题区 ===== */
|
|
|
|
|
+.confirm-hero {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ margin: 28px 0 24px;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.page-title {
|
|
.page-title {
|
|
|
- font-size: 32px;
|
|
|
|
|
- font-weight: 600;
|
|
|
|
|
|
|
+ font-size: 40px;
|
|
|
|
|
+ font-weight: 900;
|
|
|
color: var(--text-primary);
|
|
color: var(--text-primary);
|
|
|
- margin: 0 0 32px;
|
|
|
|
|
|
|
+ margin: 0 0 10px;
|
|
|
|
|
+ letter-spacing: 3px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.info-card {
|
|
|
|
|
|
|
+.page-subtitle {
|
|
|
|
|
+ font-size: 20px;
|
|
|
|
|
+ color: var(--text-secondary);
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 表单卡片 ===== */
|
|
|
|
|
+.form-card {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
- max-width: 500px;
|
|
|
|
|
- background: var(--bg-card);
|
|
|
|
|
- border-radius: var(--radius-xl);
|
|
|
|
|
- box-shadow: var(--shadow-md);
|
|
|
|
|
- padding: 24px;
|
|
|
|
|
- margin-bottom: 32px;
|
|
|
|
|
|
|
+ max-width: 640px;
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.88);
|
|
|
|
|
+ border-radius: 32px;
|
|
|
|
|
+ padding: 8px 0;
|
|
|
|
|
+ box-shadow:
|
|
|
|
|
+ 0 24px 64px rgba(30, 64, 175, 0.10),
|
|
|
|
|
+ 0 8px 24px rgba(0, 0, 0, 0.06);
|
|
|
|
|
+ backdrop-filter: blur(20px);
|
|
|
|
|
+ -webkit-backdrop-filter: blur(20px);
|
|
|
|
|
+ border: 1px solid rgba(255, 255, 255, 0.60);
|
|
|
|
|
+ margin-bottom: 12px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-hint {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ color: #94a3b8;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ letter-spacing: 0.5px;
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.info-row {
|
|
|
|
|
|
|
+.form-row {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
- justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
- padding: 16px 0;
|
|
|
|
|
- border-bottom: 1px solid var(--border-light);
|
|
|
|
|
|
|
+ padding: 0 32px;
|
|
|
|
|
+ min-height: 80px;
|
|
|
|
|
+ border-bottom: 1px solid rgba(226, 232, 240, 0.80);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.info-row:last-child {
|
|
|
|
|
|
|
+.form-row:last-child {
|
|
|
border-bottom: none;
|
|
border-bottom: none;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.info-label {
|
|
|
|
|
- font-size: 16px;
|
|
|
|
|
- color: var(--text-muted);
|
|
|
|
|
|
|
+.form-row-readonly {
|
|
|
|
|
+ cursor: default;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-.info-value {
|
|
|
|
|
- font-size: 18px;
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
|
|
+.form-row-editable {
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: background 0.15s;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-row-editable:hover {
|
|
|
|
|
+ background: rgba(59, 130, 246, 0.04);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-row-editable:active {
|
|
|
|
|
+ background: rgba(59, 130, 246, 0.08);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-label {
|
|
|
|
|
+ font-size: 22px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: var(--text-secondary);
|
|
|
|
|
+ width: 140px;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ letter-spacing: 0.5px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-value {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
color: var(--text-primary);
|
|
color: var(--text-primary);
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+ letter-spacing: 1px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-value-editable-wrapper {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
|
+ gap: 8px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-value-editable {
|
|
|
|
|
+ color: var(--primary);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-value-placeholder {
|
|
|
|
|
+ color: #94a3b8;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ font-size: 22px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.edit-icon {
|
|
|
|
|
+ width: 22px;
|
|
|
|
|
+ height: 22px;
|
|
|
|
|
+ color: var(--primary);
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ opacity: 0.7;
|
|
|
|
|
+ transition: opacity 0.15s;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.form-row-editable:hover .edit-icon {
|
|
|
|
|
+ opacity: 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 底部按钮 ===== */
|
|
|
.confirm-actions {
|
|
.confirm-actions {
|
|
|
display: grid;
|
|
display: grid;
|
|
|
- grid-template-columns: 1fr 2fr;
|
|
|
|
|
- gap: 20px;
|
|
|
|
|
|
|
+ grid-template-columns: 1fr 1.8fr;
|
|
|
|
|
+ gap: 16px;
|
|
|
width: 100%;
|
|
width: 100%;
|
|
|
- max-width: 500px;
|
|
|
|
|
|
|
+ max-width: 640px;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.btn-back,
|
|
.btn-back,
|
|
|
.btn-confirm {
|
|
.btn-confirm {
|
|
|
- height: 64px;
|
|
|
|
|
- font-size: 20px;
|
|
|
|
|
- font-weight: 500;
|
|
|
|
|
- border-radius: var(--radius-lg);
|
|
|
|
|
|
|
+ height: 78px;
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ font-weight: 800;
|
|
|
|
|
+ border-radius: 999px;
|
|
|
cursor: pointer;
|
|
cursor: pointer;
|
|
|
- transition: all var(--transition-fast);
|
|
|
|
|
|
|
+ transition: all 0.22s ease;
|
|
|
|
|
+ letter-spacing: 1.5px;
|
|
|
display: flex;
|
|
display: flex;
|
|
|
align-items: center;
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
justify-content: center;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.btn-back {
|
|
.btn-back {
|
|
|
- background: var(--bg-card);
|
|
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.80);
|
|
|
color: var(--text-secondary);
|
|
color: var(--text-secondary);
|
|
|
border: 2px solid var(--border-light);
|
|
border: 2px solid var(--border-light);
|
|
|
|
|
+ backdrop-filter: blur(10px);
|
|
|
|
|
+ -webkit-backdrop-filter: blur(10px);
|
|
|
|
|
+ box-shadow: 0 8px 24px rgba(0, 0, 0, 0.06);
|
|
|
|
|
+ gap: 8px;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.btn-back:hover {
|
|
.btn-back:hover {
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.95);
|
|
|
border-color: var(--text-muted);
|
|
border-color: var(--text-muted);
|
|
|
|
|
+ transform: translateY(-2px);
|
|
|
|
|
+ box-shadow: 0 12px 32px rgba(0, 0, 0, 0.10);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn-back:active {
|
|
|
|
|
+ transform: scale(0.97);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.back-icon {
|
|
|
|
|
+ width: 22px;
|
|
|
|
|
+ height: 22px;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.btn-confirm {
|
|
.btn-confirm {
|
|
|
- background: var(--primary);
|
|
|
|
|
|
|
+ background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
|
|
color: white;
|
|
color: white;
|
|
|
border: none;
|
|
border: none;
|
|
|
- box-shadow: var(--shadow-md);
|
|
|
|
|
|
|
+ box-shadow: 0 12px 28px rgba(37, 99, 235, 0.28);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.btn-confirm:hover:not(:disabled) {
|
|
.btn-confirm:hover:not(:disabled) {
|
|
|
- background: var(--primary-dark);
|
|
|
|
|
|
|
+ box-shadow: 0 16px 36px rgba(37, 99, 235, 0.36);
|
|
|
transform: translateY(-2px);
|
|
transform: translateY(-2px);
|
|
|
- box-shadow: var(--shadow-lg);
|
|
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn-confirm:active {
|
|
|
|
|
+ transform: scale(0.97);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.btn-confirm:disabled {
|
|
.btn-confirm:disabled {
|
|
|
- opacity: 0.7;
|
|
|
|
|
|
|
+ background: linear-gradient(135deg, #93c5fd 0%, #60a5fa 100%);
|
|
|
cursor: not-allowed;
|
|
cursor: not-allowed;
|
|
|
|
|
+ box-shadow: none;
|
|
|
|
|
+ transform: none;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
.loading-spinner {
|
|
.loading-spinner {
|
|
|
- width: 24px;
|
|
|
|
|
- height: 24px;
|
|
|
|
|
- border: 3px solid rgba(255, 255, 255, 0.3);
|
|
|
|
|
|
|
+ width: 26px;
|
|
|
|
|
+ height: 26px;
|
|
|
|
|
+ border: 3px solid rgba(255, 255, 255, 0.35);
|
|
|
border-top-color: white;
|
|
border-top-color: white;
|
|
|
border-radius: 50%;
|
|
border-radius: 50%;
|
|
|
animation: spin 1s linear infinite;
|
|
animation: spin 1s linear infinite;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@keyframes spin {
|
|
@keyframes spin {
|
|
|
- to {
|
|
|
|
|
- transform: rotate(360deg);
|
|
|
|
|
|
|
+ to { transform: rotate(360deg); }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 弹窗遮罩 ===== */
|
|
|
|
|
+.modal-overlay {
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ inset: 0;
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.50);
|
|
|
|
|
+ backdrop-filter: blur(4px);
|
|
|
|
|
+ -webkit-backdrop-filter: blur(4px);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ z-index: 1000;
|
|
|
|
|
+ animation: fadeIn 0.2s ease;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@keyframes fadeIn {
|
|
|
|
|
+ from { opacity: 0; }
|
|
|
|
|
+ to { opacity: 1; }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 弹窗卡片 ===== */
|
|
|
|
|
+.modal-card {
|
|
|
|
|
+ width: 560px;
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.96);
|
|
|
|
|
+ border-radius: 32px;
|
|
|
|
|
+ padding: 40px 36px 36px;
|
|
|
|
|
+ box-shadow:
|
|
|
|
|
+ 0 40px 80px rgba(0, 0, 0, 0.20),
|
|
|
|
|
+ 0 16px 40px rgba(0, 0, 0, 0.12);
|
|
|
|
|
+ backdrop-filter: blur(20px);
|
|
|
|
|
+ -webkit-backdrop-filter: blur(20px);
|
|
|
|
|
+ animation: slideUp 0.22s ease;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+@keyframes slideUp {
|
|
|
|
|
+ from { transform: translateY(20px) scale(0.98); opacity: 0; }
|
|
|
|
|
+ to { transform: translateY(0) scale(1); opacity: 1; }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 弹窗标题 ===== */
|
|
|
|
|
+.modal-header {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ margin-bottom: 24px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.modal-header h2 {
|
|
|
|
|
+ font-size: 30px;
|
|
|
|
|
+ font-weight: 800;
|
|
|
|
|
+ color: var(--text-primary);
|
|
|
|
|
+ margin: 0 0 8px;
|
|
|
|
|
+ letter-spacing: 2px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 文本输入弹窗 ===== */
|
|
|
|
|
+.modal-input-wrapper {
|
|
|
|
|
+ background: linear-gradient(160deg, #f0f7ff 0%, #e8f4fd 100%);
|
|
|
|
|
+ border: 2px solid rgba(59, 130, 246, 0.18);
|
|
|
|
|
+ border-radius: 20px;
|
|
|
|
|
+ padding: 0 24px;
|
|
|
|
|
+ height: 96px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ margin-bottom: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.modal-text-input {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ font-size: 30px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ color: var(--text-primary);
|
|
|
|
|
+ background: transparent;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ outline: none;
|
|
|
|
|
+ letter-spacing: 1px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.modal-text-input::placeholder {
|
|
|
|
|
+ font-size: 26px;
|
|
|
|
|
+ font-weight: 500;
|
|
|
|
|
+ color: #b0bec5;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.modal-text-actions {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: 1fr 1.5fr;
|
|
|
|
|
+ gap: 14px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 来访事由选项弹窗 ===== */
|
|
|
|
|
+.modal-reason-card {
|
|
|
|
|
+ width: 560px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.reason-options {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
+ gap: 14px;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.reason-btn {
|
|
|
|
|
+ height: 72px;
|
|
|
|
|
+ font-size: 22px;
|
|
|
|
|
+ font-weight: 700;
|
|
|
|
|
+ color: var(--text-primary);
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.80);
|
|
|
|
|
+ border: 2px solid var(--border-light);
|
|
|
|
|
+ border-radius: 20px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: all 0.18s ease;
|
|
|
|
|
+ letter-spacing: 0.5px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.reason-btn:hover {
|
|
|
|
|
+ background: rgba(59, 130, 246, 0.06);
|
|
|
|
|
+ border-color: rgba(59, 130, 246, 0.30);
|
|
|
|
|
+ transform: translateY(-1px);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.reason-btn:active {
|
|
|
|
|
+ transform: scale(0.97);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.reason-btn-active {
|
|
|
|
|
+ background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ border-color: transparent;
|
|
|
|
|
+ box-shadow: 0 8px 20px rgba(37, 99, 235, 0.24);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.reason-btn-active:hover {
|
|
|
|
|
+ background: linear-gradient(135deg, #2563eb 0%, #1e40af 100%);
|
|
|
|
|
+ border-color: transparent;
|
|
|
|
|
+ box-shadow: 0 10px 24px rgba(37, 99, 235, 0.30);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.modal-reason-actions {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: 1fr 1.5fr;
|
|
|
|
|
+ gap: 14px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 弹窗通用按钮 ===== */
|
|
|
|
|
+.btn-modal-cancel,
|
|
|
|
|
+.btn-modal-save {
|
|
|
|
|
+ height: 72px;
|
|
|
|
|
+ font-size: 24px;
|
|
|
|
|
+ font-weight: 800;
|
|
|
|
|
+ border-radius: 999px;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: all 0.20s ease;
|
|
|
|
|
+ letter-spacing: 1.5px;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn-modal-cancel {
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.80);
|
|
|
|
|
+ color: var(--text-secondary);
|
|
|
|
|
+ border: 2px solid var(--border-light);
|
|
|
|
|
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.06);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn-modal-cancel:hover {
|
|
|
|
|
+ background: rgba(255, 255, 255, 0.95);
|
|
|
|
|
+ border-color: var(--text-muted);
|
|
|
|
|
+ transform: translateY(-1px);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn-modal-save {
|
|
|
|
|
+ background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%);
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ border: none;
|
|
|
|
|
+ box-shadow: 0 10px 24px rgba(37, 99, 235, 0.26);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn-modal-save:hover {
|
|
|
|
|
+ box-shadow: 0 14px 32px rgba(37, 99, 235, 0.34);
|
|
|
|
|
+ transform: translateY(-1px);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.btn-modal-cancel:active,
|
|
|
|
|
+.btn-modal-save:active {
|
|
|
|
|
+ transform: scale(0.97);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* ===== 响应式适配 ===== */
|
|
|
|
|
+@media (max-height: 700px) {
|
|
|
|
|
+ .confirm-content {
|
|
|
|
|
+ padding: 0 24px 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .confirm-hero {
|
|
|
|
|
+ margin: 16px 0 16px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .page-title {
|
|
|
|
|
+ font-size: 32px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .page-subtitle {
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .form-row {
|
|
|
|
|
+ min-height: 68px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .form-label {
|
|
|
|
|
+ font-size: 20px;
|
|
|
|
|
+ width: 120px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .form-value {
|
|
|
|
|
+ font-size: 22px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .confirm-actions {
|
|
|
|
|
+ grid-template-columns: 1fr 1.5fr;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .btn-back,
|
|
|
|
|
+ .btn-confirm {
|
|
|
|
|
+ height: 68px;
|
|
|
|
|
+ font-size: 22px;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
</style>
|
|
</style>
|