| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | export const getLedgerPage = (params) => { |
| | | return request({ |
| | | url: "/device/ledger/page", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | export const editLedger = (data) => { |
| | | return request({ |
| | | url: "/device/ledger", |
| | | method: "put", |
| | | data, |
| | | }); |
| | | }; |
| | |
| | | } |
| | | |
| | | // æ¥è¯¢å表 |
| | | export function invoiceListPage(query) { |
| | | return request({ |
| | | url: "/purchase/registration/listPage", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | // export function invoiceListPage(query) { |
| | | // return request({ |
| | | // url: "/purchase/registration/listPage", |
| | | // method: "get", |
| | | // params: query, |
| | | // }); |
| | | // } |
| | | |
| | | export function productRecordPage(query) { |
| | | return request({ |
| | |
| | | }); |
| | | } |
| | | |
| | | export function getProductRecordById(params) { |
| | | // export function getProductRecordById(params) { |
| | | // return request({ |
| | | // url: "/purchase/registration/getProductRecordById", |
| | | // method: "get", |
| | | // params: params, |
| | | // }); |
| | | // } |
| | | export function getProductRecordById(data) { |
| | | return request({ |
| | | url: "/purchase/registration/getProductRecordById", |
| | | method: "get", |
| | | params: params, |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | |
| | | data: query, |
| | | }); |
| | | } |
| | | // æ¥è¯¢å表 |
| | | export function invoiceListPage(query) { |
| | | return request({ |
| | | url: "/sales/product/listPagePurchaseLedger", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/runManagement/index", |
| | | "style": { |
| | | "navigationBarTitleText": "è¿è¡ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/equipmentManagement/repair/index", |
| | | "style": { |
| | | "navigationBarTitleText": "è®¾å¤æ¥ä¿®", |
| | |
| | | <template> |
| | | <view class="notice-page"> |
| | | <PageHeader title="éç¥å
Œ" @back="goBack" /> |
| | | <PageHeader title="éç¥å
Œ" |
| | | @back="goBack" /> |
| | | <!-- æç´¢è¡¨å --> |
| | | <!-- <view class="search_form"> |
| | | <up-button type="primary" size="small" @click="openForm('add')">æ°å¢å
Œ</up-button> |
| | |
| | | å é¤ |
| | | </up-button> |
| | | </view> --> |
| | | |
| | | <!-- éç¥å
¬åæ¿ --> |
| | | <view class="notice-board"> |
| | | <!-- ç»ä¸éç¥åºå --> |
| | | <view class="notice-section" v-if="totalNoticeCount > 0"> |
| | | <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 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" /> |
| | | <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 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"> |
| | | <text class="type" |
| | | :class="'type-' + notice.type"> |
| | | {{ notice.type }} |
| | | </text> |
| | | <text class="priority" :class="'priority-' + notice.priority"> |
| | | <text class="priority" |
| | | :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </text> |
| | | <text class="status" :class="'status-' + getNoticeStatus(notice)"> |
| | | <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> |
| | | <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" /> |
| | | <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 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" /> |
| | | <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 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 text |
| | | type="error" |
| | | size="mini" |
| | | @click="handleDelete(notice.id)"> |
| | | å é¤ |
| | | </up-button> |
| | | </view> |
| | |
| | | </view> |
| | | <view class="card-footer"> |
| | | <view class="card-meta"> |
| | | <text class="priority" :class="'priority-' + notice.priority"> |
| | | <text class="priority" |
| | | :class="'priority-' + notice.priority"> |
| | | {{ getPriorityText(notice.priority) }} |
| | | </text> |
| | | <text class="status" :class="'status-' + getNoticeStatus(notice)"> |
| | | <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> |
| | | <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" /> |
| | | <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"> |
| | | <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" |
| | | > |
| | | <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 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 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="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 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-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 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-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 }" |
| | | /> |
| | | <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> |
| | |
| | | </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"; |
| | | 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 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, |
| | | // ååºå¼æ°æ® |
| | | const data = reactive({ |
| | | searchForm: { |
| | | title: "", |
| | | type: undefined, |
| | | status: undefined, |
| | | }, |
| | | form: { |
| | | id: undefined, |
| | | title: "", |
| | | type: null, |
| | | content: "", |
| | | status: 0, |
| | | priority: 1, |
| | | remark: "", |
| | | expirationDate: "", |
| | | }; |
| | | } |
| | | dialogVisible.value = true; |
| | | }; |
| | | }, |
| | | 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 handleEdit = (row) => { |
| | | if (isNoticeExpired(row)) { |
| | | uni.showToast({ |
| | | title: "å·²è¿æçå
¬åä¸å¯ç¼è¾", |
| | | icon: "none" |
| | | 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(); |
| | | }); |
| | | } |
| | | }, |
| | | }); |
| | | 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" |
| | | // é¢çæ¹éå é¤ï¼ç®åæªå®ç°éä¸é»è¾ï¼ä»
å ä½ï¼ |
| | | 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(); |
| | | }); |
| | | 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" |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | addNotice(form.value).then(res => { |
| | | uni.showToast({ |
| | | title: "æ°å¢æå", |
| | | icon: "success", |
| | | }); |
| | | resetTable(); |
| | | }); |
| | | 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 { |
| | | // æ°å¢æ¨¡å¼ |
| | | addNotice(form.value).then(res => { |
| | | uni.showToast({ |
| | | title: "æ°å¢æå", |
| | | icon: "success" |
| | | }); |
| | | resetTable(); |
| | | }) |
| | | holidayNotices.value = records; |
| | | } |
| | | dialogVisible.value = false; |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | 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(); |
| | | }); |
| | | }; |
| | | |
| | | const totalNoticeCount = ref(0) |
| | | const fetchCount = () => { |
| | | getCount().then(res => { |
| | | totalNoticeCount.value = res.data.reduce((total, item) => total + item.count, 0); |
| | | // ä¸åå è½½æ´å¤ |
| | | 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; |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | 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%; |
| | | .notice-page { |
| | | min-height: 100vh; |
| | | background: #f5f7fa; |
| | | padding-bottom: 16px; |
| | | display: flex; |
| | | gap: 10px; |
| | | 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> |
| | |
| | | <template> |
| | | <view class="repair-add"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader :title="operationType === 'edit' ? 'ç¼è¾æ¥ä¿®' : 'æ°å¢æ¥ä¿®'" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="sendForm" ref="formRef" :rules="formRules" :model="form" label-width="110"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="设å¤åç§°" prop="deviceLedgerId" required border-bottom> |
| | | <u-input |
| | | v-model="deviceNameText" |
| | | placeholder="è¯·éæ©è®¾å¤åç§°" |
| | | @click="showDevicePicker" |
| | | clearable |
| | | readonly="" |
| | | /> |
| | | <template #right> |
| | | <u-icon name="scan" @click="startScan" class="scan-icon" /> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="è§æ ¼åå·" prop="deviceModel" border-bottom> |
| | | <u-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®æ¥æ" prop="repairTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.repairTime" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®äºº" prop="repairName" required border-bottom> |
| | | <u-input |
| | | v-model="form.repairName" |
| | | placeholder="请è¾å
¥æ¥ä¿®äºº" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="æ
éç°è±¡" prop="remark" required border-bottom> |
| | | <u-textarea |
| | | v-model="form.remark" |
| | | rows="3" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | clearable |
| | | count |
| | | maxlength="200" |
| | | /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" type="primary" @click="sendForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- 设å¤éæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showDevice" |
| | | :actions="deviceActionList" |
| | | title="éæ©è®¾å¤åç§°" |
| | | @select="onDeviceSelect" |
| | | @close="showDevice = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </view> |
| | | <view class="repair-add"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader :title="operationType === 'edit' ? 'ç¼è¾æ¥ä¿®' : 'æ°å¢æ¥ä¿®'" |
| | | @back="goBack" /> |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="sendForm" |
| | | ref="formRef" |
| | | :rules="formRules" |
| | | :model="form" |
| | | label-width="110"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯"> |
| | | <u-form-item label="设å¤åç§°" |
| | | prop="deviceLedgerId" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="deviceNameText" |
| | | placeholder="è¯·éæ©è®¾å¤åç§°" |
| | | @click="showDevicePicker" |
| | | clearable |
| | | readonly="" /> |
| | | <template #right> |
| | | <u-icon name="scan" |
| | | @click="startScan" |
| | | class="scan-icon" /> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="è§æ ¼åå·" |
| | | prop="deviceModel" |
| | | border-bottom> |
| | | <u-input v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable /> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®æ¥æ" |
| | | prop="repairTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.repairTime" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker" |
| | | clearable /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" |
| | | @click="showDatePicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®ç¶æ" |
| | | prop="repairTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="repairStatusText" |
| | | placeholder="è¯·éæ©æ¥ä¿®ç¶æ" |
| | | readonly |
| | | @click="openRepairStatusPicker" |
| | | clearable /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" |
| | | @click="openRepairStatusPicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="æ¥ä¿®äºº" |
| | | prop="repairName" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.repairName" |
| | | placeholder="请è¾å
¥æ¥ä¿®äºº" |
| | | clearable /> |
| | | </u-form-item> |
| | | <u-form-item label="æ
éç°è±¡" |
| | | prop="remark" |
| | | required |
| | | border-bottom> |
| | | <u-textarea v-model="form.remark" |
| | | rows="3" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | clearable |
| | | count |
| | | maxlength="200" /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" |
| | | type="primary" |
| | | @click="sendForm" |
| | | :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- 设å¤éæ©å¨ --> |
| | | <up-action-sheet :show="showDevice" |
| | | :actions="deviceActionList" |
| | | title="éæ©è®¾å¤åç§°" |
| | | @select="onDeviceSelect" |
| | | @close="showDevice = false" /> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker :show="showDate" |
| | | v-model="pickerDateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted, onUnmounted } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import { getDeviceLedger } from '@/api/equipmentManagement/ledger'; |
| | | import { addRepair, editRepair, getRepairById } from '@/api/equipmentManagement/repair'; |
| | | import dayjs from "dayjs"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi'; |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import { ref, computed, onMounted, onUnmounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { |
| | | addRepair, |
| | | editRepair, |
| | | getRepairById, |
| | | } from "@/api/equipmentManagement/repair"; |
| | | import dayjs from "dayjs"; |
| | | import { formatDateToYMD } from "@/utils/ruoyi"; |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®è¡¨å", |
| | | }); |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®è¡¨å", |
| | | }); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const operationType = ref('add'); |
| | | const loading = ref(false); |
| | | const showDevice = ref(false); |
| | | const showDate = ref(false); |
| | | const pickerDateValue = ref(Date.now()); |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const operationType = ref("add"); |
| | | const loading = ref(false); |
| | | const showDevice = ref(false); |
| | | const showDate = ref(false); |
| | | const pickerDateValue = ref(Date.now()); |
| | | |
| | | // 设å¤é项 |
| | | const deviceOptions = ref([]); |
| | | const deviceNameText = ref(''); |
| | | const deviceActionList = computed(() => { |
| | | return deviceOptions.value.map(item => ({ |
| | | name: item.deviceName, |
| | | value: item.id |
| | | })); |
| | | }); |
| | | // 设å¤é项 |
| | | const deviceOptions = ref([]); |
| | | const deviceNameText = ref(""); |
| | | const deviceActionList = computed(() => { |
| | | return deviceOptions.value.map(item => ({ |
| | | name: item.deviceName, |
| | | value: item.id, |
| | | })); |
| | | }); |
| | | |
| | | // æ«ç ç¸å
³ç¶æ |
| | | const isScanning = ref(false); |
| | | const scanTimer = ref(null); |
| | | // æ«ç ç¸å
³ç¶æ |
| | | const isScanning = ref(false); |
| | | const scanTimer = ref(null); |
| | | |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | deviceLedgerId: [{ required: true, trigger: "change", message: "è¯·éæ©è®¾å¤åç§°" }], |
| | | repairTime: [{ required: true, trigger: "change", message: "è¯·éæ©æ¥ä¿®æ¥æ" }], |
| | | repairName: [{ required: true, trigger: "blur", message: "请è¾å
¥æ¥ä¿®äºº" }], |
| | | remark: [{ required: true, trigger: "blur", message: "请è¾å
¥æ
éç°è±¡" }], |
| | | }; |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | deviceLedgerId: [ |
| | | { required: true, trigger: "change", message: "è¯·éæ©è®¾å¤åç§°" }, |
| | | ], |
| | | repairTime: [ |
| | | { required: true, trigger: "change", message: "è¯·éæ©æ¥ä¿®æ¥æ" }, |
| | | ], |
| | | repairName: [{ required: true, trigger: "blur", message: "请è¾å
¥æ¥ä¿®äºº" }], |
| | | remark: [{ required: true, trigger: "blur", message: "请è¾å
¥æ
éç°è±¡" }], |
| | | }; |
| | | |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | deviceLedgerId: undefined, // 设å¤ID |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æ |
| | | repairName: undefined, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | }); |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | deviceLedgerId: undefined, // 设å¤ID |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æ |
| | | repairName: undefined, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | }); |
| | | |
| | | // å 载设å¤å表 |
| | | const loadDeviceName = async () => { |
| | | try { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data || []; |
| | | } catch (e) { |
| | | showToast('è·å设å¤å表失败'); |
| | | } |
| | | }; |
| | | // æ¥ä¿®ç¶æé项 |
| | | const repairStatusOptions = ref([ |
| | | { name: "å¾
ç»´ä¿®", value: "0" }, |
| | | { name: "å®ç»", value: "1" }, |
| | | { name: "失败", value: "2" }, |
| | | ]); |
| | | const repairStatusText = ref(""); |
| | | |
| | | // 设置设å¤è§æ ¼åå· |
| | | const setDeviceModel = (id) => { |
| | | const option = deviceOptions.value.find((item) => item.id === id); |
| | | if (option) { |
| | | form.value.deviceModel = option.deviceModel; |
| | | deviceNameText.value = option.deviceName; |
| | | } |
| | | }; |
| | | // æå¼æ¥ä¿®ç¶æéæ©å¨ |
| | | const openRepairStatusPicker = () => { |
| | | uni.showActionSheet({ |
| | | itemList: repairStatusOptions.value.map(item => item.name), |
| | | success: res => { |
| | | form.value.status = repairStatusOptions.value[res.tapIndex].value; |
| | | repairStatusText.value = repairStatusOptions.value[res.tapIndex].name; |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // å è½½è¡¨åæ°æ®ï¼ç¼è¾æ¨¡å¼ï¼ |
| | | const loadForm = async (id) => { |
| | | if (id) { |
| | | operationType.value = 'edit'; |
| | | try { |
| | | const { code, data } = await getRepairById(id); |
| | | if (code == 200) { |
| | | form.value.deviceLedgerId = data.deviceLedgerId; |
| | | form.value.deviceModel = data.deviceModel; |
| | | form.value.repairTime = dayjs(data.repairTime).format("YYYY-MM-DD"); |
| | | form.value.repairName = data.repairName; |
| | | form.value.remark = data.remark; |
| | | // 设置设å¤åç§°æ¾ç¤º |
| | | const device = deviceOptions.value.find(item => item.id === data.deviceLedgerId); |
| | | if (device) { |
| | | deviceNameText.value = device.deviceName; |
| | | } |
| | | } |
| | | } catch (e) { |
| | | showToast('è·å详æ
失败'); |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | operationType.value = 'add'; |
| | | } |
| | | }; |
| | | // å 载设å¤å表 |
| | | const loadDeviceName = async () => { |
| | | try { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data || []; |
| | | } catch (e) { |
| | | showToast("è·å设å¤å表失败"); |
| | | } |
| | | }; |
| | | |
| | | // æ«æäºç»´ç åè½ |
| | | const startScan = () => { |
| | | if (isScanning.value) { |
| | | showToast('æ£å¨æ«æä¸ï¼è¯·ç¨å...'); |
| | | return; |
| | | } |
| | | |
| | | // è°ç¨uni-appçæ«ç API |
| | | uni.scanCode({ |
| | | scanType: ['qrCode', 'barCode'], |
| | | success: (res) => { |
| | | handleScanResult(res.result); |
| | | }, |
| | | fail: (err) => { |
| | | console.error('æ«ç 失败:', err); |
| | | showToast('æ«ç 失败ï¼è¯·éè¯'); |
| | | } |
| | | }); |
| | | }; |
| | | // 设置设å¤è§æ ¼åå· |
| | | const setDeviceModel = id => { |
| | | const option = deviceOptions.value.find(item => item.id === id); |
| | | if (option) { |
| | | form.value.deviceModel = option.deviceModel; |
| | | deviceNameText.value = option.deviceName; |
| | | } |
| | | }; |
| | | |
| | | // å¤çæ«ç ç»æ |
| | | const handleScanResult = (scanResult) => { |
| | | if (!scanResult) { |
| | | showToast('æ«ç ç»æä¸ºç©º'); |
| | | return; |
| | | } |
| | | |
| | | isScanning.value = true; |
| | | showToast('æ«ç æå'); |
| | | |
| | | // 3ç§åå¤çæ«ç ç»æ |
| | | scanTimer.value = setTimeout(() => { |
| | | processScanResult(scanResult); |
| | | isScanning.value = false; |
| | | }, 100); |
| | | }; |
| | | function getDeviceIdByRegExp(url) { |
| | | // å¹é
deviceId=åé¢çæ°å |
| | | const reg = /deviceId=(\d+)/; |
| | | const match = url.match(reg); |
| | | // 妿å¹é
å°ç»æï¼è¿åæ°åç±»åï¼å¦åè¿ånull |
| | | return match ? Number(match[1]) : null; |
| | | } |
| | | // å è½½è¡¨åæ°æ®ï¼ç¼è¾æ¨¡å¼ï¼ |
| | | const loadForm = async id => { |
| | | if (id) { |
| | | operationType.value = "edit"; |
| | | try { |
| | | const { code, data } = await getRepairById(id); |
| | | if (code == 200) { |
| | | form.value.deviceLedgerId = data.deviceLedgerId; |
| | | form.value.deviceModel = data.deviceModel; |
| | | form.value.repairTime = dayjs(data.repairTime).format("YYYY-MM-DD"); |
| | | form.value.repairName = data.repairName; |
| | | form.value.remark = data.remark; |
| | | repairStatusText.value = |
| | | repairStatusOptions.value.find(item => item.value == data.status) |
| | | ?.name || ""; |
| | | // 设置设å¤åç§°æ¾ç¤º |
| | | const device = deviceOptions.value.find( |
| | | item => item.id === data.deviceLedgerId |
| | | ); |
| | | if (device) { |
| | | deviceNameText.value = device.deviceName; |
| | | } |
| | | } |
| | | } catch (e) { |
| | | showToast("è·å详æ
失败"); |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | operationType.value = "add"; |
| | | } |
| | | }; |
| | | |
| | | // å¤çæ«ç ç»æå¹¶å¹é
è®¾å¤ |
| | | const processScanResult = (scanResult) => { |
| | | const deviceId = getDeviceIdByRegExp(scanResult); |
| | | const matchedDevice = deviceOptions.value.find(item => item.id == deviceId); |
| | | |
| | | if (matchedDevice) { |
| | | // æ¾å°å¹é
ç设å¤ï¼èªå¨å¡«å
|
| | | form.value.deviceLedgerId = matchedDevice.id; |
| | | deviceNameText.value = matchedDevice.deviceName; |
| | | form.value.deviceModel = matchedDevice.deviceModel; |
| | | showToast('设å¤ä¿¡æ¯å·²èªå¨å¡«å
'); |
| | | } else { |
| | | // æªæ¾å°å¹é
çè®¾å¤ |
| | | showToast('æªæ¾å°å¹é
ç设å¤ï¼è¯·æå¨éæ©'); |
| | | } |
| | | }; |
| | | // æ«æäºç»´ç åè½ |
| | | const startScan = () => { |
| | | if (isScanning.value) { |
| | | showToast("æ£å¨æ«æä¸ï¼è¯·ç¨å..."); |
| | | return; |
| | | } |
| | | |
| | | // æ¾ç¤ºè®¾å¤éæ©å¨ |
| | | const showDevicePicker = () => { |
| | | showDevice.value = true; |
| | | }; |
| | | // è°ç¨uni-appçæ«ç API |
| | | uni.scanCode({ |
| | | scanType: ["qrCode", "barCode"], |
| | | success: res => { |
| | | handleScanResult(res.result); |
| | | }, |
| | | fail: err => { |
| | | console.error("æ«ç 失败:", err); |
| | | showToast("æ«ç 失败ï¼è¯·éè¯"); |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // 确认设å¤éæ© |
| | | const onDeviceSelect = (e) => { |
| | | form.value.deviceLedgerId = e.value; |
| | | setDeviceModel(e.value); |
| | | showDevice.value = false; |
| | | }; |
| | | // å¤çæ«ç ç»æ |
| | | const handleScanResult = scanResult => { |
| | | if (!scanResult) { |
| | | showToast("æ«ç ç»æä¸ºç©º"); |
| | | return; |
| | | } |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | isScanning.value = true; |
| | | showToast("æ«ç æå"); |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = (e) => { |
| | | form.value.repairTime = formatDateToYMD(e.value); |
| | | pickerDateValue.value = dayjs(e.value).format("YYYY-MM-DD"); |
| | | showDate.value = false; |
| | | }; |
| | | // 3ç§åå¤çæ«ç ç»æ |
| | | scanTimer.value = setTimeout(() => { |
| | | processScanResult(scanResult); |
| | | isScanning.value = false; |
| | | }, 100); |
| | | }; |
| | | function getDeviceIdByRegExp(url) { |
| | | // å¹é
deviceId=åé¢çæ°å |
| | | const reg = /deviceId=(\d+)/; |
| | | const match = url.match(reg); |
| | | // 妿å¹é
å°ç»æï¼è¿åæ°åç±»åï¼å¦åè¿ånull |
| | | return match ? Number(match[1]) : null; |
| | | } |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶è·ååæ° |
| | | getPageParams(); |
| | | }); |
| | | // å¤çæ«ç ç»æå¹¶å¹é
è®¾å¤ |
| | | const processScanResult = scanResult => { |
| | | const deviceId = getDeviceIdByRegExp(scanResult); |
| | | const matchedDevice = deviceOptions.value.find(item => item.id == deviceId); |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶è·å设å¤å表ååæ° |
| | | loadDeviceName(); |
| | | getPageParams(); |
| | | }); |
| | | if (matchedDevice) { |
| | | // æ¾å°å¹é
ç设å¤ï¼èªå¨å¡«å
|
| | | form.value.deviceLedgerId = matchedDevice.id; |
| | | deviceNameText.value = matchedDevice.deviceName; |
| | | form.value.deviceModel = matchedDevice.deviceModel; |
| | | showToast("设å¤ä¿¡æ¯å·²èªå¨å¡«å
"); |
| | | } else { |
| | | // æªæ¾å°å¹é
çè®¾å¤ |
| | | showToast("æªæ¾å°å¹é
ç设å¤ï¼è¯·æå¨éæ©"); |
| | | } |
| | | }; |
| | | |
| | | // ç»ä»¶å¸è½½æ¶æ¸
ç宿¶å¨ |
| | | onUnmounted(() => { |
| | | if (scanTimer.value) { |
| | | clearTimeout(scanTimer.value); |
| | | } |
| | | }); |
| | | // æ¾ç¤ºè®¾å¤éæ©å¨ |
| | | const showDevicePicker = () => { |
| | | showDevice.value = true; |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const sendForm = async () => { |
| | | try { |
| | | // æå¨éªè¯è¡¨å |
| | | let isValid = true; |
| | | let errorMessage = ''; |
| | | if (!form.value.deviceLedgerId) { |
| | | isValid = false; |
| | | errorMessage = 'è¯·éæ©è®¾å¤åç§°'; |
| | | } else if (!form.value.repairTime || form.value.repairTime.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = 'è¯·éæ©æ¥ä¿®æ¥æ'; |
| | | } else if (!form.value.repairName || form.value.repairName.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请è¾å
¥æ¥ä¿®äºº'; |
| | | } else if (!form.value.remark || form.value.remark.trim() === '') { |
| | | isValid = false; |
| | | errorMessage = '请è¾å
¥æ
éç°è±¡'; |
| | | } |
| | | // 确认设å¤éæ© |
| | | const onDeviceSelect = e => { |
| | | form.value.deviceLedgerId = e.value; |
| | | setDeviceModel(e.value); |
| | | showDevice.value = false; |
| | | }; |
| | | |
| | | if (!isValid) { |
| | | showToast(errorMessage); |
| | | return; |
| | | } |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = e => { |
| | | form.value.repairTime = formatDateToYMD(e.value); |
| | | pickerDateValue.value = dayjs(e.value).format("YYYY-MM-DD"); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | | // åå¤æäº¤æ°æ® |
| | | const submitData = { ...form.value }; |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶è·ååæ° |
| | | getPageParams(); |
| | | }); |
| | | |
| | | const { code } = id |
| | | ? await editRepair({ id: id, ...submitData }) |
| | | : await addRepair(submitData); |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶è·å设å¤å表ååæ° |
| | | loadDeviceName(); |
| | | getPageParams(); |
| | | }); |
| | | |
| | | if (code == 200) { |
| | | showToast(`${id ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | showToast('表åéªè¯å¤±è´¥'); |
| | | } |
| | | }; |
| | | // ç»ä»¶å¸è½½æ¶æ¸
ç宿¶å¨ |
| | | onUnmounted(() => { |
| | | if (scanTimer.value) { |
| | | clearTimeout(scanTimer.value); |
| | | } |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync('repairId'); |
| | | uni.navigateBack(); |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const sendForm = async () => { |
| | | try { |
| | | // æå¨éªè¯è¡¨å |
| | | let isValid = true; |
| | | let errorMessage = ""; |
| | | if (!form.value.deviceLedgerId) { |
| | | isValid = false; |
| | | errorMessage = "è¯·éæ©è®¾å¤åç§°"; |
| | | } else if (!form.value.repairTime || form.value.repairTime.trim() === "") { |
| | | isValid = false; |
| | | errorMessage = "è¯·éæ©æ¥ä¿®æ¥æ"; |
| | | } else if (!form.value.repairName || form.value.repairName.trim() === "") { |
| | | isValid = false; |
| | | errorMessage = "请è¾å
¥æ¥ä¿®äºº"; |
| | | } else if (!form.value.remark || form.value.remark.trim() === "") { |
| | | isValid = false; |
| | | errorMessage = "请è¾å
¥æ
éç°è±¡"; |
| | | } |
| | | |
| | | // è·å页é¢åæ° |
| | | const getPageParams = () => { |
| | | // 使ç¨uni.getStorageSyncè·åid |
| | | const id = uni.getStorageSync('repairId'); |
| | | |
| | | // æ ¹æ®æ¯å¦æidåæ°æ¥å¤ææ¯æ°å¢è¿æ¯ç¼è¾ |
| | | if (id) { |
| | | // ç¼è¾æ¨¡å¼ï¼è·å详æ
|
| | | loadForm(id); |
| | | // å¯éï¼è·å忏
é¤åå¨çidï¼é¿å
å½±ååç»æä½ |
| | | uni.removeStorageSync('repairId'); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | loadForm(); |
| | | } |
| | | }; |
| | | if (!isValid) { |
| | | showToast(errorMessage); |
| | | return; |
| | | } |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | // 使ç¨uni.getStorageSyncè·åid |
| | | const id = uni.getStorageSync('repairId'); |
| | | return id; |
| | | }; |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | |
| | | // åå¤æäº¤æ°æ® |
| | | const submitData = { ...form.value }; |
| | | |
| | | const { code } = id |
| | | ? await editRepair({ id: id, ...submitData }) |
| | | : await addRepair(submitData); |
| | | |
| | | if (code == 200) { |
| | | showToast(`${id ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | setTimeout(() => { |
| | | uni.navigateBack(); |
| | | }, 1500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | loading.value = false; |
| | | showToast("表åéªè¯å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync("repairId"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // è·å页é¢åæ° |
| | | const getPageParams = () => { |
| | | // 使ç¨uni.getStorageSyncè·åid |
| | | const id = uni.getStorageSync("repairId"); |
| | | |
| | | // æ ¹æ®æ¯å¦æidåæ°æ¥å¤ææ¯æ°å¢è¿æ¯ç¼è¾ |
| | | if (id) { |
| | | // ç¼è¾æ¨¡å¼ï¼è·å详æ
|
| | | loadForm(id); |
| | | // å¯éï¼è·å忏
é¤åå¨çidï¼é¿å
å½±ååç»æä½ |
| | | uni.removeStorageSync("repairId"); |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ |
| | | loadForm(); |
| | | } |
| | | }; |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | // 使ç¨uni.getStorageSyncè·åid |
| | | const id = uni.getStorageSync("repairId"); |
| | | return id; |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .repair-add { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | @import "@/static/scss/form-common.scss"; |
| | | .repair-add { |
| | | 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; |
| | | } |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | } |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | |
| | | .scan-icon { |
| | | color: #1989fa; |
| | | font-size: 18px; |
| | | margin-left: 8px; |
| | | cursor: pointer; |
| | | } |
| | | .scan-icon { |
| | | color: #1989fa; |
| | | font-size: 18px; |
| | | margin-left: 8px; |
| | | cursor: pointer; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="repair-maintain"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="æ°å¢ç»´ä¿®" @back="goBack" /> |
| | | |
| | | <!-- 表åå
容 --> |
| | | <u-form ref="formRef" :model="form" :rules="formRules" label-width="140rpx"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="维修信æ¯" inset> |
| | | <u-form-item prop="maintenanceName" label="维修人" required> |
| | | <u-input |
| | | v-model="form.maintenanceName" |
| | | placeholder="请è¾å
¥ç»´ä¿®äºº" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item prop="maintenanceResult" label="ç»´ä¿®ç»æ" required> |
| | | <u-input |
| | | v-model="form.maintenanceResult" |
| | | type="textarea" |
| | | rows="3" |
| | | placeholder="请è¾å
¥ç»´ä¿®ç»æ" |
| | | clearable |
| | | maxlength="200" |
| | | show-word-limit |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="ç»´ä¿®æ¥æ" prop="maintenanceTime" required border-bottom> |
| | | <u-input |
| | | v-model="form.maintenanceTime" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker = true" |
| | | clearable |
| | | /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" @click="showDatePicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" @click="submitForm" :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker |
| | | :show="showDatePicker" |
| | | v-model="pickerDateValue" |
| | | mode="datetime" |
| | | title="éæ©æ¥æ" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" |
| | | /> |
| | | </view> |
| | | <view class="repair-maintain"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="æ°å¢ç»´ä¿®" |
| | | @back="goBack" /> |
| | | <!-- 表åå
容 --> |
| | | <u-form ref="formRef" |
| | | :model="form" |
| | | :rules="formRules" |
| | | label-width="140rpx"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="维修信æ¯" |
| | | inset> |
| | | <u-form-item prop="maintenanceName" |
| | | label="维修人" |
| | | required> |
| | | <u-input v-model="form.maintenanceName" |
| | | placeholder="请è¾å
¥ç»´ä¿®äºº" |
| | | clearable /> |
| | | </u-form-item> |
| | | <u-form-item prop="maintenanceResult" |
| | | label="ç»´ä¿®ç»æ" |
| | | required> |
| | | <u-input v-model="form.maintenanceResult" |
| | | type="textarea" |
| | | rows="3" |
| | | placeholder="请è¾å
¥ç»´ä¿®ç»æ" |
| | | clearable |
| | | maxlength="200" |
| | | show-word-limit /> |
| | | </u-form-item> |
| | | <u-form-item label="ç»´ä¿®ç¶æ" |
| | | prop="repairTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="repairStatusText" |
| | | placeholder="è¯·éæ©ç»´ä¿®ç¶æ" |
| | | readonly |
| | | @click="openRepairStatusPicker" |
| | | clearable /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" |
| | | @click="openRepairStatusPicker"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç»´ä¿®æ¥æ" |
| | | prop="maintenanceTime" |
| | | required |
| | | border-bottom> |
| | | <u-input v-model="form.maintenanceTime" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | readonly |
| | | @click="showDatePicker = true" |
| | | clearable /> |
| | | <template #right> |
| | | <u-icon name="arrow-right" |
| | | @click="showDatePicker = true"></u-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | <!-- æäº¤æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" |
| | | @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" |
| | | @click="submitForm" |
| | | :loading="loading">ä¿å</u-button> |
| | | </view> |
| | | </u-form> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker :show="showDatePicker" |
| | | v-model="pickerDateValue" |
| | | mode="datetime" |
| | | title="éæ©æ¥æ" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import { addMaintain } from '@/api/equipmentManagement/repair'; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | import { ref, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { addMaintain } from "@/api/equipmentManagement/repair"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | defineOptions({ |
| | | name: "设å¤ç»´ä¿®è¡¨å", |
| | | }); |
| | | defineOptions({ |
| | | name: "设å¤ç»´ä¿®è¡¨å", |
| | | }); |
| | | |
| | | const userStore = useUserStore(); |
| | | const userStore = useUserStore(); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const loading = ref(false); |
| | | const showDatePicker = ref(false); |
| | | const pickerDateValue = ref(Date.now());; // ä½¿ç¨æ¶é´æ³ |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(null); |
| | | const loading = ref(false); |
| | | const showDatePicker = ref(false); |
| | | const pickerDateValue = ref(Date.now()); // ä½¿ç¨æ¶é´æ³ |
| | | |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | maintenanceName: [{ required: true, trigger: "blur", message: "请è¾å
¥ç»´ä¿®äºº" }], |
| | | maintenanceResult: [{ required: true, trigger: "blur", message: "请è¾å
¥ç»´ä¿®ç»æ" }], |
| | | maintenanceTime: [{ required: true, trigger: "change", message: "è¯·éæ©ç»´ä¿®æ¥æ" }], |
| | | }; |
| | | // 表åéªè¯è§å |
| | | const formRules = { |
| | | maintenanceName: [ |
| | | { required: true, trigger: "blur", message: "请è¾å
¥ç»´ä¿®äºº" }, |
| | | ], |
| | | maintenanceResult: [ |
| | | { required: true, trigger: "blur", message: "请è¾å
¥ç»´ä¿®ç»æ" }, |
| | | ], |
| | | maintenanceTime: [ |
| | | { required: true, trigger: "change", message: "è¯·éæ©ç»´ä¿®æ¥æ" }, |
| | | ], |
| | | }; |
| | | const repairStatusOptions = ref([ |
| | | { name: "å¾
ç»´ä¿®", value: "0" }, |
| | | { name: "å®ç»", value: "1" }, |
| | | { name: "失败", value: "2" }, |
| | | ]); |
| | | const repairStatusText = ref("å®ç»"); |
| | | // æå¼æ¥ä¿®ç¶æéæ©å¨ |
| | | const openRepairStatusPicker = () => { |
| | | uni.showActionSheet({ |
| | | itemList: repairStatusOptions.value.map(item => item.name), |
| | | success: res => { |
| | | form.value.status = repairStatusOptions.value[res.tapIndex].value; |
| | | repairStatusText.value = repairStatusOptions.value[res.tapIndex].name; |
| | | }, |
| | | }); |
| | | }; |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | maintenanceName: userStore.nickName || "", // é»è®¤ä½¿ç¨å½åç¨æ·æµç§° |
| | | maintenanceResult: undefined, // ç»´ä¿®ç»æ |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // ç»´ä¿®æ¥æï¼åªæ¾ç¤ºæ¥æï¼ |
| | | }); |
| | | |
| | | // ä½¿ç¨ ref 声æè¡¨åæ°æ® |
| | | const form = ref({ |
| | | maintenanceName: userStore.nickName || '', // é»è®¤ä½¿ç¨å½åç¨æ·æµç§° |
| | | maintenanceResult: undefined, // ç»´ä¿®ç»æ |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), // ç»´ä¿®æ¥æï¼åªæ¾ç¤ºæ¥æï¼ |
| | | }); |
| | | // èªå®ä¹showToast彿° |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // èªå®ä¹showToast彿° |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | }; |
| | | // éç½®è¡¨åæ°æ®åæ ¡éªç¶æ |
| | | const resetForm = () => { |
| | | form.value = { |
| | | maintenanceName: userStore.nickName || "", |
| | | maintenanceResult: undefined, |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | }; |
| | | |
| | | // éç½®è¡¨åæ°æ®åæ ¡éªç¶æ |
| | | const resetForm = () => { |
| | | form.value = { |
| | | maintenanceName: userStore.nickName || '', |
| | | maintenanceResult: undefined, |
| | | maintenanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"), |
| | | }; |
| | | }; |
| | | const resetFormAndValidate = () => { |
| | | resetForm(); |
| | | }; |
| | | |
| | | const resetFormAndValidate = () => { |
| | | resetForm(); |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | // 使ç¨uview-plusç表åéªè¯æ¹å¼ |
| | | const valid = await formRef.value.validate(); |
| | | if (valid) { |
| | | submitFormData(); |
| | | } |
| | | } catch (e) { |
| | | showToast("表åéªè¯å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = async () => { |
| | | try { |
| | | // 使ç¨uview-plusç表åéªè¯æ¹å¼ |
| | | const valid = await formRef.value.validate(); |
| | | if (valid) { |
| | | submitFormData(); |
| | | } |
| | | } catch (e) { |
| | | showToast('表åéªè¯å¤±è´¥'); |
| | | } |
| | | }; |
| | | // æäº¤è¡¨åæ°æ® |
| | | const submitFormData = async () => { |
| | | try { |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | |
| | | // æäº¤è¡¨åæ°æ® |
| | | const submitFormData = async () => { |
| | | try { |
| | | loading.value = true; |
| | | const id = getPageId(); |
| | | |
| | | if (!id) { |
| | | showToast('åæ°é误'); |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | |
| | | // åå¤æäº¤æ°æ®ï¼maintenanceTime å ä¸å½åæ¶åç§ |
| | | const submitData = { ...form.value }; |
| | | |
| | | const { code } = await addMaintain({ id: id, ...submitData }); |
| | | |
| | | if (code == 200) { |
| | | showToast('æ°å¢ç»´ä¿®æå'); |
| | | resetFormAndValidate(); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | console.log(e); |
| | | |
| | | loading.value = false; |
| | | showToast('æä½å¤±è´¥'); |
| | | } |
| | | }; |
| | | if (!id) { |
| | | showToast("åæ°é误"); |
| | | loading.value = false; |
| | | return; |
| | | } |
| | | form.value.status = Number(form.value.status); |
| | | // åå¤æäº¤æ°æ®ï¼maintenanceTime å ä¸å½åæ¶åç§ |
| | | const submitData = { ...form.value }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync('repairId'); |
| | | uni.navigateBack(); |
| | | }; |
| | | const { code } = await addMaintain({ id: id, ...submitData }); |
| | | |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | const id = uni.getStorageSync('repairId'); |
| | | return id; |
| | | }; |
| | | if (code == 200) { |
| | | showToast("æ°å¢ç»´ä¿®æå"); |
| | | resetFormAndValidate(); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 500); |
| | | } else { |
| | | loading.value = false; |
| | | } |
| | | } catch (e) { |
| | | console.log(e); |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = (e) => { |
| | | form.value.maintenanceTime = dayjs(e.value).format('YYYY-MM-DD HH:mm:ss') |
| | | pickerDateValue.value = e.value |
| | | showDatePicker.value = false; |
| | | }; |
| | | loading.value = false; |
| | | showToast("æä½å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | // åå§åè¡¨åæ°æ® |
| | | const initForm = () => { |
| | | // 设置维修人为å½åç¨æ·æµç§° |
| | | form.value.maintenanceName = userStore.nickName || ''; |
| | | // 设置å½åæ¥æï¼åªå
å«å¹´ææ¥ï¼ |
| | | form.value.maintenanceTime = dayjs().format('YYYY-MM-DD HH:mm:ss'); |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync("repairId"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶åå§å表å |
| | | initForm(); |
| | | }); |
| | | // è·å页é¢ID |
| | | const getPageId = () => { |
| | | const id = uni.getStorageSync("repairId"); |
| | | return id; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶åå§å表å |
| | | initForm(); |
| | | }); |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = e => { |
| | | form.value.maintenanceTime = dayjs(e.value).format("YYYY-MM-DD HH:mm:ss"); |
| | | pickerDateValue.value = e.value; |
| | | showDatePicker.value = false; |
| | | }; |
| | | |
| | | // åå§åè¡¨åæ°æ® |
| | | const initForm = () => { |
| | | form.value.status = "1"; |
| | | // 设置维修人为å½åç¨æ·æµç§° |
| | | form.value.maintenanceName = userStore.nickName || ""; |
| | | // 设置å½åæ¥æï¼åªå
å«å¹´ææ¥ï¼ |
| | | form.value.maintenanceTime = dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶åå§å表å |
| | | initForm(); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶åå§å表å |
| | | initForm(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | .repair-maintain { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | padding-bottom: 5rem; |
| | | } |
| | | @import "@/static/scss/form-common.scss"; |
| | | .repair-maintain { |
| | | 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; |
| | | } |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | } |
| | | // ååºå¼è°æ´ |
| | | @media (max-width: 768px) { |
| | | .submit-section { |
| | | padding: 12px; |
| | | } |
| | | } |
| | | |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="notice-page"> |
| | | <PageHeader title="è¿è¡ç®¡ç" |
| | | @back="goBack" /> |
| | | <!-- éç¥å
¬åæ¿ --> |
| | | <view class="notice-board"> |
| | | <!-- ç»ä¸éç¥åºå --> |
| | | <view class="notice-section"> |
| | | <view class="section-header"> |
| | | <h3>设å¤è¿è¡è®°å½</h3> |
| | | </view> |
| | | <view class="notice-cards"> |
| | | <!-- æ¾åéç¥ --> |
| | | <view v-for="notice in holidayNotices" |
| | | :key="'holiday-' + notice.id" |
| | | class="notice-card holiday-card" |
| | | :class="{ 'urgent': isOverdue(notice) }"> |
| | | <view class="card-header"> |
| | | <view class="card-title"> |
| | | <view class="holiday-icon"> |
| | | <up-icon name="calendar" |
| | | size="18" |
| | | color="#67c23a" /> |
| | | </view> |
| | | <text>设å¤åç§°ï¼{{ notice.deviceName }}</text> |
| | | </view> |
| | | <view class="card-actions warning" |
| | | v-if="isOverdue(notice)"> |
| | | <up-icon name="info-circle" |
| | | size="16" |
| | | color="#fff" /> |
| | | <text>{{ 'è¶
æ¶æªå¯å¨' }}</text> |
| | | </view> |
| | | <view v-else |
| | | class="card-actions" |
| | | :class="getTagType(notice.status)"> |
| | | <up-icon :name="getIconName(notice.status)" |
| | | size="16" |
| | | color="#fff" /> |
| | | <text>{{ notice.status || 'æªç¥' }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>è§æ ¼åå·ï¼{{ notice.deviceModel || "-" }}</text> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>计åè¿è¡æ¶é´ï¼{{ notice.planRuntimeTime || "-" }}</text> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>å¼å§è¿è¡æ¶é´ï¼{{ notice.startRuntimeTime || "-" }}</text> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>ç»æè¿è¡æ¶é´ï¼{{ notice.endRuntimeTime || "-" }}</text> |
| | | </view> |
| | | <view class="card-content"> |
| | | <text>è¿è¡æ¶é¿ï¼{{ notice.runtimeDuration || "-" }}</text> |
| | | </view> |
| | | <up-button text |
| | | v-if="isOverdue(notice)" |
| | | type="warning" |
| | | size="small" |
| | | @click="handleEdit(notice, 'å¯å¨è¿è¡')" |
| | | :disabled="isNoticeExpired(notice)"> |
| | | <up-icon name="play-circle" |
| | | size="16" |
| | | style="margin-right: 10rpx;" |
| | | color="#fff" /> |
| | | ç«å³å¯å¨ |
| | | </up-button> |
| | | <up-button text |
| | | v-else-if="notice.status" |
| | | :type="getTagType2(notice.status)" |
| | | size="small" |
| | | @click="handleEdit(notice, notice.status === 'è¿è¡ä¸' ? '忢è¿è¡' : 'å¯å¨è¿è¡')" |
| | | :disabled="isNoticeExpired(notice)"> |
| | | <up-icon :name="getIconName2(notice.status)" |
| | | size="16" |
| | | color="#fff" /> |
| | | {{ notice.status === 'è¿è¡ä¸' ? '忢è¿è¡' : 'ç«å³å¯å¨' }} |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç©ºç¶æ --> |
| | | <view class="empty-state" |
| | | v-if="holidayNotices.length === 0 && maintenanceNotices.length === 0"> |
| | | <text>ææ éç¥å
Œ</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from "vue"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import { |
| | | getLedgerPage, |
| | | editLedger, |
| | | } from "@/api/equipmentManagement/runManagement.js"; |
| | | |
| | | // è·åæ ç¾ç±»å |
| | | const getTagType = status => { |
| | | switch (status) { |
| | | case "è¿è¡ä¸": |
| | | return "success"; |
| | | case "忢è¿è¡": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | const getTagType2 = status => { |
| | | switch (status) { |
| | | case "忢è¿è¡": |
| | | return "success"; |
| | | case "è¿è¡ä¸": |
| | | return "error"; |
| | | default: |
| | | return "info"; |
| | | } |
| | | }; |
| | | // è·å徿 åç§° |
| | | const getIconName = status => { |
| | | switch (status) { |
| | | case "è¿è¡ä¸": |
| | | return "play-circle"; |
| | | case "忢è¿è¡": |
| | | return "pause-circle"; |
| | | default: |
| | | return "question-circle"; |
| | | } |
| | | }; |
| | | // è·å徿 åç§°2 |
| | | const getIconName2 = status => { |
| | | switch (status) { |
| | | case "忢è¿è¡": |
| | | return "play-circle"; |
| | | case "è¿è¡ä¸": |
| | | return "pause-circle"; |
| | | default: |
| | | return "question-circle"; |
| | | } |
| | | }; |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const isOverdue = notice => { |
| | | if ( |
| | | notice.status == "è¿è¡ä¸" || |
| | | !notice.planRuntimeTime || |
| | | notice.startRuntimeTime |
| | | ) { |
| | | return false; |
| | | } |
| | | const planTime = new Date(notice.planRuntimeTime).getTime(); |
| | | const currentTime = new Date().getTime(); |
| | | return currentTime > planTime; |
| | | }; |
| | | |
| | | 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 handleEdit = async (device, status) => { |
| | | try { |
| | | const currentTime = new Date() |
| | | .toLocaleString("zh-CN", { |
| | | year: "numeric", |
| | | month: "2-digit", |
| | | day: "2-digit", |
| | | hour: "2-digit", |
| | | minute: "2-digit", |
| | | second: "2-digit", |
| | | hour12: false, |
| | | }) |
| | | .replace(/\//g, "-"); |
| | | |
| | | // æ´æ°è®¾å¤ç¶æåç¸å
³æ¶é´å段 |
| | | if (status === "å¯å¨è¿è¡") { |
| | | device.status = "è¿è¡ä¸"; |
| | | device.startRuntimeTime = currentTime; |
| | | device.endRuntimeTime = null; // æ¸
ç©ºç»ææ¶é´ |
| | | device.runtimeDuration = null; // æ¸
空è¿è¡æ¶é¿ |
| | | } else { |
| | | device.status = "忢è¿è¡"; |
| | | device.endRuntimeTime = currentTime; |
| | | // 计ç®è¿è¡æ¶é¿ |
| | | if (device.startRuntimeTime) { |
| | | const startTime = new Date(device.startRuntimeTime); |
| | | const endTime = new Date(currentTime); |
| | | const duration = endTime - startTime; |
| | | const hours = Math.floor(duration / (1000 * 60 * 60)); |
| | | const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60)); |
| | | device.runtimeDuration = `${hours}å°æ¶${minutes}åé`; |
| | | } |
| | | } |
| | | const params = { |
| | | id: device.id, |
| | | status: device.status, |
| | | planRuntimeTime: device.planRuntimeTime, |
| | | startRuntimeTime: device.startRuntimeTime, |
| | | endRuntimeTime: device.endRuntimeTime, |
| | | runtimeDuration: device.runtimeDuration, |
| | | }; |
| | | // è°ç¨APIæ´æ°è®¾å¤ç¶æ |
| | | const response = await editLedger(params); |
| | | if (response.code === 200) { |
| | | showToast(`${device.deviceName} ${status}æå`); |
| | | // å·æ°å表 |
| | | await fetchHolidayNotices(); |
| | | } else { |
| | | showToast(response.msg || "æä½å¤±è´¥"); |
| | | } |
| | | } catch (error) { |
| | | console.error("æ´æ°è®¾å¤ç¶æå¤±è´¥:", error); |
| | | showToast("æä½å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | const holidayNotices = ref([]); |
| | | const maintenanceNotices = ref([]); |
| | | |
| | | const fetchHolidayNotices = (append = false) => { |
| | | getLedgerPage({}).then(res => { |
| | | holidayNotices.value = res?.data?.records || []; |
| | | }); |
| | | }; |
| | | |
| | | // çå½å¨æ |
| | | onMounted(() => { |
| | | fetchHolidayNotices(); |
| | | }); |
| | | </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: #bec4c3; |
| | | } |
| | | |
| | | .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; |
| | | padding: 4rpx 8rpx; |
| | | border-radius: 10rpx; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | .success { |
| | | background: #67c23a; |
| | | color: #fff; |
| | | } |
| | | .error { |
| | | background: #f56c6c; |
| | | color: #fff; |
| | | } |
| | | .info { |
| | | background: #a8a9aa; |
| | | color: #fff; |
| | | } |
| | | .warning { |
| | | background: #e6a23c; |
| | | color: #fff; |
| | | } |
| | | |
| | | .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> |
| | |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- è¥éç®¡çæ¨¡å --> |
| | | <!-- <view class="common-module marketing-module">--> |
| | | <!-- <view class="module-header">--> |
| | | <!-- <view class="module-title-container">--> |
| | | <!-- <text class="module-title">è¥é管ç</text>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="module-content">--> |
| | | <!-- <up-grid :border="false"--> |
| | | <!-- col="4">--> |
| | | <!-- <up-grid-item v-for="(item, index) in marketingItems"--> |
| | | <!-- :key="index"--> |
| | | <!-- @click="handleCommonItemClick(item)">--> |
| | | <!-- <view class="icon-container"--> |
| | | <!-- :style="{ background: item.bgColor }">--> |
| | | <!-- <up-icon :name="item.icon"--> |
| | | <!-- :size="58"--> |
| | | <!-- color="#ffffff"></up-icon>--> |
| | | <!-- </view>--> |
| | | <!-- <text class="item-label">{{item.label}}</text>--> |
| | | <!-- </up-grid-item>--> |
| | | <!-- </up-grid>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <view class="common-module marketing-module"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">è¥é管ç</text> |
| | | </view> |
| | | </view> |
| | | <view class="module-content"> |
| | | <up-grid :border="false" |
| | | col="4"> |
| | | <up-grid-item v-for="(item, index) in marketingItems" |
| | | :key="index" |
| | | @click="handleCommonItemClick(item)"> |
| | | <view class="icon-container" |
| | | :style="{ background: item.bgColor }"> |
| | | <up-icon :name="item.icon" |
| | | :size="58" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-label">{{item.label}}</text> |
| | | </up-grid-item> |
| | | </up-grid> |
| | | </view> |
| | | </view> |
| | | <!-- <!– éè´ç®¡çæ¨¡å –>--> |
| | | <!-- <view class="common-module purchase-module">--> |
| | | <!-- <view class="module-header">--> |
| | | <!-- <view class="module-title-container">--> |
| | | <!-- <text class="module-title">éè´ç®¡ç</text>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="module-content">--> |
| | | <!-- <up-grid :border="false"--> |
| | | <!-- col="4">--> |
| | | <!-- <up-grid-item v-for="(item, index) in purchaseItems"--> |
| | | <!-- :key="index"--> |
| | | <!-- @click="handleCommonItemClick(item)">--> |
| | | <!-- <view class="icon-container"--> |
| | | <!-- :style="{ background: item.bgColor }">--> |
| | | <!-- <up-icon :name="item.icon"--> |
| | | <!-- :size="58"--> |
| | | <!-- color="#ffffff"></up-icon>--> |
| | | <!-- </view>--> |
| | | <!-- <text class="item-label">{{item.label}}</text>--> |
| | | <!-- </up-grid-item>--> |
| | | <!-- </up-grid>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- <!– åååå
¬æ¨¡å –>--> |
| | | <view class="common-module purchase-module"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">éè´ç®¡ç</text> |
| | | </view> |
| | | </view> |
| | | <view class="module-content"> |
| | | <up-grid :border="false" |
| | | col="4"> |
| | | <up-grid-item v-for="(item, index) in purchaseItems" |
| | | :key="index" |
| | | @click="handleCommonItemClick(item)"> |
| | | <view class="icon-container" |
| | | :style="{ background: item.bgColor }"> |
| | | <up-icon :name="item.icon" |
| | | :size="58" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-label">{{item.label}}</text> |
| | | </up-grid-item> |
| | | </up-grid> |
| | | </view> |
| | | </view> |
| | | <!-- <!– åååå
¬æ¨¡å –> --> |
| | | <view class="common-module collaboration-module"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | |
| | | </view> |
| | | </view> |
| | | <!-- 设å¤ç®¡ç模å --> |
| | | <!-- <view class="common-module equipment-module">--> |
| | | <!-- <view class="module-header">--> |
| | | <!-- <view class="module-title-container">--> |
| | | <!-- <text class="module-title">设å¤ç®¡ç</text>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <!-- <view class="module-content">--> |
| | | <!-- <up-grid :border="false"--> |
| | | <!-- col="4">--> |
| | | <!-- <up-grid-item v-for="(item, index) in equipmentItems"--> |
| | | <!-- :key="index"--> |
| | | <!-- @click="handleCommonItemClick(item)">--> |
| | | <!-- <view class="icon-container"--> |
| | | <!-- :style="{ background: item.bgColor }">--> |
| | | <!-- <up-icon :name="item.icon"--> |
| | | <!-- :size="58"--> |
| | | <!-- color="#ffffff"></up-icon>--> |
| | | <!-- </view>--> |
| | | <!-- <text class="item-label">{{item.label}}</text>--> |
| | | <!-- </up-grid-item>--> |
| | | <!-- </up-grid>--> |
| | | <!-- </view>--> |
| | | <!-- </view>--> |
| | | <view class="common-module equipment-module"> |
| | | <view class="module-header"> |
| | | <view class="module-title-container"> |
| | | <text class="module-title">设å¤ç®¡ç</text> |
| | | </view> |
| | | </view> |
| | | <view class="module-content"> |
| | | <up-grid :border="false" |
| | | col="4"> |
| | | <up-grid-item v-for="(item, index) in equipmentItems" |
| | | :key="index" |
| | | @click="handleCommonItemClick(item)"> |
| | | <view class="icon-container" |
| | | :style="{ background: item.bgColor }"> |
| | | <up-icon :name="item.icon" |
| | | :size="58" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-label">{{item.label}}</text> |
| | | </up-grid-item> |
| | | </up-grid> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | |
| | | // åååå
¬åè½æ°æ® |
| | | const collaborationItems = reactive([ |
| | | // { |
| | | // icon: "/static/images/icon/gongchuguanli@2x.png", |
| | | // label: "å
¬åºç®¡ç", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | // label: "请å管ç", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | // label: "åºå·®ç®¡ç", |
| | | // }, |
| | | { |
| | | icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | icon: "/static/images/icon/gongchuguanli@2x.png", |
| | | label: "èå¤ç®¡ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | icon: "/static/images/icon/baoxiaoguanli.png", |
| | | label: "è´¢å¡ç®¡ç", |
| | | }, |
| | | // { |
| | | // icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | // label: "æ¥é管ç", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | // label: "éè´ç®¡ç", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | // label: "æ¥ä»·ç®¡ç", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | // label: "åºåºç®¡ç", |
| | | // }, |
| | | { |
| | | icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | icon: "/static/images/icon/huiyiliebiao@2x.png", |
| | | label: "ä¼è®®ç®¡ç", |
| | | }, |
| | | // { |
| | | // icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | // label: "ä¼è®®è®¾ç½®", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | // label: "ä¼è®®å表", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | // label: "ä¼è®®ç³è¯·", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | // label: "ä¼è®®å®¡æ¹", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | // label: "ä¼è®®åå¸", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | // label: "ä¼è®®æ»ç»", |
| | | // }, |
| | | // { |
| | | // icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | // label: "ä¼è®®çæ¿", |
| | | // }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/tongzhigonggao@2x.png", |
| | | label: "éç¥å
Œ", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/zhishiku@2x.png", |
| | | label: "ç¥è¯åº", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/yongyinguanli@2x.png", |
| | | label: "ç¨å°ç®¡ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/guizhangzhidu@2x.png", |
| | | label: "è§ç« å¶åº¦", |
| | | }, |
| | | // { |
| | |
| | | // icon: '/static/images/icon/shebeitaizhang@2x.png', |
| | | // label: '设å¤å°è´¦', |
| | | // }, |
| | | { |
| | | icon: "/static/images/icon/shbeibaoxiu@2x.png", |
| | | label: "è¿è¡ç®¡ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/shbeibaoxiu@2x.png", |
| | | label: "è®¾å¤æ¥ä¿®", |
| | |
| | | url: "/pages/equipmentManagement/ledger/index", |
| | | }); |
| | | break; |
| | | case "è¿è¡ç®¡ç": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/runManagement/index", |
| | | }); |
| | | break; |
| | | case "è®¾å¤æ¥ä¿®": |
| | | uni.navigateTo({ |
| | | url: "/pages/equipmentManagement/repair/index", |
| | |
| | | ]); |
| | | const caiwu = reactive([ |
| | | { |
| | | icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | icon: "/static/images/icon/baoxiaoguanli.png", |
| | | label: "æ¥é管ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | icon: "/static/images/icon/caigouguanli.png", |
| | | label: "éè´ç®¡ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | icon: "/static/images/icon/baojiaguanli.png", |
| | | label: "æ¥ä»·ç®¡ç", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/chuchaiguanli@2x.png", |
| | | icon: "/static/images/icon/chukuguanli@2x.png", |
| | | label: "åºåºç®¡ç", |
| | | }, |
| | | ]); |
| | | |
| | | const huiyi = reactive([ |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/huiyishezhi@2x.png", |
| | | label: "ä¼è®®è®¾ç½®", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/huiyiliebiao@2x.png", |
| | | label: "ä¼è®®å表", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/huiyishenqing@2x.png", |
| | | label: "ä¼è®®ç³è¯·", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/huiyishenpi@2x.png", |
| | | label: "ä¼è®®å®¡æ¹", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/huiyifabu@2x.png", |
| | | label: "ä¼è®®åå¸", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/huiyizongjie@2x.png", |
| | | label: "ä¼è®®æ»ç»", |
| | | }, |
| | | { |
| | | icon: "/static/images/icon/qingjiaguanli@2x.png", |
| | | icon: "/static/images/icon/huiyikanban@2x.png", |
| | | label: "ä¼è®®çæ¿", |
| | | }, |
| | | ]); |
| | |
| | | <template> |
| | | <view class="account-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="æ°å¢ä»æ¬¾" @back="onClickLeft" /> |
| | | |
| | | <PageHeader title="æ°å¢ä»æ¬¾" |
| | | @back="onClickLeft" /> |
| | | <!-- 表åå
容 --> |
| | | <u-form @submit="onSubmit" ref="formRef" label-width="110" input-align="right" error-message-align="right"> |
| | | <u-form @submit="onSubmit" |
| | | ref="formRef" |
| | | label-width="110" |
| | | input-align="right" |
| | | error-message-align="right"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯" class="form-section"> |
| | | <u-form-item label="éè´ååå·" class="form-item"> |
| | | <u-input |
| | | v-model="form.purchaseContractNumber" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | <u-cell-group title="åºæ¬ä¿¡æ¯" |
| | | class="form-section"> |
| | | <u-form-item label="éè´ååå·" |
| | | class="form-item"> |
| | | <u-input v-model="form.purchaseContractNumber" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="éå®ååå·" class="form-item"> |
| | | <u-input |
| | | v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | <u-form-item label="éå®ååå·" |
| | | class="form-item"> |
| | | <u-input v-model="form.salesContractNo" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="ä¾åºååç§°" class="form-item"> |
| | | <u-input |
| | | v-model="form.supplierName" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | <u-form-item label="ä¾åºååç§°" |
| | | class="form-item"> |
| | | <u-input v-model="form.supplierName" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="å票å·" class="form-item"> |
| | | <!-- <u-form-item label="å票å·" class="form-item"> |
| | | <u-input |
| | | v-model="form.invoiceNumber" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item label="å票éé¢(å
)" class="form-item"> |
| | | </u-form-item> --> |
| | | <!-- <u-form-item label="å票éé¢(å
)" class="form-item"> |
| | | <u-input |
| | | v-model="form.invoiceAmount" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | </u-form-item> |
| | | </u-form-item> --> |
| | | <view class="tip-text">å¾
仿¬¾éé¢ï¼{{ currentNoReceiptAmount }} å
</view> |
| | | <u-form-item label="æ¬æ¬¡ä»æ¬¾éé¢" prop="currentPaymentAmount" required class="form-item"> |
| | | <u-input |
| | | v-model="form.currentPaymentAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="changeNum" |
| | | clearable |
| | | /> |
| | | <u-form-item label="æ¬æ¬¡ä»æ¬¾éé¢" |
| | | prop="currentPaymentAmount" |
| | | required |
| | | class="form-item"> |
| | | <u-input v-model="form.currentPaymentAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="changeNum" |
| | | clearable /> |
| | | </u-form-item> |
| | | <u-form-item label="仿¬¾å½¢å¼" prop="paymentMethod" required class="form-item"> |
| | | <u-input |
| | | v-model="form.paymentMethod" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showPaymentTypePicker" |
| | | /> |
| | | <u-form-item label="仿¬¾å½¢å¼" |
| | | prop="paymentMethod" |
| | | required |
| | | class="form-item"> |
| | | <u-input v-model="form.paymentMethod" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showPaymentTypePicker" /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showPaymentTypePicker" |
| | | ></up-icon> |
| | | </template> |
| | | <up-icon name="arrow-right" |
| | | @click="showPaymentTypePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="仿¬¾æ¥æ" prop="paymentDate" required class="form-item"> |
| | | <u-input |
| | | v-model="form.paymentDate" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showDatePicker" |
| | | /> |
| | | <u-form-item label="仿¬¾æ¥æ" |
| | | prop="paymentDate" |
| | | required |
| | | class="form-item"> |
| | | <u-input v-model="form.paymentDate" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | @click="showDatePicker" /> |
| | | <template #right> |
| | | <up-icon |
| | | name="arrow-right" |
| | | @click="showDatePicker" |
| | | ></up-icon> |
| | | </template> |
| | | <up-icon name="arrow-right" |
| | | @click="showDatePicker"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | <u-form-item label="ç»è®°äºº" class="form-item"> |
| | | <u-input |
| | | v-model="form.registrant" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly |
| | | /> |
| | | <u-form-item label="ç»è®°äºº" |
| | | class="form-item"> |
| | | <u-input v-model="form.registrant" |
| | | placeholder="èªå¨å¡«å
" |
| | | readonly /> |
| | | </u-form-item> |
| | | <u-form-item label="ç»è®°æ¥æ" prop="registrationtDate" required class="form-item"> |
| | | <u-input |
| | | v-model="form.registrationtDate" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | /> |
| | | <u-form-item label="ç»è®°æ¥æ" |
| | | prop="registrationtDate" |
| | | required |
| | | class="form-item"> |
| | | <u-input v-model="form.registrationtDate" |
| | | placeholder="è¯·éæ©" |
| | | readonly /> |
| | | </u-form-item> |
| | | </u-cell-group> |
| | | |
| | | <!-- æäº¤æé® --> |
| | | <FooterButtons |
| | | :loading="loading" |
| | | @cancel="onClickLeft" |
| | | @confirm="onSubmit" |
| | | /> |
| | | <FooterButtons :loading="loading" |
| | | @cancel="onClickLeft" |
| | | @confirm="onSubmit" /> |
| | | </u-form> |
| | | |
| | | <!-- 仿¬¾æ¹å¼éæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showPaymentType" |
| | | title="鿩仿¬¾æ¹å¼" |
| | | :actions="receipt_payment_type" |
| | | @select="onPaymentTypeConfirm" |
| | | @close="showPaymentType = false" |
| | | /> |
| | | |
| | | <up-action-sheet :show="showPaymentType" |
| | | title="鿩仿¬¾æ¹å¼" |
| | | :actions="receipt_payment_type" |
| | | @select="onPaymentTypeConfirm" |
| | | @close="showPaymentType = false" /> |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-datetime-picker |
| | | :show="showDate" |
| | | v-model="form.paymentDate" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | <up-datetime-picker :show="showDate" |
| | | v-model="form.paymentDate" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed } from 'vue' |
| | | import FooterButtons from '@/components/FooterButtons.vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { useDict } from '@/utils/dict' |
| | | import {paymentRegistrationAdd} from "@/api/procurementManagement/paymentEntry"; |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import { ref, onMounted, computed } from "vue"; |
| | | import FooterButtons from "@/components/FooterButtons.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { useDict } from "@/utils/dict"; |
| | | import { paymentRegistrationAdd } from "@/api/procurementManagement/paymentEntry"; |
| | | import { formatDateToYMD } from "@/utils/ruoyi"; |
| | | |
| | | // æ¿æ¢ toast å notify æ¹æ³ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | // æ¿æ¢ toast å notify æ¹æ³ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | const showNotify = ({ type, message }) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: type === 'warning' ? 'none' : 'success' |
| | | }) |
| | | } |
| | | const showNotify = ({ type, message }) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: type === "warning" ? "none" : "success", |
| | | }); |
| | | }; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // 表åå¼ç¨ |
| | | const formRef = ref() |
| | | // 表åå¼ç¨ |
| | | const formRef = ref(); |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const showPaymentType = ref(false) |
| | | const showDate = ref(false) |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false); |
| | | const showPaymentType = ref(false); |
| | | const showDate = ref(false); |
| | | |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | purchaseContractNumber: '', |
| | | salesContractNo: '', |
| | | supplierName: '', |
| | | invoiceNumber: '', |
| | | invoiceAmount: '', |
| | | taxRate: '', |
| | | currentPaymentAmount: '', |
| | | receiptPaymentType: '', |
| | | paymentMethod: '', |
| | | registrant: '', |
| | | paymentDate: '', |
| | | registrationtDate: '', |
| | | ticketRegistrationId: '' |
| | | }) |
| | | const currentNoReceiptAmount = ref(0) |
| | | // è¡¨åæ°æ® |
| | | const form = ref({ |
| | | purchaseContractNumber: "", |
| | | salesContractNo: "", |
| | | supplierName: "", |
| | | invoiceNumber: "", |
| | | invoiceAmount: "", |
| | | taxRate: "", |
| | | currentPaymentAmount: "", |
| | | receiptPaymentType: "", |
| | | paymentMethod: "", |
| | | registrant: "", |
| | | paymentDate: "", |
| | | registrationtDate: "", |
| | | ticketRegistrationId: "", |
| | | }); |
| | | const currentNoReceiptAmount = ref(0); |
| | | |
| | | // è·ååå
¸æ°æ® |
| | | const { receipt_payment_type: dictReceiptPaymentType } = useDict('receipt_payment_type') |
| | | // è·ååå
¸æ°æ® |
| | | const { receipt_payment_type: dictReceiptPaymentType } = useDict( |
| | | "receipt_payment_type" |
| | | ); |
| | | |
| | | // 转æ¢åå
¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ |
| | | const receipt_payment_type = computed(() => { |
| | | return dictReceiptPaymentType.value.map(item => ({ |
| | | name: item.label, |
| | | value: item.value |
| | | })) |
| | | }) |
| | | // 转æ¢åå
¸æ°æ®æ ¼å¼ä¸ºéæ©å¨éè¦çæ ¼å¼ |
| | | const receipt_payment_type = computed(() => { |
| | | return dictReceiptPaymentType.value.map(item => ({ |
| | | name: item.label, |
| | | value: item.value, |
| | | })); |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const onClickLeft = () => { |
| | | uni.removeStorageSync('invoiceLedgerEditRow'); |
| | | uni.navigateBack() |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const onClickLeft = () => { |
| | | uni.removeStorageSync("invoiceLedgerEditRow"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // æ¾ç¤ºä»æ¬¾æ¹å¼éæ©å¨ |
| | | const showPaymentTypePicker = () => { |
| | | showPaymentType.value = true |
| | | } |
| | | const changeNum = () => { |
| | | if (form.value.currentPaymentAmount > currentNoReceiptAmount.value) { |
| | | form.value.currentPaymentAmount = currentNoReceiptAmount.value |
| | | showToast('ä¸å¯å¤§äºå¾
仿¬¾éé¢') |
| | | } |
| | | } |
| | | // æ¾ç¤ºä»æ¬¾æ¹å¼éæ©å¨ |
| | | const showPaymentTypePicker = () => { |
| | | showPaymentType.value = true; |
| | | }; |
| | | const changeNum = () => { |
| | | if (form.value.currentPaymentAmount > currentNoReceiptAmount.value) { |
| | | form.value.currentPaymentAmount = currentNoReceiptAmount.value; |
| | | showToast("ä¸å¯å¤§äºå¾
仿¬¾éé¢"); |
| | | } |
| | | }; |
| | | |
| | | // ç¡®è®¤ä»æ¬¾æ¹å¼éæ© |
| | | const onPaymentTypeConfirm = (item) => { |
| | | form.value.receiptPaymentType = item.value |
| | | form.value.paymentMethod = item.name |
| | | showPaymentType.value = false |
| | | } |
| | | // ç¡®è®¤ä»æ¬¾æ¹å¼éæ© |
| | | const onPaymentTypeConfirm = item => { |
| | | form.value.receiptPaymentType = item.value; |
| | | form.value.paymentMethod = item.name; |
| | | showPaymentType.value = false; |
| | | }; |
| | | |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true |
| | | } |
| | | // æ¾ç¤ºæ¥æéæ©å¨ |
| | | const showDatePicker = () => { |
| | | showDate.value = true; |
| | | }; |
| | | |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = (e) => { |
| | | form.value.paymentDate = formatDateToYMD(e.value) |
| | | showDate.value = false |
| | | } |
| | | // ç¡®è®¤æ¥æéæ© |
| | | const onDateConfirm = e => { |
| | | form.value.paymentDate = formatDateToYMD(e.value); |
| | | showDate.value = false; |
| | | }; |
| | | |
| | | // æäº¤è¡¨å |
| | | const onSubmit = () => { |
| | | // 表åéªè¯ |
| | | if (!form.value.currentPaymentAmount) { |
| | | showNotify({ type: 'warning', message: '请è¾å
¥ä»æ¬¾éé¢' }) |
| | | return |
| | | // æäº¤è¡¨å |
| | | const onSubmit = () => { |
| | | // 表åéªè¯ |
| | | if (!form.value.currentPaymentAmount) { |
| | | showNotify({ type: "warning", message: "请è¾å
¥ä»æ¬¾éé¢" }); |
| | | return; |
| | | } |
| | | if (!form.value.receiptPaymentType) { |
| | | showNotify({ type: "warning", message: "è¯·éæ©ä»æ¬¾å½¢å¼" }); |
| | | return; |
| | | } |
| | | if (!form.value.paymentDate) { |
| | | showNotify({ type: "warning", message: "è¯·éæ©ä»æ¬¾æ¥æ" }); |
| | | return; |
| | | } |
| | | loading.value = true; |
| | | paymentRegistrationAdd(form.value) |
| | | .then(() => { |
| | | showToast("æäº¤æå"); |
| | | onClickLeft(); |
| | | }) |
| | | .catch(error => { |
| | | loading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // åå§åæ°æ® |
| | | const initData = () => { |
| | | const rowStr = uni.getStorageSync("invoiceLedgerEditRow"); |
| | | const row = JSON.parse(rowStr); |
| | | form.value = { ...row }; |
| | | form.value.ticketRegistrationId = row.id; |
| | | form.value.id = null; |
| | | form.value.id = ""; |
| | | currentNoReceiptAmount.value = row.pendingTicketsTotal |
| | | ? parseFloat(row.pendingTicketsTotal).toFixed(2) |
| | | : "0"; |
| | | form.value.registrant = userStore.nickName; |
| | | form.value.registrationtDate = getCurrentDate(); |
| | | form.value.paymentDate = getCurrentDate(); |
| | | }; |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | if (!form.value.receiptPaymentType) { |
| | | showNotify({ type: 'warning', message: 'è¯·éæ©ä»æ¬¾å½¢å¼' }) |
| | | return |
| | | } |
| | | if (!form.value.paymentDate) { |
| | | showNotify({ type: 'warning', message: 'è¯·éæ©ä»æ¬¾æ¥æ' }) |
| | | return |
| | | } |
| | | loading.value = true |
| | | paymentRegistrationAdd(form.value) |
| | | .then(() => { |
| | | showToast('æäº¤æå') |
| | | onClickLeft() |
| | | }) |
| | | .catch((error) => { |
| | | loading.value = false |
| | | }) |
| | | } |
| | | |
| | | // åå§åæ°æ® |
| | | const initData = () => { |
| | | const rowStr = uni.getStorageSync('invoiceLedgerEditRow') |
| | | const row = JSON.parse(rowStr) |
| | | form.value = { ...row }; |
| | | form.value.ticketRegistrationId = row.id; |
| | | form.value.id = null; |
| | | form.value.id = ""; |
| | | currentNoReceiptAmount.value = row.unPaymentAmountTotal |
| | | form.value.registrant = userStore.nickName |
| | | form.value.registrationtDate = getCurrentDate(); |
| | | form.value.paymentDate = getCurrentDate(); |
| | | } |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | onMounted(() => { |
| | | initData() |
| | | }) |
| | | onMounted(() => { |
| | | initData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | @import "@/static/scss/form-common.scss"; |
| | | .tip-text { |
| | | font-size: 16px; |
| | | color: #383838; |
| | | margin-top: 10px; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.supplierNameOrContractNo" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- çéå¼å
³ --> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºå¾
仿¬¾ä¸º0</text> |
| | | <u-switch v-model="searchForm.status" @change="getList" active-color="#2979ff" inactive-color="#e5e5e5"/> |
| | | </view> |
| | | </view> |
| | | |
| | | |
| | | |
| | | <!-- å表åºå --> |
| | | <view class="ledger-list" v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" :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.purchaseContractNumber }}</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.salesContractNo }}</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.invoiceNumber }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票éé¢(å
)</text> |
| | | <text class="detail-value">{{ item.invoiceAmount }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">已仿¬¾éé¢(å
)</text> |
| | | <text class="detail-value">{{ item.paymentAmountTotal || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¾
仿¬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatNumber(item.unPaymentAmountTotal) }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.unPaymentAmountTotal == 0" |
| | | @click="openForm('add', item)" |
| | | > |
| | | æ°å¢ä»æ¬¾ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æ æ°æ®æç¤º --> |
| | | <view class="no-data" v-else> |
| | | <text>ææ ä»æ¬¾æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.supplierNameOrContractNo" |
| | | @change="getList" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | <!-- çéå¼å
³ --> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºå¾
仿¬¾ä¸º0</text> |
| | | <u-switch v-model="searchForm.status" |
| | | @change="getList" |
| | | active-color="#2979ff" |
| | | inactive-color="#e5e5e5" /> |
| | | </view> |
| | | </view> |
| | | <!-- å表åºå --> |
| | | <view class="ledger-list" |
| | | v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" |
| | | :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.purchaseContractNumber }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <u-tag :type="getTagClass(item.statusName)">{{ item.statusName || '--' }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">éå®ååå·</text> |
| | | <text class="detail-value">{{ item.salesContractNo }}</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.invoiceNumber }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产å大类</text> |
| | | <text class="detail-value">{{ item.productCategory }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ item.specificationModel }}</text> |
| | | </view> |
| | | <!-- <view class="detail-row"> |
| | | <text class="detail-label">å票éé¢(å
)</text> |
| | | <text class="detail-value">{{ item.invoiceAmount }}</text> |
| | | </view> --> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">已仿¬¾éé¢(å
)</text> |
| | | <text class="detail-value">{{ item.ticketsTotal ? parseFloat(item.ticketsTotal).toFixed(2) : '0' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¾
仿¬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ item.pendingTicketsTotal ? parseFloat(item.pendingTicketsTotal).toFixed(2) : '0' }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <u-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.unPaymentAmountTotal == 0" |
| | | @click="openForm('add', item)"> |
| | | æ°å¢ä»æ¬¾ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- æ æ°æ®æç¤º --> |
| | | <view class="no-data" |
| | | v-else> |
| | | <text>ææ ä»æ¬¾æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | import {invoiceListPage} from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | import { ref } from "vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | // æ¿æ¢ toast æ¹æ³ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { invoiceListPage } from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const tableData = ref([]) |
| | | const tableLoading = ref(false) |
| | | // ååºå¼æ°æ® |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | // æ¥è¯¢åæ°è®¾ç½®ä¸º-1è·åå
¨é¨æ°æ® |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1 |
| | | }) |
| | | // æ¥è¯¢åæ°è®¾ç½®ä¸º-1è·åå
¨é¨æ°æ® |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | supplierNameOrContractNo: '', |
| | | status: true, |
| | | customerName: '', |
| | | customerContractNo: '', |
| | | projectName: '' |
| | | }) |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | supplierNameOrContractNo: "", |
| | | status: true, |
| | | customerName: "", |
| | | customerContractNo: "", |
| | | projectName: "", |
| | | }); |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (!type) { |
| | | return "info"; |
| | | } |
| | | if (type == "æªå®æä»æ¬¾") { |
| | | return "warning"; |
| | | } else if (type == "已宿仿¬¾") { |
| | | return "success"; |
| | | } else { |
| | | return "info"; |
| | | } |
| | | }; |
| | | // æ ¼å¼åæ°å |
| | | const formatNumber = value => { |
| | | return parseFloat(value || 0).toFixed(2); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ°å |
| | | const formatNumber = (value) => { |
| | | return parseFloat(value || 0).toFixed(2) |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | tableLoading.value = true; |
| | | invoiceListPage({ ...searchForm.value, ...page.value }) |
| | | .then(res => { |
| | | console.log(res.data); |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records || []; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | tableLoading.value = false; |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | tableLoading.value = true |
| | | invoiceListPage({ ...searchForm.value, ...page.value }).then((res) => { |
| | | tableLoading.value = false |
| | | tableData.value = res.records || [] |
| | | closeToast() |
| | | }).catch(() => { |
| | | tableLoading.value = false |
| | | closeToast() |
| | | }) |
| | | } |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // æå¼æ°å¢è¡¨å |
| | | const openForm = (type, item) => { |
| | | if (item.unPaymentAmountTotal == 0) { |
| | | showToast("æ éå仿¬¾"); |
| | | return; |
| | | } |
| | | uni.setStorageSync("operationType", type); |
| | | uni.setStorageSync("invoiceLedgerEditRow", JSON.stringify(item)); |
| | | uni.navigateTo({ url: "/pages/procurementManagement/paymentEntry/add" }); |
| | | }; |
| | | |
| | | // æå¼æ°å¢è¡¨å |
| | | const openForm = (type, item) => { |
| | | if (item.unPaymentAmountTotal == 0) { |
| | | showToast('æ éå仿¬¾') |
| | | return |
| | | } |
| | | uni.setStorageSync('operationType', type); |
| | | uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)) |
| | | uni.navigateTo({ url: '/pages/procurementManagement/paymentEntry/add' }) |
| | | } |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/procurement-common.scss'; |
| | | @import "@/styles/procurement-common.scss"; |
| | | |
| | | // 仿¬¾ç»è®°ç¹ææ ·å¼ |
| | | .detail-value { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | } |
| | | // 仿¬¾ç»è®°ç¹ææ ·å¼ |
| | | .detail-value { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="account-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="ç¼è¾æ¥ç¥¨å°è´¦" @back="goBack" /> |
| | | |
| | | <up-form @submit="submitForm" ref="formRef" label-width="120" :model="form"> |
| | | <up-form-item label="éè´ååå·" prop="purchaseContractNumber"> |
| | | <up-input v-model="form.purchaseContractNumber" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="éå®ååå·" prop="salesContractNo"> |
| | | <up-input v-model="form.salesContractNo" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å«ç¨åä»·(å
)" prop="taxInclusiveUnitPrice"> |
| | | <up-input v-model="form.taxInclusiveUnitPrice" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å建æ¶é´" prop="createdAt"> |
| | | <up-input v-model="form.createdAt" placeholder="èªå¨çæ" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å票å·" prop="invoiceNumber"> |
| | | <up-input v-model="form.invoiceNumber" placeholder="请è¾å
¥" disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="æ¥ç¥¨æ°" prop="ticketsNum" required :rules="rules.ticketsNum"> |
| | | <up-input |
| | | v-model="form.ticketsNum" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="inputTicketsNum" |
| | | /> |
| | | </up-form-item> |
| | | <up-form-item label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)" prop="ticketsAmount" required :rules="rules.ticketsAmount"> |
| | | <up-input |
| | | v-model="form.ticketsAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="inputTicketsAmount" |
| | | /> |
| | | </up-form-item> |
| | | <view class="tip-text">æªæ¥ç¥¨æ°ï¼{{ formatAmount(form.futureTickets) }} å
</view> |
| | | |
| | | <!-- 使ç¨å
Œ
±åºé¨æé®ç»ä»¶ --> |
| | | <FooterButtons |
| | | show |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | @cancel="goBack" |
| | | @confirm="onSubmit" |
| | | /> |
| | | </up-form> |
| | | </view> |
| | | <view class="account-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="ç¼è¾æ¥ç¥¨å°è´¦" |
| | | @back="goBack" /> |
| | | <up-form @submit="submitForm" |
| | | ref="formRef" |
| | | label-width="120" |
| | | :model="form"> |
| | | <up-form-item label="éè´ååå·" |
| | | prop="purchaseContractNumber"> |
| | | <up-input v-model="form.purchaseContractNumber" |
| | | placeholder="èªå¨çæ" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="éå®ååå·" |
| | | prop="salesContractNo"> |
| | | <up-input v-model="form.salesContractNo" |
| | | placeholder="èªå¨çæ" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice"> |
| | | <up-input v-model="form.taxInclusiveUnitPrice" |
| | | placeholder="èªå¨çæ" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å建æ¶é´" |
| | | prop="createdAt"> |
| | | <up-input v-model="form.createdAt" |
| | | placeholder="èªå¨çæ" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="å票å·" |
| | | prop="invoiceNumber"> |
| | | <up-input v-model="form.invoiceNumber" |
| | | placeholder="请è¾å
¥" |
| | | disabled /> |
| | | </up-form-item> |
| | | <up-form-item label="æ¥ç¥¨æ°" |
| | | prop="ticketsNum" |
| | | required |
| | | :rules="rules.ticketsNum"> |
| | | <up-input v-model="form.ticketsNum" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="inputTicketsNum" /> |
| | | </up-form-item> |
| | | <up-form-item label="æ¬æ¬¡æ¥ç¥¨éé¢(å
)" |
| | | prop="ticketsAmount" |
| | | required |
| | | :rules="rules.ticketsAmount"> |
| | | <up-input v-model="form.ticketsAmount" |
| | | type="number" |
| | | placeholder="请è¾å
¥" |
| | | @blur="inputTicketsAmount" /> |
| | | </up-form-item> |
| | | <view class="tip-text">æªæ¥ç¥¨æ°ï¼{{ formatAmount(form.futureTickets) }} å
</view> |
| | | <!-- 使ç¨å
Œ
±åºé¨æé®ç»ä»¶ --> |
| | | <FooterButtons show |
| | | cancelText="åæ¶" |
| | | confirmText="ä¿å" |
| | | @cancel="goBack" |
| | | @confirm="onSubmit" /> |
| | | </up-form> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { getToken } from '@/utils/auth' |
| | | import { invoiceLedgerSaveOrUpdate } from '@/api/salesManagement/invoiceLedger.js' |
| | | import config from '@/config.js' |
| | | import {getProductRecordById, updateRegistration} from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | import PageHeader from '@/components/PageHeader.vue'; |
| | | import FooterButtons from '@/components/FooterButtons.vue'; |
| | | import { ref, onMounted } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import { invoiceLedgerSaveOrUpdate } from "@/api/salesManagement/invoiceLedger.js"; |
| | | import config from "@/config.js"; |
| | | import { |
| | | getProductRecordById, |
| | | updateRegistration, |
| | | } from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import FooterButtons from "@/components/FooterButtons.vue"; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | const formRef = ref() |
| | | let form = ref({ |
| | | salesLedgerId: '', |
| | | customerId: '', |
| | | invoiceNo: '', |
| | | invoiceTotal: '', |
| | | taxRate: '', |
| | | invoicePerson: '', |
| | | invoiceDate: '', |
| | | customerName: '', |
| | | fileList: [], |
| | | createTime: '', |
| | | taxInclusiveTotalPrice: '', |
| | | taxInclusiveUnitPrice: '' |
| | | }) |
| | | const fileList = ref([]) |
| | | const currentId = ref('') |
| | | const temFutureTickets = ref(0) |
| | | const formRef = ref(); |
| | | let form = ref({ |
| | | salesLedgerId: "", |
| | | customerId: "", |
| | | invoiceNo: "", |
| | | invoiceTotal: "", |
| | | taxRate: "", |
| | | invoicePerson: "", |
| | | invoiceDate: "", |
| | | customerName: "", |
| | | fileList: [], |
| | | createTime: "", |
| | | taxInclusiveTotalPrice: "", |
| | | taxInclusiveUnitPrice: "", |
| | | }); |
| | | const fileList = ref([]); |
| | | const currentId = ref(""); |
| | | const temFutureTickets = ref(0); |
| | | |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | ticketsNum: [ |
| | | { required: true, message: '请è¾å
¥æ¥ç¥¨æ°', trigger: 'blur' } |
| | | ], |
| | | ticketsAmount: [ |
| | | { required: true, message: '请è¾å
¥æ¬æ¬¡æ¥ç¥¨éé¢', trigger: 'blur' } |
| | | ] |
| | | }; |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | ticketsNum: [{ required: true, message: "请è¾å
¥æ¥ç¥¨æ°", trigger: "blur" }], |
| | | ticketsAmount: [ |
| | | { required: true, message: "请è¾å
¥æ¬æ¬¡æ¥ç¥¨éé¢", trigger: "blur" }, |
| | | ], |
| | | }; |
| | | |
| | | const goBack = () => { |
| | | uni.removeStorageSync('invoiceLedgerEditRow'); |
| | | uni.navigateBack() |
| | | } |
| | | const inputTicketsNum = () => { |
| | | // ç¡®ä¿å«ç¨åä»·åå¨ä¸ä¸ä¸ºé¶ |
| | | if (!form.value.taxInclusiveUnitPrice || Number(form.value.taxInclusiveUnitPrice) === 0) { |
| | | uni.showToast({ |
| | | title: "å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹", |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | if (Number(form.value.ticketsNum) > Number(temFutureTickets.value)) { |
| | | uni.showToast({ |
| | | title: "æ¥ç¥¨æ°ä¸å¾å¤§äºæªæ¥ç¥¨æ°", |
| | | icon: 'none' |
| | | }); |
| | | form.value.ticketsNum = temFutureTickets.value |
| | | } |
| | | |
| | | // ç¡®ä¿æææ°å¼é½è½¬æ¢ä¸ºæ°åç±»åè¿è¡è®¡ç® |
| | | const ticketsAmount = Number(form.value.ticketsNum) * Number(form.value.taxInclusiveUnitPrice); |
| | | const futureTickets = Number(temFutureTickets.value) - Number(form.value.ticketsNum); |
| | | form.value.futureTickets = Number(futureTickets.toFixed(2)); |
| | | form.value.ticketsAmount = Number(ticketsAmount.toFixed(2)); |
| | | }; |
| | | const inputTicketsAmount = () => { |
| | | // ç¡®ä¿å«ç¨åä»·åå¨ä¸ä¸ä¸ºé¶ |
| | | if (!form.value.taxInclusiveUnitPrice || Number(form.value.taxInclusiveUnitPrice) === 0) { |
| | | uni.showToast({ |
| | | title: "å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹", |
| | | icon: 'none' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | if (Number(form.value.ticketsAmount) > Number(form.value.futureTickets*form.value.taxInclusiveUnitPrice)) { |
| | | uni.showToast({ |
| | | title: "æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæ»éé¢", |
| | | icon: 'none' |
| | | }); |
| | | form.value.ticketsAmount = (form.value.futureTickets*form.value.taxInclusiveUnitPrice).toFixed(2) |
| | | const ticketsNum = Number(form.value.ticketsAmount) / Number(form.value.taxInclusiveUnitPrice); |
| | | form.value.ticketsNum = Number(ticketsNum.toFixed(2)) |
| | | return; |
| | | } |
| | | |
| | | // ç¡®ä¿æææ°å¼é½è½¬æ¢ä¸ºæ°åç±»åè¿è¡è®¡ç® |
| | | const ticketsNum = Number(form.value.ticketsAmount) / Number(form.value.taxInclusiveUnitPrice); |
| | | form.value.ticketsNum = Number(ticketsNum.toFixed(2)); |
| | | }; |
| | | const formatAmount = (val) => { |
| | | if (val === undefined || val === null || val === '') return '0.00' |
| | | const num = Number(val) |
| | | if (Number.isNaN(num)) return '0.00' |
| | | return num.toFixed(2) |
| | | } |
| | | const goBack = () => { |
| | | uni.removeStorageSync("invoiceLedgerEditRow"); |
| | | uni.navigateBack(); |
| | | }; |
| | | const inputTicketsNum = () => { |
| | | // ç¡®ä¿å«ç¨åä»·åå¨ä¸ä¸ä¸ºé¶ |
| | | if ( |
| | | !form.value.taxInclusiveUnitPrice || |
| | | Number(form.value.taxInclusiveUnitPrice) === 0 |
| | | ) { |
| | | uni.showToast({ |
| | | title: "å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹", |
| | | icon: "none", |
| | | }); |
| | | return; |
| | | } |
| | | if (Number(form.value.ticketsNum) > Number(temFutureTickets.value)) { |
| | | uni.showToast({ |
| | | title: "æ¥ç¥¨æ°ä¸å¾å¤§äºæªæ¥ç¥¨æ°", |
| | | icon: "none", |
| | | }); |
| | | form.value.ticketsNum = temFutureTickets.value; |
| | | } |
| | | |
| | | const loadDetail = async (id) => { |
| | | try { |
| | | uni.showLoading({ |
| | | title: 'å è½½ä¸...' |
| | | }); |
| | | const res = await getProductRecordById({ id }) |
| | | const data = res?.data || res |
| | | form.value = { ...data } |
| | | temFutureTickets.value = data.futureTickets; |
| | | fileList.value = data?.fileList || [] |
| | | if (!form.value.invoicePerson) { |
| | | form.value.invoicePerson = userStore.nickName |
| | | } |
| | | if (!form.value.invoiceDate) { |
| | | form.value.invoiceDate = dayjs().format('YYYY-MM-DD') |
| | | } |
| | | uni.hideLoading(); |
| | | } catch (e) { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: 'å 载失败', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | } |
| | | // ç¡®ä¿æææ°å¼é½è½¬æ¢ä¸ºæ°åç±»åè¿è¡è®¡ç® |
| | | const ticketsAmount = |
| | | Number(form.value.ticketsNum) * Number(form.value.taxInclusiveUnitPrice); |
| | | const futureTickets = |
| | | Number(temFutureTickets.value) - Number(form.value.ticketsNum); |
| | | form.value.futureTickets = Number(futureTickets.toFixed(2)); |
| | | form.value.ticketsAmount = Number(ticketsAmount.toFixed(2)); |
| | | }; |
| | | const inputTicketsAmount = () => { |
| | | // ç¡®ä¿å«ç¨åä»·åå¨ä¸ä¸ä¸ºé¶ |
| | | if ( |
| | | !form.value.taxInclusiveUnitPrice || |
| | | Number(form.value.taxInclusiveUnitPrice) === 0 |
| | | ) { |
| | | uni.showToast({ |
| | | title: "å«ç¨åä»·ä¸è½ä¸ºé¶ææªå®ä¹", |
| | | icon: "none", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | const submitForm = async () => { |
| | | try { |
| | | // æäº¤è¡¨åçå
·ä½é»è¾ |
| | | await updateRegistration(form.value) |
| | | uni.showToast({ |
| | | title: 'æäº¤æå', |
| | | icon: 'success' |
| | | }); |
| | | setTimeout(() => { goBack() }, 800) |
| | | } catch (e) { |
| | | uni.showToast({ |
| | | title: 'æäº¤å¤±è´¥ï¼è¯·éè¯', |
| | | icon: 'none' |
| | | }); |
| | | } |
| | | } |
| | | if ( |
| | | Number(form.value.ticketsAmount) > |
| | | Number(form.value.futureTickets * form.value.taxInclusiveUnitPrice) |
| | | ) { |
| | | uni.showToast({ |
| | | title: "æ¬æ¬¡æ¥ç¥¨éé¢ä¸å¾å¤§äºæ»éé¢", |
| | | icon: "none", |
| | | }); |
| | | form.value.ticketsAmount = ( |
| | | form.value.futureTickets * form.value.taxInclusiveUnitPrice |
| | | ).toFixed(2); |
| | | const ticketsNum = |
| | | Number(form.value.ticketsAmount) / |
| | | Number(form.value.taxInclusiveUnitPrice); |
| | | form.value.ticketsNum = Number(ticketsNum.toFixed(2)); |
| | | return; |
| | | } |
| | | |
| | | // 表åæäº¤ |
| | | const onSubmit = () => { |
| | | formRef.value.validate().then(() => { |
| | | // 表åéªè¯éè¿ï¼æäº¤è¡¨å |
| | | submitForm(); |
| | | }).catch(error => { |
| | | // 表åéªè¯å¤±è´¥ |
| | | console.log('表åéªè¯å¤±è´¥', error); |
| | | }); |
| | | }; |
| | | // ç¡®ä¿æææ°å¼é½è½¬æ¢ä¸ºæ°åç±»åè¿è¡è®¡ç® |
| | | const ticketsNum = |
| | | Number(form.value.ticketsAmount) / Number(form.value.taxInclusiveUnitPrice); |
| | | form.value.ticketsNum = Number(ticketsNum.toFixed(2)); |
| | | }; |
| | | const formatAmount = val => { |
| | | if (val === undefined || val === null || val === "") return "0.00"; |
| | | const num = Number(val); |
| | | if (Number.isNaN(num)) return "0.00"; |
| | | return num.toFixed(2); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | const rowStr = uni.getStorageSync('invoiceLedgerEditRow') |
| | | if (rowStr) { |
| | | try { |
| | | const row = JSON.parse(rowStr) |
| | | currentId.value = row.id |
| | | loadDetail(currentId.value) |
| | | } catch (e) { |
| | | // ignore |
| | | } |
| | | } |
| | | }); |
| | | const loadDetail = async (id, purchaseLedgerId, productModelId) => { |
| | | try { |
| | | uni.showLoading({ |
| | | title: "å è½½ä¸...", |
| | | }); |
| | | const res = await getProductRecordById({ |
| | | id: id, |
| | | purchaseLedgerId: purchaseLedgerId, |
| | | productModelId: productModelId, |
| | | }); |
| | | const data = res?.data || res; |
| | | form.value = { ...data }; |
| | | temFutureTickets.value = data.futureTickets; |
| | | fileList.value = data?.fileList || []; |
| | | if (!form.value.invoicePerson) { |
| | | form.value.invoicePerson = userStore.nickName; |
| | | } |
| | | if (!form.value.invoiceDate) { |
| | | form.value.invoiceDate = dayjs().format("YYYY-MM-DD"); |
| | | } |
| | | uni.hideLoading(); |
| | | } catch (e) { |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: "å 载失败", |
| | | icon: "none", |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | const submitForm = async () => { |
| | | try { |
| | | // æäº¤è¡¨åçå
·ä½é»è¾ |
| | | await updateRegistration(form.value); |
| | | uni.showToast({ |
| | | title: "æäº¤æå", |
| | | icon: "success", |
| | | }); |
| | | setTimeout(() => { |
| | | goBack(); |
| | | }, 800); |
| | | } catch (e) { |
| | | uni.showToast({ |
| | | title: "æäº¤å¤±è´¥ï¼è¯·éè¯", |
| | | icon: "none", |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | // 表åæäº¤ |
| | | const onSubmit = () => { |
| | | formRef.value |
| | | .validate() |
| | | .then(() => { |
| | | // 表åéªè¯éè¿ï¼æäº¤è¡¨å |
| | | submitForm(); |
| | | }) |
| | | .catch(error => { |
| | | // 表åéªè¯å¤±è´¥ |
| | | console.log("表åéªè¯å¤±è´¥", error); |
| | | }); |
| | | }; |
| | | const purchaseLedgerId = ref(""); |
| | | const productModelId = ref({}); |
| | | |
| | | onMounted(() => { |
| | | const rowStr = uni.getStorageSync("invoiceLedgerEditRow"); |
| | | if (rowStr) { |
| | | try { |
| | | const row = JSON.parse(rowStr); |
| | | currentId.value = row.id; |
| | | purchaseLedgerId.value = row.purchaseLedgerId; |
| | | productModelId.value = row.productModelId; |
| | | loadDetail(currentId.value, purchaseLedgerId.value, productModelId.value); |
| | | } catch (e) { |
| | | // ignore |
| | | } |
| | | } |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/static/scss/form-common.scss'; |
| | | @import "@/static/scss/form-common.scss"; |
| | | </style> |
| | | |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.searchText" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="search-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç»è®¡ä¿¡æ¯ --> |
| | | <view class="summary-info" v-if="tableData.length > 0"> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»è®°å½æ°</text> |
| | | <text class="summary-value">{{ tableData.length }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»éé¢</text> |
| | | <text class="summary-value highlight">{{ formatAmount(totalAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- 仿¬¾åå²å表 --> |
| | | <view class="history-list" v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" :key="index"> |
| | | <view class="history-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.purchaseContractNumber }}</text> |
| | | </view> |
| | | <view class="item-tag" :class="getTagClass(item.paymentMethod)"> |
| | | <text class="tag-text">{{ item.paymentMethod }}</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.supplierName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">仿¬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.currentPaymentAmount) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">仿¬¾æ¥æ</text> |
| | | <text class="detail-value">{{ item.paymentDate }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="detail-info"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»è®°äºº</text> |
| | | <text class="detail-value">{{ item.registrant }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»è®°æ¥æ</text> |
| | | <text class="detail-value">{{ item.registrationtDate }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.searchText" |
| | | @change="getList" |
| | | clearable /> |
| | | </view> |
| | | <view class="search-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç»è®¡ä¿¡æ¯ --> |
| | | <view class="summary-info" |
| | | v-if="tableData.length > 0"> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»è®°å½æ°</text> |
| | | <text class="summary-value">{{ tableData.length }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»éé¢</text> |
| | | <text class="summary-value highlight">{{ formatAmount(totalAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- 仿¬¾åå²å表 --> |
| | | <view class="history-list" |
| | | v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" |
| | | :key="index"> |
| | | <view class="history-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.purchaseContractNumber }}</text> |
| | | </view> |
| | | <view class="item-tag" |
| | | :class="getTagClass(item.paymentMethod)"> |
| | | <text class="tag-text">{{ item.paymentMethod }}</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.supplierName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">仿¬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.currentPaymentAmount) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">仿¬¾æ¥æ</text> |
| | | <text class="detail-value">{{ item.paymentDate }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="detail-info"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»è®°äºº</text> |
| | | <text class="detail-value">{{ item.registrant }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»è®°æ¥æ</text> |
| | | <text class="detail-value">{{ item.registrationtDate }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <!-- <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openForm(item)" |
| | | > |
| | | ç¼è¾ä»æ¬¾ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="no-data"> |
| | | <text>ææ ä»æ¬¾å岿°æ®</text> |
| | | </view> |
| | | </view> |
| | | </u-button> --> |
| | | <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.registrant !== userStore.nickName" |
| | | @click="deleteItem(item)"> |
| | | å é¤ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ ä»æ¬¾å岿°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import {paymentHistoryListPage} from "@/api/procurementManagement/paymentEntry"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | const userStore = useUserStore() |
| | | import { ref, computed } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { paymentHistoryListPage } from "@/api/procurementManagement/paymentEntry"; |
| | | import { delPaymentRegistration } from "@/api/procurementManagement/procurementInvoiceLedger"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | searchText: '', |
| | | }); |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | searchText: "", |
| | | }); |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]); |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]); |
| | | |
| | | // å页忰 |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | // å页忰 |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | |
| | | const totalAmount = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.receiptPaymentAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | const totalAmount = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.receiptPaymentAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const deleteItem = item => { |
| | | uni.showModal({ |
| | | title: "确认å é¤", |
| | | content: `æ¯å¦ç¡®è®¤å é¤è¯¥æ°æ®åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | // è°ç¨å 餿¥å£ |
| | | delPaymentRegistration([item.id]) |
| | | .then(() => { |
| | | uni.showToast({ |
| | | title: "å 餿å", |
| | | icon: "success", |
| | | }); |
| | | // å·æ°å表 |
| | | getList(); |
| | | }) |
| | | .catch(() => { |
| | | uni.showToast({ |
| | | title: "å é¤å¤±è´¥", |
| | | icon: "error", |
| | | }); |
| | | }); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | ...searchForm.value, |
| | | ...page.value, |
| | | }; |
| | | paymentHistoryListPage(params) |
| | | .then(res => { |
| | | tableData.value = res.records; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | uni.showToast({ |
| | | title: "æ¥è¯¢å¤±è´¥", |
| | | icon: "error", |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const params = { |
| | | ...searchForm.value, |
| | | ...page.value |
| | | }; |
| | | paymentHistoryListPage(params).then((res) => { |
| | | tableData.value = res.records; |
| | | closeToast() |
| | | }).catch(() => { |
| | | closeToast() |
| | | uni.showToast({ |
| | | title: 'æ¥è¯¢å¤±è´¥', |
| | | icon: 'error' |
| | | }); |
| | | }); |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == "çµæ±") { |
| | | return "tag-electric"; |
| | | } else if (type == "æ¿å
") { |
| | | return "tag-acceptance"; |
| | | } else { |
| | | return "tag-unknown"; |
| | | } |
| | | }; |
| | | |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = (type) => { |
| | | if (type == 'çµæ±') { |
| | | return "tag-electric"; |
| | | } else if (type == 'æ¿å
') { |
| | | return "tag-acceptance"; |
| | | } else { |
| | | return "tag-unknown"; |
| | | } |
| | | }; |
| | | // æ ¼å¼åéé¢ |
| | | const formatAmount = amount => { |
| | | return amount ? parseFloat(amount).toFixed(2) : "0.00"; |
| | | }; |
| | | |
| | | // æ ¼å¼åéé¢ |
| | | const formatAmount = (amount) => { |
| | | return amount ? parseFloat(amount).toFixed(2) : '0.00'; |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æå¼ç¼è¾è¡¨å |
| | | const openForm = (item) => { |
| | | uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)) |
| | | uni.navigateTo({ url: '/pages/procurementManagement/paymentEntry/edit' }) |
| | | } |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°å表 |
| | | getList(); |
| | | }); |
| | | // æå¼ç¼è¾è¡¨å |
| | | const openForm = item => { |
| | | uni.setStorageSync("invoiceLedgerEditRow", JSON.stringify(item)); |
| | | uni.navigateTo({ url: "/pages/procurementManagement/paymentEntry/edit" }); |
| | | }; |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°å表 |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/procurement-common.scss'; |
| | | @import "@/styles/procurement-common.scss"; |
| | | |
| | | // 仿¬¾æµæ°´ç¹ææ ·å¼ |
| | | .action-buttons { |
| | | padding: 12px 0 0 0; // ä¸å
Œ
±æ ·å¼ä¸ç 0 0 16px 0 ä¸å |
| | | } |
| | | // 仿¬¾æµæ°´ç¹ææ ·å¼ |
| | | .action-buttons { |
| | | padding: 12px 0 0 0; // ä¸å
Œ
±æ ·å¼ä¸ç 0 0 16px 0 ä¸å |
| | | } |
| | | |
| | | .item-tag { |
| | | padding: 2px 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 2px 4px ä¸å |
| | | } |
| | | .item-tag { |
| | | padding: 2px 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 2px 4px ä¸å |
| | | } |
| | | |
| | | .tag-text { |
| | | font-size: 14px; // ä¸å
Œ
±æ ·å¼ä¸ç 11px ä¸å |
| | | color: #ffffff; |
| | | font-weight: 500; |
| | | } |
| | | .tag-text { |
| | | font-size: 14px; // ä¸å
Œ
±æ ·å¼ä¸ç 11px ä¸å |
| | | color: #ffffff; |
| | | font-weight: 500; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.searchText" |
| | | @change="handleQuery" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <!-- <view class="filter-button" @click="showFilter = true">--> |
| | | <!-- <up-icon name="list" size="24" color="#999"></up-icon>--> |
| | | <!-- </view>--> |
| | | <view class="filter-button" @click="handleQuery"> |
| | | <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.salesContractNo }}</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.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·ååå·</text> |
| | | <text class="detail-value">{{ item.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®</text> |
| | | <text class="detail-value">{{ item.projectName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产å大类</text> |
| | | <text class="detail-value">{{ item.productCategory }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ item.specificationModel }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票å·</text> |
| | | <text class="detail-value">{{ item.invoiceNo || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.invoiceTotal) }}</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">{{ item.invoicePerson }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å½å
¥æ¥æ</text> |
| | | <text class="detail-value">{{ formatDateTime(item.createTime) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¼ç¥¨æ¥æ</text> |
| | | <text class="detail-value">{{ item.invoiceDate || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <up-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.invoicePerson !== userStore.nickName" |
| | | @click="openEdit(item)" |
| | | > |
| | | ç¼è¾ |
| | | </up-button> |
| | | <up-button |
| | | type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | :disabled="item.invoicePerson !== userStore.nickName" |
| | | @click="handleDelete(item)" |
| | | > |
| | | å é¤ |
| | | </up-button> |
| | | <!-- <up-button--> |
| | | <!-- size="small"--> |
| | | <!-- plain--> |
| | | <!-- class="action-btn"--> |
| | | <!-- v-if="item.invoiceFileName"--> |
| | | <!-- @click="openFileActions(item.commonFiles || [])"--> |
| | | <!-- >--> |
| | | <!-- æ¥çéä»¶--> |
| | | <!-- </up-button>--> |
| | | <!-- <up-button--> |
| | | <!-- type="primary"--> |
| | | <!-- size="small"--> |
| | | <!-- class="action-btn"--> |
| | | <!-- v-else--> |
| | | <!-- :disabled="item.invoicePerson !== userStore.nickName"--> |
| | | <!-- @click="openUpload(item)"--> |
| | | <!-- >--> |
| | | <!-- ä¸ä¼ --> |
| | | <!-- </up-button>--> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="no-data"> |
| | | <text>ææ å¼ç¥¨å°è´¦æ°æ®</text> |
| | | </view> |
| | | |
| | | <!-- çéå¼¹çª --> |
| | | <up-popup v-model="showFilter" mode="bottom" round><up-transition> |
| | | <view class="filter-popup"> |
| | | <up-cell-group title="ç鿡件" inset> |
| | | <up-input |
| | | label="å¼ç¥¨æ¥æ" |
| | | readonly |
| | | placeholder="è¯·éæ©æ¥æèå´" |
| | | @click="showInvoiceRange = true" |
| | | v-model="invoiceRangeLabel" |
| | | /> |
| | | <up-input |
| | | label="å½å
¥æ¥æ" |
| | | readonly |
| | | @click="showCreateDatePicker = true" |
| | | v-model="searchForm.createTimeStart" |
| | | /> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºæå票è¡</text> |
| | | <up-switch v-model="searchForm.status" size="20" /> |
| | | </view> |
| | | </up-cell-group> |
| | | <view class="filter-actions"> |
| | | <up-button @click="resetFilter">éç½®</up-button> |
| | | <up-button type="primary" @click="confirmFilter">ç¡®å®</up-button> |
| | | </view> |
| | | </view> |
| | | </up-transition></up-popup> |
| | | |
| | | <!-- æ¥åï¼å¼ç¥¨æ¥æèå´ --> |
| | | <up-popup v-model="showInvoiceRange" mode="bottom"><up-transition> |
| | | <up-datetime-picker |
| | | mode="date" |
| | | type="range" |
| | | title="éæ©å¼ç¥¨æ¥æèå´" |
| | | @confirm="onInvoiceRangeConfirm" |
| | | @cancel="showInvoiceRange = false" |
| | | /> |
| | | </up-transition></up-popup> |
| | | |
| | | <!-- æ¥æï¼å½å
¥æ¥æ --> |
| | | <up-popup v-model="showCreateDatePicker" mode="bottom"><up-transition> |
| | | <up-datetime-picker |
| | | mode="date" |
| | | type="selector" |
| | | v-model="currentCreateDate" |
| | | title="éæ©å½å
¥æ¥æ" |
| | | @confirm="onCreateDateConfirm" |
| | | @cancel="showCreateDatePicker = false" |
| | | /> |
| | | </up-transition></up-popup> |
| | | |
| | | |
| | | |
| | | <!-- åè¡ä¸ä¼ å¼¹çªï¼æ 表åï¼ --> |
| | | <up-popup v-model="showUpload" mode="bottom" round><up-transition> |
| | | <view class="upload-container"> |
| | | <up-cell-group title="ä¸ä¼ éä»¶ï¼ä»
æ¯æ pdfï¼æå¤§10MBï¼æå¤10个ï¼" inset> |
| | | <up-upload |
| | | accept="pdf" |
| | | multiple |
| | | :maxCount="10" |
| | | :afterRead="afterReadRowUpload" |
| | | :beforeRead="beforeReadPdf" |
| | | > |
| | | <up-button type="primary">ç¹å»ä¸ä¼ </up-button> |
| | | </up-upload> |
| | | <view class="uploaded-list" v-if="fileList.length"> |
| | | <view class="uploaded-item" v-for="(f, idx) in fileList" :key="idx"> |
| | | <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text> |
| | | <up-button size="mini" type="error" plain @click="removeUploaded(idx)">ç§»é¤</up-button> |
| | | </view> |
| | | </view> |
| | | </up-cell-group> |
| | | <view class="filter-actions"> |
| | | <up-button @click="showUpload = false">åæ¶</up-button> |
| | | <up-button type="primary" @click="confirmUpload">确认</up-button> |
| | | </view> |
| | | </view> |
| | | </up-transition></up-popup> |
| | | |
| | | <!-- éä»¶åè¡¨éæ© --> |
| | | <up-action-sheet v-model="showFileSheet" :actions="fileActions" cancel-text="åæ¶" close-on-click-action @select="onSelectFile"> |
| | | <view class="up-action-sheet__cancel" @click="showFileSheet = false"> |
| | | åæ¶ |
| | | </view> |
| | | </up-action-sheet> |
| | | </view> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.searchText" |
| | | @change="handleQuery" |
| | | clearable /> |
| | | </view> |
| | | <!-- <view class="filter-button" @click="showFilter = true">--> |
| | | <!-- <up-icon name="list" size="24" color="#999"></up-icon>--> |
| | | <!-- </view>--> |
| | | <view class="filter-button" |
| | | @click="handleQuery"> |
| | | <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.salesContractNo }}</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.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·ååå·</text> |
| | | <text class="detail-value">{{ item.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®</text> |
| | | <text class="detail-value">{{ item.projectName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产å大类</text> |
| | | <text class="detail-value">{{ item.productCategory }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">è§æ ¼åå·</text> |
| | | <text class="detail-value">{{ item.specificationModel }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票å·</text> |
| | | <text class="detail-value">{{ item.invoiceNo || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.invoiceTotal) }}</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">{{ item.invoicePerson }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å½å
¥æ¥æ</text> |
| | | <text class="detail-value">{{ formatDateTime(item.createTime) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¼ç¥¨æ¥æ</text> |
| | | <text class="detail-value">{{ item.invoiceDate || '-' }}</text> |
| | | </view> |
| | | </view> |
| | | <view class="action-buttons"> |
| | | <up-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.invoicePerson !== userStore.nickName" |
| | | @click="openEdit(item)"> |
| | | ç¼è¾ |
| | | </up-button> |
| | | <up-button type="error" |
| | | size="small" |
| | | plain |
| | | class="action-btn" |
| | | :disabled="item.invoicePerson !== userStore.nickName" |
| | | @click="handleDelete(item)"> |
| | | å é¤ |
| | | </up-button> |
| | | <!-- <up-button--> |
| | | <!-- size="small"--> |
| | | <!-- plain--> |
| | | <!-- class="action-btn"--> |
| | | <!-- v-if="item.invoiceFileName"--> |
| | | <!-- @click="openFileActions(item.commonFiles || [])"--> |
| | | <!-- >--> |
| | | <!-- æ¥çéä»¶--> |
| | | <!-- </up-button>--> |
| | | <!-- <up-button--> |
| | | <!-- type="primary"--> |
| | | <!-- size="small"--> |
| | | <!-- class="action-btn"--> |
| | | <!-- v-else--> |
| | | <!-- :disabled="item.invoicePerson !== userStore.nickName"--> |
| | | <!-- @click="openUpload(item)"--> |
| | | <!-- >--> |
| | | <!-- ä¸ä¼ --> |
| | | <!-- </up-button>--> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ å¼ç¥¨å°è´¦æ°æ®</text> |
| | | </view> |
| | | <!-- çéå¼¹çª --> |
| | | <up-popup v-model="showFilter" |
| | | mode="bottom" |
| | | round><up-transition> |
| | | <view class="filter-popup"> |
| | | <up-cell-group title="ç鿡件" |
| | | inset> |
| | | <up-input label="å¼ç¥¨æ¥æ" |
| | | readonly |
| | | placeholder="è¯·éæ©æ¥æèå´" |
| | | @click="showInvoiceRange = true" |
| | | v-model="invoiceRangeLabel" /> |
| | | <up-input label="å½å
¥æ¥æ" |
| | | readonly |
| | | @click="showCreateDatePicker = true" |
| | | v-model="searchForm.createTimeStart" /> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºæå票è¡</text> |
| | | <up-switch v-model="searchForm.status" |
| | | size="20" /> |
| | | </view> |
| | | </up-cell-group> |
| | | <view class="filter-actions"> |
| | | <up-button @click="resetFilter">éç½®</up-button> |
| | | <up-button type="primary" |
| | | @click="confirmFilter">ç¡®å®</up-button> |
| | | </view> |
| | | </view> |
| | | </up-transition></up-popup> |
| | | <!-- æ¥åï¼å¼ç¥¨æ¥æèå´ --> |
| | | <up-popup v-model="showInvoiceRange" |
| | | mode="bottom"><up-transition> |
| | | <up-datetime-picker mode="date" |
| | | type="range" |
| | | title="éæ©å¼ç¥¨æ¥æèå´" |
| | | @confirm="onInvoiceRangeConfirm" |
| | | @cancel="showInvoiceRange = false" /> |
| | | </up-transition></up-popup> |
| | | <!-- æ¥æï¼å½å
¥æ¥æ --> |
| | | <up-popup v-model="showCreateDatePicker" |
| | | mode="bottom"><up-transition> |
| | | <up-datetime-picker mode="date" |
| | | type="selector" |
| | | v-model="currentCreateDate" |
| | | title="éæ©å½å
¥æ¥æ" |
| | | @confirm="onCreateDateConfirm" |
| | | @cancel="showCreateDatePicker = false" /> |
| | | </up-transition></up-popup> |
| | | <!-- åè¡ä¸ä¼ å¼¹çªï¼æ 表åï¼ --> |
| | | <up-popup v-model="showUpload" |
| | | mode="bottom" |
| | | round><up-transition> |
| | | <view class="upload-container"> |
| | | <up-cell-group title="ä¸ä¼ éä»¶ï¼ä»
æ¯æ pdfï¼æå¤§10MBï¼æå¤10个ï¼" |
| | | inset> |
| | | <up-upload accept="pdf" |
| | | multiple |
| | | :maxCount="10" |
| | | :afterRead="afterReadRowUpload" |
| | | :beforeRead="beforeReadPdf"> |
| | | <up-button type="primary">ç¹å»ä¸ä¼ </up-button> |
| | | </up-upload> |
| | | <view class="uploaded-list" |
| | | v-if="fileList.length"> |
| | | <view class="uploaded-item" |
| | | v-for="(f, idx) in fileList" |
| | | :key="idx"> |
| | | <text class="file-name">{{ f.name || getFileNameFromUrl(f.url) }}</text> |
| | | <up-button size="mini" |
| | | type="error" |
| | | plain |
| | | @click="removeUploaded(idx)">ç§»é¤</up-button> |
| | | </view> |
| | | </view> |
| | | </up-cell-group> |
| | | <view class="filter-actions"> |
| | | <up-button @click="showUpload = false">åæ¶</up-button> |
| | | <up-button type="primary" |
| | | @click="confirmUpload">确认</up-button> |
| | | </view> |
| | | </view> |
| | | </up-transition></up-popup> |
| | | <!-- éä»¶åè¡¨éæ© --> |
| | | <up-action-sheet v-model="showFileSheet" |
| | | :actions="fileActions" |
| | | cancel-text="åæ¶" |
| | | close-on-click-action |
| | | @select="onSelectFile"> |
| | | <view class="up-action-sheet__cancel" |
| | | @click="showFileSheet = false"> |
| | | åæ¶ |
| | | </view> |
| | | </up-action-sheet> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {reactive, ref} from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import {getToken} from '@/utils/auth' |
| | | import config from '@/config.js' |
| | | import { |
| | | commitFile, |
| | | delInvoiceLedgerByRegProductId, |
| | | registrationProductPage |
| | | } from '@/api/salesManagement/invoiceLedger.js' |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | import { reactive, ref } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import PageHeader from "@/components/PageHeader.vue"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getToken } from "@/utils/auth"; |
| | | import config from "@/config.js"; |
| | | import { |
| | | commitFile, |
| | | delInvoiceLedgerByRegProductId, |
| | | registrationProductPage, |
| | | } from "@/api/salesManagement/invoiceLedger.js"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }) |
| | | } |
| | | const closeToast = () => { |
| | | uni.hideLoading() |
| | | } |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | const userStore = useUserStore() |
| | | const userStore = useUserStore(); |
| | | |
| | | // åè¡¨ä¸æ¥è¯¢ |
| | | const ledgerList = ref([]) |
| | | const page = reactive({ current: -1, size: -1 }) |
| | | const searchForm = reactive({ |
| | | searchText: '', |
| | | status: false, |
| | | createTimeStart: '' |
| | | }) |
| | | // åè¡¨ä¸æ¥è¯¢ |
| | | const ledgerList = ref([]); |
| | | const page = reactive({ current: -1, size: -1 }); |
| | | const searchForm = reactive({ |
| | | searchText: "", |
| | | status: false, |
| | | createTimeStart: "", |
| | | }); |
| | | |
| | | // é¡¶é¨äº¤äº |
| | | const showFilter = ref(false) |
| | | const showInvoiceRange = ref(false) |
| | | const showCreateDatePicker = ref(false) |
| | | const invoiceRangeLabel = ref('') |
| | | const currentCreateDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | // é¡¶é¨äº¤äº |
| | | const showFilter = ref(false); |
| | | const showInvoiceRange = ref(false); |
| | | const showCreateDatePicker = ref(false); |
| | | const invoiceRangeLabel = ref(""); |
| | | const currentCreateDate = ref([ |
| | | new Date().getFullYear(), |
| | | new Date().getMonth() + 1, |
| | | new Date().getDate(), |
| | | ]); |
| | | |
| | | const currentId = ref('') |
| | | const fileList = ref([]) // è¡ä¸ä¼ æéç¨ä¸ä¼ å表 |
| | | const currentId = ref(""); |
| | | const fileList = ref([]); // è¡ä¸ä¼ æéç¨ä¸ä¼ å表 |
| | | |
| | | // è¡ä¸ä¼ å¼¹çª |
| | | const showUpload = ref(false) |
| | | // è¡ä¸ä¼ å¼¹çª |
| | | const showUpload = ref(false); |
| | | |
| | | // éä»¶æ¥ç |
| | | const showFileSheet = ref(false) |
| | | const fileActions = ref([]) |
| | | let currentFilesToOpen = [] |
| | | // éä»¶æ¥ç |
| | | const showFileSheet = ref(false); |
| | | const fileActions = ref([]); |
| | | let currentFilesToOpen = []; |
| | | |
| | | const formatAmount = (val) => { |
| | | if (val === undefined || val === null || val === '') return '0.00' |
| | | const num = Number(val) |
| | | if (Number.isNaN(num)) return '0.00' |
| | | return num.toFixed(2) |
| | | } |
| | | const formatDateTime = (val) => { |
| | | if (!val) return '' |
| | | return dayjs(val).format('YYYY-MM-DD HH:mm:ss') |
| | | } |
| | | const formatAmount = val => { |
| | | if (val === undefined || val === null || val === "") return "0.00"; |
| | | const num = Number(val); |
| | | if (Number.isNaN(num)) return "0.00"; |
| | | return num.toFixed(2); |
| | | }; |
| | | const formatDateTime = val => { |
| | | if (!val) return ""; |
| | | return dayjs(val).format("YYYY-MM-DD HH:mm:ss"); |
| | | }; |
| | | |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | const handleQuery = () => { |
| | | getList() |
| | | } |
| | | const handleQuery = () => { |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = async () => { |
| | | try { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const { invoiceDate, ...rest } = searchForm |
| | | const res = await registrationProductPage({ ...rest, ...page }) |
| | | // å
¼å®¹ä¸åè¿åç»æ |
| | | ledgerList.value = res?.data?.records || res?.records || res?.data || [] |
| | | closeToast() |
| | | } catch (e) { |
| | | closeToast() |
| | | showToast('è·åå表失败') |
| | | } |
| | | } |
| | | const getList = async () => { |
| | | try { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const { invoiceDate, ...rest } = searchForm; |
| | | const res = await registrationProductPage({ ...rest, ...page }); |
| | | // å
¼å®¹ä¸åè¿åç»æ |
| | | ledgerList.value = res?.data?.records || res?.records || res?.data || []; |
| | | closeToast(); |
| | | } catch (e) { |
| | | closeToast(); |
| | | showToast("è·åå表失败"); |
| | | } |
| | | }; |
| | | |
| | | // çéé»è¾ |
| | | const resetFilter = () => { |
| | | searchForm.searchText = '' |
| | | searchForm.status = false |
| | | const start = dayjs().startOf('month').format('YYYY-MM-DD') |
| | | const end = dayjs().endOf('month').format('YYYY-MM-DD') |
| | | searchForm.invoiceDate = [start, end] |
| | | searchForm.invoiceDateStart = start |
| | | searchForm.invoiceDateEnd = end |
| | | searchForm.createTimeStart = '' |
| | | invoiceRangeLabel.value = '' |
| | | } |
| | | const confirmFilter = () => { |
| | | showFilter.value = false |
| | | getList() |
| | | } |
| | | const onInvoiceRangeConfirm = ({ selectedValues }) => { |
| | | try { |
| | | const start = dayjs(selectedValues[0]).format('YYYY-MM-DD') |
| | | const end = dayjs(selectedValues[1]).format('YYYY-MM-DD') |
| | | searchForm.invoiceDateStart = start |
| | | searchForm.invoiceDateEnd = end |
| | | invoiceRangeLabel.value = `${start} è³ ${end}` |
| | | showInvoiceRange.value = false |
| | | } catch (err) { |
| | | showInvoiceRange.value = false |
| | | } |
| | | } |
| | | const onCreateDateConfirm = ({ selectedValues }) => { |
| | | try { |
| | | searchForm.createTimeStart = selectedValues.join('-') |
| | | currentCreateDate.value = selectedValues |
| | | showCreateDatePicker.value = false |
| | | } catch (err) { |
| | | showCreateDatePicker.value = false |
| | | } |
| | | } |
| | | // çéé»è¾ |
| | | const resetFilter = () => { |
| | | searchForm.searchText = ""; |
| | | searchForm.status = false; |
| | | const start = dayjs().startOf("month").format("YYYY-MM-DD"); |
| | | const end = dayjs().endOf("month").format("YYYY-MM-DD"); |
| | | searchForm.invoiceDate = [start, end]; |
| | | searchForm.invoiceDateStart = start; |
| | | searchForm.invoiceDateEnd = end; |
| | | searchForm.createTimeStart = ""; |
| | | invoiceRangeLabel.value = ""; |
| | | }; |
| | | const confirmFilter = () => { |
| | | showFilter.value = false; |
| | | getList(); |
| | | }; |
| | | const onInvoiceRangeConfirm = ({ selectedValues }) => { |
| | | try { |
| | | const start = dayjs(selectedValues[0]).format("YYYY-MM-DD"); |
| | | const end = dayjs(selectedValues[1]).format("YYYY-MM-DD"); |
| | | searchForm.invoiceDateStart = start; |
| | | searchForm.invoiceDateEnd = end; |
| | | invoiceRangeLabel.value = `${start} è³ ${end}`; |
| | | showInvoiceRange.value = false; |
| | | } catch (err) { |
| | | showInvoiceRange.value = false; |
| | | } |
| | | }; |
| | | const onCreateDateConfirm = ({ selectedValues }) => { |
| | | try { |
| | | searchForm.createTimeStart = selectedValues.join("-"); |
| | | currentCreateDate.value = selectedValues; |
| | | showCreateDatePicker.value = false; |
| | | } catch (err) { |
| | | showCreateDatePicker.value = false; |
| | | } |
| | | }; |
| | | |
| | | // ç¼è¾é»è¾æ¹ä¸ºè·³è½¬æ°é¡µé¢ |
| | | const openEdit = (row) => { |
| | | try { |
| | | uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(row)) |
| | | uni.navigateTo({ url: '/pages/sales/invoiceLedger/detail' }) |
| | | } catch (e) { |
| | | showToast('跳转失败') |
| | | } |
| | | } |
| | | // ç¼è¾é»è¾æ¹ä¸ºè·³è½¬æ°é¡µé¢ |
| | | const openEdit = row => { |
| | | try { |
| | | uni.setStorageSync("invoiceLedgerEditRow", JSON.stringify(row)); |
| | | uni.navigateTo({ url: "/pages/sales/invoiceLedger/detail" }); |
| | | } catch (e) { |
| | | showToast("跳转失败"); |
| | | } |
| | | }; |
| | | |
| | | // å é¤ |
| | | const handleDelete = (row) => { |
| | | uni.showModal({ |
| | | title: 'å é¤ç¡®è®¤', |
| | | content: '该å票å°è´¦å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼', |
| | | success: async (res) => { |
| | | if (res.confirm) { |
| | | try { |
| | | showLoadingToast('å¤çä¸...') |
| | | await delInvoiceLedgerByRegProductId(row.id) |
| | | closeToast() |
| | | showToast('å 餿å') |
| | | getList() |
| | | } catch (e) { |
| | | closeToast() |
| | | showToast('å é¤å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | // å é¤ |
| | | const handleDelete = row => { |
| | | uni.showModal({ |
| | | title: "å é¤ç¡®è®¤", |
| | | content: "该å票å°è´¦å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", |
| | | success: async res => { |
| | | if (res.confirm) { |
| | | try { |
| | | showLoadingToast("å¤çä¸..."); |
| | | await delInvoiceLedgerByRegProductId(row.id); |
| | | closeToast(); |
| | | showToast("å 餿å"); |
| | | getList(); |
| | | } catch (e) { |
| | | closeToast(); |
| | | showToast("å é¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // è¡ä¸ä¼ |
| | | const openUpload = (row) => { |
| | | currentId.value = row.id |
| | | fileList.value = [] |
| | | showUpload.value = true |
| | | } |
| | | const confirmUpload = async () => { |
| | | try { |
| | | const payload = { fileList: fileList.value, id: currentId.value } |
| | | showLoadingToast('æäº¤ä¸...') |
| | | await commitFile(payload) |
| | | closeToast() |
| | | showToast('æäº¤æå') |
| | | showUpload.value = false |
| | | fileList.value = [] |
| | | currentId.value = '' |
| | | getList() |
| | | } catch (e) { |
| | | closeToast() |
| | | showToast('æäº¤å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } |
| | | // è¡ä¸ä¼ |
| | | const openUpload = row => { |
| | | currentId.value = row.id; |
| | | fileList.value = []; |
| | | showUpload.value = true; |
| | | }; |
| | | const confirmUpload = async () => { |
| | | try { |
| | | const payload = { fileList: fileList.value, id: currentId.value }; |
| | | showLoadingToast("æäº¤ä¸..."); |
| | | await commitFile(payload); |
| | | closeToast(); |
| | | showToast("æäº¤æå"); |
| | | showUpload.value = false; |
| | | fileList.value = []; |
| | | currentId.value = ""; |
| | | getList(); |
| | | } catch (e) { |
| | | closeToast(); |
| | | showToast("æäº¤å¤±è´¥ï¼è¯·éè¯"); |
| | | } |
| | | }; |
| | | |
| | | // ä¸ä¼ ç¸å
³ |
| | | const beforeReadPdf = (file) => { |
| | | // å
¼å®¹å¤æä»¶ |
| | | const files = Array.isArray(file) ? file : [file] |
| | | for (const f of files) { |
| | | const sizeOk = f.size <= 10 * 1024 * 1024 |
| | | const ext = (f.name || '').split('.').pop()?.toLowerCase() |
| | | if (ext !== 'pdf') { |
| | | showToast('ä»
æ¯æpdfæä»¶') |
| | | return false |
| | | } |
| | | if (!sizeOk) { |
| | | showToast('ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿10MB') |
| | | return false |
| | | } |
| | | } |
| | | return true |
| | | } |
| | | // ä¸ä¼ ç¸å
³ |
| | | const beforeReadPdf = file => { |
| | | // å
¼å®¹å¤æä»¶ |
| | | const files = Array.isArray(file) ? file : [file]; |
| | | for (const f of files) { |
| | | const sizeOk = f.size <= 10 * 1024 * 1024; |
| | | const ext = (f.name || "").split(".").pop()?.toLowerCase(); |
| | | if (ext !== "pdf") { |
| | | showToast("ä»
æ¯æpdfæä»¶"); |
| | | return false; |
| | | } |
| | | if (!sizeOk) { |
| | | showToast("ä¸ä¼ æä»¶å¤§å°ä¸è½è¶
è¿10MB"); |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | }; |
| | | |
| | | const uploadSingleFile = async (fileObj) => { |
| | | return new Promise((resolve, reject) => { |
| | | showLoadingToast('æ£å¨ä¸ä¼ ...') |
| | | uni.uploadFile({ |
| | | url: config.baseUrl + '/invoiceLedger/uploadFile', |
| | | filePath: fileObj.url || fileObj.file?.path || fileObj.tempFilePath, |
| | | name: 'file', |
| | | header: { Authorization: 'Bearer ' + getToken() }, |
| | | success: (res) => { |
| | | closeToast() |
| | | try { |
| | | const data = JSON.parse(res.data || '{}') |
| | | if (data.code === 200) { |
| | | resolve(data.data) |
| | | } else { |
| | | reject(new Error(data.msg || 'ä¸ä¼ 失败')) |
| | | } |
| | | } catch (err) { |
| | | reject(err) |
| | | } |
| | | }, |
| | | fail: (err) => { |
| | | closeToast() |
| | | reject(err) |
| | | } |
| | | }) |
| | | }) |
| | | } |
| | | const uploadSingleFile = async fileObj => { |
| | | return new Promise((resolve, reject) => { |
| | | showLoadingToast("æ£å¨ä¸ä¼ ..."); |
| | | uni.uploadFile({ |
| | | url: config.baseUrl + "/invoiceLedger/uploadFile", |
| | | filePath: fileObj.url || fileObj.file?.path || fileObj.tempFilePath, |
| | | name: "file", |
| | | header: { Authorization: "Bearer " + getToken() }, |
| | | success: res => { |
| | | closeToast(); |
| | | try { |
| | | const data = JSON.parse(res.data || "{}"); |
| | | if (data.code === 200) { |
| | | resolve(data.data); |
| | | } else { |
| | | reject(new Error(data.msg || "ä¸ä¼ 失败")); |
| | | } |
| | | } catch (err) { |
| | | reject(err); |
| | | } |
| | | }, |
| | | fail: err => { |
| | | closeToast(); |
| | | reject(err); |
| | | }, |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | const afterReadEditUpload = async (file) => { |
| | | try { |
| | | const files = Array.isArray(file) ? file : file?.file ? [file] : [file] |
| | | for (const f of files) { |
| | | const uploaded = await uploadSingleFile(f) |
| | | fileList.value.push(uploaded) |
| | | } |
| | | showToast('ä¸ä¼ æå') |
| | | } catch (e) { |
| | | showToast('ä¸ä¼ 失败') |
| | | } |
| | | } |
| | | const afterReadEditUpload = async file => { |
| | | try { |
| | | const files = Array.isArray(file) ? file : file?.file ? [file] : [file]; |
| | | for (const f of files) { |
| | | const uploaded = await uploadSingleFile(f); |
| | | fileList.value.push(uploaded); |
| | | } |
| | | showToast("ä¸ä¼ æå"); |
| | | } catch (e) { |
| | | showToast("ä¸ä¼ 失败"); |
| | | } |
| | | }; |
| | | |
| | | const afterReadRowUpload = async (file) => { |
| | | try { |
| | | const files = Array.isArray(file) ? file : file?.file ? [file] : [file] |
| | | for (const f of files) { |
| | | const uploaded = await uploadSingleFile(f) |
| | | fileList.value.push(uploaded) |
| | | } |
| | | showToast('ä¸ä¼ æå') |
| | | } catch (e) { |
| | | showToast('ä¸ä¼ 失败') |
| | | } |
| | | } |
| | | const afterReadRowUpload = async file => { |
| | | try { |
| | | const files = Array.isArray(file) ? file : file?.file ? [file] : [file]; |
| | | for (const f of files) { |
| | | const uploaded = await uploadSingleFile(f); |
| | | fileList.value.push(uploaded); |
| | | } |
| | | showToast("ä¸ä¼ æå"); |
| | | } catch (e) { |
| | | showToast("ä¸ä¼ 失败"); |
| | | } |
| | | }; |
| | | |
| | | const removeUploaded = (index) => { |
| | | fileList.value.splice(index, 1) |
| | | } |
| | | const removeUploaded = index => { |
| | | fileList.value.splice(index, 1); |
| | | }; |
| | | |
| | | const getFileNameFromUrl = (url) => { |
| | | try { |
| | | if (!url) return '' |
| | | return decodeURIComponent(url.split('/').pop()) |
| | | } catch (e) { |
| | | return url |
| | | } |
| | | } |
| | | const getFileNameFromUrl = url => { |
| | | try { |
| | | if (!url) return ""; |
| | | return decodeURIComponent(url.split("/").pop()); |
| | | } catch (e) { |
| | | return url; |
| | | } |
| | | }; |
| | | |
| | | // éä»¶æ¥ç |
| | | const openFileActions = (commonFiles) => { |
| | | currentFilesToOpen = commonFiles || [] |
| | | fileActions.value = (commonFiles || []).map((f, idx) => ({ name: getFileNameFromUrl(f.url || ''), index: idx })) |
| | | showFileSheet.value = true |
| | | } |
| | | const onSelectFile = async (action) => { |
| | | try { |
| | | const item = currentFilesToOpen[action.index] |
| | | if (!item || !item.url) return |
| | | showLoadingToast('ä¸è½½ä¸...') |
| | | uni.downloadFile({ |
| | | url: item.url, |
| | | success: (res) => { |
| | | closeToast() |
| | | if (res.statusCode === 200) { |
| | | uni.openDocument({ filePath: res.tempFilePath }) |
| | | } else { |
| | | showToast('ä¸è½½å¤±è´¥') |
| | | } |
| | | }, |
| | | fail: () => { |
| | | closeToast() |
| | | showToast('ä¸è½½å¤±è´¥') |
| | | } |
| | | }) |
| | | } catch (e) { |
| | | closeToast() |
| | | showToast('æå¼å¤±è´¥') |
| | | } |
| | | } |
| | | // éä»¶æ¥ç |
| | | const openFileActions = commonFiles => { |
| | | currentFilesToOpen = commonFiles || []; |
| | | fileActions.value = (commonFiles || []).map((f, idx) => ({ |
| | | name: getFileNameFromUrl(f.url || ""), |
| | | index: idx, |
| | | })); |
| | | showFileSheet.value = true; |
| | | }; |
| | | const onSelectFile = async action => { |
| | | try { |
| | | const item = currentFilesToOpen[action.index]; |
| | | if (!item || !item.url) return; |
| | | showLoadingToast("ä¸è½½ä¸..."); |
| | | uni.downloadFile({ |
| | | url: item.url, |
| | | success: res => { |
| | | closeToast(); |
| | | if (res.statusCode === 200) { |
| | | uni.openDocument({ filePath: res.tempFilePath }); |
| | | } else { |
| | | showToast("ä¸è½½å¤±è´¥"); |
| | | } |
| | | }, |
| | | fail: () => { |
| | | closeToast(); |
| | | showToast("ä¸è½½å¤±è´¥"); |
| | | }, |
| | | }); |
| | | } catch (e) { |
| | | closeToast(); |
| | | showToast("æå¼å¤±è´¥"); |
| | | } |
| | | }; |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | // å¼ç¥¨å°è´¦ç¹ææ ·å¼ |
| | | .filter-popup { |
| | | padding: 12px 12px 20px; |
| | | } |
| | | // å¼ç¥¨å°è´¦ç¹ææ ·å¼ |
| | | .filter-popup { |
| | | padding: 12px 12px 20px; |
| | | } |
| | | |
| | | .switch-row { |
| | | padding: 12px 16px; |
| | | } |
| | | .switch-row { |
| | | padding: 12px 16px; |
| | | } |
| | | |
| | | .filter-actions { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 12px 16px 16px; |
| | | justify-content: space-between; |
| | | } |
| | | .filter-actions { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 12px 16px 16px; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .edit-container { |
| | | padding-bottom: 5rem; |
| | | } |
| | | .edit-container { |
| | | padding-bottom: 5rem; |
| | | } |
| | | |
| | | .uploaded-list { |
| | | padding: 8px 16px 0 16px; |
| | | } |
| | | .uploaded-list { |
| | | padding: 8px 16px 0 16px; |
| | | } |
| | | |
| | | .uploaded-item { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 8px 0; |
| | | border-bottom: 1px solid #f5f5f5; |
| | | } |
| | | .uploaded-item { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 8px 0; |
| | | border-bottom: 1px solid #f5f5f5; |
| | | } |
| | | |
| | | .file-name { |
| | | font-size: 12px; |
| | | color: #333; |
| | | margin-right: 8px; |
| | | flex: 1; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | .file-name { |
| | | font-size: 12px; |
| | | color: #333; |
| | | margin-right: 8px; |
| | | flex: 1; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | .tip-text { |
| | | padding: 4px 16px 0 16px; |
| | | font-size: 12px; |
| | | color: #888; |
| | | } |
| | | |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | .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; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="å¼ç¥¨ç»è®°" @back="goBack" /> |
| | | |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | class="search-text" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°æç´¢" |
| | | v-model="customerName" |
| | | clearable |
| | | @change="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="total > 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.salesContractNo }}</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.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·ååå·</text> |
| | | <text class="detail-value">{{ item.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¸å¡å</text> |
| | | <text class="detail-value">{{ item.salesman }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®åç§°</text> |
| | | <text class="detail-value">{{ item.projectName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ååéé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ item.contractAmount }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å·²å¼ç¥¨éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ item.invoiceTotal }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æªå¼ç¥¨éé¢(å
)</text> |
| | | <text class="detail-value redlight">{{ item.noInvoiceAmountTotal }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æä½æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <up-button |
| | | type="primary" |
| | | size="small" |
| | | @click="handleAddInvoice(item)" |
| | | class="action-btn" |
| | | :disabled="item.noInvoiceAmountTotal == 0" |
| | | > |
| | | æ°å¢å¼ç¥¨ |
| | | </up-button> |
| | | <up-button |
| | | size="small" |
| | | @click="handleViewDetail(item)" |
| | | class="action-btn" |
| | | > |
| | | æ¥ç详æ
|
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="no-data"> |
| | | <text>ææ éå®å°è´¦æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="å¼ç¥¨ç»è®°" |
| | | @back="goBack" /> |
| | | <!-- æç´¢åçéåºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input class="search-text" |
| | | placeholder="请è¾å
¥å®¢æ·åç§°æç´¢" |
| | | v-model="customerName" |
| | | clearable |
| | | @change="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="total > 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.salesContractNo }}</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.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·ååå·</text> |
| | | <text class="detail-value">{{ item.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ä¸å¡å</text> |
| | | <text class="detail-value">{{ item.salesman }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®åç§°</text> |
| | | <text class="detail-value">{{ item.projectName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ååéé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ item.contractAmount }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å·²å¼ç¥¨éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ item.invoiceTotal }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">æªå¼ç¥¨éé¢(å
)</text> |
| | | <text class="detail-value redlight">{{ item.noInvoiceAmountTotal }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé®åºå --> |
| | | <view class="action-buttons"> |
| | | <up-button type="primary" |
| | | size="small" |
| | | @click="handleAddInvoice(item)" |
| | | class="action-btn" |
| | | :disabled="item.noInvoiceAmountTotal == 0"> |
| | | æ°å¢å¼ç¥¨ |
| | | </up-button> |
| | | <up-button size="small" |
| | | @click="handleViewDetail(item)" |
| | | class="action-btn"> |
| | | æ¥ç详æ
|
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ éå®å°è´¦æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import {ledgerListPage} from "@/api/salesManagement/salesLedger"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | const userStore = useUserStore() |
| | | import { ref } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { ledgerListPage } from "@/api/salesManagement/salesLedger"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢å
³é®è¯ |
| | | const customerName = ref(''); |
| | | // æç´¢å
³é®è¯ |
| | | const customerName = ref(""); |
| | | |
| | | // éå®å°è´¦æ°æ® |
| | | const ledgerList = ref([]); |
| | | const total = ref(0); |
| | | // éå®å°è´¦æ°æ® |
| | | const ledgerList = ref([]); |
| | | const total = ref(0); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const page = { |
| | | current: -1, |
| | | size: -1 |
| | | } |
| | | ledgerListPage({...page, customerName: customerName.value}).then((res) => { |
| | | ledgerList.value = res.records; |
| | | total.value = res.total; |
| | | closeToast() |
| | | }).catch(() => { |
| | | closeToast() |
| | | }); |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const page = { |
| | | current: -1, |
| | | size: -1, |
| | | }; |
| | | ledgerListPage({ ...page, customerName: customerName.value }) |
| | | .then(res => { |
| | | ledgerList.value = res.records; |
| | | // total.value = res.total; |
| | | total.value = 100; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // å¤çæ°å¢å¼ç¥¨ |
| | | const handleAddInvoice = (item) => { |
| | | try { |
| | | // åå¨éä¸çååä¿¡æ¯ |
| | | uni.setStorageSync('editData', JSON.stringify(item)); |
| | | |
| | | // è·³è½¬å°æ°å¢å¼ç¥¨é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: '/pages/sales/invoicingRegistration/add' |
| | | }); |
| | | } catch (error) { |
| | | console.error('å¤çæ°å¢å¼ç¥¨å¤±è´¥:', error); |
| | | uni.showToast({ |
| | | title: 'æä½å¤±è´¥ï¼è¯·éè¯', |
| | | icon: 'error' |
| | | }); |
| | | } |
| | | }; |
| | | // å¤çæ°å¢å¼ç¥¨ |
| | | const handleAddInvoice = item => { |
| | | try { |
| | | // åå¨éä¸çååä¿¡æ¯ |
| | | uni.setStorageSync("editData", JSON.stringify(item)); |
| | | |
| | | // å¤çæ¥ç详æ
|
| | | const handleViewDetail = (item) => { |
| | | try { |
| | | // å卿°æ® |
| | | uni.setStorageSync('editData', JSON.stringify(item)); |
| | | |
| | | // 跳转å°è¯¦æ
é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: '/pages/sales/invoicingRegistration/view' |
| | | }); |
| | | } catch (error) { |
| | | console.error('å¤çæ¥ç详æ
失败:', error); |
| | | uni.showToast({ |
| | | title: 'æä½å¤±è´¥ï¼è¯·éè¯', |
| | | icon: 'error' |
| | | }); |
| | | } |
| | | }; |
| | | // è·³è½¬å°æ°å¢å¼ç¥¨é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/invoicingRegistration/add", |
| | | }); |
| | | } catch (error) { |
| | | console.error("å¤çæ°å¢å¼ç¥¨å¤±è´¥:", error); |
| | | uni.showToast({ |
| | | title: "æä½å¤±è´¥ï¼è¯·éè¯", |
| | | icon: "error", |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°å表 |
| | | getList(); |
| | | }); |
| | | // å¤çæ¥ç详æ
|
| | | const handleViewDetail = item => { |
| | | try { |
| | | // å卿°æ® |
| | | uni.setStorageSync("editData", JSON.stringify(item)); |
| | | |
| | | // 跳转å°è¯¦æ
é¡µé¢ |
| | | uni.navigateTo({ |
| | | url: "/pages/sales/invoicingRegistration/view", |
| | | }); |
| | | } catch (error) { |
| | | console.error("å¤çæ¥ç详æ
失败:", error); |
| | | uni.showToast({ |
| | | title: "æä½å¤±è´¥ï¼è¯·éè¯", |
| | | icon: "error", |
| | | }); |
| | | } |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°å表 |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | // å¼ç¥¨ç»è®°ç¹ææ ·å¼ |
| | | .nav-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | // å¼ç¥¨ç»è®°ç¹ææ ·å¼ |
| | | .nav-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .nav-text { |
| | | font-size: 14px; |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | .nav-text { |
| | | font-size: 14px; |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .header-center { |
| | | flex: 1; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: absolute; |
| | | left: 0; |
| | | right: 0; |
| | | pointer-events: none; |
| | | } |
| | | .header-center { |
| | | flex: 1; |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | position: absolute; |
| | | left: 0; |
| | | right: 0; |
| | | pointer-events: none; |
| | | } |
| | | |
| | | .page-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | pointer-events: auto; |
| | | } |
| | | .page-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | pointer-events: auto; |
| | | } |
| | | |
| | | .header-right { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .header-right { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .status-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | } |
| | | .status-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 4px; |
| | | } |
| | | |
| | | .signal, .wifi, .battery { |
| | | width: 16px; |
| | | height: 8px; |
| | | background: #333; |
| | | border-radius: 2px; |
| | | } |
| | | .signal, |
| | | .wifi, |
| | | .battery { |
| | | width: 16px; |
| | | height: 8px; |
| | | background: #333; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | .detail-value.redlight { |
| | | color: red; |
| | | font-weight: 500; |
| | | } |
| | | .detail-value.redlight { |
| | | color: red; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .fab-button { |
| | | bottom: 30px; // ä¸å
¶ä»é¡µé¢ç calc(30px + env(safe-area-inset-bottom)) ä¸å |
| | | } |
| | | .fab-button { |
| | | bottom: 30px; // ä¸å
¶ä»é¡µé¢ç calc(30px + env(safe-area-inset-bottom)) ä¸å |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.customerName" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="filter-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- çéå¼å
³ --> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºå¾
忬¾ä¸º0</text> |
| | | <up-switch v-model="searchForm.status" @change="getList" size="18"/> |
| | | </view> |
| | | </view> |
| | | |
| | | |
| | | |
| | | <!-- å表åºå --> |
| | | <view class="ledger-list" v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" :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.salesContractNo }}</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.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·ååå·</text> |
| | | <text class="detail-value">{{ item.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®åç§°</text> |
| | | <text class="detail-value">{{ item.projectName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产å大类</text> |
| | | <text class="detail-value">{{ item.productCategory }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票å·</text> |
| | | <text class="detail-value">{{ item.invoiceNo || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatNumber(item.invoiceTotal) }}</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">{{ formatNumber(item.receiptPaymentAmountTotal) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¾
忬¾éé¢(å
)</text> |
| | | <text class="detail-value danger">{{ formatNumber(item.noReceiptAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <up-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.noReceiptAmount == 0" |
| | | @click="openForm(item)" |
| | | > |
| | | æ°å¢å款 |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æ æ°æ®æç¤º --> |
| | | <view class="no-data" v-else> |
| | | <text>ææ åæ¬¾æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | <view class="sales-account"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.customerName" |
| | | @change="getList" |
| | | clearable /> |
| | | </view> |
| | | <view class="filter-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | <!-- çéå¼å
³ --> |
| | | <view class="switch-row"> |
| | | <text class="switch-label">䏿¾ç¤ºå¾
忬¾ä¸º0</text> |
| | | <up-switch v-model="searchForm.status" |
| | | @change="getList" |
| | | size="18" /> |
| | | </view> |
| | | </view> |
| | | <!-- å表åºå --> |
| | | <view class="ledger-list" |
| | | v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" |
| | | :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.salesContractNo }}</text> |
| | | </view> |
| | | <view class="item-tag"> |
| | | <u-tag :type="getTagClass(item.statusName)">{{ item.statusName || '--' }}</u-tag> |
| | | </view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·åç§°</text> |
| | | <text class="detail-value">{{ item.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·ååå·</text> |
| | | <text class="detail-value">{{ item.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®åç§°</text> |
| | | <text class="detail-value">{{ item.projectName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">产å大类</text> |
| | | <text class="detail-value">{{ item.productCategory }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票å·</text> |
| | | <text class="detail-value">{{ item.invoiceNo || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å票éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatNumber(item.invoiceTotal) }}</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">{{ formatNumber(item.receiptPaymentAmountTotal) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¾
忬¾éé¢(å
)</text> |
| | | <text class="detail-value danger">{{ formatNumber(item.noReceiptAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <up-button type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.noReceiptAmount == 0" |
| | | @click="openForm(item)"> |
| | | æ°å¢å款 |
| | | </up-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- æ æ°æ®æç¤º --> |
| | | <view class="no-data" |
| | | v-else> |
| | | <text>ææ åæ¬¾æ°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from 'vue' |
| | | import { |
| | | bindInvoiceNoRegPage, |
| | | } from '@/api/salesManagement/receiptPayment' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { ref } from "vue"; |
| | | import { bindInvoiceNoRegPage } from "@/api/salesManagement/receiptPayment"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = (message) => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: 'none' |
| | | }) |
| | | } |
| | | // æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | const showToast = message => { |
| | | uni.showToast({ |
| | | title: message, |
| | | icon: "none", |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éå è½½æç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // å
³éå è½½æç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | |
| | | // ååºå¼æ°æ® |
| | | const tableData = ref([]) |
| | | const tableLoading = ref(false) |
| | | // ååºå¼æ°æ® |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | |
| | | // æ¥è¯¢åæ°è®¾ç½®ä¸º-1è·åå
¨é¨æ°æ® |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1 |
| | | }) |
| | | // æ¥è¯¢åæ°è®¾ç½®ä¸º-1è·åå
¨é¨æ°æ® |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | customerName: '', |
| | | status: true, |
| | | customerContractNo: '', |
| | | projectName: '' |
| | | }) |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | customerName: "", |
| | | status: true, |
| | | customerContractNo: "", |
| | | projectName: "", |
| | | }); |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (!type) { |
| | | return "info"; |
| | | } |
| | | if (type == "æªå®æå款") { |
| | | return "warning"; |
| | | } else { |
| | | return "success"; |
| | | } |
| | | }; |
| | | // æ ¼å¼åæ°å |
| | | const formatNumber = value => { |
| | | return parseFloat(value || 0).toFixed(2); |
| | | }; |
| | | |
| | | // æ ¼å¼åæ°å |
| | | const formatNumber = (value) => { |
| | | return parseFloat(value || 0).toFixed(2) |
| | | } |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | bindInvoiceNoRegPage({ ...searchForm.value, ...page.value }) |
| | | .then(res => { |
| | | tableData.value = res.data.records || []; |
| | | }) |
| | | .catch(() => { |
| | | showToast("è·åæ°æ®å¤±è´¥"); |
| | | }) |
| | | .finally(() => { |
| | | closeToast(); |
| | | }); |
| | | }; |
| | | |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | bindInvoiceNoRegPage({ ...searchForm.value, ...page.value }) |
| | | .then((res) => { |
| | | tableData.value = res.data.records || [] |
| | | }) |
| | | .catch(() => { |
| | | showToast('è·åæ°æ®å¤±è´¥') |
| | | }) |
| | | .finally(() => { |
| | | closeToast() |
| | | }) |
| | | } |
| | | // æå¼æ°å¢è¡¨å |
| | | const openForm = item => { |
| | | if (item.noReceiptAmount == 0) { |
| | | showToast("æ éå忬¾"); |
| | | return; |
| | | } |
| | | uni.setStorageSync("invoiceLedgerEditRow", JSON.stringify(item)); |
| | | uni.navigateTo({ url: "/pages/sales/receiptPayment/add" }); |
| | | }; |
| | | |
| | | // æå¼æ°å¢è¡¨å |
| | | const openForm = (item) => { |
| | | if (item.noReceiptAmount == 0) { |
| | | showToast('æ éå忬¾') |
| | | return |
| | | } |
| | | uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)) |
| | | uni.navigateTo({ url: '/pages/sales/receiptPayment/add' }) |
| | | } |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | onShow(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | // 忬¾ç»è®°ç¹ææ ·å¼ |
| | | .detail-value { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | } |
| | | // 忬¾ç»è®°ç¹ææ ·å¼ |
| | | .detail-value { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: flex-end; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="receipt-payment-history"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.searchText" |
| | | @change="getList" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="search-button" @click="getList"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç»è®¡ä¿¡æ¯ --> |
| | | <view class="summary-info" v-if="tableData.length > 0"> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»è®°å½æ°</text> |
| | | <text class="summary-value">{{ tableData.length }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»éé¢</text> |
| | | <text class="summary-value highlight">{{ formatAmount(totalAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- 忬¾åå²å表 --> |
| | | <view class="history-list" v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" :key="index"> |
| | | <view class="history-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.salesContractNo }}</text> |
| | | </view> |
| | | <view class="item-tag" :class="getTagClass(item.receiptPaymentType)"> |
| | | <text class="tag-text">{{ formatReceiptType(item.receiptPaymentType) }}</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.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·åç§°</text> |
| | | <text class="detail-value">{{ item.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®åç§°</text> |
| | | <text class="detail-value">{{ item.projectName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾æ¥æ</text> |
| | | <text class="detail-value">{{ item.receiptPaymentDate }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.receiptPaymentAmount) }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="detail-info"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»è®°äºº</text> |
| | | <text class="detail-value">{{ item.registrant }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»è®°æ¥æ</text> |
| | | <text class="detail-value">{{ item.createTime }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <u-button |
| | | <view class="receipt-payment-history"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <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.searchText" |
| | | @change="getList" |
| | | clearable /> |
| | | </view> |
| | | <view class="search-button" |
| | | @click="getList"> |
| | | <up-icon name="search" |
| | | size="24" |
| | | color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <!-- ç»è®¡ä¿¡æ¯ --> |
| | | <view class="summary-info" |
| | | v-if="tableData.length > 0"> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»è®°å½æ°</text> |
| | | <text class="summary-value">{{ tableData.length }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»éé¢</text> |
| | | <text class="summary-value highlight">{{ formatAmount(totalAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- 忬¾åå²å表 --> |
| | | <view class="history-list" |
| | | v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" |
| | | :key="index"> |
| | | <view class="history-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.salesContractNo }}</text> |
| | | </view> |
| | | <view class="item-tag" |
| | | :class="getTagClass(item.receiptPaymentType)"> |
| | | <text class="tag-text">{{ formatReceiptType(item.receiptPaymentType) }}</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.customerContractNo }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">客æ·åç§°</text> |
| | | <text class="detail-value">{{ item.customerName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">项ç®åç§°</text> |
| | | <text class="detail-value">{{ item.projectName }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾æ¥æ</text> |
| | | <text class="detail-value">{{ item.receiptPaymentDate }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.receiptPaymentAmount) }}</text> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="detail-info"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»è®°äºº</text> |
| | | <text class="detail-value">{{ item.registrant }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»è®°æ¥æ</text> |
| | | <text class="detail-value">{{ item.createTime }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- æä½æé® --> |
| | | <view class="action-buttons"> |
| | | <!-- <u-button |
| | | type="primary" |
| | | size="small" |
| | | class="action-btn" |
| | |
| | | @click="openForm(item)" |
| | | > |
| | | ç¼è¾å款 |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="no-data"> |
| | | <text>ææ åæ¬¾å岿°æ®</text> |
| | | </view> |
| | | </view> |
| | | </u-button> --> |
| | | <u-button type="error" |
| | | size="small" |
| | | class="action-btn" |
| | | :disabled="item.registrant !== userStore.nickName" |
| | | @click="delitem(item)"> |
| | | å é¤ |
| | | </u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ åæ¬¾å岿°æ®</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import { receiptPaymentHistoryListPage } from "@/api/salesManagement/receiptPayment.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | const userStore = useUserStore() |
| | | import { ref, computed } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { |
| | | receiptPaymentHistoryListPage, |
| | | receiptPaymentDel, |
| | | } from "@/api/salesManagement/receiptPayment.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | const userStore = useUserStore(); |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | searchText: '', |
| | | }); |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | searchText: "", |
| | | }); |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]); |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]); |
| | | |
| | | // å页忰 |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | // å页忰 |
| | | const page = ref({ |
| | | current: -1, |
| | | size: -1, |
| | | }); |
| | | |
| | | const totalAmount = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.receiptPaymentAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | const totalAmount = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.receiptPaymentAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack(); |
| | | }; |
| | | const delitem = item => { |
| | | uni.showModal({ |
| | | title: "确认å é¤", |
| | | content: `ç¡®å®å é¤è¯¥å款记å½åï¼`, |
| | | success: res => { |
| | | if (res.confirm) { |
| | | // è°ç¨å 餿¥å£ |
| | | receiptPaymentDel([item.id]).then(() => { |
| | | uni.showToast({ |
| | | title: "å 餿å", |
| | | icon: "success", |
| | | }); |
| | | // å·æ°å表 |
| | | getList(); |
| | | }); |
| | | } |
| | | }, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast('å è½½ä¸...') |
| | | const params = { |
| | | ...searchForm.value, |
| | | ...page.value |
| | | }; |
| | | receiptPaymentHistoryListPage(params).then((res) => { |
| | | tableData.value = res.records; |
| | | closeToast() |
| | | }).catch(() => { |
| | | closeToast() |
| | | uni.showToast({ |
| | | title: 'æ¥è¯¢å¤±è´¥', |
| | | icon: 'error' |
| | | }); |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const params = { |
| | | ...searchForm.value, |
| | | ...page.value, |
| | | }; |
| | | receiptPaymentHistoryListPage(params) |
| | | .then(res => { |
| | | tableData.value = res.records; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | uni.showToast({ |
| | | title: "æ¥è¯¢å¤±è´¥", |
| | | icon: "error", |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = (type) => { |
| | | if (type == 0) { |
| | | return "çµæ±"; |
| | | } else if (type == 1) { |
| | | return "æ¿å
"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | // æ ¼å¼å忬¾æ¹å¼ |
| | | const formatReceiptType = type => { |
| | | if (type == 0) { |
| | | return "çµæ±"; |
| | | } else if (type == 1) { |
| | | return "æ¿å
"; |
| | | } else { |
| | | return "æªç¥"; |
| | | } |
| | | }; |
| | | |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = (type) => { |
| | | if (type == 0) { |
| | | return "tag-electric"; |
| | | } else if (type == 1) { |
| | | return "tag-acceptance"; |
| | | } else { |
| | | return "tag-unknown"; |
| | | } |
| | | }; |
| | | // è·åæ ç¾æ ·å¼ç±» |
| | | const getTagClass = type => { |
| | | if (type == 0) { |
| | | return "tag-electric"; |
| | | } else if (type == 1) { |
| | | return "tag-acceptance"; |
| | | } else { |
| | | return "tag-unknown"; |
| | | } |
| | | }; |
| | | |
| | | // æ ¼å¼åéé¢ |
| | | const formatAmount = (amount) => { |
| | | return amount ? parseFloat(amount).toFixed(2) : '0.00'; |
| | | }; |
| | | // æå¼ç¼è¾è¡¨å |
| | | const openForm = (item) => { |
| | | uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)) |
| | | uni.navigateTo({ url: '/pages/sales/receiptPayment/edit' }) |
| | | } |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°å表 |
| | | getList(); |
| | | }); |
| | | // æ ¼å¼åéé¢ |
| | | const formatAmount = amount => { |
| | | return amount ? parseFloat(amount).toFixed(2) : "0.00"; |
| | | }; |
| | | // æå¼ç¼è¾è¡¨å |
| | | const openForm = item => { |
| | | uni.setStorageSync("invoiceLedgerEditRow", JSON.stringify(item)); |
| | | uni.navigateTo({ url: "/pages/sales/receiptPayment/edit" }); |
| | | }; |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶å·æ°å表 |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | @import '@/styles/sales-common.scss'; |
| | | @import "@/styles/sales-common.scss"; |
| | | |
| | | // 忬¾æµæ°´ç¹ææ ·å¼ |
| | | .receipt-payment-history { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | } |
| | | // 忬¾æµæ°´ç¹ææ ·å¼ |
| | | .receipt-payment-history { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | } |
| | | |
| | | .action-buttons { |
| | | padding: 12px 0 0 0; // ä¸å
Œ
±æ ·å¼ä¸ç 0 0 16px 0 ä¸å |
| | | } |
| | | .action-buttons { |
| | | padding: 12px 0 0 0; // ä¸å
Œ
±æ ·å¼ä¸ç 0 0 16px 0 ä¸å |
| | | } |
| | | |
| | | .item-tag { |
| | | padding: 2px 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 2px 4px ä¸å |
| | | } |
| | | .item-tag { |
| | | padding: 2px 8px; // ä¸å
Œ
±æ ·å¼ä¸ç 2px 4px ä¸å |
| | | } |
| | | |
| | | .tag-electric { |
| | | background: #4caf50; |
| | | } |
| | | .tag-electric { |
| | | background: #4caf50; |
| | | } |
| | | |
| | | .tag-acceptance { |
| | | background: #ff9800; |
| | | } |
| | | .tag-acceptance { |
| | | background: #ff9800; |
| | | } |
| | | |
| | | .tag-unknown { |
| | | background: #9e9e9e; |
| | | } |
| | | .tag-unknown { |
| | | background: #9e9e9e; |
| | | } |
| | | |
| | | .tag-text { |
| | | font-size: 14px; // ä¸å
Œ
±æ ·å¼ä¸ç 11px ä¸å |
| | | color: #ffffff; |
| | | font-weight: 500; |
| | | } |
| | | .tag-text { |
| | | font-size: 14px; // ä¸å
Œ
±æ ·å¼ä¸ç 11px ä¸å |
| | | color: #ffffff; |
| | | font-weight: 500; |
| | | } |
| | | </style> |
| | |
| | | <template> |
| | | <view class="receipt-payment-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="客æ·å¾æ¥è¯¦æ
" @back="goBack" /> |
| | | |
| | | <!-- ç»è®¡ä¿¡æ¯ --> |
| | | <view class="summary-info" v-if="tableData.length > 0"> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»è®°å½æ°</text> |
| | | <text class="summary-value">{{ tableData.length }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">å¼ç¥¨æ»éé¢</text> |
| | | <text class="summary-value">{{ formatAmount(invoiceTotal) }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">忬¾æ»éé¢</text> |
| | | <text class="summary-value highlight">{{ formatAmount(receiptTotal) }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">åºæ¶æ»éé¢</text> |
| | | <text class="summary-value danger">{{ formatAmount(unReceiptTotal) }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- 忬¾è®°å½æç»å表 --> |
| | | <view class="detail-list" v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" :key="index" class="detail-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="record-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-index">{{ index + 1 }}</text> |
| | | </view> |
| | | <view class="item-date">{{ item.happenTime }}</view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¼ç¥¨éé¢(å
)</text> |
| | | <text class="detail-value">{{ formatAmount(item.invoiceAmount) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.receiptAmount) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åºæ¶éé¢(å
)</text> |
| | | <text class="detail-value danger">{{ formatAmount(item.unReceiptAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else class="no-data"> |
| | | <text>ææ åæ¬¾è®°å½</text> |
| | | </view> |
| | | </view> |
| | | <view class="receipt-payment-detail"> |
| | | <!-- 使ç¨éç¨é¡µé¢å¤´é¨ç»ä»¶ --> |
| | | <PageHeader title="客æ·å¾æ¥è¯¦æ
" |
| | | @back="goBack" /> |
| | | <!-- ç»è®¡ä¿¡æ¯ --> |
| | | <view class="summary-info" |
| | | v-if="tableData.length > 0"> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">æ»è®°å½æ°</text> |
| | | <text class="summary-value">{{ tableData.length }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">å¼ç¥¨æ»éé¢</text> |
| | | <text class="summary-value">{{ formatAmount(invoiceTotal) }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">忬¾æ»éé¢</text> |
| | | <text class="summary-value highlight">{{ formatAmount(receiptTotal) }}</text> |
| | | </view> |
| | | <view class="summary-item"> |
| | | <text class="summary-label">åºæ¶æ»éé¢</text> |
| | | <text class="summary-value danger">{{ formatAmount(unReceiptTotal) }}</text> |
| | | </view> |
| | | </view> |
| | | <!-- 忬¾è®°å½æç»å表 --> |
| | | <view class="detail-list" |
| | | v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" |
| | | :key="index" |
| | | class="detail-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="record-icon"> |
| | | <up-icon name="file-text" |
| | | size="16" |
| | | color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="item-index">{{ index + 1 }}</text> |
| | | </view> |
| | | <view class="item-date">{{ item.happenTime }}</view> |
| | | </view> |
| | | <up-divider></up-divider> |
| | | <view class="item-details"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å¼ç¥¨éé¢(å
)</text> |
| | | <text class="detail-value">{{ formatAmount(item.invoiceTotal) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">忬¾éé¢(å
)</text> |
| | | <text class="detail-value highlight">{{ formatAmount(item.receiptPaymentAmount) }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">åºæ¶éé¢(å
)</text> |
| | | <text class="detail-value danger">{{ formatAmount(item.unReceiptPaymentAmount) }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | <view v-else |
| | | class="no-data"> |
| | | <text>ææ åæ¬¾è®°å½</text> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, computed, onMounted } from 'vue'; |
| | | import { onShow } from '@dcloudio/uni-app'; |
| | | import { customerInteractions } from "@/api/salesManagement/receiptPayment.js"; |
| | | import { ref, computed, onMounted } from "vue"; |
| | | import { onShow } from "@dcloudio/uni-app"; |
| | | import { customerInteractions } from "@/api/salesManagement/receiptPayment.js"; |
| | | |
| | | // 客æ·ä¿¡æ¯ |
| | | const customerId = ref(''); |
| | | // 客æ·ä¿¡æ¯ |
| | | const customerId = ref(""); |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]); |
| | | // è¡¨æ ¼æ°æ® |
| | | const tableData = ref([]); |
| | | |
| | | const invoiceTotal = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.invoiceAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | const invoiceTotal = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.invoiceTotal) || 0); |
| | | }, 0); |
| | | }); |
| | | |
| | | const receiptTotal = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.receiptAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | const receiptTotal = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.receiptPaymentAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | |
| | | const unReceiptTotal = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.unReceiptAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | const unReceiptTotal = computed(() => { |
| | | return tableData.value.reduce((sum, item) => { |
| | | return sum + (parseFloat(item.unReceiptPaymentAmount) || 0); |
| | | }, 0); |
| | | }); |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync('customerId') |
| | | uni.navigateBack(); |
| | | }; |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync("customerId"); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | | // è·å页é¢åæ° |
| | | const getPageParams = () => { |
| | | // 仿¬å°åå¨è·å客æ·ID |
| | | const storedCustomerId = uni.getStorageSync('customerId'); |
| | | if (storedCustomerId) { |
| | | customerId.value = storedCustomerId; |
| | | } |
| | | }; |
| | | // è·å页é¢åæ° |
| | | const getPageParams = () => { |
| | | // 仿¬å°åå¨è·å客æ·ID |
| | | const storedCustomerId = uni.getStorageSync("customerId"); |
| | | if (storedCustomerId) { |
| | | customerId.value = storedCustomerId; |
| | | } |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | if (!customerId.value) { |
| | | uni.showToast({ |
| | | title: '客æ·ä¿¡æ¯ç¼ºå¤±', |
| | | icon: 'error' |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | showLoadingToast('å è½½ä¸...') |
| | | const param = { |
| | | customerId: customerId.value, |
| | | current: -1, |
| | | size: -1 |
| | | }; |
| | | |
| | | customerInteractions(param).then((res) => { |
| | | tableData.value = res.data; |
| | | closeToast() |
| | | }).catch(() => { |
| | | closeToast() |
| | | uni.showToast({ |
| | | title: 'æ¥è¯¢å¤±è´¥', |
| | | icon: 'error' |
| | | }); |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | const getList = () => { |
| | | if (!customerId.value) { |
| | | uni.showToast({ |
| | | title: "客æ·ä¿¡æ¯ç¼ºå¤±", |
| | | icon: "error", |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | // æ ¼å¼åéé¢ |
| | | const formatAmount = (amount) => { |
| | | return amount ? parseFloat(amount).toFixed(2) : '0.00'; |
| | | }; |
| | | showLoadingToast("å è½½ä¸..."); |
| | | const param = { |
| | | customerId: customerId.value, |
| | | current: -1, |
| | | size: -1, |
| | | }; |
| | | |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = (message) => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true |
| | | }); |
| | | }; |
| | | customerInteractions(param) |
| | | .then(res => { |
| | | tableData.value = res.data; |
| | | closeToast(); |
| | | }) |
| | | .catch(() => { |
| | | closeToast(); |
| | | uni.showToast({ |
| | | title: "æ¥è¯¢å¤±è´¥", |
| | | icon: "error", |
| | | }); |
| | | }); |
| | | }; |
| | | |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | // æ ¼å¼åéé¢ |
| | | const formatAmount = amount => { |
| | | return amount ? parseFloat(amount).toFixed(2) : "0.00"; |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶è·ååæ°å¹¶å·æ°å表 |
| | | getPageParams(); |
| | | getList(); |
| | | }); |
| | | // æ¾ç¤ºå è½½æç¤º |
| | | const showLoadingToast = message => { |
| | | uni.showLoading({ |
| | | title: message, |
| | | mask: true, |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶è·ååæ°å¹¶å·æ°å表 |
| | | getPageParams(); |
| | | getList(); |
| | | }); |
| | | // å
³éæç¤º |
| | | const closeToast = () => { |
| | | uni.hideLoading(); |
| | | }; |
| | | |
| | | onShow(() => { |
| | | // 页颿¾ç¤ºæ¶è·ååæ°å¹¶å·æ°å表 |
| | | getPageParams(); |
| | | getList(); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | // 页é¢å è½½æ¶è·ååæ°å¹¶å·æ°å表 |
| | | getPageParams(); |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .receipt-payment-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | } |
| | | .receipt-payment-detail { |
| | | min-height: 100vh; |
| | | background: #f8f9fa; |
| | | position: relative; |
| | | } |
| | | |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | .u-divider { |
| | | margin: 0 !important; |
| | | } |
| | | |
| | | .summary-info { |
| | | background: #ffffff; |
| | | margin: 20px 20px 0 20px; |
| | | border-radius: 12px; |
| | | padding: 16px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | } |
| | | .summary-info { |
| | | background: #ffffff; |
| | | margin: 20px 20px 0 20px; |
| | | border-radius: 12px; |
| | | padding: 16px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); |
| | | } |
| | | |
| | | .summary-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | .summary-item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | |
| | | .summary-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | } |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .summary-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | .summary-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | } |
| | | |
| | | .summary-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 600; |
| | | } |
| | | .summary-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .summary-value.danger { |
| | | color: #ff4757; |
| | | font-weight: 600; |
| | | } |
| | | .summary-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .detail-list { |
| | | padding: 20px; |
| | | } |
| | | .summary-value.danger { |
| | | color: #ff4757; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .detail-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; |
| | | } |
| | | .detail-list { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .item-header { |
| | | padding: 10px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | .detail-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-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | .item-header { |
| | | padding: 10px 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | } |
| | | |
| | | .record-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .item-index { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | .record-icon { |
| | | width: 24px; |
| | | height: 24px; |
| | | background: #2979ff; |
| | | border-radius: 4px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .item-date { |
| | | font-size: 12px; |
| | | color: #666; |
| | | } |
| | | .item-index { |
| | | font-size: 14px; |
| | | color: #333; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | .item-date { |
| | | font-size: 12px; |
| | | color: #666; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | .item-details { |
| | | padding: 16px 0; |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | justify-content: space-between; |
| | | margin-bottom: 8px; |
| | | |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | } |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | } |
| | | |
| | | .detail-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | .detail-label { |
| | | font-size: 12px; |
| | | color: #777777; |
| | | min-width: 60px; |
| | | } |
| | | |
| | | .detail-value.danger { |
| | | color: #ff4757; |
| | | font-weight: 500; |
| | | } |
| | | .detail-value { |
| | | font-size: 12px; |
| | | color: #000000; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 16px; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | color: #999; |
| | | } |
| | | .detail-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .detail-value.danger { |
| | | color: #ff4757; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .no-data { |
| | | padding: 40px 0; |
| | | text-align: center; |
| | | color: #999; |
| | | } |
| | | </style> |