| | |
| | | <template> |
| | | <view class="main-production-plan"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="主ç产计å" @back="goBack" /> |
| | | |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请è¾å
¥è®¡åå·æäº§ååç§°" |
| | | v-model="searchForm.keyword" |
| | | @change="handleQuery" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="filter-button" @click="handleQuery"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å表åºå --> |
| | | <scroll-view scroll-y class="list-container" v-if="tableData.length > 0" @scrolltolower="loadMore"> |
| | | <view v-for="(item, index) in tableData" :key="item.id || index" @click="goDetail(item)"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">{{ item.mpsNo }}</text> |
| | | </view> |
| | | <view class="item-right"> |
| | | <up-tag :text="getStatusText(item.status)" :type="getStatusType(item.status)" size="mini" /> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产ååç§°</text> |
| | | <text class="detail-value">{{ item.productName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ item.model || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æéæ°é</text> |
| | | <text class="detail-value highlight">{{ item.qtyRequired || 0 }} {{ item.unit || 'æ¹' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">éæ±æ¥æ</text> |
| | | <text class="detail-value">{{ formatDate(item.requiredDate) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ¥æº</text> |
| | | <text class="detail-value">{{ item.source === 'éå®' ? 'éå®' : 'å
é¨' }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="item-footer"> |
| | | <text class="more-detail">æ¥ç详æ
</text> |
| | | <up-icon name="arrow-right" size="14" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <up-loadmore :status="loadStatus" v-if="tableData.length >= page.size" /> |
| | | </scroll-view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <up-empty mode="data" text="ææ ä¸»çäº§è®¡åæ°æ®"></up-empty> |
| | | </view> |
| | | </view> |
| | | <view class="main-production-plan"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="主ç产计å" |
| | | @back="goBack"> |
| | | <!-- <template #right> |
| | | <view class="header-right"> |
| | | <u-button v-if="!selectMode" |
| | | size="mini" |
| | | @click="enterSelectMode">åå¹¶ä¸å</u-button> |
| | | <u-button v-else |
| | | size="mini" |
| | | @click="exitSelectMode">åæ¶</u-button> |
| | | </view> |
| | | </template> --> |
| | | </PageHeader> |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥è®¡åå·æäº§ååç§°" |
| | | v-model="searchForm.keyword" |
| | | @change="handleQuery" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" |
| | | @click="handleQuery"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- å表åºå --> |
| | | <scroll-view scroll-y |
| | | class="list-container" |
| | | v-if="tableData.length > 0"> |
| | | <up-checkbox-group v-if="selectMode" |
| | | v-model="selectedIds" |
| | | placement="column"> |
| | | <view v-for="(item, index) in tableData" |
| | | :key="item.id || index" |
| | | @click="toggleSelect(item)"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">{{ item.mpsNo }}</text> |
| | | </view> |
| | | <view class="item-right"> |
| | | <up-checkbox :name="String(item.id)" |
| | | :label="''" |
| | | @click.stop></up-checkbox> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产ååç§°</text> |
| | | <text class="detail-value">{{ item.productName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ item.model || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¯ä¸åæ°é</text> |
| | | <text class="detail-value highlight">{{ getRemainingQty(item) }} {{ item.unit || 'æ¹' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </up-checkbox-group> |
| | | <view v-else> |
| | | <view v-for="(item, index) in tableData" |
| | | :key="item.id || index" |
| | | @click="goDetail(item)"> |
| | | <view class="ledger-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="document-icon"> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-id">{{ item.mpsNo }}</text> |
| | | </view> |
| | | <view class="item-right"> |
| | | <up-tag :text="getStatusText(item.status)" |
| | | :type="getStatusType(item.status)" |
| | | size="mini" /> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产ååç§°</text> |
| | | <text class="detail-value">{{ item.productName || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ item.model || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æéæ°é</text> |
| | | <text class="detail-value highlight">{{ item.qtyRequired || 0 }} {{ item.unit || 'æ¹' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å·²ä¸åæ°é</text> |
| | | <text class="detail-value">{{ item.quantityIssued || 0 }} {{ item.unit || 'æ¹' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">éæ±æ¥æ</text> |
| | | <text class="detail-value">{{ formatDate(item.requiredDate) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æ¥æº</text> |
| | | <text class="detail-value">{{ item.source === 'éå®' ? 'éå®' : 'å
é¨' }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <u-button v-if="canEdit(item)" |
| | | size="small" |
| | | class="action-btn" |
| | | @click.stop="goEdit(item)">ç¼è¾</u-button> |
| | | <u-button v-if="canIssue(item)" |
| | | size="small" |
| | | class="action-btn" |
| | | type="primary" |
| | | @click.stop="goIssue([item])">ä¸å</u-button> |
| | | <u-button v-if="canDelete(item)" |
| | | size="small" |
| | | class="action-btn" |
| | | type="error" |
| | | @click.stop="handleDelete(item)">å é¤</u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <up-empty mode="data" |
| | | text="ææ ä¸»çäº§è®¡åæ°æ®"></up-empty> |
| | | </view> |
| | | <FooterButtons v-if="selectMode" |
| | | cancelText="åæ¶" |
| | | confirmText="ä¸å" |
| | | :confirmDisabled="selectedIds.length === 0" |
| | | @cancel="exitSelectMode" |
| | | @confirm="goIssueSelected" /> |
| | | <view class="fab-button" |
| | | @click="goAdd"> |
| | | <up-icon name="plus" |
| | | size="24" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs, getCurrentInstance } from "vue"; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import dayjs from "dayjs"; |
| | | import { productionPlanListPage } from "@/api/productionManagement/productionPlan.js"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { ref, reactive, toRefs } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | productionPlanDelete, |
| | | productionPlanListPage, |
| | | } from "@/api/productionManagement/productionPlan.js"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import FooterButtons from "@/components/FooterButtons.vue"; |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | // å è½½ç¶æ |
| | | const loading = ref(false); |
| | | // åè¡¨æ°æ® |
| | | const tableData = ref([]); |
| | | |
| | | // å è½½ç¶æ |
| | | const loading = ref(false); |
| | | const loadStatus = ref('loadmore'); |
| | | // åè¡¨æ°æ® |
| | | const tableData = ref([]); |
| | | const page = reactive({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | |
| | | // å页é
ç½® |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 10, |
| | | total: 0, |
| | | }); |
| | | // æç´¢è¡¨åæ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | keyword: "", |
| | | mpsNo: "", |
| | | productName: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | // æç´¢è¡¨åæ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | keyword: "", |
| | | mpsNo: "", |
| | | productName: "" |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const selectMode = ref(false); |
| | | const selectedIds = ref([]); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = (date) => { |
| | | return date ? dayjs(date).format('YYYY-MM-DD') : '-'; |
| | | }; |
| | | // æ ¼å¼åæ¥æ |
| | | const formatDate = date => { |
| | | return date ? dayjs(date).format("YYYY-MM-DD") : "-"; |
| | | }; |
| | | |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | 0: "å¾
ä¸å", |
| | | 1: "é¨åä¸å", |
| | | 2: "å·²ä¸å", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | // è·åç¶æææ¬ |
| | | const getStatusText = status => { |
| | | const statusMap = { |
| | | 0: "å¾
ä¸å", |
| | | 1: "é¨åä¸å", |
| | | 2: "å·²ä¸å", |
| | | }; |
| | | return statusMap[status] || "æªç¥"; |
| | | }; |
| | | |
| | | // è·åç¶æç±»å (uView tag type) |
| | | const getStatusType = (status) => { |
| | | const typeMap = { |
| | | 0: "warning", |
| | | 1: "primary", |
| | | 2: "info", |
| | | }; |
| | | return typeMap[status] || "info"; |
| | | }; |
| | | // è·åç¶æç±»å (uView tag type) |
| | | const getStatusType = status => { |
| | | const typeMap = { |
| | | 0: "warning", |
| | | 1: "primary", |
| | | 2: "info", |
| | | }; |
| | | return typeMap[status] || "info"; |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | tableData.value = []; |
| | | getList(); |
| | | }; |
| | | const getRemainingQty = row => { |
| | | const required = Number(row?.qtyRequired || 0); |
| | | const issued = Number(row?.quantityIssued || 0); |
| | | const remaining = required - issued; |
| | | return Number((remaining > 0 ? remaining : 0).toFixed(4)); |
| | | }; |
| | | |
| | | // å è½½æ´å¤ |
| | | const loadMore = () => { |
| | | if (loadStatus.value === 'nomore' || loading.value) return; |
| | | page.current++; |
| | | getList(); |
| | | }; |
| | | const canEdit = row => { |
| | | return String(row?.status) === "0" && row?.source !== "éå®"; |
| | | }; |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | loading.value = true; |
| | | loadStatus.value = 'loading'; |
| | | |
| | | // æé 请æ±åæ° |
| | | // PC端æ¥å£æ¯æ mpsNo, productName çï¼è¿éç®åå¤çï¼å¦æ keyword åå¨ï¼åå°è¯å¹é
|
| | | const params = { |
| | | current: page.current, |
| | | size: page.size, |
| | | mpsNo: searchForm.value.keyword, // ç®åå¤çï¼æç´¢å· |
| | | productName: searchForm.value.keyword // ç®åå¤çï¼æç´¢åç§° |
| | | }; |
| | | |
| | | productionPlanListPage(params).then((res) => { |
| | | loading.value = false; |
| | | const records = res.data.records || []; |
| | | if (page.current === 1) { |
| | | tableData.value = records; |
| | | } else { |
| | | tableData.value = [...tableData.value, ...records]; |
| | | } |
| | | |
| | | if (records.length < page.size) { |
| | | loadStatus.value = 'nomore'; |
| | | } else { |
| | | loadStatus.value = 'loadmore'; |
| | | } |
| | | page.total = res.data.total || 0; |
| | | }).catch(() => { |
| | | loading.value = false; |
| | | loadStatus.value = 'loadmore'; |
| | | uni.showToast({ |
| | | title: 'å 载失败', |
| | | icon: 'error' |
| | | }); |
| | | }); |
| | | }; |
| | | const canDelete = row => { |
| | | return String(row?.status) === "0"; |
| | | }; |
| | | |
| | | // 跳转详æ
|
| | | const goDetail = (item) => { |
| | | uni.navigateTo({ |
| | | url: `/pages/productionManagement/mainProductionPlan/detail?data=${encodeURIComponent(JSON.stringify(item))}` |
| | | }); |
| | | }; |
| | | const canIssue = row => { |
| | | return String(row?.status) !== "2" && getRemainingQty(row) > 0; |
| | | }; |
| | | |
| | | // 页颿¾ç¤ºæ¶å è½½æ°æ® |
| | | onShow(() => { |
| | | handleQuery(); |
| | | }); |
| | | const enterSelectMode = () => { |
| | | selectMode.value = true; |
| | | selectedIds.value = []; |
| | | }; |
| | | |
| | | const exitSelectMode = () => { |
| | | selectMode.value = false; |
| | | selectedIds.value = []; |
| | | }; |
| | | |
| | | const toggleSelect = item => { |
| | | if (!item?.id) return; |
| | | const id = String(item.id); |
| | | const idx = selectedIds.value.indexOf(id); |
| | | if (idx >= 0) selectedIds.value.splice(idx, 1); |
| | | else selectedIds.value.push(id); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const handleQuery = () => { |
| | | getList(); |
| | | }; |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | loading.value = true; |
| | | exitSelectMode(); |
| | | |
| | | const params = { |
| | | current: page.current, |
| | | size: page.size, |
| | | mpsNo: searchForm.value.keyword, // ç®åå¤çï¼æç´¢å· |
| | | productName: searchForm.value.keyword, // ç®åå¤çï¼æç´¢åç§° |
| | | }; |
| | | |
| | | productionPlanListPage(params) |
| | | .then(res => { |
| | | loading.value = false; |
| | | const payload = res?.data; |
| | | if (Array.isArray(payload)) { |
| | | tableData.value = payload; |
| | | } else if (payload && typeof payload === "object") { |
| | | tableData.value = payload.records || payload.rows || payload.data || []; |
| | | } else { |
| | | tableData.value = []; |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | loading.value = false; |
| | | uni.showToast({ |
| | | title: "å 载失败", |
| | | icon: "error", |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // 跳转详æ
|
| | | const goDetail = item => { |
| | | if (selectMode.value) return; |
| | | uni.navigateTo({ |
| | | url: `/pages/productionManagement/mainProductionPlan/detail?data=${encodeURIComponent( |
| | | JSON.stringify(item) |
| | | )}`, |
| | | }); |
| | | }; |
| | | |
| | | const goAdd = () => { |
| | | uni.navigateTo({ |
| | | url: "/pages/productionManagement/mainProductionPlan/edit", |
| | | }); |
| | | }; |
| | | |
| | | const goEdit = item => { |
| | | uni.navigateTo({ |
| | | url: `/pages/productionManagement/mainProductionPlan/edit?data=${encodeURIComponent( |
| | | JSON.stringify(item) |
| | | )}`, |
| | | }); |
| | | }; |
| | | |
| | | const goIssue = rows => { |
| | | const list = Array.isArray(rows) ? rows : []; |
| | | if (list.length === 0) return; |
| | | const first = list[0]; |
| | | const sumRemaining = Number( |
| | | list.reduce((sum, r) => sum + getRemainingQty(r), 0).toFixed(4) |
| | | ); |
| | | const payload = { |
| | | productName: first.productName || "", |
| | | model: first.model || "", |
| | | productId: first.productId ?? undefined, |
| | | ids: list.map(r => r.id), |
| | | planCompleteTime: |
| | | formatDate(first.requiredDate) === "-" |
| | | ? "" |
| | | : formatDate(first.requiredDate), |
| | | totalAssignedQuantity: sumRemaining, |
| | | maxQuantity: sumRemaining, |
| | | }; |
| | | uni.navigateTo({ |
| | | url: `/pages/productionManagement/mainProductionPlan/issue?data=${encodeURIComponent( |
| | | JSON.stringify(payload) |
| | | )}`, |
| | | }); |
| | | }; |
| | | |
| | | const goIssueSelected = () => { |
| | | const rows = tableData.value.filter(r => |
| | | selectedIds.value.includes(String(r.id)) |
| | | ); |
| | | if (rows.length === 0) { |
| | | uni.showToast({ title: "è¯·éæ©è¦ä¸åç计å", icon: "none" }); |
| | | return; |
| | | } |
| | | const first = rows[0]; |
| | | const modelId = first.productModelId; |
| | | const invalid = rows.some(r => r.productModelId !== modelId || !canIssue(r)); |
| | | if (invalid) { |
| | | uni.showToast({ |
| | | title: "åªè½åå¹¶ä¸åç¸åè§æ ¼ä¸å¯ä¸åç计å", |
| | | icon: "none", |
| | | }); |
| | | return; |
| | | } |
| | | goIssue(rows); |
| | | }; |
| | | |
| | | const handleDelete = item => { |
| | | if (!item?.id) return; |
| | | uni.showModal({ |
| | | title: "å é¤æç¤º", |
| | | content: "确认å é¤è¯¥ç产计åï¼å é¤åæ æ³æ¢å¤", |
| | | success: res => { |
| | | if (!res.confirm) return; |
| | | uni.showLoading({ title: "å é¤ä¸...", mask: true }); |
| | | productionPlanDelete([item.id]) |
| | | .then(() => { |
| | | uni.showToast({ title: "å 餿å", icon: "success" }); |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | uni.showToast({ title: "å é¤å¤±è´¥", icon: "error" }); |
| | | }) |
| | | .finally(() => { |
| | | uni.hideLoading(); |
| | | }); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 页颿¾ç¤ºæ¶å è½½æ°æ® |
| | | onShow(() => { |
| | | handleQuery(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | .main-production-plan { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | .main-production-plan { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .list-container { |
| | | flex: 1; |
| | | height: 0; |
| | | } |
| | | .list-container { |
| | | flex: 1; |
| | | height: 0; |
| | | padding-bottom: 140rpx; |
| | | } |
| | | |
| | | .ledger-item { |
| | | background: #fff; |
| | | margin: 20rpx; |
| | | padding: 20rpx; |
| | | border-radius: 12rpx; |
| | | box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .item-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding-bottom: 10rpx; |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .document-icon { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background: #3c9cff; |
| | | border-radius: 8rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-right: 16rpx; |
| | | } |
| | | |
| | | .item-id { |
| | | font-size: 28rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .item-details { |
| | | padding: 10rpx 0; |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 12rpx; |
| | | |
| | | .detail-label { |
| | | font-size: 26rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 26rpx; |
| | | color: #333; |
| | | |
| | | &.highlight { |
| | | color: #f56c6c; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .item-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | padding-top: 16rpx; |
| | | border-top: 1rpx solid #f0f0f0; |
| | | |
| | | .more-detail { |
| | | font-size: 24rpx; |
| | | color: #999; |
| | | margin-right: 8rpx; |
| | | } |
| | | } |
| | | } |
| | | .header-right { |
| | | display: flex; |
| | | align-items: center; |
| | | padding-right: 12rpx; |
| | | } |
| | | |
| | | .no-data { |
| | | padding-top: 200rpx; |
| | | } |
| | | .ledger-item { |
| | | background: #fff; |
| | | margin: 20rpx; |
| | | padding: 20rpx; |
| | | border-radius: 12rpx; |
| | | box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05); |
| | | |
| | | .item-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | padding-bottom: 10rpx; |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .document-icon { |
| | | width: 40rpx; |
| | | height: 40rpx; |
| | | background: #3c9cff; |
| | | border-radius: 8rpx; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | margin-right: 16rpx; |
| | | } |
| | | |
| | | .item-id { |
| | | font-size: 28rpx; |
| | | font-weight: bold; |
| | | color: #333; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .action-buttons { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | align-items: center; |
| | | gap: 16rpx; |
| | | padding-top: 16rpx; |
| | | border-top: 1rpx solid #f0f0f0; |
| | | } |
| | | |
| | | .item-details { |
| | | padding: 10rpx 0; |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 12rpx; |
| | | |
| | | .detail-label { |
| | | font-size: 26rpx; |
| | | color: #999; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 26rpx; |
| | | color: #333; |
| | | |
| | | &.highlight { |
| | | color: #f56c6c; |
| | | font-weight: bold; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .item-right :deep(.up-checkbox__label) { |
| | | display: none; |
| | | } |
| | | } |
| | | |
| | | .fab-button { |
| | | position: fixed; |
| | | right: 30rpx; |
| | | bottom: 140rpx; |
| | | width: 100rpx; |
| | | height: 100rpx; |
| | | background: #3c9cff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 8rpx 24rpx rgba(60, 156, 255, 0.3); |
| | | z-index: 1001; |
| | | } |
| | | |
| | | .no-data { |
| | | padding-top: 200rpx; |
| | | } |
| | | </style> |