| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="notice-page"> |
| | | <PageHeader title="éç¥å
Œ" @back="goBack" /> |
| | | <!-- æç´¢è¡¨å --> |
| | | <!-- <view class="search_form"> |
| | | <up-button type="primary" size="small" @click="openForm('add')">æ°å¢å
Œ</up-button> |
| | | <up-button type="error" size="small" plain @click="handleDeleteBatch" :disabled="!selectedIds.length"> |
| | | å é¤ |
| | | </up-button> |
| | | </view> --> |
| | | |
| | | <!-- éç¥å
¬åæ¿ --> |
| | | <view class="notice-board"> |
| | | <!-- ç»ä¸éç¥åºå --> |
| | | <view class="notice-section" v-if="totalNoticeCount > 0"> |
| | | <view class="section-header"> |
| | | <h3>� éç¥å
Œ</h3> |
| | | <text class="section-count">{{ totalNoticeCount }}æ¡</text> |
| | | </view> |
| | | <view class="notice-cards"> |
| | | <!-- æ¾åéç¥ --> |
| | | <view |
| | | v-for="notice in holidayNotices" |
| | | :key="'holiday-' + notice.id" |
| | | class="notice-card holiday-card" |
| | | :class="{ 'urgent': notice.priority === '3' }" |
| | | > |
| | | <view class="card-header"> |
| | | <view class="card-title"> |
| | | <view class="holiday-icon"> |
| | | <up-icon name="calendar" size="18" color="#67c23a" /> |
| | | </view> |
| | | <text>{{ notice.title }}</text> |
| | | </view> |
| | | <!-- <view class="card-actions">--> |
| | | <!-- <up-button--> |
| | | <!-- text--> |
| | | <!-- type="primary"--> |
| | | <!-- size="mini"--> |
| | | <!-- @click="handleEdit(notice)"--> |
| | | <!-- :disabled="isNoticeExpired(notice)"--> |
| | | <!-- >--> |
| | | <!-- ç¼è¾--> |
| | | <!-- </up-button>--> |
| | | <!-- <up-button--> |
| | | <!-- text--> |
| | | <!-- type="error"--> |
| | | <!-- size="mini"--> |
| | | <!-- @click="handleDelete(notice.id)"--> |
| | | <!-- >--> |
| | | <!-- å é¤--> |
| | | <!-- </up-button>--> |
| | | <!-- </view>--> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>{{ notice.content }}</text> |
| | | </view> |
| | | <view class="card-footer"> |
| | | <view class="card-meta"> |
| | | <text class="type" :class="'type-' + notice.type"> |
| | | {{ notice.type }} |
| | | </text> |
| | | <text class="priority" :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </text> |
| | | <text class="status" :class="'status-' + getNoticeStatus(notice)"> |
| | | {{ getStatusText(getNoticeStatus(notice)) }} |
| | | </text> |
| | | </view> |
| | | <view class="card-info"> |
| | | <text class="creator">{{ notice.createUserName }}</text> |
| | | <text class="expiration" v-if="notice.expirationDate">æªæ¢æ¥æï¼{{ notice.expirationDate }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="card-remark" v-if="notice.remark"> |
| | | <up-icon name="info-circle" size="16" color="#409eff" /> |
| | | <text>{{ notice.remark }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 设å¤ç»´ä¿®éç¥ --> |
| | | <view |
| | | v-for="notice in maintenanceNotices" |
| | | :key="'maintenance-' + notice.id" |
| | | class="notice-card maintenance-card" |
| | | :class="{ 'urgent': notice.priority === '3' }" |
| | | > |
| | | <view class="card-header"> |
| | | <view class="card-title"> |
| | | <view class="maintenance-icon"> |
| | | <up-icon name="wrench" size="18" color="#e6a23c" /> |
| | | </view> |
| | | <text>{{ notice.title }}</text> |
| | | </view> |
| | | <view class="card-actions"> |
| | | <up-button |
| | | text |
| | | type="primary" |
| | | size="mini" |
| | | @click="handleEdit(notice)" |
| | | :disabled="isNoticeExpired(notice)" |
| | | > |
| | | ç¼è¾ |
| | | </up-button> |
| | | <up-button |
| | | text |
| | | type="error" |
| | | size="mini" |
| | | @click="handleDelete(notice.id)" |
| | | > |
| | | å é¤ |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>{{ notice.content }}</text> |
| | | </view> |
| | | <view class="card-footer"> |
| | | <view class="card-meta"> |
| | | <text class="priority" :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </text> |
| | | <text class="status" :class="'status-' + getNoticeStatus(notice)"> |
| | | {{ getStatusText(getNoticeStatus(notice)) }} |
| | | </text> |
| | | </view> |
| | | <view class="card-info"> |
| | | <text class="creator">{{ notice.createUserName }}</text> |
| | | <text class="expiration" v-if="notice.expirationDate">æªæ¢æ¥æï¼{{ notice.expirationDate }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="card-remark" v-if="notice.remark"> |
| | | <up-icon name="info-circle" size="16" color="#409eff" /> |
| | | <text>{{ notice.remark }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- ç©ºç¶æ --> |
| | | <view class="empty-state" v-if="holidayNotices.length === 0 && maintenanceNotices.length === 0"> |
| | | <text>ææ éç¥å
Œ</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æ°å¢/ç¼è¾å¼¹çª --> |
| | | <up-popup |
| | | v-model:show="dialogVisible" |
| | | mode="bottom" |
| | | :round="18" |
| | | :safeAreaInsetBottom="true" |
| | | @close="resetForm" |
| | | > |
| | | <view class="dialog-container"> |
| | | <view class="dialog-header"> |
| | | <text class="dialog-title">{{ dialogTitle }}</text> |
| | | </view> |
| | | <view class="dialog-body"> |
| | | <up-form |
| | | ref="formRef" |
| | | :model="form" |
| | | :rules="rules" |
| | | labelWidth="80" |
| | | > |
| | | <up-form-item label="å
¬åæ é¢" prop="title"> |
| | | <up-input v-model="form.title" placeholder="请è¾å
¥å
¬åæ é¢" /> |
| | | </up-form-item> |
| | | <up-form-item label="å
¬åç±»å" prop="type"> |
| | | <up-input v-model="form.type" placeholder="请è¾å
¥å
¬åç±»å" /> |
| | | </up-form-item> |
| | | <up-form-item label="ç¶æ"> |
| | | <up-radio-group v-model="form.status"> |
| | | <up-radio :name="0">è稿</up-radio> |
| | | <up-radio :name="1">æ£å¼åå¸</up-radio> |
| | | </up-radio-group> |
| | | </up-form-item> |
| | | <up-form-item label="ä¼å
级" prop="priority"> |
| | | <up-select |
| | | v-model="form.priority" |
| | | :options="priorityOptions" |
| | | placeholder="è¯·éæ©ä¼å
级" |
| | | /> |
| | | </up-form-item> |
| | | <up-form-item label="è¿ææ¶é´" prop="expirationDate"> |
| | | <up-datetime-picker |
| | | v-model="form.expirationDate" |
| | | mode="date" |
| | | @confirm="onExpireConfirm" |
| | | > |
| | | <up-input |
| | | :value="form.expirationDate" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | readonly |
| | | /> |
| | | </up-datetime-picker> |
| | | </up-form-item> |
| | | <up-form-item label="å
¬åå
容" prop="content"> |
| | | <up-textarea |
| | | v-model="form.content" |
| | | placeholder="请è¾å
¥å
¬åå
容" |
| | | :maxlength="500" |
| | | count |
| | | /> |
| | | </up-form-item> |
| | | <up-form-item label="夿³¨"> |
| | | <up-textarea |
| | | v-model="form.remark" |
| | | placeholder="请è¾å
¥å¤æ³¨ä¿¡æ¯" |
| | | :maxlength="200" |
| | | count |
| | | /> |
| | | </up-form-item> |
| | | </up-form> |
| | | </view> |
| | | <view class="dialog-footer"> |
| | | <up-button |
| | | text="åæ¶" |
| | | type="info" |
| | | plain |
| | | @click="dialogVisible = false" |
| | | :customStyle="{ marginRight: '10px', flex: 1 }" |
| | | /> |
| | | <up-button |
| | | text="ç¡®å®" |
| | | type="primary" |
| | | @click="submitForm" |
| | | :customStyle="{ flex: 1 }" |
| | | /> |
| | | </view> |
| | | </view> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref, reactive, toRefs } from "vue"; |
| | | import { onReachBottom } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { |
| | | addNotice, |
| | | delNotice, |
| | | getCount, |
| | | listNotice, |
| | | updateNotice |
| | | } from "@/api/collaborativeApproval/noticeManagement.js"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: undefined, |
| | | status: undefined, |
| | | }, |
| | | form: { |
| | | id: undefined, |
| | | title: "", |
| | | type: null, |
| | | content: "", |
| | | status: 0, |
| | | priority: 1, |
| | | remark: "", |
| | | expirationDate: "", |
| | | }, |
| | | rules: { |
| | | title: [ |
| | | {required: true, message: "å
¬åæ é¢ä¸è½ä¸ºç©º", trigger: "blur"} |
| | | ], |
| | | type: [ |
| | | {required: true, message: "è¯·éæ©å
¬åç±»å", trigger: "change"} |
| | | ], |
| | | content: [ |
| | | {required: true, message: "å
¬åå
容ä¸è½ä¸ºç©º", trigger: "blur"} |
| | | ], |
| | | expirationDate: [ |
| | | {required: true, message: "è¯·éæ©æ¥æ", trigger: "change"} |
| | | ] |
| | | } |
| | | }); |
| | | |
| | | const {searchForm, form, rules} = toRefs(data); |
| | | |
| | | // 页é¢ç¶æ |
| | | const dialogVisible = ref(false); |
| | | const dialogTitle = ref(""); |
| | | const selectedIds = ref([]); |
| | | const formRef = ref(); |
| | | |
| | | const priorityOptions = [ |
| | | { label: "æ®é", value: 1 }, |
| | | { label: "éè¦", value: 2 }, |
| | | { label: "ç´§æ¥", value: 3 }, |
| | | ]; |
| | | |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | const onExpireConfirm = (e) => { |
| | | if (!e) return; |
| | | // uview-plus datetime-picker confirm äºä»¶è¿åç value |
| | | const value = e.value || e; |
| | | form.value.expirationDate = value; |
| | | }; |
| | | |
| | | |
| | | const getPriorityText = (priority) => { |
| | | const priorityMap = {"1": "æ®é", "2": "éè¦", "3": "ç´§æ¥"}; |
| | | return priorityMap[priority] || "æ®é"; |
| | | }; |
| | | |
| | | const getStatusText = (status) => { |
| | | const statusMap = {"0": "è稿", "1": "å·²åå¸", "2": "å·²è¿æ"}; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | |
| | | const isNoticeExpired = (notice) => { |
| | | if (!notice || !notice.expirationDate) { |
| | | return false; |
| | | } |
| | | |
| | | const expiration = new Date(notice.expirationDate); |
| | | |
| | | if (Number.isNaN(expiration.getTime())) { |
| | | return false; |
| | | } |
| | | |
| | | expiration.setHours(23, 59, 59, 999); |
| | | |
| | | return new Date() > expiration; |
| | | }; |
| | | |
| | | const getNoticeStatus = (notice) => { |
| | | const normalizedStatus = notice && notice.status !== undefined && notice.status !== null |
| | | ? String(notice.status) |
| | | : "0"; |
| | | |
| | | return isNoticeExpired(notice) ? "2" : normalizedStatus; |
| | | }; |
| | | |
| | | const openForm = (type) => { |
| | | if (type === 'add') { |
| | | dialogTitle.value = "æ°å¢å
Œ"; |
| | | form.value = { |
| | | id: undefined, |
| | | title: "", |
| | | type: undefined, |
| | | content: "", |
| | | status: 0, |
| | | priority: 1, |
| | | remark: "", |
| | | expirationDate: "", |
| | | }; |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleEdit = (row) => { |
| | | if (isNoticeExpired(row)) { |
| | | uni.showToast({ |
| | | title: "å·²è¿æçå
¬åä¸å¯ç¼è¾", |
| | | icon: "none" |
| | | }); |
| | | return; |
| | | } |
| | | dialogTitle.value = "ç¼è¾å
Œ"; |
| | | form.value = {...row}; |
| | | dialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleDelete = (id) => { |
| | | if (!id) return; |
| | | uni.showModal({ |
| | | title: "æç¤º", |
| | | content: "确认å é¤è¿æ¡å
¬ååï¼", |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | delNotice(id).then(() => { |
| | | uni.showToast({ |
| | | title: "å 餿å", |
| | | icon: "success" |
| | | }); |
| | | resetTable(); |
| | | }); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // é¢çæ¹éå é¤ï¼ç®åæªå®ç°éä¸é»è¾ï¼ä»
å ä½ï¼ |
| | | const handleDeleteBatch = () => { |
| | | if (!selectedIds.value.length) return; |
| | | uni.showModal({ |
| | | title: "æç¤º", |
| | | content: "确认å é¤éä¸çå
¬ååï¼", |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | // æ ¹æ®selectedIdsæ§è¡æ¹éå é¤é»è¾ï¼å¯æéæ©å±ï¼ |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const submitForm = () => { |
| | | formRef.value.validate((valid) => { |
| | | if (valid) { |
| | | if (form.value.id) { |
| | | // ç¼è¾æ¨¡å¼ |
| | | updateNotice(form.value).then(res => { |
| | | uni.showToast({ |
| | | title: "ä¿®æ¹æå", |
| | | icon: "success" |
| | | }); |
| | | resetTable(); |
| | | }) |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | addNotice(form.value).then(res => { |
| | | uni.showToast({ |
| | | title: "æ°å¢æå", |
| | | icon: "success" |
| | | }); |
| | | resetTable(); |
| | | }) |
| | | } |
| | | dialogVisible.value = false; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const totalNoticeCount = ref(0) |
| | | const fetchCount = () => { |
| | | getCount().then(res => { |
| | | totalNoticeCount.value = res.data.reduce((total, item) => total + item.count, 0); |
| | | }); |
| | | } |
| | | |
| | | const holidayNotices = ref([]) |
| | | const maintenanceNotices = ref([]) |
| | | const holidayNoticePage = ref({ |
| | | total: 0, |
| | | current: 1, |
| | | size: 9 |
| | | }) |
| | | |
| | | const maintenanceNoticePage = ref({ |
| | | total: 0, |
| | | current: 1, |
| | | size: 9 |
| | | }) |
| | | |
| | | const isLoadingMore = ref(false) |
| | | |
| | | const fetchHolidayNotices = (append = false) => { |
| | | listNotice({...holidayNoticePage.value}).then(res => { |
| | | const records = res?.data?.records || [] |
| | | holidayNoticePage.value.total = res?.data?.total || 0 |
| | | if (append && holidayNotices.value.length) { |
| | | holidayNotices.value = [...holidayNotices.value, ...records] |
| | | } else { |
| | | holidayNotices.value = records |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const fetchMaintenanceNotices = (append = false) => { |
| | | listNotice({...holidayNoticePage.value, type: 2}).then(res => { |
| | | const records = res?.data?.records || [] |
| | | maintenanceNoticePage.value.total = res?.data?.total || 0 |
| | | if (append && maintenanceNotices.value.length) { |
| | | maintenanceNotices.value = [...maintenanceNotices.value, ...records] |
| | | } else { |
| | | maintenanceNotices.value = records |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleCurrentChange = (val) => { |
| | | holidayNoticePage.value.size = val.limit |
| | | holidayNoticePage.value.current = val.page |
| | | maintenanceNoticePage.value.size = val.limit |
| | | maintenanceNoticePage.value.current = val.page |
| | | fetchHolidayNotices() |
| | | fetchMaintenanceNotices() |
| | | }; |
| | | |
| | | const resetTable = () => { |
| | | holidayNoticePage.value.current = 1 |
| | | holidayNoticePage.value.size = 9 |
| | | maintenanceNoticePage.value.current = 1 |
| | | maintenanceNoticePage.value.size = 9 |
| | | fetchHolidayNotices() |
| | | fetchMaintenanceNotices() |
| | | fetchCount() |
| | | }; |
| | | |
| | | const resetForm = () => { |
| | | formRef.value?.resetFields(); |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | fetchCount() |
| | | fetchHolidayNotices() |
| | | fetchMaintenanceNotices() |
| | | }); |
| | | |
| | | // ä¸åå è½½æ´å¤ |
| | | onReachBottom(() => { |
| | | if (isLoadingMore.value) return; |
| | | isLoadingMore.value = true; |
| | | |
| | | holidayNoticePage.value.current += 1; |
| | | maintenanceNoticePage.value.current += 1; |
| | | |
| | | Promise.all([ |
| | | new Promise((resolve) => { |
| | | fetchHolidayNotices(true); |
| | | resolve(); |
| | | }), |
| | | new Promise((resolve) => { |
| | | fetchMaintenanceNotices(true); |
| | | resolve(); |
| | | }) |
| | | ]).finally(() => { |
| | | isLoadingMore.value = false; |
| | | }); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .notice-page { |
| | | min-height: 100vh; |
| | | background: #f5f7fa; |
| | | padding-bottom: 16px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .search_form { |
| | | background: #ffffff; |
| | | padding: 12px 16px; |
| | | margin: 8px 12px 12px; |
| | | border-radius: 10px; |
| | | box-shadow: 0 4px 12px rgba(0, 0, 0, 0.04); |
| | | display: flex; |
| | | justify-content: flex-start; |
| | | align-items: center; |
| | | } |
| | | |
| | | .search_title { |
| | | font-weight: 500; |
| | | color: #333; |
| | | margin-right: 8px; |
| | | } |
| | | |
| | | .ml10 { |
| | | margin-left: 10px; |
| | | } |
| | | |
| | | .notice-board { |
| | | padding: 0 12px 16px; |
| | | } |
| | | |
| | | .notice-section { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | align-items: center; |
| | | margin: 4px 4px 12px; |
| | | } |
| | | |
| | | .section-header h3 { |
| | | margin: 0; |
| | | color: #303133; |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .section-count { |
| | | margin-left: 10px; |
| | | background: #409eff; |
| | | color: white; |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | } |
| | | |
| | | .notice-cards { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .notice-card { |
| | | background: white; |
| | | border-radius: 12px; |
| | | padding: 14px 14px 10px; |
| | | box-shadow: 0 4px 10px rgba(15, 23, 42, 0.06); |
| | | transition: all 0.3s ease; |
| | | border-left: 4px solid transparent; |
| | | } |
| | | |
| | | .notice-card:hover { |
| | | transform: translateY(-2px); |
| | | box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); |
| | | } |
| | | |
| | | .holiday-card { |
| | | border-left-color: #67c23a; |
| | | } |
| | | |
| | | .maintenance-card { |
| | | border-left-color: #e6a23c; |
| | | } |
| | | |
| | | .urgent { |
| | | border-left-color: #f56c6c; |
| | | background: linear-gradient(135deg, #fff5f5 0%, #ffffff 100%); |
| | | } |
| | | |
| | | .card-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: flex-start; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-title { |
| | | display: flex; |
| | | align-items: center; |
| | | font-size: 15px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | flex: 1; |
| | | } |
| | | |
| | | .holiday-icon { |
| | | color: #67c23a; |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .maintenance-icon { |
| | | color: #e6a23c; |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .card-actions { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .card-content { |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-content text { |
| | | color: #606266; |
| | | line-height: 1.6; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .card-footer { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .card-meta { |
| | | display: flex; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .type, .priority, .status { |
| | | padding: 2px 8px; |
| | | border-radius: 12px; |
| | | font-size: 12px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .type-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .type-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .priority-1 { |
| | | background: #f0f9ff; |
| | | color: #0369a1; |
| | | } |
| | | |
| | | .priority-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .priority-3 { |
| | | background: #fef2f2; |
| | | color: #dc2626; |
| | | } |
| | | |
| | | .status-0 { |
| | | background: #f3f4f6; |
| | | color: #6b7280; |
| | | } |
| | | |
| | | .status-1 { |
| | | background: #d1fae5; |
| | | color: #059669; |
| | | } |
| | | |
| | | .status-2 { |
| | | background: #fef3c7; |
| | | color: #d97706; |
| | | } |
| | | |
| | | .card-info { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: flex-end; |
| | | font-size: 12px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .creator { |
| | | font-weight: 500; |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | .expiration { |
| | | margin-top: 2px; |
| | | } |
| | | |
| | | .card-remark { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 6px; |
| | | padding: 8px 12px; |
| | | background: #f8f9fa; |
| | | border-radius: 6px; |
| | | font-size: 12px; |
| | | color: #606266; |
| | | border-left: 3px solid #409eff; |
| | | } |
| | | |
| | | .empty-state { |
| | | text-align: center; |
| | | padding: 48px 16px; |
| | | color: #999; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | text-align: right; |
| | | } |
| | | |
| | | /* ç§»å¨ç«¯å¼¹çªæ ·å¼ */ |
| | | .dialog-container { |
| | | background: #ffffff; |
| | | border-radius: 18px 18px 0 0; |
| | | max-height: 80vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .dialog-header { |
| | | padding: 16px 20px 8px 20px; |
| | | } |
| | | |
| | | .dialog-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .dialog-body { |
| | | flex: 1; |
| | | padding: 0 16px 12px 16px; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .dialog-footer { |
| | | display: flex; |
| | | padding: 12px 16px 16px 16px; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | |
| | | /* ååºå¼è®¾è®¡ */ |
| | | @media (max-width: 768px) { |
| | | .search_form { |
| | | flex-direction: column; |
| | | gap: 15px; |
| | | align-items: flex-start; |
| | | } |
| | | |
| | | .search_form > div { |
| | | width: 100%; |
| | | display: flex; |
| | | gap: 10px; |
| | | } |
| | | } |
| | | </style> |