src/pages.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/equipmentManagement/ledger/detail.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/equipmentManagement/ledger/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/pages/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/static/images/banner/view-background.png | 补丁 | 查看 | 原始文档 | blame | 历史 |
src/pages.json
@@ -292,6 +292,20 @@ "navigationBarTitleText": "å®¢æ·æè®¿", "navigationStyle": "custom" } }, { "path": "pages/equipmentManagement/ledger/index", "style": { "navigationBarTitleText": "设å¤å°è´¦", "navigationStyle": "custom" } }, { "path": "pages/equipmentManagement/ledger/detail", "style": { "navigationBarTitleText": "设å¤å°è´¦è¯¦æ ", "navigationStyle": "custom" } } ], "subPackages": [ src/pages/equipmentManagement/ledger/detail.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,408 @@ <template> <view class="ledger-detail"> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader :title="operationType === 'edit' ? 'ç¼è¾è®¾å¤å°è´¦' : 'æ°å¢è®¾å¤å°è´¦'" @back="goBack" /> <!-- 表åå 容 --> <van-form @submit="sendForm" ref="formRef" label-width="110px" input-align="right" error-message-align="right" scroll-to-error scroll-to-error-position="center"> <!-- åºæ¬ä¿¡æ¯ --> <van-cell-group title="åºæ¬ä¿¡æ¯" inset> <van-field v-model="form.deviceName" label="设å¤åç§°" placeholder="请è¾å ¥è®¾å¤åç§°" :rules="formRules.deviceName" required clearable /> <van-field v-model="form.deviceModel" label="è§æ ¼åå·" placeholder="请è¾å ¥è§æ ¼åå·" :readonly="form.deviceModel != null && operationType === 'edit'" :rules="formRules.deviceModel" required clearable /> <van-field v-model="form.supplierName" label="ä¾åºå" required placeholder="请è¾å ¥ä¾åºå" :rules="formRules.supplierName" clearable /> <van-field v-model="form.unit" label="åä½" required placeholder="请è¾å ¥åä½" :rules="formRules.unit" clearable /> <van-field v-model="form.taxRate" required label="ç¨ç(%)" placeholder="è¯·éæ©" readonly :rules="formRules.taxRate" @click="showTaxRatePicker" clearable /> <van-field v-model="form.number" label="æ°é" required type="number" placeholder="请è¾å ¥æ°é" :rules="formRules.number" @blur="mathNum" clearable /> <van-field v-model="form.taxIncludingPriceUnit" label="å«ç¨åä»·" required type="number" placeholder="请è¾å ¥å«ç¨åä»·" :rules="formRules.taxIncludingPriceUnit" @blur="mathNum" clearable /> <van-field v-model="form.taxIncludingPriceTotal" label="å«ç¨æ»ä»·" placeholder="èªå¨çæ" readonly /> <van-field v-model="form.unTaxIncludingPriceTotal" label="ä¸å«ç¨æ»ä»·" placeholder="èªå¨çæ" readonly /> <van-field v-model="form.createTime" label="å½å ¥æ¥æ" placeholder="è¯·éæ©" readonly @click="showDatePicker" required clearable /> </van-cell-group> <!-- æäº¤æé® --> <view class="footer-btns"> <van-button class="cancel-btn" @click="goBack">åæ¶</van-button> <van-button class="save-btn" native-type="submit" form-type="submit" :loading="loading">ä¿å</van-button> </view> </van-form> <!-- ç¨çéæ©å¨ --> <van-popup v-model:show="showTaxRate" position="bottom"> <van-picker :model-value="taxRatePickerValue" :columns="taxRateOptions" @confirm="onTaxRateConfirm" @cancel="showTaxRate = false" /> </van-popup> <!-- æ¥æéæ©å¨ --> <van-popup v-model:show="showDate" position="bottom"> <van-date-picker v-model="currentDate" title="éæ©æ¥æ" @confirm="onDateConfirm" @cancel="showDate = false" /> </van-popup> </view> </template> <script setup> import { ref, computed, onMounted } from 'vue'; import { onShow } from '@dcloudio/uni-app'; import PageHeader from '@/components/PageHeader.vue'; import { getLedgerById, addLedger, editLedger } from '@/api/equipmentManagement/ledger'; import dayjs from "dayjs"; import { calculateTaxIncludeTotalPrice, calculateTaxExclusiveTotalPrice, } from "@/utils/summarizeTable"; import { showToast } from 'vant'; defineOptions({ name: "设å¤å°è´¦è¡¨å", }); // 表åå¼ç¨ const formRef = ref(null); const operationType = ref(''); const loading = ref(false); const showTaxRate = ref(false); const taxRatePickerValue = ref([]); const showDate = ref(false); const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]); // 表åéªè¯è§å const formRules = { deviceName: [{ required: true, trigger: "blur", message: "请è¾å ¥" }], deviceModel: [{ required: true, trigger: "blur", message: "请è¾å ¥" }], supplierName: [{ required: true, trigger: "blur", message: "请è¾å ¥" }], unit: [{ required: true, trigger: "blur", message: "请è¾å ¥" }], number: [{ required: true, trigger: "blur", message: "请è¾å ¥" }], taxIncludingPriceUnit: [{ required: true, trigger: "blur", message: "请è¾å ¥" }], taxRate: [{ required: true, trigger: "change", message: "请è¾å ¥" }], }; // ä½¿ç¨ ref 声æè¡¨åæ°æ® const form = ref({ deviceName: undefined, // 设å¤åç§° deviceModel: undefined, // è§æ ¼åå· supplierName: undefined, // ä¾åºå unit: undefined, // åä½ number: undefined, // æ°é taxIncludingPriceUnit: undefined, // å«ç¨åä»· taxIncludingPriceTotal: undefined, // å«ç¨æ»ä»· taxRate: undefined, // ç¨ç unTaxIncludingPriceTotal: undefined, // ä¸å«ç¨æ»ä»· createTime: dayjs().format("YYYY-MM-DD"), // å½å ¥æ¥æ }); // ç¨çé项 const taxRateOptions = computed(() => { return [ { text: '1', value: 1 }, { text: '6', value: 6 }, { text: '13', value: 13 } ] }); // å è½½è¡¨åæ°æ® const loadForm = async (id) => { if (id) { operationType.value = 'edit'; } try { const { code, data } = await getLedgerById(id); if (code == 200) { form.value.deviceName = data.deviceName; form.value.deviceModel = data.deviceModel; form.value.supplierName = data.supplierName; form.value.unit = data.unit; form.value.number = data.number; form.value.taxIncludingPriceUnit = data.taxIncludingPriceUnit; form.value.taxIncludingPriceTotal = data.taxIncludingPriceTotal; form.value.taxRate = data.taxRate; form.value.unTaxIncludingPriceTotal = data.unTaxIncludingPriceTotal; form.value.createTime = data.createTime; } } catch (e) { showToast('è·å详æ 失败'); } }; // æ°å¦è®¡ç® const mathNum = () => { if (!form.value.taxIncludingPriceUnit) { showToast("请è¾å ¥åä»·"); return; } if (!form.value.number) { showToast("请è¾å ¥æ°é"); return; } form.value.taxIncludingPriceTotal = calculateTaxIncludeTotalPrice( form.value.taxIncludingPriceUnit, form.value.number ); if (form.value.taxRate) { form.value.unTaxIncludingPriceTotal = calculateTaxExclusiveTotalPrice( form.value.taxIncludingPriceTotal, form.value.taxRate ); } }; // æ¸ é¤è¡¨åæ ¡éªç¶æ const clearValidate = () => { formRef.value?.clearValidate(); }; // éç½®è¡¨åæ°æ®åæ ¡éªç¶æ const resetForm = () => { form.value = { deviceName: undefined, deviceModel: undefined, supplierName: undefined, unit: undefined, number: undefined, taxIncludingPriceUnit: undefined, taxIncludingPriceTotal: undefined, taxRate: undefined, unTaxIncludingPriceTotal: undefined, createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), }; }; const resetFormAndValidate = () => { resetForm(); clearValidate(); }; // æäº¤è¡¨å const sendForm = async () => { try { // æå¨éªè¯è¡¨å await formRef.value?.validate(); loading.value = true; const id = getPageId(); // åå¤æäº¤æ°æ®ï¼createTime å ä¸å½åæ¶åç§ const submitData = { ...form.value }; if (submitData.createTime && !submitData.createTime.includes(':')) { // 妿 createTime åªå 嫿¥æï¼æ·»å å½åæ¶åç§ submitData.createTime = submitData.createTime + ' ' + dayjs().format('HH:mm:ss'); } const { code } = id ? await editLedger({ id: id, ...submitData }) : await addLedger(submitData); if (code == 200) { showToast("æä½æå"); setTimeout(() => { uni.navigateBack(); }, 1500); } else { loading.value = false; } } catch (e) { loading.value = false; showToast('表åéªè¯å¤±è´¥'); } }; // è¿åä¸ä¸é¡µ const goBack = () => { uni.navigateBack(); }; // è·å页é¢åæ° const getPageParams = () => { const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; const options = currentPage.options; if (options.id) { // ç¼è¾æ¨¡å¼ï¼è·å详æ loadForm(options.id); } else { // æ°å¢æ¨¡å¼ operationType.value = 'add'; } }; // è·å页é¢ID const getPageId = () => { const pages = getCurrentPages(); const currentPage = pages[pages.length - 1]; const options = currentPage.options; return options.id; }; // æ¾ç¤ºç¨çéæ©å¨ const showTaxRatePicker = () => { showTaxRate.value = true; }; // 确认ç¨çéæ© const onTaxRateConfirm = ({ selectedValues, selectedOptions }) => { form.value.taxRate = selectedOptions[0].value; taxRatePickerValue.value = selectedValues; showTaxRate.value = false; mathNum(); // éæ°è®¡ç® }; // æ¾ç¤ºæ¥æéæ©å¨ const showDatePicker = () => { showDate.value = true; }; // ç¡®è®¤æ¥æéæ© const onDateConfirm = ({ selectedValues }) => { // åªä¿åå¹´ææ¥ï¼ä¸å 嫿¶åç§ form.value.createTime = selectedValues.join('-'); currentDate.value = selectedValues; showDate.value = false; }; onShow(() => { // 页颿¾ç¤ºæ¶è·ååæ° getPageParams(); }); onMounted(() => { // 页é¢å è½½æ¶è·ååæ° getPageParams(); }); </script> <style scoped lang="scss"> .ledger-detail { min-height: 100vh; background: #f8f9fa; padding-bottom: 5rem; } .footer-btns { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; display: flex; justify-content: space-around; align-items: center; padding: 0.75rem 0; box-shadow: 0 -0.125rem 0.5rem rgba(0,0,0,0.05); z-index: 1000; } .cancel-btn { font-weight: 400; font-size: 1rem; color: #FFFFFF; width: 6.375rem; background: #C7C9CC; box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; } .save-btn { font-weight: 400; font-size: 1rem; color: #FFFFFF; width: 14rem; background: linear-gradient( 140deg, #00BAFF 0%, #006CFB 100%); box-shadow: 0 0.25rem 0.625rem 0 rgba(3,88,185,0.2); border-radius: 2.5rem 2.5rem 2.5rem 2.5rem; } // ååºå¼è°æ´ @media (max-width: 768px) { .submit-section { padding: 12px; } } .tip-text { padding: 4px 16px 0 16px; font-size: 12px; color: #888; } </style> src/pages/equipmentManagement/ledger/index.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,359 @@ <template> <view class="device-ledger"> <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> <PageHeader title="设å¤å°è´¦" @back="goBack" /> <!-- æç´¢åçéåºå --> <view class="search-filter-section"> <view class="search-bar"> <view class="search-input"> <input class="search-text" placeholder="请è¾å ¥è®¾å¤åç§°" v-model="searchKeyword" confirm-type="search" @confirm="getList" /> </view> <view class="filter-button" @click="getList"> <up-icon name="search" size="24" color="#999"></up-icon> </view> </view> </view> <!-- 设å¤å°è´¦å表 --> <view class="ledger-list" v-if="ledgerList.length > 0"> <view v-for="(item, index) in ledgerList" :key="index"> <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.deviceName }}</text> </view> </view> <up-divider></up-divider> <view class="item-details"> <view class="detail-row"> <text class="detail-label">è§æ ¼åå·</text> <text class="detail-value">{{ item.deviceModel || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">ä¾åºå</text> <text class="detail-value">{{ item.supplierName || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">åä½</text> <text class="detail-value">{{ item.unit || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">æ°é</text> <text class="detail-value">{{ item.number || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">å«ç¨åä»·</text> <text class="detail-value highlight">{{ item.taxIncludingPriceUnit || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">å«ç¨æ»ä»·</text> <text class="detail-value highlight">{{ item.taxIncludingPriceTotal || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">ç¨ç</text> <text class="detail-value">{{ item.taxRate || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">ä¸å«ç¨æ»ä»·</text> <text class="detail-value highlight">{{ item.unTaxIncludingPriceTotal || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">å½å ¥äºº</text> <text class="detail-value">{{ item.createUser || '-' }}</text> </view> <view class="detail-row"> <text class="detail-label">å½å ¥æ¥æ</text> <text class="detail-value">{{ item.createTime || '-' }}</text> </view> </view> <!-- æé®åºåï¼åè invoiceLedger çæ ·å¼ --> <view class="action-buttons"> <van-button type="primary" size="small" class="action-btn" @click="edit(item.id)" > ç¼è¾ </van-button> <van-button type="danger" size="small" plain class="action-btn" @click="deleteRow(item.id)" > å é¤ </van-button> </view> </view> </view> </view> <view v-else class="no-data"> <text>ææ è®¾å¤å°è´¦æ°æ®</text> </view> <!-- æµ®å¨æ°å¢æé® --> <view class="fab-button" @click="add"> <up-icon name="plus" size="24" color="#ffffff"></up-icon> </view> </view> </template> <script setup> import { ref, onMounted } from 'vue' import { onShow } from '@dcloudio/uni-app' import PageHeader from '@/components/PageHeader.vue' import { getLedgerPage, delLedger } from '@/api/equipmentManagement/ledger' import useUserStore from "@/store/modules/user" import { showToast } from 'vant'; const userStore = useUserStore() // æç´¢å ³é®è¯ const searchKeyword = ref('') // 设å¤å°è´¦æ°æ® const ledgerList = ref([]) // è¿åä¸ä¸é¡µ const goBack = () => { uni.navigateBack() } // æ¥è¯¢å表ï¼current/size åºå®ä¼ -1ï¼ const getList = () => { const params = { current: -1, size: -1, deviceName: searchKeyword.value || undefined, } getLedgerPage(params) .then((res) => { ledgerList.value = res.records || res.data?.records || [] }) .catch(() => { showToast('è·åæ°æ®å¤±è´¥') }) } // æ°å¢ - 跳转å°è¯¦æ é¡µé¢ const add = () => { uni.navigateTo({ url: '/pages/equipmentManagement/ledger/detail' }) } // ç¼è¾ - 跳转å°è¯¦æ é¡µé¢ const edit = (id) => { if (!id) return uni.navigateTo({ url: `/pages/equipmentManagement/ledger/detail?id=${id}` }) } // å é¤ const deleteRow = async (id) => { if (!id) return uni.showModal({ title: 'æç¤º', content: 'æ¤æä½å°æ°¸ä¹ å é¤è¯¥è®°å½, æ¯å¦ç»§ç»?', success: async (res) => { if (!res.confirm) return try { await delLedger(id) showToast('å 餿å') getList() } catch (e) { showToast('å é¤å¤±è´¥') } } }) } onMounted(() => { getList() }) onShow(() => { getList() }) </script> <style scoped lang="scss"> .u-divider { margin: 0 !important; } .device-ledger { min-height: 100vh; background: #f8f9fa; position: relative; padding-bottom: 80px; } .search-filter-section { padding: 10px 20px; background: #ffffff; } .search-bar { display: flex; align-items: center; gap: 12px; } .search-input { flex: 1; background: #f5f5f5; border-radius: 24px; padding: 10px 16px; display: flex; align-items: center; gap: 8px; } .search-text { flex: 1; font-size: 14px; color: #333; background: transparent; border: none; outline: none; } .search-text::placeholder { color: #999; } .filter-button { width: 40px; height: 40px; border-radius: 8px; display: flex; align-items: center; justify-content: center; } .ledger-list { padding: 20px; } .ledger-item { background: #ffffff; border-radius: 12px; margin-bottom: 16px; overflow: hidden; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); padding: 0 16px; } .item-header { padding: 16px 0; display: flex; align-items: center; justify-content: space-between; } .item-left { display: flex; align-items: center; gap: 8px; } .document-icon { width: 24px; height: 24px; background: #2979ff; border-radius: 4px; display: flex; align-items: center; justify-content: center; } .item-id { font-size: 14px; color: #333; font-weight: 500; } .item-details { padding: 16px 0; } .detail-row { display: flex; align-items: flex-end; justify-content: space-between; margin-bottom: 8px; &:last-child { margin-bottom: 0; } } .detail-label { font-size: 12px; color: #777777; min-width: 60px; } .detail-value { font-size: 12px; color: #000000; text-align: right; flex: 1; margin-left: 16px; } .detail-value.highlight { color: #2979ff; font-weight: 500; } .no-data { padding: 40px 0; text-align: center; color: #999; } // æé®æ ·å¼ï¼åè invoiceLedger .action-buttons { display: flex; gap: 12px; padding: 0 0 16px 0; justify-content: space-between; } .action-btn { flex: 1; } .fab-button { position: fixed; bottom: calc(30px + env(safe-area-inset-bottom)); right: 30px; width: 56px; height: 56px; background: #2979ff; border-radius: 50%; display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 16px rgba(41, 121, 255, 0.3); z-index: 1000; } </style> src/pages/index.vue
@@ -11,8 +11,8 @@ <view class="hero-section"> <view class="bg-img"> <view class="hero-content"> <text class="hero-title">产ååºå管çç³»ç»</text> <text class="hero-subtitle">髿ã便æ·çä¸å¡ç®¡çå ¥å£</text> <text class="hero-title"></text> <text class="hero-subtitle"></text> </view> <view class="hero-wave"></view> </view> @@ -355,9 +355,14 @@ url: '/pages/cooperativeOffice/collaborativeApproval/index' }); break; case 'å®¢æ·æè®¿': case 'å®¢æ·æè®¿': uni.navigateTo({ url: '/pages/cooperativeOffice/clientVisit/index' }); break; case '设å¤å°è´¦': uni.navigateTo({ url: '/pages/equipmentManagement/ledger/index' }); break; default: @@ -494,7 +499,8 @@ .bg-img { width: 100%; height: 8.75rem; background: linear-gradient(135deg, #2979ff 0%, #1565c0 100%); background-image: url("../static/images/banner/view-background.png"); background-size: cover; border-radius: 0.75rem; position: relative; overflow: hidden; src/static/images/banner/view-background.png