| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // æ¥è¯¢å
¥åºä¿¡æ¯å表 |
| | | export const getStockInPage = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPage", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // æ¥è¯¢ç产å
¥åºä¿¡æ¯å表 |
| | | export const getStockInPageByProduction = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPageByProduction", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // åºåºå°è´¦-æ¥è¯¢èªå®ä¹å
¥åºä¿¡æ¯å表 |
| | | export const getStockInPageByCustom = (params) => { |
| | | return request({ |
| | | url: "/stockmanagement/listPageByCustom", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | // å
¥åºç®¡ç-æ¥è¯¢èªå®ä¹å
¥åºä¿¡æ¯å表 |
| | | export const getInPageByCustom = (params) => { |
| | | return request({ |
| | | url: "/stockin/listPageByCustom", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // åºåºå°è´¦-æ¥è¯¢ç产åºåºä¿¡æ¯å表 |
| | | export const getStockInPageByProduct = (params) => { |
| | | return request({ |
| | | url: "/stockmanagement/listPageByProduct", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // ä¿®æ¹å
¥åºåä¿¡æ¯ |
| | | export const updateStockIn = (data) => { |
| | | return request({ |
| | | url: "/stockin/update", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // ä¿®æ¹åºåä¿¡æ¯ |
| | | export const updateManagement = (data) => { |
| | | return request({ |
| | | url: "/stockin/updateManagement", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | // æ°å¢ååå
¥åºä¿¡æ¯ |
| | | export function addSutockIn(data) { |
| | | return request({ |
| | | url: '/stockin/add', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // æ°å¢èªå®ä¹å
¥åºä¿¡æ¯ |
| | | export function addStockInCustom(data) { |
| | | return request({ |
| | | url: '/stockin/addCustom', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // ç¼è¾èªå®ä¹å
¥åºä¿¡æ¯ |
| | | export function updateStockInCustom(data) { |
| | | return request({ |
| | | url: '/stockin/updateCustom', |
| | | method: 'post', |
| | | data: data |
| | | }) |
| | | } |
| | | |
| | | // å é¤å
¥åºä¿¡æ¯ |
| | | export function delStockIn(ids) { |
| | | return request({ |
| | | url: '/stockin/del', |
| | | method: 'post', |
| | | data: ids |
| | | }) |
| | | } |
| | | |
| | | // å é¤èªå®ä¹å
¥åºä¿¡æ¯ |
| | | export function delStockInCustom(ids) { |
| | | return request({ |
| | | url: '/stockin/delteCustom', |
| | | method: 'post', |
| | | data: ids |
| | | }) |
| | | } |
| | | |
| | | // 导åºå
¥åºä¿¡æ¯ |
| | | export function exportStockIn(query) { |
| | | return request({ |
| | | url: '/stockin/export', |
| | | method: 'get', |
| | | params: query, |
| | | responseType: 'blob' |
| | | }) |
| | | } |
| | | |
| | | export function selectProductRecordListByPuechaserId(query) { |
| | | return request({ |
| | | url: '/stockin/productlist', |
| | | method: 'get', |
| | | params: query |
| | | }) |
| | | } |
| | | |
| | | |
| | | // |
| | | |
| | |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index1", |
| | | "style": { |
| | | "navigationBarTitleText": "å
¬åºç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index2", |
| | | "style": { |
| | | "navigationBarTitleText": "请å管ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index3", |
| | | "style": { |
| | | "navigationBarTitleText": "åºå·®ç®¡ç", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/cooperativeOffice/collaborativeApproval/index", |
| | | "style": { |
| | | "navigationBarTitleText": "审æ¹ç®¡ç", |
| | |
| | | "navigationBarTitleText": "çäº§æ ¸ç®", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/inventoryManagement/receiptManagement/index", |
| | | "style": { |
| | | "navigationBarTitleText": "èªå®ä¹å
¥åº", |
| | | "navigationStyle": "custom" |
| | | } |
| | | }, |
| | | { |
| | | "path": "pages/inventoryManagement/receiptManagement/detail", |
| | | "style": { |
| | | "navigationBarTitleText": "æ°å¢å
¥åº", |
| | | "navigationStyle": "custom" |
| | | } |
| | | } |
| | | ], |
| | | "subPackages": [ |
| | |
| | | <text class="info-label">ç³è¯·æ¥æ</text> |
| | | <text class="info-value">{{ approvalData.approveTime }}</text> |
| | | </view> |
| | | |
| | | <!-- approveType=2 请åç¸å
³å段 --> |
| | | <template v-if="approvalData.approveType === 2"> |
| | | <view class="info-row"> |
| | | <text class="info-label">请åå¼å§æ¶é´</text> |
| | | <text class="info-value">{{ approvalData.startDate || '-' }}</text> |
| | | </view> |
| | | <view class="info-row"> |
| | | <text class="info-label">请åç»ææ¶é´</text> |
| | | <text class="info-value">{{ approvalData.endDate || '-' }}</text> |
| | | </view> |
| | | </template> |
| | | |
| | | <!-- approveType=3 åºå·®ç¸å
³å段 --> |
| | | <view v-if="approvalData.approveType === 3" class="info-row"> |
| | | <text class="info-label">åºå·®å°ç¹</text> |
| | | <text class="info-value">{{ approvalData.location || '-' }}</text> |
| | | </view> |
| | | |
| | | <!-- approveType=4 æ¥éç¸å
³å段 --> |
| | | <view v-if="approvalData.approveType === 4" class="info-row"> |
| | | <text class="info-label">æ¥ééé¢</text> |
| | | <text class="info-value">{{ approvalData.price ? `Â¥${approvalData.price}` : '-' }}</text> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | |
| | | <u-form-item prop="approveTime" label="ç³è¯·æ¥æ" required> |
| | | <u-input |
| | | v-model="form.approveTime" |
| | | placeholder="è¯·éæ©" |
| | | readonly |
| | | placeholder="è¯·éæ©" |
| | | @click="showDatePicker" |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <!-- approveType=2 请åç¸å
³å段 --> |
| | | <template v-if="approveType === 2"> |
| | | <u-form-item prop="startDate" label="请åå¼å§æ¶é´" required> |
| | | <u-input |
| | | v-model="form.startDate" |
| | | readonly |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | @click="showStartDatePicker" |
| | | /> |
| | | </u-form-item> |
| | | <u-form-item prop="endDate" label="请åç»ææ¶é´" required> |
| | | <u-input |
| | | v-model="form.endDate" |
| | | readonly |
| | | placeholder="è¯·éæ©ç»ææ¶é´" |
| | | @click="showEndDatePicker" |
| | | /> |
| | | </u-form-item> |
| | | </template> |
| | | |
| | | <!-- approveType=3 åºå·®ç¸å
³å段 --> |
| | | <u-form-item v-if="approveType === 3" prop="location" label="åºå·®å°ç¹" required> |
| | | <u-input |
| | | v-model="form.location" |
| | | placeholder="请è¾å
¥åºå·®å°ç¹" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <!-- approveType=4 æ¥éç¸å
³å段 --> |
| | | <u-form-item v-if="approveType === 4" prop="price" label="æ¥ééé¢" required> |
| | | <u-input |
| | | v-model="form.price" |
| | | type="number" |
| | | placeholder="请è¾å
¥æ¥ééé¢" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | </u-form> |
| | |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <u-popup v-model="showDate" mode="bottom"> |
| | | <u-datetime-picker |
| | | <up-popup :show="showDate" mode="bottom" @close="showDate = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="currentDate" |
| | | title="éæ©æ¥æ" |
| | | mode="date" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDate = false" |
| | | mode="date" |
| | | /> |
| | | </u-popup> |
| | | </up-popup> |
| | | |
| | | <!-- 请åå¼å§æ¶é´éæ©å¨ --> |
| | | <up-popup :show="showStartDate" mode="bottom" @close="showStartDate = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="startDateValue" |
| | | @confirm="onStartDateConfirm" |
| | | @cancel="showStartDate = false" |
| | | mode="date" |
| | | /> |
| | | </up-popup> |
| | | |
| | | <!-- 请åç»ææ¶é´éæ©å¨ --> |
| | | <up-popup :show="showEndDate" mode="bottom" @close="showEndDate = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="endDateValue" |
| | | @confirm="onEndDateConfirm" |
| | | @cancel="showEndDate = false" |
| | | mode="date" |
| | | /> |
| | | </up-popup> |
| | | <!-- å®¡æ ¸æµç¨åºå --> |
| | | <view class="approval-process"> |
| | | <view class="approval-header"> |
| | |
| | | approveReason: "", |
| | | checkResult: "", |
| | | tempFileIds: [], |
| | | approverList: [] // æ°å¢å段ï¼å卿æèç¹ç审æ¹äººid |
| | | approverList: [], // æ°å¢å段ï¼å卿æèç¹ç审æ¹äººid |
| | | startDate: "", |
| | | endDate: "", |
| | | location: "", |
| | | price: "" |
| | | }, |
| | | rules: { |
| | | approveTime: [{ required: false, message: "请è¾å
¥", trigger: "change" },], |
| | |
| | | approveDeptId: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | approveReason: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | checkResult: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | startDate: [{ required: false, message: "è¯·éæ©å¼å§æ¶é´", trigger: "change" }], |
| | | endDate: [{ required: false, message: "è¯·éæ©ç»ææ¶é´", trigger: "change" }], |
| | | location: [{ required: false, message: "请è¾å
¥åºå·®å°ç¹", trigger: "blur" }], |
| | | price: [{ required: false, message: "请è¾å
¥æ¥ééé¢", trigger: "blur" }], |
| | | }, |
| | | }); |
| | | const { form, rules } = toRefs(data); |
| | |
| | | const formRef = ref(null); |
| | | const message = ref(""); |
| | | const showDate = ref(false) |
| | | const currentDate = ref([new Date().getFullYear(), new Date().getMonth() + 1, new Date().getDate()]) |
| | | const currentDate = ref(Date.now()) |
| | | const showStartDate = ref(false) |
| | | const startDateValue = ref(Date.now()) |
| | | const showEndDate = ref(false) |
| | | const endDateValue = ref(Date.now()) |
| | | const userStore = useUserStore() |
| | | const approveType = ref(0) |
| | | |
| | | const getProductOptions = () => { |
| | | getDept().then((res) => { |
| | |
| | | |
| | | // 仿¬å°åå¨è·ååæ° |
| | | operationType.value = uni.getStorageSync('operationType') || 'add'; |
| | | approveType.value = uni.getStorageSync('approveType') || 0; |
| | | |
| | | // 妿æ¯ç¼è¾æ¨¡å¼ï¼ä»æ¬å°åå¨è·åæ°æ® |
| | | if (operationType.value === 'edit') { |
| | |
| | | // æ¸
餿¬å°åå¨çæ°æ® |
| | | uni.removeStorageSync('operationType'); |
| | | uni.removeStorageSync('invoiceLedgerEditRow'); |
| | | uni.removeStorageSync('approveType'); |
| | | uni.navigateBack(); |
| | | }; |
| | | |
| | |
| | | // æ¶éææèç¹ç审æ¹äººid |
| | | console.log('approverNodes---', approverNodes.value) |
| | | form.value.approveUserIds = approverNodes.value.map(node => node.userId).join(',') |
| | | form.value.approveType = 0 |
| | | form.value.approveType = approveType.value |
| | | if (operationType.value === "add" || currentApproveStatus.value == 3) { |
| | | approveProcessAdd(form.value).then(res => { |
| | | showToast("æäº¤æå"); |
| | |
| | | currentDate.value = formatDateToYMD(e.value) |
| | | showDate.value = false; |
| | | } |
| | | |
| | | // æ¾ç¤ºè¯·åå¼å§æ¶é´éæ©å¨ |
| | | const showStartDatePicker = () => { |
| | | showStartDate.value = true |
| | | } |
| | | |
| | | // 确认请åå¼å§æ¶é´éæ© |
| | | const onStartDateConfirm = (e) => { |
| | | form.value.startDate = formatDateToYMD(e.value) |
| | | showStartDate.value = false |
| | | } |
| | | |
| | | const showEndDatePicker = () => { |
| | | showEndDate.value = true |
| | | } |
| | | |
| | | // 确认请åç»ææ¶é´éæ© |
| | | const onEndDateConfirm = (e) => { |
| | | form.value.endDate = formatDateToYMD(e.value) |
| | | showEndDate.value = false |
| | | } |
| | | |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | |
| | | <text class="detail-label">ç³è¯·æ¥æ</text> |
| | | <text class="detail-value">{{ item.approveTime }}</text> |
| | | </view> |
| | | |
| | | <!-- approveType=2 请åç¸å
³å段 --> |
| | | <template v-if="item.approveType === 2"> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">请åå¼å§æ¶é´</text> |
| | | <text class="detail-value">{{ item.startDate || '-' }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">请åç»ææ¶é´</text> |
| | | <text class="detail-value">{{ item.endDate || '-' }}</text> |
| | | </view> |
| | | </template> |
| | | |
| | | <!-- approveType=3 åºå·®ç¸å
³å段 --> |
| | | <view v-if="item.approveType === 3" class="detail-row"> |
| | | <text class="detail-label">åºå·®å°ç¹</text> |
| | | <text class="detail-value">{{ item.location || '-' }}</text> |
| | | </view> |
| | | |
| | | <!-- approveType=4 æ¥éç¸å
³å段 --> |
| | | <view v-if="item.approveType === 4" class="detail-row"> |
| | | <text class="detail-label">æ¥ééé¢</text> |
| | | <text class="detail-value highlightYellow">{{ item.price ? `Â¥${item.price}` : '-' }}</text> |
| | | </view> |
| | | |
| | | <view class="detail-row"> |
| | | <text class="detail-label">ç»ææ¥æ</text> |
| | | <text class="detail-value">{{ item.approveOverTime }}</text> |
| | |
| | | import {onShow} from "@dcloudio/uni-app"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | |
| | | // æ¥æ¶ç¶ç»ä»¶ä¼ éç approveType åæ° |
| | | const props = defineProps({ |
| | | approveType: { |
| | | type: Number, |
| | | default: 0 |
| | | } |
| | | }); |
| | | |
| | | const userStore = useUserStore() |
| | | // æ°æ® |
| | | const ledgerList = ref([]); |
| | |
| | | size: -1, |
| | | }; |
| | | approveProcessListPage({ |
| | | ...page,approveType: 0,...searchForm.value |
| | | ...page,approveType: props.approveType,...searchForm.value |
| | | }) |
| | | .then((res) => { |
| | | ledgerList.value = res.data.records; |
| | |
| | | uni.setStorageSync('invoiceLedgerEditRow', JSON.stringify(item)); |
| | | uni.setStorageSync('operationType', 'edit'); |
| | | uni.setStorageSync('approveId', item.approveId); |
| | | uni.setStorageSync('approveType', props.approveType); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/detail", |
| | | }); |
| | |
| | | // æ·»å æ°è®°å½ |
| | | const handleAdd = () => { |
| | | uni.setStorageSync('operationType', 'add'); |
| | | uni.setStorageSync('approveType', props.approveType); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/detail", |
| | | url: `/pages/cooperativeOffice/collaborativeApproval/detail?approveType=${props.approveType}`, |
| | | }); |
| | | }; |
| | | // ç¹å»å®¡æ ¸ |
| | | const approve = (item) => { |
| | | uni.setStorageSync('approveId', item.approveId); |
| | | uni.setStorageSync('approveType', props.approveType); |
| | | uni.navigateTo({ |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/approve" |
| | | url: "/pages/cooperativeOffice/collaborativeApproval/approve?approveType=" + props.approveType |
| | | }) |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="1" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="2" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="3" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="container"> |
| | | <!-- å¼å
¥index.vueç»ä»¶å¹¶ä¼ éåæ° --> |
| | | <ApprovalProcessIndex :approveType="4" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import ApprovalProcessIndex from './index.vue' |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .container { |
| | | width: 100%; |
| | | height: 100%; |
| | | } |
| | | </style> |
| | |
| | | </up-grid> |
| | | </view> |
| | | </view> |
| | | <!-- å
¥åºç®¡ç --> |
| | | <view class="common-module collaboration-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 inventoryManagement" |
| | | :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 production-module"> |
| | |
| | | // åååå
¬åè½æ°æ® |
| | | 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/xietongshenpi@2x.png', |
| | | label: 'åå审æ¹', |
| | | }, |
| | |
| | | icon: '/static/images/icon/kehubaifang@2x.png', |
| | | label: 'å®¢æ·æè®¿', |
| | | } |
| | | ]); |
| | | // åååå
¬åè½æ°æ®inventoryManagement/receiptManagement |
| | | const inventoryManagement = reactive([ |
| | | { |
| | | icon: '/static/images/icon/rukuguanli@2x.png', |
| | | label: 'èªå®ä¹å
¥åº', |
| | | }, |
| | | ]); |
| | | |
| | | // ç产管æ§åè½æ°æ® |
| | |
| | | |
| | | // 设å¤ç®¡çåè½æ°æ® |
| | | const equipmentItems = reactive([ |
| | | // { |
| | | // icon: '/static/images/icon/shebeitaizhang@2x.png', |
| | | // label: '设å¤å°è´¦', |
| | | // }, |
| | | { |
| | | icon: '/static/images/icon/shebeitaizhang@2x.png', |
| | | label: '设å¤å°è´¦', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/shbeibaoxiu@2x.png', |
| | | label: 'è®¾å¤æ¥ä¿®', |
| | |
| | | icon: '/static/images/icon/xunjianshangchuan@2x.png', |
| | | label: 'å·¡æ£ä¸ä¼ ', |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/guzhangfenxi@2x.png', |
| | | label: 'åæè¿½æº¯', |
| | | bgColor: '#ff9800' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/zhinengpaidan@2x.png', |
| | | label: 'æºè½æ´¾å', |
| | | bgColor: '#ff6b35' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/zuoyezhidao@2x.png', |
| | | label: 'ä½ä¸æå¯¼', |
| | | bgColor: '#4caf50' |
| | | }, |
| | | { |
| | | icon: '/static/images/icon/jieguoyanzheng@2x.png', |
| | | label: 'ç»æéªè¯', |
| | | bgColor: '#9c27b0' |
| | | } |
| | | // { |
| | | // icon: '/static/images/icon/guzhangfenxi@2x.png', |
| | | // label: 'åæè¿½æº¯', |
| | | // bgColor: '#ff9800' |
| | | // }, |
| | | // { |
| | | // icon: '/static/images/icon/zhinengpaidan@2x.png', |
| | | // label: 'æºè½æ´¾å', |
| | | // bgColor: '#ff6b35' |
| | | // }, |
| | | // { |
| | | // icon: '/static/images/icon/zuoyezhidao@2x.png', |
| | | // label: 'ä½ä¸æå¯¼', |
| | | // bgColor: '#4caf50' |
| | | // }, |
| | | // { |
| | | // icon: '/static/images/icon/jieguoyanzheng@2x.png', |
| | | // label: 'ç»æéªè¯', |
| | | // bgColor: '#9c27b0' |
| | | // } |
| | | ]); |
| | | |
| | | // å¤ç常ç¨åè½ç¹å» |
| | |
| | | url: '/pages/procurementManagement/paymentLedger/index' |
| | | }); |
| | | break; |
| | | case 'å
¬åºç®¡ç': |
| | | uni.navigateTo({ |
| | | url: '/pages/cooperativeOffice/collaborativeApproval/index1' |
| | | }); |
| | | break; |
| | | case '请å管ç': |
| | | uni.navigateTo({ |
| | | url: '/pages/cooperativeOffice/collaborativeApproval/index2' |
| | | }); |
| | | break; |
| | | case 'åºå·®ç®¡ç': |
| | | uni.navigateTo({ |
| | | url: '/pages/cooperativeOffice/collaborativeApproval/index3' |
| | | }); |
| | | break; |
| | | case 'åå审æ¹': |
| | | uni.navigateTo({ |
| | | url: '/pages/cooperativeOffice/collaborativeApproval/index' |
| | |
| | | url: '/pages/cooperativeOffice/clientVisit/index' |
| | | }); |
| | | break; |
| | | case 'èªå®ä¹å
¥åº': |
| | | uni.navigateTo({ |
| | | url: '/pages/inventoryManagement/receiptManagement/index' |
| | | }); |
| | | break; |
| | | case 'ç产订å': |
| | | uni.navigateTo({ |
| | | url: '/pages/productionManagement/productionOrder/index' |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <up-popup :show="dialogFormVisible" mode="bottom" :round="10" closeable @close="closeDia"> |
| | | <view class="form-popup"> |
| | | <view class="popup-header"> |
| | | <text class="popup-title">{{ operationType === 'add' ? 'æ°å¢èªå®ä¹å
¥åº' : 'ç¼è¾èªå®ä¹å
¥åº' }}</text> |
| | | </view> |
| | | |
| | | <scroll-view class="popup-content" scroll-y> |
| | | <view v-if="operationType === 'add'" class="add-btn-section"> |
| | | <u-button type="primary" @click="addProductRow">æ°å¢äº§å</u-button> |
| | | </view> |
| | | |
| | | <view v-for="(item, index) in productList" :key="index" class="product-item"> |
| | | <view class="item-header"> |
| | | <text class="item-title">产å {{ index + 1 }}</text> |
| | | <u-button v-if="operationType === 'add'" type="error" size="mini" class="delete-btn" @click="removeProductRow(index)">å é¤</u-button> |
| | | </view> |
| | | |
| | | <view class="item-form"> |
| | | <view class="form-field"> |
| | | <text class="field-label required">产å大类</text> |
| | | <up-input v-model="item.productCategory" placeholder="请è¾å
¥äº§å大类" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label required">è§æ ¼åå·</text> |
| | | <up-input v-model="item.specificationModel" placeholder="请è¾å
¥è§æ ¼åå·" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label required">åä½</text> |
| | | <up-input v-model="item.unit" placeholder="请è¾å
¥åä½" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label">ä¾åºå</text> |
| | | <up-input v-model="item.supplierName" placeholder="请è¾å
¥ä¾åºå" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label required">ç©åç±»å</text> |
| | | <up-input v-model="item.itemType" readonly placeholder="è¯·éæ©ç©åç±»å" @click="openItemTypePicker(index)" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label required">å
¥åºæ°é</text> |
| | | <up-input v-model="item.inboundNum" type="number" placeholder="请è¾å
¥å
¥åºæ°é" @blur="calculateTotalPrice(item)" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label required">å
¥åºæ¥æ</text> |
| | | <up-input v-model="item.inboundDate" readonly placeholder="è¯·éæ©å
¥åºæ¥æ" @click="openDatePicker(index)" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label">ç¨ç(%)</text> |
| | | <up-input v-model="item.taxRate" readonly placeholder="è¯·éæ©ç¨ç" @click="openTaxRatePicker(index)" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label">å«ç¨åä»·(å
)</text> |
| | | <up-input v-model="item.taxInclusiveUnitPrice" type="digit" placeholder="请è¾å
¥å«ç¨åä»·" @blur="calculateTotalPrice(item)" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label">å«ç¨æ»ä»·(å
)</text> |
| | | <up-input v-model="item.taxInclusiveTotalPrice" type="digit" placeholder="èªå¨è®¡ç®" @blur="calculateExclusivePrice(item)" /> |
| | | </view> |
| | | |
| | | <view class="form-field"> |
| | | <text class="field-label">ä¸å«ç¨æ»ä»·(å
)</text> |
| | | <up-input v-model="item.taxExclusiveTotalPrice" type="digit" placeholder="èªå¨è®¡ç®" disabled /> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | | |
| | | <view class="popup-footer"> |
| | | <u-button class="btn-cancel" @click="closeDia">åæ¶</u-button> |
| | | <u-button class="btn-confirm" type="primary" @click="submitForm">确认</u-button> |
| | | </view> |
| | | </view> |
| | | |
| | | <up-action-sheet :show="showItemTypePicker" :actions="itemTypeActions" title="éæ©ç©åç±»å" @select="onItemTypeSelect" @close="showItemTypePicker = false" /> |
| | | <up-action-sheet :show="showTaxRatePicker" :actions="taxRateActions" title="éæ©ç¨ç" @select="onTaxRateSelect" @close="showTaxRatePicker = false" /> |
| | | <up-popup :show="showDatePicker" mode="bottom" @close="showDatePicker = false"> |
| | | <up-datetime-picker :show="true" v-model="dateValue" @confirm="onDateConfirm" @cancel="showDatePicker = false" mode="date" /> |
| | | </up-popup> |
| | | </up-popup> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs } from 'vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import { addStockInCustom, updateStockInCustom } from '@/api/inventoryManagement/stockIn.js' |
| | | |
| | | const userStore = useUserStore() |
| | | const emit = defineEmits(['close', 'success']) |
| | | |
| | | const operationType = ref('') |
| | | const dialogFormVisible = ref(false) |
| | | const productList = ref([]) |
| | | const loading = ref(false) |
| | | |
| | | const showItemTypePicker = ref(false) |
| | | const showTaxRatePicker = ref(false) |
| | | const showDatePicker = ref(false) |
| | | const dateValue = ref(new Date().getTime()) |
| | | const currentEditIndex = ref(0) |
| | | |
| | | function formatDateTime(date = new Date(), includeTime = true) { |
| | | const d = new Date(date) |
| | | const year = d.getFullYear() |
| | | const month = String(d.getMonth() + 1).padStart(2, '0') |
| | | const day = String(d.getDate()).padStart(2, '0') |
| | | if (!includeTime) return `${year}-${month}-${day}` |
| | | const hours = String(d.getHours()).padStart(2, '0') |
| | | const minutes = String(d.getMinutes()).padStart(2, '0') |
| | | const seconds = String(d.getSeconds()).padStart(2, '0') |
| | | return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` |
| | | } |
| | | |
| | | function getCurrentDate() { |
| | | return formatDateTime(new Date(), false) |
| | | } |
| | | |
| | | const itemTypeActions = ref([ |
| | | { name: 'ç©æ', value: 'ç©æ' }, |
| | | { name: 'åæ', value: 'åæ' }, |
| | | { name: 'æå', value: 'æå' }, |
| | | { name: 'å
¶ä»', value: 'å
¶ä»' } |
| | | ]) |
| | | |
| | | const taxRateActions = ref([ |
| | | { name: '1%', value: 1 }, |
| | | { name: '6%', value: 6 }, |
| | | { name: '13%', value: 13 } |
| | | ]) |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | id: null, |
| | | supplierId: null, |
| | | supplierName: '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: '' |
| | | } |
| | | }) |
| | | const { form } = toRefs(data) |
| | | |
| | | const addProductRow = () => { |
| | | productList.value.push({ |
| | | id: null, |
| | | productCategory: '', |
| | | specificationModel: '', |
| | | unit: '', |
| | | supplierName: form.value.supplierName || '', |
| | | itemType: '', |
| | | inboundNum: 0, |
| | | inboundDate: '', |
| | | taxRate: null, |
| | | taxInclusiveUnitPrice: 0, |
| | | taxInclusiveTotalPrice: 0, |
| | | taxExclusiveTotalPrice: 0 |
| | | }) |
| | | } |
| | | |
| | | const removeProductRow = (index) => { |
| | | productList.value.splice(index, 1) |
| | | } |
| | | |
| | | const openItemTypePicker = (index) => { |
| | | currentEditIndex.value = index |
| | | showItemTypePicker.value = true |
| | | } |
| | | |
| | | const onItemTypeSelect = (item) => { |
| | | productList.value[currentEditIndex.value].itemType = item.value |
| | | showItemTypePicker.value = false |
| | | } |
| | | |
| | | const openTaxRatePicker = (index) => { |
| | | currentEditIndex.value = index |
| | | showTaxRatePicker.value = true |
| | | } |
| | | |
| | | const onTaxRateSelect = (item) => { |
| | | productList.value[currentEditIndex.value].taxRate = item.value |
| | | calculateExclusivePrice(productList.value[currentEditIndex.value]) |
| | | showTaxRatePicker.value = false |
| | | } |
| | | |
| | | const openDatePicker = (index) => { |
| | | currentEditIndex.value = index |
| | | showDatePicker.value = true |
| | | } |
| | | |
| | | const onDateConfirm = (e) => { |
| | | productList.value[currentEditIndex.value].inboundDate = formatDateToYMD(e.value) |
| | | showDatePicker.value = false |
| | | } |
| | | |
| | | const calculateTotalPrice = (row) => { |
| | | const unitPrice = Number(row.taxInclusiveUnitPrice || 0) |
| | | const quantity = Number(row.inboundNum || 0) |
| | | row.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2) |
| | | calculateExclusivePrice(row) |
| | | } |
| | | |
| | | const calculateExclusivePrice = (row) => { |
| | | const totalPrice = Number(row.taxInclusiveTotalPrice || 0) |
| | | const taxRate = Number(row.taxRate || 0) |
| | | row.taxExclusiveTotalPrice = (totalPrice / (1 + taxRate / 100)).toFixed(2) |
| | | } |
| | | |
| | | const submitForm = async () => { |
| | | try { |
| | | if (!productList.value.length) { |
| | | uni.showToast({ title: '请è³å°æ·»å 䏿¡äº§åæ°æ®', icon: 'none' }) |
| | | return |
| | | } |
| | | for (let i = 0; i < productList.value.length; i++) { |
| | | const product = productList.value[i] |
| | | if (!product.productCategory || !product.specificationModel || !product.unit) { |
| | | uni.showToast({ title: 第è¡äº§åæ°æ®æªå¡«å宿´, icon: 'none' }) |
| | | return |
| | | } |
| | | if (!product.itemType) { |
| | | uni.showToast({ title: 第è¡è¯·éæ©ç©åç±»å, icon: 'none' }) |
| | | return |
| | | } |
| | | if (!product.inboundDate) { |
| | | uni.showToast({ title: 第è¡è¯·éæ©å
¥åºæ¥æ, icon: 'none' }) |
| | | return |
| | | } |
| | | const stock = Number(product?.inboundNum ?? 0) |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | uni.showToast({ title: 第è¡å
¥åºæ°éé大äº0, icon: 'none' }) |
| | | return |
| | | } |
| | | } |
| | | const payloadList = productList.value.map(product => ({ |
| | | id: product.id ?? null, |
| | | inboundNum: Number(product.inboundNum), |
| | | productCategory: product.productCategory, |
| | | specificationModel: product.specificationModel, |
| | | unit: product.unit, |
| | | supplierName: product.supplierName || form.value.supplierName, |
| | | itemType: product.itemType, |
| | | inboundDate: formatDateTime(product.inboundDate, false), |
| | | taxRate: Number(product.taxRate || 0), |
| | | taxInclusiveUnitPrice: Number(product.taxInclusiveUnitPrice || 0), |
| | | taxInclusiveTotalPrice: Number(product.taxInclusiveTotalPrice || 0), |
| | | taxExclusiveTotalPrice: Number(product.taxExclusiveTotalPrice || 0) |
| | | })) |
| | | loading.value = true |
| | | uni.showLoading({ title: 'æäº¤ä¸...', mask: true }) |
| | | if (operationType.value === 'edit') { |
| | | await updateStockInCustom(payloadList[0]) |
| | | } else { |
| | | await addStockInCustom(payloadList) |
| | | } |
| | | uni.hideLoading() |
| | | uni.showToast({ title: operationType.value === 'edit' ? 'ç¼è¾æå' : 'æ°å¢æå', icon: 'success' }) |
| | | closeDia() |
| | | emit('success') |
| | | } catch (error) { |
| | | console.error('æäº¤å¤±è´¥:', error) |
| | | uni.hideLoading() |
| | | uni.showToast({ title: 'æä½å¤±è´¥ï¼è¯·éè¯', icon: 'none' }) |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | |
| | | const closeDia = () => { |
| | | dialogFormVisible.value = false |
| | | productList.value = [] |
| | | emit('close') |
| | | } |
| | | |
| | | const openDialog = async (type, row) => { |
| | | operationType.value = type |
| | | dialogFormVisible.value = true |
| | | if (type === 'add') { |
| | | form.value = { |
| | | id: null, |
| | | supplierId: null, |
| | | supplierName: '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: '' |
| | | } |
| | | productList.value = [] |
| | | } else { |
| | | form.value = { |
| | | id: row?.id ?? null, |
| | | supplierId: row?.supplierId ?? null, |
| | | supplierName: row?.supplierName ?? '', |
| | | recorderId: userStore.userId, |
| | | recorderName: userStore.name, |
| | | entryDate: getCurrentDate(), |
| | | remark: row?.remark ?? '' |
| | | } |
| | | productList.value = [{ |
| | | id: row?.id ?? null, |
| | | productCategory: row?.productCategory ?? '', |
| | | specificationModel: row?.specificationModel ?? '', |
| | | unit: row?.unit ?? '', |
| | | supplierName: row?.supplierName ?? '', |
| | | itemType: row?.itemType ?? '', |
| | | inboundNum: Number(row?.inboundNum ?? row?.inboundQuantity ?? 0), |
| | | inboundDate: row?.inboundDate ?? row?.createTime ?? '', |
| | | taxRate: Number(row?.taxRate ?? 0), |
| | | taxInclusiveUnitPrice: Number(row?.taxInclusiveUnitPrice ?? 0), |
| | | taxInclusiveTotalPrice: Number(row?.taxInclusiveTotalPrice ?? 0), |
| | | taxExclusiveTotalPrice: Number(row?.taxExclusiveTotalPrice ?? 0) |
| | | }] |
| | | } |
| | | } |
| | | |
| | | defineExpose({ openDialog }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .form-popup { |
| | | height: 80vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | background: #f5f5f5; |
| | | } |
| | | .popup-header { |
| | | padding: 16px; |
| | | background: #fff; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | .popup-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | } |
| | | .popup-content { |
| | | flex: 1; |
| | | height: 0; |
| | | padding: 12px; |
| | | } |
| | | .add-btn-section { |
| | | margin-bottom: 12px; |
| | | } |
| | | .product-item { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | margin-bottom: 12px; |
| | | overflow: hidden; |
| | | } |
| | | .item-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 12px 16px; |
| | | background: #f8f8f8; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | .item-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | width: 100%; |
| | | color: #333; |
| | | } |
| | | .item-form { |
| | | padding: 16px; |
| | | } |
| | | .form-field { |
| | | margin-bottom: 16px; |
| | | } |
| | | .field-label { |
| | | display: block; |
| | | font-size: 14px; |
| | | color: #666; |
| | | margin-bottom: 8px; |
| | | } |
| | | .field-label.required::before { |
| | | content: '*'; |
| | | color: #ff0000; |
| | | margin-right: 4px; |
| | | } |
| | | .popup-footer { |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 12px 16px; |
| | | background: #fff; |
| | | border-top: 1px solid #f0f0f0; |
| | | } |
| | | .btn-cancel, .btn-confirm { |
| | | flex: 1; |
| | | } |
| | | .btn-cancel { |
| | | background: #f5f5f5; |
| | | color: #666; |
| | | border: none; |
| | | } |
| | | .delete-btn { |
| | | padding: 2px 8px !important; |
| | | height: 24px !important; |
| | | font-size: 11px !important; |
| | | width: 20px !important; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="stock-detail-page"> |
| | | <PageHeader :title="operationType === 'add' ? 'æ°å¢å
¥åº' : 'ç¼è¾å
¥åº'" @back="goBack" /> |
| | | |
| | | <u-form ref="formRef" :model="form" :rules="rules" label-width="140rpx"> |
| | | <!-- åºæ¬ä¿¡æ¯ --> |
| | | <view class="form-section"> |
| | | <view class="section-title">åºæ¬ä¿¡æ¯</view> |
| | | |
| | | <u-form-item prop="supplierName" label="ä¾åºå" required> |
| | | <u-input |
| | | v-model="form.supplierName" |
| | | placeholder="请è¾å
¥ä¾åºååç§°" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="productCategory" label="产å大类" required> |
| | | <u-input |
| | | v-model="form.productCategory" |
| | | placeholder="请è¾å
¥äº§å大类" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="specificationModel" label="è§æ ¼åå·" required> |
| | | <u-input |
| | | v-model="form.specificationModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="unit" label="åä½" required> |
| | | <u-input |
| | | v-model="form.unit" |
| | | placeholder="请è¾å
¥åä½" |
| | | clearable |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="itemType" label="ç©åç±»å" required> |
| | | <u-input |
| | | v-model="form.itemType" |
| | | readonly |
| | | placeholder="è¯·éæ©ç©åç±»å" |
| | | @click="showItemTypePicker = true" |
| | | /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showItemTypePicker = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="inboundDate" label="å
¥åºæ¥æ" required> |
| | | <u-input |
| | | v-model="form.inboundDate" |
| | | readonly |
| | | placeholder="è¯·éæ©å
¥åºæ¥æ" |
| | | @click="showDatePicker = true" |
| | | /> |
| | | <template #right> |
| | | <up-icon name="calendar" @click="showDatePicker = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | </view> |
| | | |
| | | <!-- æ°éåä»·æ ¼ --> |
| | | <view class="form-section"> |
| | | <view class="section-title">æ°éåä»·æ ¼</view> |
| | | |
| | | <u-form-item prop="inboundNum" label="å
¥åºæ°é" required> |
| | | <u-input |
| | | v-model="form.inboundNum" |
| | | type="number" |
| | | placeholder="请è¾å
¥å
¥åºæ°é" |
| | | @blur="calculateTotalPrice" |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="taxInclusiveUnitPrice" label="å«ç¨åä»·" required> |
| | | <u-input |
| | | v-model="form.taxInclusiveUnitPrice" |
| | | type="digit" |
| | | placeholder="请è¾å
¥å«ç¨åä»·" |
| | | @blur="calculateTotalPrice" |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="taxInclusiveTotalPrice" label="å«ç¨æ»ä»·"> |
| | | <u-input |
| | | v-model="form.taxInclusiveTotalPrice" |
| | | type="digit" |
| | | placeholder="èªå¨è®¡ç®" |
| | | disabled |
| | | /> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="taxRate" label="ç¨ç(%)" required> |
| | | <u-input |
| | | v-model="form.taxRate" |
| | | readonly |
| | | placeholder="è¯·éæ©ç¨ç" |
| | | @click="showTaxRatePicker = true" |
| | | /> |
| | | <template #right> |
| | | <up-icon name="arrow-right" @click="showTaxRatePicker = true"></up-icon> |
| | | </template> |
| | | </u-form-item> |
| | | |
| | | <u-form-item prop="taxExclusiveTotalPrice" label="ä¸å«ç¨æ»ä»·"> |
| | | <u-input |
| | | v-model="form.taxExclusiveTotalPrice" |
| | | type="digit" |
| | | placeholder="èªå¨è®¡ç®" |
| | | disabled |
| | | /> |
| | | </u-form-item> |
| | | </view> |
| | | </u-form> |
| | | |
| | | <!-- åºé¨æé® --> |
| | | <view class="footer-btns"> |
| | | <u-button class="cancel-btn" @click="goBack">åæ¶</u-button> |
| | | <u-button class="save-btn" @click="submitForm">ä¿å</u-button> |
| | | </view> |
| | | |
| | | <!-- ç©åç±»åéæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showItemTypePicker" |
| | | :actions="itemTypeOptions" |
| | | title="éæ©ç©åç±»å" |
| | | @select="onItemTypeSelect" |
| | | @close="showItemTypePicker = false" |
| | | /> |
| | | |
| | | <!-- ç¨çéæ©å¨ --> |
| | | <up-action-sheet |
| | | :show="showTaxRatePicker" |
| | | :actions="taxRateOptions" |
| | | title="éæ©ç¨ç" |
| | | @select="onTaxRateSelect" |
| | | @close="showTaxRatePicker = false" |
| | | /> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-popup :show="showDatePicker" mode="bottom" @close="showDatePicker = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="dateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" |
| | | mode="date" |
| | | /> |
| | | </up-popup> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs, onMounted } from 'vue' |
| | | import { onLoad } from '@dcloudio/uni-app' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import { |
| | | addStockInCustom, |
| | | updateStockInCustom |
| | | } from "@/api/inventoryManagement/stockIn.js" |
| | | |
| | | const formRef = ref(null) |
| | | const operationType = ref('add') |
| | | const showItemTypePicker = ref(false) |
| | | const showTaxRatePicker = ref(false) |
| | | const showDatePicker = ref(false) |
| | | const dateValue = ref(new Date().getTime()) |
| | | |
| | | const data = reactive({ |
| | | form: { |
| | | supplierName: '', |
| | | productCategory: '', |
| | | specificationModel: '', |
| | | unit: '', |
| | | itemType: '', |
| | | inboundDate: '', |
| | | inboundNum: '', |
| | | taxInclusiveUnitPrice: '', |
| | | taxInclusiveTotalPrice: '', |
| | | taxRate: '', |
| | | taxExclusiveTotalPrice: '', |
| | | }, |
| | | rules: { |
| | | supplierName: [{ required: true, message: '请è¾å
¥ä¾åºååç§°', trigger: 'blur' }], |
| | | productCategory: [{ required: true, message: '请è¾å
¥äº§å大类', trigger: 'blur' }], |
| | | specificationModel: [{ required: true, message: '请è¾å
¥è§æ ¼åå·', trigger: 'blur' }], |
| | | unit: [{ required: true, message: '请è¾å
¥åä½', trigger: 'blur' }], |
| | | itemType: [{ required: true, message: 'è¯·éæ©ç©åç±»å', trigger: 'change' }], |
| | | inboundDate: [{ required: true, message: 'è¯·éæ©å
¥åºæ¥æ', trigger: 'change' }], |
| | | inboundNum: [{ required: true, message: '请è¾å
¥å
¥åºæ°é', trigger: 'blur' }], |
| | | taxInclusiveUnitPrice: [{ required: true, message: '请è¾å
¥å«ç¨åä»·', trigger: 'blur' }], |
| | | taxRate: [{ required: true, message: 'è¯·éæ©ç¨ç', trigger: 'change' }], |
| | | }, |
| | | }) |
| | | const { form, rules } = toRefs(data) |
| | | |
| | | // ç©åç±»åé项 |
| | | const itemTypeOptions = ref([ |
| | | { name: 'åææ', value: 'åææ' }, |
| | | { name: 'åæå', value: 'åæå' }, |
| | | { name: 'æå', value: 'æå' }, |
| | | { name: 'è¾
æ', value: 'è¾
æ' }, |
| | | { name: 'å
è£
ç©', value: 'å
è£
ç©' }, |
| | | { name: 'å
¶ä»', value: 'å
¶ä»' }, |
| | | ]) |
| | | |
| | | // ç¨çé项 |
| | | const taxRateOptions = ref([ |
| | | { name: '0%', value: 0 }, |
| | | { name: '1%', value: 1 }, |
| | | { name: '3%', value: 3 }, |
| | | { name: '6%', value: 6 }, |
| | | { name: '9%', value: 9 }, |
| | | { name: '13%', value: 13 }, |
| | | ]) |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.removeStorageSync('stockInEditRow') |
| | | uni.navigateBack() |
| | | } |
| | | |
| | | // ç©åç±»åéæ© |
| | | const onItemTypeSelect = (item) => { |
| | | form.value.itemType = item.value |
| | | showItemTypePicker.value = false |
| | | } |
| | | |
| | | // ç¨çéæ© |
| | | const onTaxRateSelect = (item) => { |
| | | form.value.taxRate = item.value |
| | | showTaxRatePicker.value = false |
| | | calculateExclusivePrice() |
| | | } |
| | | |
| | | // æ¥æéæ©ç¡®è®¤ |
| | | const onDateConfirm = (e) => { |
| | | form.value.inboundDate = formatDateToYMD(e.value) |
| | | showDatePicker.value = false |
| | | } |
| | | |
| | | // 计ç®å«ç¨æ»ä»· |
| | | const calculateTotalPrice = () => { |
| | | const num = parseFloat(form.value.inboundNum) || 0 |
| | | const price = parseFloat(form.value.taxInclusiveUnitPrice) || 0 |
| | | form.value.taxInclusiveTotalPrice = (num * price).toFixed(2) |
| | | calculateExclusivePrice() |
| | | } |
| | | |
| | | // 计ç®ä¸å«ç¨æ»ä»· |
| | | const calculateExclusivePrice = () => { |
| | | const totalPrice = parseFloat(form.value.taxInclusiveTotalPrice) || 0 |
| | | const taxRate = parseFloat(form.value.taxRate) || 0 |
| | | form.value.taxExclusiveTotalPrice = (totalPrice / (1 + taxRate / 100)).toFixed(2) |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | formRef.value.validate().then(() => { |
| | | uni.showLoading({ |
| | | title: 'ä¿åä¸...', |
| | | mask: true |
| | | }) |
| | | |
| | | const apiCall = operationType.value === 'add' ? addStockInCustom : updateStockInCustom |
| | | |
| | | apiCall(form.value).then(() => { |
| | | uni.hideLoading() |
| | | uni.showToast({ |
| | | title: 'ä¿åæå', |
| | | icon: 'success' |
| | | }) |
| | | setTimeout(() => { |
| | | goBack() |
| | | }, 1500) |
| | | }).catch(() => { |
| | | uni.hideLoading() |
| | | uni.showToast({ |
| | | title: 'ä¿å失败', |
| | | icon: 'none' |
| | | }) |
| | | }) |
| | | }).catch(() => { |
| | | uni.showToast({ |
| | | title: '请填å宿´ä¿¡æ¯', |
| | | icon: 'none' |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | onLoad((options) => { |
| | | if (options.type) { |
| | | operationType.value = options.type |
| | | } |
| | | |
| | | // ç¼è¾æ¨¡å¼ï¼å è½½æ°æ® |
| | | if (operationType.value === 'edit') { |
| | | const storedData = uni.getStorageSync('stockInEditRow') |
| | | if (storedData) { |
| | | const row = JSON.parse(storedData) |
| | | form.value = { ...row } |
| | | } |
| | | } else { |
| | | // æ°å¢æ¨¡å¼ï¼è®¾ç½®é»è®¤æ¥æ |
| | | form.value.inboundDate = formatDateToYMD(new Date()) |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .stock-detail-page { |
| | | min-height: 100vh; |
| | | background: #f5f5f5; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .form-section { |
| | | background: #fff; |
| | | margin-bottom: 12px; |
| | | padding: 16px; |
| | | } |
| | | |
| | | .section-title { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | margin-bottom: 16px; |
| | | padding-left: 12px; |
| | | border-left: 4px solid #2979ff; |
| | | } |
| | | |
| | | .footer-btns { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | display: flex; |
| | | gap: 12px; |
| | | padding: 12px 16px; |
| | | background: #fff; |
| | | box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.04); |
| | | z-index: 999; |
| | | } |
| | | |
| | | .cancel-btn { |
| | | flex: 1; |
| | | background: #f5f5f5; |
| | | color: #666; |
| | | border: none; |
| | | } |
| | | |
| | | .save-btn { |
| | | flex: 1; |
| | | background: #2979ff; |
| | | color: #fff; |
| | | border: none; |
| | | } |
| | | </style> |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <view class="stock-in-page"> |
| | | <PageHeader title="èªå®ä¹å
¥åº" @back="goBack" /> |
| | | |
| | | <!-- æç´¢åºå --> |
| | | <view class="search-section"> |
| | | <view class="search-bar"> |
| | | <view class="search-input"> |
| | | <up-input |
| | | v-model="searchForm.supplierName" |
| | | placeholder="请è¾å
¥ä¾åºååç§°" |
| | | clearable |
| | | /> |
| | | </view> |
| | | <view class="search-button" @click="handleQuery"> |
| | | <up-icon name="search" size="24" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | <view class="date-filter" @click="openDatePickerHandler"> |
| | | <text class="date-text">{{ searchForm.timeStr || 'éæ©æ¥æ' }}</text> |
| | | <up-icon name="calendar" size="18" color="#999"></up-icon> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- å表 --> |
| | | <view class="stock-list" v-if="tableData.length > 0"> |
| | | <view v-for="(item, index) in tableData" :key="index" class="stock-item"> |
| | | <view class="item-header"> |
| | | <view class="item-left"> |
| | | <view class="batch-icon"> |
| | | <up-icon name="file-text" size="16" color="#ffffff"></up-icon> |
| | | </view> |
| | | <text class="batch-text">{{ item.inboundBatches }}</text> |
| | | </view> |
| | | <view class="item-right"> |
| | | <text class="time-text">{{ item.inboundDate }}</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">{{ 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.itemType }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å
¥åºæ°é</text> |
| | | <text class="detail-value highlight">{{ item.inboundNum }} {{ item.unit }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å«ç¨åä»·</text> |
| | | <text class="detail-value">Â¥{{ item.taxInclusiveUnitPrice }}</text> |
| | | </view> |
| | | <view class="detail-row"> |
| | | <text class="detail-label">å«ç¨æ»ä»·</text> |
| | | <text class="detail-value price">Â¥{{ item.taxInclusiveTotalPrice }}</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.createBy }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <view class="item-actions"> |
| | | <u-button type="primary" size="small" @click="handleEdit(item)">ç¼è¾</u-button> |
| | | <u-button type="error" size="small" plain @click="handleDeleteSingle(item)">å é¤</u-button> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-else class="no-data"> |
| | | <text>ææ æ°æ®</text> |
| | | </view> |
| | | |
| | | <!-- æµ®å¨æä½æé® --> |
| | | <view class="fab-button" @click="handleAdd"> |
| | | <up-icon name="plus" size="24" color="#ffffff"></up-icon> |
| | | </view> |
| | | |
| | | <!-- æ¥æéæ©å¨ --> |
| | | <up-popup :show="showDatePicker" mode="bottom" @close="showDatePicker = false"> |
| | | <up-datetime-picker |
| | | :show="true" |
| | | v-model="dateValue" |
| | | @confirm="onDateConfirm" |
| | | @cancel="showDatePicker = false" |
| | | mode="date" |
| | | /> |
| | | </up-popup> |
| | | |
| | | <!-- 表åå¼¹çª --> |
| | | <form-dia-manual ref="formDiaManual" @close="getList" @success="getList" /> |
| | | </view> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, toRefs, onMounted } from 'vue' |
| | | import { onShow } from '@dcloudio/uni-app' |
| | | import dayjs from 'dayjs' |
| | | import PageHeader from '@/components/PageHeader.vue' |
| | | import FormDiaManual from './components/formDiaManual.vue' |
| | | import useUserStore from '@/store/modules/user' |
| | | import { formatDateToYMD } from '@/utils/ruoyi' |
| | | import { |
| | | getInPageByCustom, |
| | | delStockInCustom |
| | | } from "@/api/inventoryManagement/stockIn.js" |
| | | |
| | | const userStore = useUserStore() |
| | | |
| | | const tableData = ref([]) |
| | | const showDatePicker = ref(false) |
| | | const dateValue = ref(new Date().getTime()) |
| | | const formDiaManual = ref(null) |
| | | |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 20, |
| | | }) |
| | | const total = ref(0) |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: '', |
| | | timeStr: '', |
| | | }, |
| | | }) |
| | | const { searchForm } = toRefs(data) |
| | | |
| | | // ç»ä¸ç¨ dayjs è¾åº YYYY-MM-DD |
| | | const formatYMDLocal = (ts) => dayjs(Number(ts)).format('YYYY-MM-DD') |
| | | |
| | | // è¿åä¸ä¸é¡µ |
| | | const goBack = () => { |
| | | uni.navigateBack() |
| | | } |
| | | |
| | | // æ¥è¯¢å表 |
| | | const handleQuery = () => { |
| | | page.current = 1 |
| | | getList() |
| | | } |
| | | |
| | | const getList = () => { |
| | | uni.showLoading({ |
| | | title: 'å è½½ä¸...', |
| | | mask: true |
| | | }) |
| | | |
| | | const params = { |
| | | ...page, |
| | | supplierName: searchForm.value.supplierName, |
| | | timeStr: searchForm.value.timeStr |
| | | } |
| | | |
| | | getInPageByCustom(params).then(res => { |
| | | uni.hideLoading() |
| | | tableData.value = res.data.records || [] |
| | | total.value = res.data.total || 0 |
| | | }).catch(() => { |
| | | uni.hideLoading() |
| | | uni.showToast({ |
| | | title: 'å 载失败', |
| | | icon: 'none' |
| | | }) |
| | | }) |
| | | } |
| | | |
| | | // æå¼æ¥æéæ©å¨ï¼ç®åå¯é ï¼ |
| | | const openDatePickerHandler = () => { |
| | | // è¥å·²æé䏿¥æï¼ç¨å®åå§åï¼å¦åç¨ä»å¤© |
| | | dateValue.value = searchForm.value.timeStr |
| | | ? dayjs(searchForm.value.timeStr, 'YYYY-MM-DD').valueOf() |
| | | : Date.now() |
| | | showDatePicker.value = true |
| | | } |
| | | |
| | | // æ¥æéæ©ç¡®è®¤ï¼ä¸å
¶ä»é¡µä¸è´ï¼æ¿æ¶é´æ³ -> YYYY-MM-DDï¼ |
| | | const onDateConfirm = (e) => { |
| | | searchForm.value.timeStr = formatDateToYMD(e.value) |
| | | showDatePicker.value = false |
| | | handleQuery() |
| | | } |
| | | |
| | | // æ°å¢å
¥åº |
| | | const handleAdd = () => { |
| | | formDiaManual.value?.openDialog('add') |
| | | } |
| | | |
| | | // ç¼è¾ |
| | | const handleEdit = (item) => { |
| | | formDiaManual.value?.openDialog('edit', item) |
| | | } |
| | | |
| | | // å é¤åæ¡ |
| | | const handleDeleteSingle = (item) => { |
| | | // æ£æ¥æ¯å¦æ¯æ¬äººå建 |
| | | if (item.createBy !== userStore.nickName) { |
| | | uni.showToast({ |
| | | title: 'ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®', |
| | | icon: 'none' |
| | | }) |
| | | return |
| | | } |
| | | |
| | | uni.showModal({ |
| | | title: 'å é¤', |
| | | content: '确认å é¤è¯¥å
¥åºè®°å½åï¼', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | delStockInCustom({ ids: [item.id] }).then(() => { |
| | | uni.showToast({ |
| | | title: 'å 餿å', |
| | | icon: 'success' |
| | | }) |
| | | getList() |
| | | }).catch(() => { |
| | | uni.showToast({ |
| | | title: 'å é¤å¤±è´¥', |
| | | icon: 'none' |
| | | }) |
| | | }) |
| | | } |
| | | } |
| | | }) |
| | | } |
| | | |
| | | onShow(() => { |
| | | getList() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .stock-in-page { |
| | | min-height: 100vh; |
| | | background: #f5f5f5; |
| | | padding-bottom: 80px; |
| | | } |
| | | |
| | | .search-section { |
| | | background: #fff; |
| | | padding: 16px; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .search-bar { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .search-input { |
| | | flex: 1; |
| | | } |
| | | |
| | | .search-button { |
| | | width: 44px; |
| | | height: 44px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | background: #f5f5f5; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .date-filter { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 12px 16px; |
| | | background: #f5f5f5; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .date-text { |
| | | font-size: 14px; |
| | | color: #666; |
| | | } |
| | | |
| | | .stock-list { |
| | | padding: 0 16px; |
| | | } |
| | | |
| | | .stock-item { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 16px; |
| | | margin-bottom: 12px; |
| | | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); |
| | | } |
| | | |
| | | .item-header { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .item-left { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .batch-icon { |
| | | width: 32px; |
| | | height: 32px; |
| | | background: #2979ff; |
| | | border-radius: 8px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .batch-text { |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | color: #333; |
| | | } |
| | | |
| | | .time-text { |
| | | font-size: 12px; |
| | | color: #999; |
| | | } |
| | | |
| | | .item-details { |
| | | margin: 12px 0; |
| | | } |
| | | |
| | | .detail-row { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 8px 0; |
| | | } |
| | | |
| | | .detail-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | } |
| | | |
| | | .detail-value { |
| | | font-size: 14px; |
| | | color: #333; |
| | | text-align: right; |
| | | flex: 1; |
| | | margin-left: 12px; |
| | | } |
| | | |
| | | .detail-value.highlight { |
| | | color: #2979ff; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .detail-value.price { |
| | | color: #ff6b00; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | .item-actions { |
| | | display: flex; |
| | | gap: 12px; |
| | | margin-top: 12px; |
| | | padding-top: 12px; |
| | | border-top: 1px solid #f5f5f5; |
| | | } |
| | | |
| | | .no-data { |
| | | text-align: center; |
| | | padding: 60px 0; |
| | | color: #999; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .fab-button { |
| | | position: fixed; |
| | | right: 20px; |
| | | bottom: 80px; |
| | | width: 56px; |
| | | height: 56px; |
| | | background: #2979ff; |
| | | border-radius: 50%; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | box-shadow: 0 4px 12px rgba(41, 121, 255, 0.4); |
| | | z-index: 999; |
| | | } |
| | | </style> |