| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- <template>
- <div class="safety-platform-container">
- <div class="safety-platform-container__header">
- <div class="breadcrumb-title">物资盘点</div>
- </div>
- <div class="safety-platform-container__main">
- <div class="search-table-container">
- <header class="disaster-precaution__header">
- <BasicSearch
- :searchConfig="INVENTORY_LIST_SEARCH_CONFIG"
- :searchData="searchData"
- custom-reset
- @update:searchData="handleSearch"
- @custom-reset="handleReset"
- >
- <template #taskId>
- <el-select v-model="searchData.taskId" placeholder="请选择盘点任务" filterable @change="handleTaskChange">
- <el-option
- v-for="item in inventoryTaskOptions"
- :key="item.id"
- :label="item.taskName"
- :value="item.id"
- />
- </el-select>
- </template>
- <template #emergencyType>
- <el-select v-model="searchData.emergencyType" placeholder="请选择应急事件类型" filterable>
- <el-option
- v-for="item in emergencyEventDice"
- :key="item.itemCode"
- :label="item.itemValue"
- :value="item.itemCode"
- />
- </el-select>
- </template>
- <template #supplyType>
- <el-select v-model="searchData.supplyType" placeholder="请选择物资类型" filterable>
- <el-option
- v-for="item in emergencySupplyDice"
- :key="item.itemCode"
- :label="item.itemValue"
- :value="item.itemCode"
- />
- </el-select>
- </template>
- </BasicSearch>
- <div class="date-time-container" v-if="endTime">
- <span>任务期限:{{ endTime }}</span>
- <el-button type="primary" @click="handleConfirm" v-if="pagination.total && isInventory">盘点确认</el-button>
- </div>
- </header>
- <BasicTable
- :tableData="tableData"
- :tableConfig="tableConfig"
- @update:pageSize="handleSizeChange"
- @update:pageNumber="handleCurrentChange"
- >
- <template #emergencyType="scope">
- <span>{{ getEmergencyEvent(scope.row.emergencyType) }}</span>
- </template>
- <template #supplyType="scope">
- <span>{{ getEmergencySupply(scope.row.supplyType) }}</span>
- </template>
- <template #afterKeeperName="scope">
- <span :class="{ 'font-red': scope.row.afterKeeperName !== scope.row.beforeKeeperName }">
- {{ scope.row.afterKeeperName }}
- </span>
- </template>
- <template #afterQuantity="scope">
- <span :class="{ 'font-red': scope.row.afterQuantity !== scope.row.beforeQuantity }">
- {{ scope.row.afterQuantity }}
- </span>
- </template>
- <template #supplementQuantity="scope">
- <div v-if="scope.row.afterQuantity === null" />
- <div v-else>
- <span v-if="scope.row.supplementQuantity > 0">
- <span class="font-red">{{ scope.row.supplementQuantity }}</span>
- </span>
- <span v-else>
- <span>0</span>
- </span>
- </div>
- </template>
- <template #park="scope">
- <span>{{ getPark(scope.row.park) }}</span>
- </template>
- <template #beforeLocation="scope">
- <span>{{ getLocation(scope.row.beforeLocation) }}</span>
- </template>
- <template #afterLocation="scope">
- <span :class="{ 'font-red': scope.row.afterLocation !== scope.row.beforeLocation }">
- {{ getLocation(scope.row.afterLocation) }}
- </span>
- </template>
- <template #inventoryResult="scope">
- <span>{{ INVENTORY_RESULT_MAP[scope.row.inventoryResult] }}</span>
- </template>
- <template #remark="scope">
- <div class="remark--div">
- <el-tooltip
- :content="scope.row.remark"
- placement="top"
- effect="light"
- :popper-class="[
- 'custom-tooltip',
- scope.row.remark && scope.row.remark.length > 10 ? '' : 'custom-tooltip--opacity0',
- ]"
- >
- <span>{{ scope.row.remark }}</span>
- </el-tooltip>
- </div>
- </template>
- <template #imageList="scope">
- <div class="image-list" v-if="scope.row.imageList && JSON.parse(scope.row.imageList).length > 0">
- <el-image
- :src="PreviewIcon"
- :zoom-rate="1.2"
- :max-scale="7"
- :min-scale="0.2"
- :preview-src-list="JSON.parse(scope.row.imageList)"
- :initial-index="0"
- show-progress
- preview-teleported
- fit="cover"
- />
- </div>
- <span v-else>-</span>
- </template>
- </BasicTable>
- </div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, reactive, onMounted, watch, onBeforeUnmount } from 'vue';
- import { ElMessage } from 'element-plus';
- import BasicSearch from '@/components/BasicSearch.vue';
- import BasicTable from '@/components/BasicTable.vue';
- import {
- INVENTORY_LIST_SEARCH_CONFIG,
- INVENTORY_CHECK_TABLE_COLUMNS,
- INVENTORY_CHECK_TABLE_OPTIONS,
- INVENTORY_CHECK_TABLE_MAX_HEIGHT_PERMISSION,
- INVENTORY_CHECK_TABLE_MAX_HEIGHT_DEFAULT,
- } from './src/config';
- import useTableConfig from '@/hooks/useTableConfigHook';
- import { useEmergencyHook } from '../src/hoos';
- import { useEmergencySuppliesHook } from './src/hook';
- import { openMessageBox } from '@/utils/element-plus/messageBox';
- import type {
- InventoryCheckListQuery,
- InventoryCheckListResponse,
- InventoryTaskListRes,
- } from '@/types/emergency-supplier';
- import type { QueryPageRequest } from '@/types/basic-query';
- import {
- getInventoryTaskList,
- getInventoryCheckList,
- confirmInventoryTask,
- getInventoryTaskConfirm,
- } from '@/api/emergency-supplier';
- import { INVENTORY_RESULT_MAP } from './src/constant';
- import PreviewIcon from './src/svg/img-preview.svg';
- const { emergencyEventDice, getEmergencyEventDict, getEmergencyEvent } = useEmergencyHook();
- const {
- emergencySupplyDice,
- getEmergencySupplyDict,
- getEmergencySupply,
- getParkDict,
- getPark,
- getLocationDict,
- getLocation,
- } = useEmergencySuppliesHook();
- const { tableConfig, pagination } = useTableConfig(INVENTORY_CHECK_TABLE_COLUMNS, INVENTORY_CHECK_TABLE_OPTIONS);
- let inventoryCheckListQuery: QueryPageRequest<InventoryCheckListQuery> = {
- pageNumber: pagination.pageNumber,
- pageSize: pagination.pageSize,
- queryParam: {},
- };
- const tableData = ref<InventoryCheckListResponse[]>([]);
- const inventoryTaskOptions = ref<InventoryTaskListRes[]>([]);
- const endTime = ref<string>('');
- const isInventory = ref<boolean>(false);
- const searchData = reactive<InventoryCheckListQuery>({
- taskId: null,
- emergencyType: null,
- supplyType: null,
- supplyName: null,
- keeperName: null,
- inventoryResult: null,
- });
- // 定时器引用
- const pollTimer = ref<number | null>(null);
- const handleSearch = () => {
- inventoryCheckListQuery.queryParam = {};
- if (searchData.taskId) {
- inventoryCheckListQuery.queryParam.taskId = searchData.taskId;
- }
- if (searchData.emergencyType) {
- inventoryCheckListQuery.queryParam.emergencyType = searchData.emergencyType;
- }
- if (searchData.supplyType) {
- inventoryCheckListQuery.queryParam.supplyType = searchData.supplyType;
- }
- if (searchData.supplyName) {
- inventoryCheckListQuery.queryParam.supplyName = searchData.supplyName;
- }
- if (searchData.keeperName) {
- inventoryCheckListQuery.queryParam.keeperName = searchData.keeperName;
- }
- if (searchData.inventoryResult) {
- inventoryCheckListQuery.queryParam.inventoryResult = searchData.inventoryResult;
- }
- getTableData();
- };
- const getTableData = async () => {
- tableConfig.loading = true;
- const res = await getInventoryCheckList(inventoryCheckListQuery);
- tableData.value = res.records;
- pagination.total = res.totalRow;
- tableConfig.loading = false;
- };
- const handleSizeChange = (value: number) => {
- pagination.pageSize = value;
- inventoryCheckListQuery.pageSize = value;
- getTableData();
- };
- const handleCurrentChange = (value: number) => {
- pagination.pageNumber = value;
- inventoryCheckListQuery.pageNumber = value;
- getTableData();
- };
- const getFirstTaskInfo = async () => {
- const firstTask = inventoryTaskOptions.value[0];
- if (!firstTask) return;
- searchData.taskId = firstTask.id;
- endTime.value = firstTask.endTime;
- await checkTaskStatus();
- startPolling();
- };
- const getInventoryTaskOptions = async () => {
- inventoryTaskOptions.value = await getInventoryTaskList();
- await getFirstTaskInfo();
- handleSearch();
- };
- const handleTaskChange = async (id: number) => {
- await checkTaskStatus();
- startPolling();
- handleReset();
- const task = inventoryTaskOptions.value.find((item) => item.id === id);
- if (!task) return;
- endTime.value = task.endTime;
- };
- const handleReset = () => {
- for (const key in searchData) {
- if (key !== 'taskId') {
- searchData[key] = null;
- }
- }
- handleSearch();
- };
- // 检查任务状态
- const checkTaskStatus = async () => {
- if (!searchData.taskId) return;
- try {
- const res = await getInventoryTaskConfirm(searchData.taskId);
- isInventory.value = res.taskState === 2;
- } catch (error) {
- ElMessage.error(`获取任务状态失败:${error}`);
- }
- };
- // 开始轮询
- const startPolling = () => {
- // 清除之前的轮询
- if (pollTimer.value) {
- clearInterval(pollTimer.value);
- pollTimer.value = null;
- }
- // 如果有任务ID,开始轮询
- if (searchData.taskId) {
- // 设置1分钟轮询一次
- pollTimer.value = window.setInterval(checkTaskStatus, 30000);
- }
- };
- const handleConfirm = async () => {
- const confirmed = await openMessageBox('确认后将更新为盘点的数量和地点,是否确认盘点结果?', '盘点确认', 'warning');
- if (!confirmed) return;
- if (!searchData.taskId) return;
- await confirmInventoryTask(searchData.taskId);
- await checkTaskStatus();
- startPolling();
- ElMessage.success('盘点成功');
- };
- onMounted(() => {
- getInventoryTaskOptions();
- getEmergencyEventDict();
- getEmergencySupplyDict();
- getParkDict();
- getLocationDict('all');
- });
- // 组件销毁前清除定时器
- onBeforeUnmount(() => {
- if (pollTimer.value) {
- clearInterval(pollTimer.value);
- pollTimer.value = null;
- }
- });
- watch(
- () => endTime.value,
- () => {
- tableConfig.maxHeight = endTime.value
- ? INVENTORY_CHECK_TABLE_MAX_HEIGHT_PERMISSION
- : INVENTORY_CHECK_TABLE_MAX_HEIGHT_DEFAULT;
- },
- );
- </script>
- <style scoped lang="scss">
- @use '@/styles/page-details-layout.scss' as *;
- @use '@/styles/page-main-layout.scss' as *;
- @use './src/styles/page-common.scss' as *;
- .date-time-container {
- display: flex;
- align-items: center;
- gap: 20px;
- margin-top: 20px;
- span {
- font-size: 14px;
- color: $primary-color;
- }
- }
- .font-red {
- color: red;
- }
- .image-list {
- display: flex;
- justify-content: center;
- align-items: center;
- }
- </style>
|