| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859 |
- <template>
- <view class="page">
- <view class="card">
- <view class="card-title">信息填写</view>
- <!-- 时间:首行 时间* + 右侧橙色链接;次行并排两个时间选择框 -->
- <view class="section section--time">
- <view class="time-label-row">
- <text class="label label--req">时间</text>
- <text class="link" @tap.stop="openTableInfoPopup">(查看桌台信息)</text>
- </view>
- <view class="time-row">
- <view class="time-col">
- <view class="time-box time-box--readonly">
- <text class="time-clock">🕐</text>
- <text class="time-text">{{ form.startTime || '—' }}</text>
- </view>
- </view>
- <view class="time-col">
- <picker class="time-picker" mode="time" :value="form.endTime" @change="onEndTimeChange">
- <view class="time-box">
- <text class="time-clock">🕐</text>
- <text :class="['time-text', { 'is-placeholder': !form.endTime }]">
- {{ form.endTime || '选择结束时间(次日)' }}
- </text>
- </view>
- </picker>
- </view>
- </view>
- </view>
- <view class="divider" />
- <view class="row">
- <text class="label">姓名</text>
- <input
- v-model="form.name"
- class="input"
- type="text"
- placeholder="请输入姓名"
- placeholder-class="input-ph"
- />
- </view>
- <view class="divider" />
- <view class="row row-gender">
- <text class="label">性别</text>
- <view class="gender-group">
- <view
- class="gender-opt"
- :class="{ active: form.gender === 'mr' }"
- @tap.stop="selectGender('mr')"
- >
- <view class="gender-dot" :class="{ on: form.gender === 'mr' }">
- <view v-if="form.gender === 'mr'" class="gender-dot-inner" />
- </view>
- <text class="gender-txt">先生</text>
- </view>
- <view
- class="gender-opt"
- :class="{ active: form.gender === 'ms' }"
- @tap.stop="selectGender('ms')"
- >
- <view class="gender-dot" :class="{ on: form.gender === 'ms' }">
- <view v-if="form.gender === 'ms'" class="gender-dot-inner" />
- </view>
- <text class="gender-txt">女士</text>
- </view>
- </view>
- </view>
- <view class="divider" />
- <view class="row">
- <text class="label">电话</text>
- <input
- v-model="form.phone"
- class="input"
- type="number"
- maxlength="11"
- placeholder="请输入手机号"
- placeholder-class="input-ph"
- />
- </view>
- <view class="divider" />
- <view class="row row-remark">
- <text class="label label-top">备注</text>
- <view class="remark-wrap">
- <textarea
- v-model="form.remark"
- class="textarea"
- placeholder="请输入"
- placeholder-class="input-ph"
- maxlength="30"
- :show-confirm-bar="false"
- />
- <text class="remark-count">{{ (form.remark || '').length }}/30</text>
- </view>
- </view>
- </view>
- <view class="footer-spacer" />
- <view class="footer-bar">
- <view class="footer-btn hover-active" @click="handleConfirm">确定</view>
- </view>
- <!-- 桌台信息:底部弹窗(可预约时段) -->
- <view v-if="tableInfoPopupOpen" class="table-popup-root">
- <view class="table-popup-mask" @click="closeTableInfoPopup" />
- <view class="table-popup-sheet" @click.stop>
- <view class="table-popup-head">
- <text class="table-popup-title">桌台信息 ({{ tableDisplayCode }})</text>
- <view class="table-popup-close" hover-class="table-popup-close--active" @click="closeTableInfoPopup">
- <text class="table-popup-close-x">×</text>
- </view>
- </view>
- <view class="table-slot-grid">
- <view v-if="tableInfoLoading" class="table-popup-hint">加载中…</view>
- <view v-else-if="!tableTimeSlots.length" class="table-popup-hint table-popup-hint--muted">暂无可预约时段</view>
- <template v-else>
- <view v-for="(slot, i) in tableTimeSlots" :key="i" class="table-slot-tag">
- <text class="table-slot-tag-text">{{ slot.label }}</text>
- </view>
- </template>
- </view>
- <view class="table-popup-safe" />
- </view>
- </view>
- </view>
- </template>
- <script setup>
- import { onLoad } from '@dcloudio/uni-app';
- import { reactive, ref } from 'vue';
- import { useUserStore } from '@/store/user.js';
- import {
- GetReservationDetailByStoreTableRecord,
- GetTableDiningStatus,
- PostDiningWalkInReservation
- } from '@/api/dining.js';
- const userStore = useUserStore();
- /** 桌台信息弹窗 */
- const tableInfoPopupOpen = ref(false);
- const tableInfoLoading = ref(false);
- const tableDisplayCode = ref('—');
- /** 桌台可预约时段(接口返回),仅展示 */
- const tableTimeSlots = ref([]);
- const form = reactive({
- startTime: '',
- endTime: '',
- name: '',
- gender: '', // mr 先生 / ms 女士
- phone: '',
- remark: ''
- });
- /** 统一性别为 mr/ms,兼容接口/缓存/用户信息中的多种写法 */
- function normalizeGender(val) {
- if (val == null || val === '') return '';
- const raw = String(val).trim();
- const s = raw.toLowerCase();
- if (raw === '男' || raw === '先生') return 'mr';
- if (raw === '女' || raw === '女士') return 'ms';
- if (['mr', 'male', 'm', '1'].includes(s)) return 'mr';
- if (['ms', 'female', 'f', '2'].includes(s)) return 'ms';
- return '';
- }
- function selectGender(v) {
- form.gender = v === 'ms' ? 'ms' : 'mr';
- }
- function syncPhoneFromUser() {
- const u = userStore.getUserInfo || {};
- const p = u.phone ?? u.mobile ?? u.contactPhone ?? '';
- if (p && !form.phone) form.phone = String(p);
- const n = u.nickName ?? u.nickname ?? u.name ?? '';
- if (n && !form.name) form.name = String(n);
- }
- /** 开始时间固定为进入页时的当前时间(HH:mm),不可改 */
- function initStartTimeToNow() {
- const d = new Date();
- const h = String(d.getHours()).padStart(2, '0');
- const m = String(d.getMinutes()).padStart(2, '0');
- form.startTime = `${h}:${m}`;
- }
- onLoad(() => {
- initStartTimeToNow();
- syncPhoneFromUser();
- try {
- const raw = uni.getStorageSync('diningForm');
- if (raw && typeof raw === 'string') {
- const o = JSON.parse(raw);
- if (o && typeof o === 'object') {
- // 不恢复 startTime,始终以当前时间为准
- if (o.endTime) form.endTime = o.endTime;
- if (o.name) form.name = o.name;
- const gCached = normalizeGender(o.gender);
- if (gCached) form.gender = gCached;
- if (o.phone) form.phone = o.phone;
- if (o.remark) form.remark = o.remark;
- }
- }
- } catch {
- /* ignore */
- }
- // 缓存未带性别时,从登录用户信息同步(男/女、mile/female 等)
- if (!form.gender) {
- const u = userStore.getUserInfo || {};
- const gUser = normalizeGender(u.gender);
- if (gUser) form.gender = gUser;
- }
- // 缓存恢复的结束时间若早于开始时间(同日),清空需重选
- if (form.endTime && form.startTime && !isEndAfterStartSameDay(form.endTime, form.startTime)) {
- form.endTime = '';
- }
- });
- /** HH:mm 转当天分钟数 */
- function timeStrToMinutes(t) {
- if (t == null || t === '') return NaN;
- const parts = String(t).trim().split(':');
- const h = parseInt(parts[0], 10);
- const m = parseInt(parts[1] ?? '0', 10);
- if (Number.isNaN(h) || Number.isNaN(m)) return NaN;
- return h * 60 + m;
- }
- /** 同日:结束时间须严格大于开始时间 */
- function isEndAfterStartSameDay(endStr, startStr) {
- const end = timeStrToMinutes(endStr);
- const start = timeStrToMinutes(startStr);
- if (Number.isNaN(end) || Number.isNaN(start)) return false;
- return end > start;
- }
- const END_AFTER_START_TIP = '结束时间大于开始时间(同日)';
- function onEndTimeChange(e) {
- const end = e.detail.value || '';
- if (!end) {
- form.endTime = '';
- return;
- }
- if (form.startTime && !isEndAfterStartSameDay(end, form.startTime)) {
- uni.showToast({ title: END_AFTER_START_TIP, icon: 'none' });
- return;
- }
- form.endTime = end;
- }
- function resolveTableDisplayCode() {
- const no =
- uni.getStorageSync('currentTableNumber') ||
- uni.getStorageSync('currentTableNo') ||
- uni.getStorageSync('tableNumber') ||
- '';
- const tid = uni.getStorageSync('currentTableId') || '';
- if (no) return String(no);
- if (tid) return String(tid);
- return '—';
- }
- /** 桌台信息弹窗标题:优先用 /store/dining/table-dining-status 返回的 tableNumber */
- function pickTableNumberFromDiningStatus(data) {
- if (data == null || typeof data !== 'object') return '';
- const d = data.data != null && typeof data.data === 'object' ? data.data : data;
- const n = d.tableNumber ?? d.tableNo ?? d.tableName ?? d.tableCode;
- return n != null && n !== '' ? String(n) : '';
- }
- /** 从预约详情里取桌号展示文案 */
- function pickTableDisplayFromDetail(data, fallbackTableId) {
- const r = data?.record && typeof data.record === 'object' ? data.record : data;
- if (!r || typeof r !== 'object') {
- const fb = resolveTableDisplayCode();
- return fb !== '—' ? fb : String(fallbackTableId || '—');
- }
- const code =
- r.tableNumber ??
- r.tableNo ??
- r.tableName ??
- r.tableCode ??
- data?.tableNumber ??
- data?.tableNo ??
- r.tableId ??
- data?.tableId;
- if (code != null && code !== '') return String(code);
- const fb = resolveTableDisplayCode();
- return fb !== '—' ? fb : String(fallbackTableId || '—');
- }
- function mapListToSlotLabels(list) {
- if (!Array.isArray(list)) return [];
- return list
- .map((item) => {
- if (item == null) return null;
- if (typeof item === 'string') return { label: item };
- const start = item.startTime ?? item.start ?? item.begin ?? '';
- const end = item.endTime ?? item.end ?? item.finish ?? '';
- if (start !== '' && end !== '') {
- const s = String(start).length > 5 ? String(start).slice(11, 16) : String(start).slice(0, 5);
- const e = String(end).length > 5 ? String(end).slice(11, 16) : String(end).slice(0, 5);
- return { label: `${s}–${e}` };
- }
- const label = item.label ?? item.timeRange ?? item.slotText ?? item.name ?? item.text ?? '';
- return label ? { label: String(label) } : null;
- })
- .filter(Boolean);
- }
- /** 从预约详情里解析可预约时段列表 */
- function mapReservationSlots(data) {
- if (Array.isArray(data)) return mapListToSlotLabels(data);
- if (!data || typeof data !== 'object') return [];
- const nested = data.record && typeof data.record === 'object' ? data.record : {};
- const list =
- data.timeSlots ??
- data.timeSlotList ??
- data.slots ??
- data.reservableTimeSlots ??
- data.periods ??
- data.availableSlots ??
- data.reservationSlots ??
- nested.timeSlots ??
- nested.slots ??
- (Array.isArray(data.list) ? data.list : null) ??
- (Array.isArray(data.records) ? data.records : null);
- return mapListToSlotLabels(list);
- }
- async function openTableInfoPopup() {
- const storeId = uni.getStorageSync('currentStoreId') || '';
- const tableId = uni.getStorageSync('currentTableId') || '';
- if (!storeId || !tableId) {
- uni.showToast({ title: '缺少门店或桌台信息', icon: 'none' });
- return;
- }
- tableDisplayCode.value = resolveTableDisplayCode();
- tableTimeSlots.value = [];
- tableInfoLoading.value = true;
- tableInfoPopupOpen.value = true;
- let titleFromDiningStatus = '';
- try {
- const statusData = await GetTableDiningStatus(tableId, { loading: false });
- titleFromDiningStatus = pickTableNumberFromDiningStatus(statusData);
- if (titleFromDiningStatus) tableDisplayCode.value = titleFromDiningStatus;
- } catch {
- /* 标题保持本地缓存/桌号兜底 */
- }
- try {
- const data = await GetReservationDetailByStoreTableRecord({
- storeId,
- userReservationTableId: tableId
- });
- if (!titleFromDiningStatus) {
- tableDisplayCode.value = pickTableDisplayFromDetail(data, tableId);
- }
- tableTimeSlots.value = mapReservationSlots(data);
- } catch {
- tableTimeSlots.value = [];
- if (!titleFromDiningStatus) {
- tableDisplayCode.value = resolveTableDisplayCode();
- }
- } finally {
- tableInfoLoading.value = false;
- }
- }
- function closeTableInfoPopup() {
- tableInfoPopupOpen.value = false;
- }
- /** 表单性别 mr/ms → 接口 reservationUserGender:0 男 1 女 */
- function genderToReservationCode(g) {
- if (g === 'mr') return '0';
- if (g === 'ms') return '1';
- return '';
- }
- /** walk-in 接口要求 startTime/endTime 为 yyyy-MM-dd HH:mm;日期用当天(本地日历),时间与页面 HH:mm 一致 */
- function toWalkInApiDateTime(hhmm) {
- if (hhmm == null || hhmm === '') return '';
- const parts = String(hhmm).trim().split(':');
- let h = parseInt(parts[0], 10);
- let m = parseInt(parts[1] ?? '0', 10);
- if (Number.isNaN(h)) h = 0;
- if (Number.isNaN(m)) m = 0;
- const hStr = String(Math.min(23, Math.max(0, h))).padStart(2, '0');
- const mStr = String(Math.min(59, Math.max(0, m))).padStart(2, '0');
- const d = new Date();
- const y = d.getFullYear();
- const mo = String(d.getMonth() + 1).padStart(2, '0');
- const day = String(d.getDate()).padStart(2, '0');
- return `${y}-${mo}-${day} ${hStr}:${mStr}`;
- }
- async function handleConfirm() {
- if (!form.startTime || !form.endTime) {
- uni.showToast({ title: '请选择用餐时间', icon: 'none' });
- return;
- }
- if (!isEndAfterStartSameDay(form.endTime, form.startTime)) {
- uni.showToast({ title: END_AFTER_START_TIP, icon: 'none' });
- return;
- }
- const tableid = uni.getStorageSync('currentTableId') || '';
- const diners = uni.getStorageSync('currentDiners') ?? '1';
- if (!tableid) {
- uni.showToast({ title: '缺少桌台信息', icon: 'none' });
- return;
- }
- const phone = (form.phone || '').trim();
- if (!phone) {
- uni.showToast({ title: '请输入手机号', icon: 'none' });
- return;
- }
- const guestCount = parseInt(String(diners), 10);
- if (!Number.isFinite(guestCount) || guestCount < 1) {
- uni.showToast({ title: '就餐人数异常', icon: 'none' });
- return;
- }
- const tableIdNum = parseInt(String(tableid), 10);
- if (Number.isNaN(tableIdNum)) {
- uni.showToast({ title: '桌台信息异常', icon: 'none' });
- return;
- }
- const dto = {
- tableId: tableIdNum,
- guestCount,
- reservationUserPhone: phone,
- startTime: toWalkInApiDateTime(form.startTime),
- endTime: toWalkInApiDateTime(form.endTime)
- };
- const name = (form.name || '').trim();
- if (name) dto.reservationUserName = name;
- const genderCode = genderToReservationCode(form.gender);
- if (genderCode !== '') dto.reservationUserGender = genderCode;
- const remark = (form.remark || '').trim().slice(0, 30);
- if (remark) dto.remark = remark;
- try {
- await PostDiningWalkInReservation(dto);
- } catch {
- return;
- }
- uni.setStorageSync(
- 'diningForm',
- JSON.stringify({
- startTime: form.startTime,
- endTime: form.endTime,
- endNextDay: true,
- name: form.name.trim(),
- gender: form.gender === 'mr' || form.gender === 'ms' ? form.gender : '',
- phone: form.phone.trim(),
- remark: (form.remark || '').trim()
- })
- );
- uni.redirectTo({
- url: `/pages/orderFood/index?tableid=${encodeURIComponent(String(tableid))}&diners=${encodeURIComponent(String(diners))}`
- });
- }
- </script>
- <style lang="scss" scoped>
- .page {
- min-height: 100vh;
- background: #f2f3f5;
- padding: 24rpx 30rpx 200rpx;
- box-sizing: border-box;
- }
- .card {
- background: #fff;
- border-radius: 20rpx;
- padding: 36rpx 30rpx 32rpx;
- box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.04);
- }
- .card-title {
- font-size: 32rpx;
- font-weight: 600;
- color: #151515;
- margin-bottom: 28rpx;
- letter-spacing: 0.5rpx;
- }
- .section--time {
- padding-bottom: 8rpx;
- }
- /* 时间:「时间*」与「查看桌台信息」均靠左同一行 */
- .time-label-row {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- flex-wrap: wrap;
- gap: 8rpx 20rpx;
- margin-bottom: 20rpx;
- }
- .label {
- font-size: 28rpx;
- color: #333333;
- flex-shrink: 0;
- min-width: 100rpx;
- }
- .label--req::after {
- content: '*';
- color: #e61f19;
- margin-left: 2rpx;
- }
- .link {
- font-size: 26rpx;
- color: #ff7a2e;
- flex-shrink: 0;
- }
- .time-row {
- display: flex;
- flex-direction: row;
- gap: 20rpx;
- }
- .time-col {
- flex: 1;
- min-width: 0;
- }
- .time-picker {
- display: block;
- width: 100%;
- }
- .time-box {
- width: 100%;
- display: flex;
- flex-direction: row;
- align-items: center;
- gap: 10rpx;
- padding: 22rpx 18rpx;
- background: #ffffff;
- border-radius: 8rpx;
- border: 1rpx solid #e8e8e8;
- min-height: 80rpx;
- box-sizing: border-box;
- }
- .time-box--readonly {
- pointer-events: none;
- }
- .time-clock {
- font-size: 30rpx;
- line-height: 1;
- flex-shrink: 0;
- opacity: 0.45;
- }
- .time-text {
- font-size: 26rpx;
- color: #333333;
- flex: 1;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .time-text.is-placeholder {
- color: #bbbbbb;
- }
- .divider {
- height: 1rpx;
- background: #eeeeee;
- margin: 0 -6rpx;
- }
- .row {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: flex-start;
- gap: 24rpx;
- min-height: 100rpx;
- padding: 8rpx 0;
- }
- .row .label {
- width: 120rpx;
- min-width: 120rpx;
- }
- .row-gender {
- align-items: center;
- }
- .row-remark {
- align-items: flex-start;
- padding-top: 20rpx;
- padding-bottom: 12rpx;
- }
- .label-top {
- padding-top: 12rpx;
- }
- .input {
- flex: 1;
- min-width: 0;
- text-align:start;
- font-size: 28rpx;
- color: #333333;
- height: 72rpx;
- line-height: 72rpx;
- }
- .input-ph {
- color: #bbbbbb;
- }
- .gender-group {
- flex: 1;
- display: flex;
- flex-direction: row;
- justify-content: flex-start;
- align-items: center;
- gap: 48rpx;
- min-width: 0;
- }
- .gender-opt {
- display: flex;
- flex-direction: row;
- align-items: center;
- gap: 14rpx;
- }
- .gender-txt {
- font-size: 28rpx;
- color: #666666;
- }
- .gender-opt.active .gender-txt {
- color: #333333;
- }
- /* 未选:空心圆;已选:橙圈 + 内点 */
- .gender-dot {
- width: 32rpx;
- height: 32rpx;
- border-radius: 50%;
- border: 2rpx solid #cccccc;
- box-sizing: border-box;
- flex-shrink: 0;
- background: transparent;
- display: flex;
- align-items: center;
- justify-content: center;
- }
- .gender-dot.on {
- border-color: #fc743d;
- }
- .gender-dot-inner {
- width: 16rpx;
- height: 16rpx;
- border-radius: 50%;
- background: #fc743d;
- }
- .remark-wrap {
- flex: 1;
- min-width: 0;
- position: relative;
- }
- .textarea {
- width: 100%;
- min-height: 176rpx;
- padding: 20rpx 20rpx 48rpx 0;
- box-sizing: border-box;
- font-size: 28rpx;
- color: #333333;
- line-height: 1.5;
- background: #ffffff;
- border-radius: 8rpx;
- border: none;
- }
- .remark-count {
- position: absolute;
- right: 20rpx;
- bottom: 16rpx;
- font-size: 22rpx;
- color: #cccccc;
- }
- .footer-spacer {
- height: 24rpx;
- }
- .footer-bar {
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- padding: 24rpx 40rpx calc(24rpx + env(safe-area-inset-bottom));
- background: linear-gradient(180deg, rgba(242, 243, 245, 0) 0%, #f2f3f5 28%);
- box-sizing: border-box;
- z-index: 100;
- }
- .footer-btn {
- height: 92rpx;
- line-height: 92rpx;
- text-align: center;
- font-size: 32rpx;
- font-weight: 500;
- color: #ffffff;
- border-radius: 46rpx;
- background: linear-gradient(90deg, #fcb73f 0%, #fc743d 100%);
- box-shadow: 0 8rpx 24rpx rgba(252, 116, 61, 0.35);
- }
- .footer-btn.hover-active:active {
- opacity: 0.92;
- }
- /* ========== 桌台信息底部弹窗 ========== */
- .table-popup-root {
- position: fixed;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- z-index: 1000;
- pointer-events: none;
- }
- .table-popup-mask {
- position: absolute;
- left: 0;
- right: 0;
- top: 0;
- bottom: 0;
- background: rgba(0, 0, 0, 0.5);
- pointer-events: auto;
- }
- .table-popup-sheet {
- position: absolute;
- left: 0;
- right: 0;
- bottom: 0;
- background: #ffffff;
- border-radius: 24rpx 24rpx 0 0;
- padding: 28rpx 30rpx 0;
- box-sizing: border-box;
- max-height: 72vh;
- pointer-events: auto;
- box-shadow: 0 -8rpx 40rpx rgba(0, 0, 0, 0.12);
- }
- .table-popup-head {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- padding-bottom: 28rpx;
- border-bottom: 1rpx solid #f0f0f0;
- }
- .table-popup-title {
- font-size: 32rpx;
- font-weight: 600;
- color: #151515;
- }
- .table-popup-close {
- width: 56rpx;
- height: 56rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- margin-right: -8rpx;
- }
- .table-popup-close-x {
- font-size: 44rpx;
- color: #999999;
- line-height: 1;
- font-weight: 300;
- }
- .table-popup-close--active .table-popup-close-x,
- .table-popup-close:active .table-popup-close-x {
- color: #666666;
- }
- .table-slot-grid {
- display: flex;
- flex-direction: row;
- flex-wrap: wrap;
- padding: 32rpx 0 8rpx;
- gap: 20rpx 16rpx;
- }
- .table-popup-hint {
- width: 100%;
- padding: 24rpx 0 40rpx;
- font-size: 28rpx;
- color: #666666;
- text-align: center;
- }
- .table-popup-hint--muted {
- color: #999999;
- }
- .table-slot-tag {
- width: calc((100% - 32rpx) / 3);
- box-sizing: border-box;
- padding: 22rpx 12rpx;
- background: #f5f5f5;
- border-radius: 12rpx;
- display: flex;
- align-items: center;
- justify-content: center;
- min-height: 72rpx;
- }
- .table-slot-tag-text {
- font-size: 26rpx;
- color: #666666;
- text-align: center;
- line-height: 1.35;
- }
- .table-popup-safe {
- height: calc(24rpx + env(safe-area-inset-bottom));
- min-height: 24rpx;
- }
- </style>
|