Merge remote-tracking branch 'origin/ywx' into dev
| | |
| | | // 获取库存日报统计 |
| | | export const getStockDailyReport = (params) => { |
| | | return request({ |
| | | url: "/stockreport/daily", |
| | | url: "/stockin/getReportList", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | }; |
| | | |
| | | // 获取库存月报统计 |
| | | export const getStockMonthlyReport = (params) => { |
| | | return request({ |
| | | url: "/stockreport/monthly", |
| | | url: "/stockin/getReportList", |
| | | method: "get", |
| | | params, |
| | | }); |
| | |
| | | // 获取作业报表统计 |
| | | export const getWorkReport = (params) => { |
| | | return request({ |
| | | url: "/stockreport/work", |
| | | url: "/stockin/getReportList", |
| | | method: "get", |
| | | params, |
| | | }); |
| | |
| | | // 获取库存进出存统计 |
| | | export const getStockInOutReport = (params) => { |
| | | return request({ |
| | | url: "/stockreport/inout", |
| | | url: "/stockin/getReportList", |
| | | method: "get", |
| | | params, |
| | | }); |
| | |
| | | // 导出库存报表 |
| | | export const exportStockReport = (params) => { |
| | | return request({ |
| | | url: "/stockreport/export", |
| | | method: "get", |
| | | url: "/stockin/exportCopy", |
| | | method: "post", |
| | | params, |
| | | responseType: 'blob' |
| | | }); |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | // 分页查询报价单列表 |
| | | export function quotationList(query) { |
| | | export function getQuotationList(query) { |
| | | return request({ |
| | | url: "/sales/quotation/list", |
| | | method: "get", |
| | |
| | | export function updateQuotation(data) { |
| | | return request({ |
| | | url: "/sales/quotation/update", |
| | | method: "put", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <!-- <el-col :span="12"> |
| | | <el-form-item label="最低库存:" prop="minStock"> |
| | | <el-input v-model="form.minStock" placeholder="请输入最低库存" clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-col> --> |
| | | </el-row> |
| | | </el-form> |
| | | <template #footer> |
| | |
| | | exportStockManage |
| | | } from "@/api/inventoryManagement/stockManage.js"; |
| | | import { |
| | | updateManagement, |
| | | |
| | | updateManagement,addSutockIn,selectProductRecordListByPuechaserId |
| | | } from "@/api/inventoryManagement/stockIn.js"; |
| | | |
| | | |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | | const tableData = ref([]) |
| | |
| | | getStockManagePage({ ...searchForm.value, ...page }).then(res => { |
| | | tableLoading.value = false |
| | | tableData.value = res.data.records |
| | | console.log('res', res) |
| | | // console.log('res', res) |
| | | // tableData.value.map(item => { |
| | | // item.children = [] |
| | | // }) |
| | | total.value = res.data.total |
| | | // 数据加载完成后检查库存 |
| | | checkStockAndCreatePurchase(); |
| | | }).catch(() => { |
| | | tableLoading.value = false |
| | | }) |
| | |
| | | console.log(form.value) |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | // if (productData.value.length > 0) { |
| | | // form.value.productData = proxy.HaveJson(productData.value) |
| | | // } else { |
| | | // proxy.$modal.msgWarning('请添加产品信息') |
| | | // return |
| | | // } |
| | | // let tempFileIds = [] |
| | | // if (fileList.value.length > 0) { |
| | | // tempFileIds = fileList.value.map(item => item.tempId) |
| | | // } |
| | | // form.value.tempFileIds = tempFileIds |
| | | // form.value.type = 1 |
| | | |
| | | updateManagement(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("提交成功") |
| | | closeDia() |
| | | getList() |
| | | // 提交后检查库存并尝试创建请购单 |
| | | checkStockAndAutoCreatePurchase(); |
| | | checkStockAndCreatePurchase(); |
| | | }) |
| | | } |
| | | }) |
| | | } |
| | | // 检查库存并自动创建请购单 |
| | | const checkStockAndAutoCreatePurchase = async () => { |
| | | // const handList = () => { |
| | | // selectProductRecordListByPuechaserId().then(res => { |
| | | // productModelList.value = res.data.filter(item => item.productName === value) |
| | | // console.log('productModelList.value', productModelList.value) |
| | | // }) |
| | | // } |
| | | // 检查库存并创建请购单 |
| | | const checkStockAndCreatePurchase = async () => { |
| | | const stockList = tableData.value; |
| | | handList() |
| | | for (const item of stockList) { |
| | | if (item.inboundNum0 < item.minStock) { |
| | | try { |
| | | await checkStockAndCreatePurchase(); |
| | | const stockInData = { |
| | | nickName: userStore.nickName,// 使用新格式化函数 |
| | | details: selectedRows.value.map(product => ({ |
| | | id: product.id, |
| | | inboundQuantity: Number(product.quantityStock) |
| | | })), |
| | | }; |
| | | console.log('准备提交的数据:', JSON.parse(JSON.stringify(stockInData))); |
| | | // 调用API |
| | | loading.value = true |
| | | await addSutockIn(stockInData) |
| | | |
| | | proxy.$modal.msgSuccess('新增入库成功') |
| | | loading.value = false |
| | | // // 生成请购单 |
| | | // const createRes = await createPurchaseRequest({ |
| | | // productId: item.productId, |
| | | // requiredQuantity: item.minStock - item.inboundNum0, |
| | | // supplierId: item.supplierId |
| | | // }); |
| | | // if (createRes.code === 200) { |
| | | // // 流转请购单到采购模块 |
| | | // await transferPurchaseRequest({ requestId: createRes.data.id }); |
| | | // proxy.$modal.msgSuccess(`产品 ${item.productName} 请购单已生成并流转`); |
| | | // } |
| | | } catch (error) { |
| | | console.error('自动补货失败:', error); |
| | | proxy.$modal.msgError('自动补货失败,请手动处理'); |
| | | console.error(`产品 ${item.productName} 生成请购单失败:`, error); |
| | | proxy.$modal.msgError(`产品 ${item.productName} 生成请购单失败,请手动处理`); |
| | | |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | // 关闭弹框 |
| | |
| | | } |
| | | onMounted(() => { |
| | | getList() |
| | | checkStockAndAutoCreatePurchase(); |
| | | checkStockAndCreatePurchase(); |
| | | // 每小时检查一次库存 |
| | | const intervalId = setInterval(checkStockAndCreatePurchase, 60 * 60 * 1000); |
| | | |
| | | onUnmounted(() => { |
| | | // 组件卸载时清除定时器 |
| | | clearInterval(intervalId); |
| | | }); |
| | | }) |
| | | </script> |
| | | |
| | |
| | | range-separator="至" |
| | | start-placeholder="开始月份" |
| | | end-placeholder="结束月份" |
| | | format="YYYY-MM" |
| | | value-format="YYYY-MM" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 240px;" |
| | | /> |
| | | <el-date-picker |
| | |
| | | <el-table-column |
| | | v-if="searchForm.reportType === 'daily'" |
| | | label="日期" |
| | | prop="date" |
| | | prop="createTime" |
| | | width="100" |
| | | align="center" |
| | | /> |
| | | <el-table-column |
| | | v-if="searchForm.reportType === 'monthly'" |
| | | label="月份" |
| | | prop="month" |
| | | prop="createTime" |
| | | width="100" |
| | | align="center" |
| | | /> |
| | |
| | | width="70" |
| | | show-overflow-tooltip |
| | | /> |
| | | <el-table-column |
| | | <!-- <el-table-column |
| | | label="期初库存" |
| | | prop="beginStock" |
| | | width="100" |
| | | align="center" |
| | | /> |
| | | /> --> |
| | | <el-table-column |
| | | label="入库数量" |
| | | prop="inboundNum" |
| | | width="100" |
| | | align="center" |
| | | /> |
| | | <el-table-column |
| | | <!-- <el-table-column |
| | | label="出库数量" |
| | | prop="outboundNum" |
| | | prop="" |
| | | width="100" |
| | | align="center" |
| | | /> |
| | | /> --> |
| | | <el-table-column |
| | | label="期末库存" |
| | | prop="endStock" |
| | | label="现在库存" |
| | | prop="inboundNum0" |
| | | width="100" |
| | | align="center" |
| | | /> |
| | |
| | | exportStockReport |
| | | } from '@/api/inventoryManagement/stockReport' |
| | | |
| | | |
| | | const { proxy } = getCurrentInstance() |
| | | // 响应式数据 |
| | | const tableLoading = ref(false) |
| | | const trendChart = ref(null) |
| | |
| | | } |
| | | |
| | | if (response.code === 200) { |
| | | reportData.value = response.data |
| | | // generateMockData() |
| | | reportData.value.tableData = response.data.tableData |
| | | reportData.value.summary = response.data.summary |
| | | reportData.value.chartData = response.data.chartData |
| | | nextTick(() => { |
| | | initCharts() |
| | | }) |
| | | |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error('查询失败:' + error.message) |
| | |
| | | tableLoading.value = false |
| | | } |
| | | } |
| | | // // 生成假数据 |
| | | // const generateMockData = () => { |
| | | // // 生成统计卡片假数据 |
| | | // const summary = { |
| | | // totalIn: 1000, |
| | | // totalOut: 600, |
| | | // currentStock: 400, |
| | | // turnoverRate: 30 |
| | | // } |
| | | |
| | | // // 生成图表假数据 |
| | | // const trendDates = ['2025-09-15', '2025-09-16', '2025-09-17', '2025-09-18', '2025-09-19'] |
| | | // const trendValues = [300, 350, 400, 380, 420] |
| | | // const comparisonDates = ['2025-09-15', '2025-09-16', '2025-09-17'] |
| | | // const inValues = [100, 150, 200] |
| | | // const outValues = [80, 120, 100] |
| | | |
| | | // const chartData = { |
| | | // trendDates, |
| | | // trendValues, |
| | | // comparisonDates, |
| | | // inValues, |
| | | // outValues |
| | | // } |
| | | |
| | | // reportData.value = { |
| | | // summary, |
| | | // chartData, |
| | | // tableData: [] |
| | | // } |
| | | // } |
| | | // 验证搜索表单 |
| | | const validateSearchForm = () => { |
| | | if (searchForm.reportType === 'daily') { |
| | |
| | | // 获取查询参数 |
| | | const getQueryParams = () => { |
| | | const params = { |
| | | reportType: searchForm.reportType |
| | | reportType: searchForm.reportType, |
| | | reportDate: "", |
| | | startMonth: "", |
| | | endMonth: "", |
| | | startDate: "", |
| | | endDate: "" |
| | | } |
| | | |
| | | if (searchForm.reportType === 'daily') { |
| | |
| | | |
| | | try { |
| | | const params = getQueryParams() |
| | | const response = await exportStockReport(params) |
| | | |
| | | // const response = await exportStockReport(params) |
| | | proxy.download("/stockin/exportCopy", params, '库存报表.xlsx') |
| | | // 创建下载链接 |
| | | const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }) |
| | | const url = window.URL.createObjectURL(blob) |
| | | const link = document.createElement('a') |
| | | link.href = url |
| | | link.download = `${getTableTitle()}_${new Date().getTime()}.xlsx` |
| | | document.body.appendChild(link) |
| | | link.click() |
| | | document.body.removeChild(link) |
| | | window.URL.revokeObjectURL(url) |
| | | // const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }) |
| | | // const url = window.URL.createObjectURL(blob) |
| | | // const link = document.createElement('a') |
| | | // link.href = url |
| | | // link.download = `${getTableTitle()}_${new Date().getTime()}.xlsx` |
| | | // document.body.appendChild(link) |
| | | // link.click() |
| | | // document.body.removeChild(link) |
| | | // window.URL.revokeObjectURL(url) |
| | | |
| | | ElMessage.success('导出成功') |
| | | // ElMessage.success('导出成功') |
| | | } catch (error) { |
| | | ElMessage.error('导出失败:' + error.message) |
| | | } |
| | |
| | | </div> |
| | | </template> |
| | | <el-table :data="form.products" border style="width: 100%"> |
| | | <el-table-column prop="productName" label="产品名称" width="200"> |
| | | <el-table-column prop="product" label="产品名称" width="200"> |
| | | <template #default="scope"> |
| | | <el-input v-model="scope.row.productName" placeholder="请输入产品名称" /> |
| | | <el-input v-model="scope.row.product" placeholder="请输入产品名称" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="specification" label="规格型号" width="150"> |
| | |
| | | <div style="margin-top: 20px;"> |
| | | <h4>产品明细</h4> |
| | | <el-table :data="currentQuotation.products" border style="width: 100%"> |
| | | <el-table-column prop="productName" label="产品名称" /> |
| | | <el-table-column prop="product" label="产品名称" /> |
| | | <el-table-column prop="specification" label="规格型号" /> |
| | | <el-table-column prop="quantity" label="数量" /> |
| | | <el-table-column prop="unit" label="单位" /> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed } from 'vue' |
| | | import { ref, reactive, computed,onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Search } from '@element-plus/icons-vue' |
| | | import Pagination from '@/components/PIMTable/Pagination.vue' |
| | | // import Pagination from '@/components/PIMTable/Pagination.vue' |
| | | import {getQuotationList,addQuotation,updateQuotation,deleteQuotation} from '@/api/salesManagement/salesQuotation.js' |
| | | |
| | | // 响应式数据 |
| | | const loading = ref(false) |
| | |
| | | status: '' |
| | | }) |
| | | |
| | | const quotationList = ref([ |
| | | { |
| | | id: 1, |
| | | quotationNo: 'QT202312001', |
| | | customer: '上海科技有限公司', |
| | | salesperson: '陈志强', |
| | | quotationDate: '2023-12-01', |
| | | validDate: '2023-12-31', |
| | | totalAmount: 50000.00, |
| | | paymentMethod: '全款到付', |
| | | deliveryPeriod: '30天', |
| | | status: '已发送', |
| | | remark: '重要客户报价', |
| | | products: [ |
| | | { productName: '工业传感器', specification: 'SEN-001', quantity: 10, unit: '个', unitPrice: 5000, amount: 50000 } |
| | | ] |
| | | }, |
| | | { |
| | | id: 2, |
| | | quotationNo: 'QT202312002', |
| | | customer: '深圳电子有限公司', |
| | | salesperson: '刘雅婷', |
| | | quotationDate: '2023-12-02', |
| | | validDate: '2023-12-31', |
| | | totalAmount: 35000.00, |
| | | paymentMethod: '分期付款', |
| | | deliveryPeriod: '20天', |
| | | status: '客户确认', |
| | | remark: '常规报价', |
| | | products: [ |
| | | { productName: '控制模块', specification: 'CTL-002', quantity: 5, unit: '个', unitPrice: 7000, amount: 35000 } |
| | | ] |
| | | }, |
| | | { |
| | | id: 3, |
| | | quotationNo: 'QT202312003', |
| | | customer: '北京贸易公司', |
| | | salesperson: '王建国', |
| | | quotationDate: '2023-12-03', |
| | | validDate: '2023-12-31', |
| | | totalAmount: 28000.00, |
| | | paymentMethod: '月结', |
| | | deliveryPeriod: '15天', |
| | | status: '草稿', |
| | | remark: '新客户报价', |
| | | products: [ |
| | | { productName: '数据采集器', specification: 'DAQ-003', quantity: 4, unit: '个', unitPrice: 7000, amount: 28000 } |
| | | ] |
| | | } |
| | | ]) |
| | | const quotationList = ref([]) |
| | | |
| | | const pagination = reactive({ |
| | | total: 3, |
| | |
| | | const viewDialogVisible = ref(false) |
| | | const dialogTitle = ref('新增报价') |
| | | const form = reactive({ |
| | | quotationNo: '', |
| | | customer: '', |
| | | salesperson: '', |
| | | quotationDate: '', |
| | |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | const handleSearch = () => { |
| | | // 搜索逻辑已在computed中处理 |
| | | } |
| | | |
| | | const resetSearch = () => { |
| | | searchForm.quotationNo = '' |
| | | searchForm.customer = '' |
| | |
| | | }).then(() => { |
| | | const index = quotationList.value.findIndex(item => item.id === row.id) |
| | | if (index > -1) { |
| | | quotationList.value.splice(index, 1) |
| | | pagination.total-- |
| | | deleteQuotation(row.id).then(res=>{ |
| | | // console.log(res) |
| | | if(res.code===200){ |
| | | ElMessage.success('删除成功') |
| | | handleSearch() |
| | | } |
| | | }) |
| | | // quotationList.value.splice(index, 1) |
| | | // pagination.total-- |
| | | // ElMessage.success('删除成功') |
| | | } |
| | | }) |
| | | } |
| | |
| | | // 编辑 |
| | | const index = quotationList.value.findIndex(item => item.id === editId.value) |
| | | if (index > -1) { |
| | | quotationList.value[index] = { ...form, id: editId.value } |
| | | updateQuotation(form).then(res=>{ |
| | | // console.log(res) |
| | | if(res.code===200){ |
| | | ElMessage.success('编辑成功') |
| | | dialogVisible.value = false |
| | | handleSearch() |
| | | } |
| | | }) |
| | | // quotationList.value[index] = { ...form, id: editId.value } |
| | | // ElMessage.success('编辑成功') |
| | | } |
| | | } else { |
| | | // 新增 |
| | | const newId = Math.max(...quotationList.value.map(item => item.id)) + 1 |
| | | const quotationNo = `QT${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}${String(new Date().getDate()).padStart(2, '0')}${String(newId).padStart(3, '0')}` |
| | | quotationList.value.push({ |
| | | ...form, |
| | | id: newId, |
| | | quotationNo: quotationNo |
| | | }) |
| | | pagination.total++ |
| | | // const newId = Math.max(...quotationList.value.map(item => item.id)) + 1 |
| | | form.quotationNo = `QT${new Date().getFullYear()}${String(new Date().getMonth() + 1).padStart(2, '0')}${String(new Date().getDate()).padStart(2, '0')}` |
| | | |
| | | addQuotation(form).then(res=>{ |
| | | // console.log(res) |
| | | if(res.code===200){ |
| | | ElMessage.success('新增成功') |
| | | } |
| | | dialogVisible.value = false |
| | | handleSearch() |
| | | } |
| | | }) |
| | | |
| | | // quotationList.value.push({ |
| | | // ...form, |
| | | // // id: newId, |
| | | // quotationNo: quotationNo |
| | | // }) |
| | | // pagination.total++ |
| | | // ElMessage.success('新增成功') |
| | | } |
| | | |
| | | } |
| | | }) |
| | | } |
| | |
| | | pagination.currentPage = val.page |
| | | pagination.pageSize = val.limit |
| | | } |
| | | const handleSearch = ()=>{ |
| | | const params = { |
| | | page:pagination, |
| | | ...searchForm |
| | | } |
| | | getQuotationList(params).then(res=>{ |
| | | // console.log(res) |
| | | if(res.code===200){ |
| | | quotationList.value = res.data.records |
| | | pagination.total = res.data.total |
| | | } |
| | | }) |
| | | } |
| | | |
| | | onMounted(()=>{ |
| | | handleSearch() |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |