index.vue 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. <template>
  2. <div class="app-container">
  3. <!-- 搜索栏 -->
  4. <el-card shadow="never">
  5. <el-form :model="queryParams" inline>
  6. <TenantSelect v-model="queryParams.tenantIds" placeholder="请选择机构名称" prop="tenantIds" @change="fetchWarehouseOptions" />
  7. <el-form-item label="库房" prop="storeId">
  8. <el-select v-model="queryParams.storeId" placeholder="全部" clearable class="!w-180px">
  9. <el-option v-for="w in warehouseOptions" :key="w.id" :label="w.storeName" :value="w.id" />
  10. </el-select>
  11. </el-form-item>
  12. <el-form-item label="月份范围" prop="month">
  13. <el-date-picker
  14. v-model="queryParams.month"
  15. type="monthrange"
  16. value-format="YYYY-MM"
  17. range-separator="至"
  18. start-placeholder="开始月份"
  19. end-placeholder="结束月份"
  20. class="!w-240px"
  21. />
  22. </el-form-item>
  23. <el-form-item label="关键字" prop="keyword">
  24. <el-input v-model="queryParams.keyword" placeholder="物资名称/物资编码" clearable class="!w-240px" />
  25. </el-form-item>
  26. <el-form-item>
  27. <el-button type="primary" @click="handleSearch">搜索</el-button>
  28. <el-button @click="handleReset">重置</el-button>
  29. <el-button v-hasPermi="['warehouses:stock-search:export']" :loading="exportLoading" type="success" plain @click="handleExport"><Icon icon="ep:download" class="mr-5px" />导出</el-button>
  30. </el-form-item>
  31. </el-form>
  32. </el-card>
  33. <el-card shadow="never" class="mt-4">
  34. <el-table :data="tableData" v-loading="loading" :header-cell-style="tableHeaderColor">
  35. <el-table-column prop="storeName" label="库房" align="center" />
  36. <el-table-column prop="categoryName" label="物资类别" align="center" />
  37. <el-table-column prop="materialName" label="物资名称" align="center" />
  38. <el-table-column prop="materialUnit" label="计量单位" align="center" />
  39. <el-table-column label="期初余额" align="center">
  40. <el-table-column prop="beginQty" label="数量" align="center" />
  41. <el-table-column prop="beginPrice" label="单价" align="center" :formatter="(row) => fmtMoney(row.beginPrice)" />
  42. <el-table-column prop="beginAmount" label="金额" align="center" :formatter="(row) => fmtMoney(row.beginAmount)" />
  43. </el-table-column>
  44. <el-table-column label="本期收入" align="center">
  45. <el-table-column prop="inQty" label="数量" align="center" />
  46. <el-table-column prop="inPrice" label="单价" align="center" :formatter="(row) => fmtMoney(row.inPrice)" />
  47. <el-table-column prop="inAmount" label="金额" align="center" :formatter="(row) => fmtMoney(row.inAmount)" />
  48. </el-table-column>
  49. <el-table-column label="本期支出" align="center">
  50. <el-table-column prop="outQty" label="数量" align="center" />
  51. <el-table-column prop="outPrice" label="单价" align="center" :formatter="(row) => fmtMoney(row.outPrice)" />
  52. <el-table-column prop="outAmount" label="金额" align="center" :formatter="(row) => fmtMoney(row.outAmount)" />
  53. </el-table-column>
  54. <el-table-column label="本期结余" align="center">
  55. <el-table-column prop="endQty" label="数量" align="center" />
  56. <el-table-column prop="endPrice" label="单价" align="center" :formatter="(row) => fmtMoney(row.endPrice)" />
  57. <el-table-column prop="closingAmount" label="金额" align="center" :formatter="(row) => fmtMoney(row.endAmount)" />
  58. </el-table-column>
  59. <el-table-column label="操作" align="center" fixed="right">
  60. <template #default="{ row }">
  61. <el-button link type="primary" @click="handleView(row)">查看</el-button>
  62. </template>
  63. </el-table-column>
  64. </el-table>
  65. <el-pagination
  66. class="mt-4"
  67. :current-page="queryParams.pageNo"
  68. :page-size="queryParams.pageSize"
  69. :total="total"
  70. layout="total, sizes, prev, pager, next, jumper"
  71. @size-change="handleSizeChange"
  72. @current-change="handleCurrentChange"
  73. />
  74. </el-card>
  75. <!-- 库存查看弹窗 -->
  76. <StockDetailDialog v-model="stockDialogVisible" :detail="currentStockDetail" />
  77. </div>
  78. </template>
  79. <script setup>
  80. import { onMounted, reactive, ref } from 'vue'
  81. import { ElMessage } from 'element-plus'
  82. import { materialStockSearchPage, materialStockFlowDetail, materialStockSearchExport } from '@/api/material/stockSearch'
  83. import { useUserStore } from '@/store/modules/user'
  84. import { storeList } from '@/api/material/storeManage'
  85. import download from '@/utils/download'
  86. const userStore = useUserStore()
  87. const message = useMessage()
  88. const StockDetailDialog = defineAsyncComponent(() => import('./components/StockDetailDialog.vue'))
  89. const tableHeaderColor = () => ({
  90. background: '#F5F7FA',
  91. color: '#606266',
  92. fontWeight: '600',
  93. })
  94. // 搜索条件
  95. const queryParams = reactive({
  96. pageNo: 1,
  97. pageSize: 10,
  98. tenantIds: userStore.orgTenantId,
  99. storeId: '',
  100. month: [],
  101. keyword: '',
  102. })
  103. // 列表
  104. const tableData = ref([])
  105. const loading = ref(false)
  106. const total = ref(0)
  107. const currentStockDetail = ref({})
  108. const warehouseOptions = ref([])
  109. const stockDialogVisible = ref(false)
  110. const fmtMoney = (n) => `¥${n}`
  111. const exportLoading = ref(false)
  112. const fetchWarehouseOptions = async () => {
  113. const res = await storeList({
  114. tenantIds: queryParams.tenantIds?.length ? queryParams.tenantIds : undefined,
  115. })
  116. const data = res ?? []
  117. console.log(data)
  118. warehouseOptions.value = Array.isArray(data) ? data : []
  119. }
  120. const getTableData = async () => {
  121. loading.value = true
  122. let params = {
  123. pageNo: queryParams.pageNo,
  124. pageSize: queryParams.pageSize,
  125. tenantIds: queryParams.tenantIds,
  126. storeId: queryParams.storeId,
  127. month: queryParams.month,
  128. keyword: queryParams.keyword,
  129. }
  130. try {
  131. const res = await materialStockSearchPage(params)
  132. tableData.value = res.list
  133. total.value = res.total
  134. } catch (error) {
  135. tableData.value = []
  136. total.value = 0
  137. } finally {
  138. loading.value = false
  139. }
  140. }
  141. onMounted(() => {
  142. getTableData()
  143. fetchWarehouseOptions()
  144. })
  145. const handleSearch = () => {
  146. queryParams.pageNo = 1
  147. getTableData()
  148. }
  149. const handleReset = () => {
  150. queryParams.storeId = ''
  151. queryParams.month = []
  152. queryParams.keyword = ''
  153. queryParams.pageNo = 1
  154. queryParams.tenantIds = userStore.orgTenantId
  155. queryParams.pageSize = 10
  156. getTableData()
  157. }
  158. const handleSizeChange = (size) => {
  159. queryParams.pageSize = size
  160. getTableData()
  161. }
  162. const handleCurrentChange = (page) => {
  163. queryParams.pageNo = page
  164. getTableData()
  165. }
  166. const handleView = async(row) => {
  167. const [startMonth] = queryParams.month || []
  168. if (!startMonth) {
  169. ElMessage.error('请选择月份')
  170. return
  171. }
  172. try {
  173. const res = await materialStockFlowDetail({
  174. inboundItemId: row.inboundItemId,
  175. month: startMonth,
  176. })
  177. currentStockDetail.value = res
  178. stockDialogVisible.value = true
  179. } catch (error) {
  180. ElMessage.error(error.message)
  181. }
  182. }
  183. const handleExport = async() => {
  184. try {
  185. // 导出的二次确认
  186. await message.exportConfirm()
  187. // 发起导出
  188. exportLoading.value = true
  189. const data = await materialStockSearchExport(queryParams)
  190. download.excel(data, '库存查询报表.xls')
  191. } catch {
  192. } finally {
  193. exportLoading.value = false
  194. }
  195. }
  196. </script>
  197. <style scoped>
  198. .mt-4 {
  199. margin-top: 16px;
  200. }
  201. .mb-4 {
  202. margin-bottom: 16px;
  203. }
  204. </style>