perf: 1.优化储丝柜单柜卷包产量计算方式,支持未出料结束计算统计 2.新增储丝柜单柜卷包产量桑基图
| | |
| | | private Date shiftEndTime; |
| | | |
| | | /** |
| | | * è¯¥çæ¬¡å
计ç®åºç产é |
| | | * è¯¥çæ¬¡å
计ç®åºç产éï¼ä½ä¸ºè®°å½æ¶æ£æ°è¡¨ç¤ºå¢å ï¼è´æ°è¡¨ç¤ºåé¤ï¼ |
| | | */ |
| | | private Double output; |
| | | |
| | | /** |
| | | * æä½ç±»åæè¿°ï¼å¦ "çæ¬¡ç´¯è®¡", "æ£é¤å¤´é¨", "æ£é¤å°¾é¨"ï¼ |
| | | */ |
| | | private String calcType; |
| | | |
| | | /** |
| | | * å½ä¸æ°æ®çæ¶é´ç¹ï¼ç¨äºè¿½æº¯æ°æ®æ¥æºï¼ |
| | | */ |
| | | private Date hitTime; |
| | | } |
| | |
| | | private List<StoreSilkDetailVo> rollerDetailList; |
| | | |
| | | /** |
| | | * å
è£
æºäº§éæç» |
| | | * å
è£
æºäº§éæç»ï¼æç»ç»æï¼ |
| | | */ |
| | | private List<StoreSilkDetailVo> packerDetailList; |
| | | |
| | | /** |
| | | * å·æ¥æºæä½è¿ç¨è®°å½ï¼å¢åæç»ï¼ |
| | | */ |
| | | private List<StoreSilkDetailVo> rollerRecordList; |
| | | |
| | | /** |
| | | * å
è£
æºæä½è¿ç¨è®°å½ï¼å¢åæç»ï¼ |
| | | */ |
| | | private List<StoreSilkDetailVo> packerRecordList; |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.qa.analy.domain.StoreSilkInfo; |
| | | import org.springframework.stereotype.Service; |
| | | import org.dromara.qa.analy.domain.bo.FeedmatchTimeDataBo; |
| | | import org.dromara.qa.analy.domain.vo.FeedmatchTimeDataVo; |
| | |
| | | private LambdaQueryWrapper<FeedmatchTimeData> buildQueryWrapper(FeedmatchTimeDataBo bo) { |
| | | Map<String, Object> params = bo.getParams(); |
| | | LambdaQueryWrapper<FeedmatchTimeData> lqw = Wrappers.lambdaQuery(); |
| | | lqw.eq(bo.getTime() != null, FeedmatchTimeData::getTime, bo.getTime()); |
| | | lqw.eq(bo.getShift() != null, FeedmatchTimeData::getShift, bo.getShift()); |
| | | lqw.between(params.get("beginTime") != null && params.get("endTime") != null, |
| | | FeedmatchTimeData::getTime, params.get("beginTime"), params.get("endTime")); |
| | | lqw.eq(StringUtils.isNotBlank(bo.getKey()), FeedmatchTimeData::getKey, bo.getKey()); |
| | | return lqw; |
| | | } |
| | |
| | | // å·å
产éç»è®¡ |
| | | Double rollerOutput = 0.0; |
| | | Double packerOutput = 0.0; |
| | | // æç»å表 |
| | | // æç»å表ï¼ä»
åæç»æ£æ°ç»æï¼ |
| | | List<StoreSilkDetailVo> rollerDetailList = new ArrayList<>(); |
| | | List<StoreSilkDetailVo> packerDetailList = new ArrayList<>(); |
| | | // æä½è®°å½å表ï¼åææå¢åè¿ç¨ï¼ |
| | | List<StoreSilkDetailVo> rollerRecordList = new ArrayList<>(); |
| | | List<StoreSilkDetailVo> packerRecordList = new ArrayList<>(); |
| | | |
| | | for (int s = 0; s < distShiftList.size(); s++) { |
| | | MdShiftBo shiftBo = distShiftList.get(s); |
| | |
| | | // å
æç»è®¡ç»ææ¶å»ç´¯è®¡å¼å è¿æ¥ï¼current = Qty(calcEnd) |
| | | currentRollerOutput += rData.getQty(); |
| | | |
| | | // è®°å½è¿ç¨ï¼çæ¬¡æªæ¢ç´¯è®¡ |
| | | StoreSilkDetailVo endRecord = new StoreSilkDetailVo(); |
| | | endRecord.setFsNum(fsNum.substring(2, 3)); |
| | | endRecord.setSiloNum(containerNum); |
| | | endRecord.setPipeNum(channel); |
| | | endRecord.setEquNo(equNo); |
| | | endRecord.setShiftCode(shift); |
| | | endRecord.setShiftStartTime(calcStartDate); |
| | | endRecord.setShiftEndTime(calcEndDate); |
| | | endRecord.setOutput(rData.getQty()); |
| | | endRecord.setCalcType("çæ¬¡æªæ¢ç´¯è®¡"); |
| | | endRecord.setHitTime(rData.getTime()); |
| | | rollerRecordList.add(endRecord); |
| | | |
| | | // 2) æ£â头âï¼å¦æç»è®¡å¼å§æ¶å»æäºç次å¼å§ï¼ååå» Qty(calcStart) |
| | | if (calcStartDate.after(stimDate)) { |
| | | LocalDateTime calcStartLdt = LocalDateTime.ofInstant(calcStartDate.toInstant(), zone); |
| | |
| | | RollerTimeData rBeginData = rollerTimeDataMapper.selectOne(beginRlqw); |
| | | if (rBeginData != null) { |
| | | currentRollerOutput -= rBeginData.getQty(); |
| | | |
| | | // è®°å½è¿ç¨ï¼æ£é¤å¤´é¨äº§é |
| | | StoreSilkDetailVo beginRecord = new StoreSilkDetailVo(); |
| | | beginRecord.setFsNum(fsNum.substring(2, 3)); |
| | | beginRecord.setSiloNum(containerNum); |
| | | beginRecord.setPipeNum(channel); |
| | | beginRecord.setEquNo(equNo); |
| | | beginRecord.setShiftCode(shift); |
| | | beginRecord.setShiftStartTime(calcStartDate); |
| | | beginRecord.setShiftEndTime(calcEndDate); |
| | | beginRecord.setOutput(-rBeginData.getQty()); // è´æ°è¡¨ç¤ºæ£é¤ |
| | | beginRecord.setCalcType("æ£é¤åºæå累计"); |
| | | beginRecord.setHitTime(rBeginData.getTime()); |
| | | rollerRecordList.add(beginRecord); |
| | | } |
| | | } |
| | | } |
| | |
| | | // å
æç»è®¡ç»ææ¶å»ç´¯è®¡å¼å è¿æ¥ï¼current = Qty(calcEnd) |
| | | currentPackerOutput += pData.getTsQty(); |
| | | |
| | | // è®°å½è¿ç¨ï¼çæ¬¡æªæ¢ç´¯è®¡ |
| | | StoreSilkDetailVo endRecord = new StoreSilkDetailVo(); |
| | | endRecord.setFsNum(fsNum.substring(2, 3)); |
| | | endRecord.setSiloNum(containerNum); |
| | | endRecord.setPipeNum(channel); |
| | | endRecord.setEquNo(equNo); |
| | | endRecord.setShiftCode(shift); |
| | | endRecord.setShiftStartTime(calcStartDate); |
| | | endRecord.setShiftEndTime(calcEndDate); |
| | | endRecord.setOutput(pData.getTsQty()); |
| | | endRecord.setCalcType("çæ¬¡æªæ¢ç´¯è®¡"); |
| | | endRecord.setHitTime(pData.getTime()); |
| | | packerRecordList.add(endRecord); |
| | | |
| | | // 2) æ£â头âï¼å¦æç»è®¡å¼å§æ¶å»æäºç次å¼å§ï¼ååå» Qty(calcStart) |
| | | if (calcStartDate.after(stimDate)) { |
| | | LocalDateTime calcStartLdt = LocalDateTime.ofInstant(calcStartDate.toInstant(), zone); |
| | |
| | | PackerTimeData pBeginData = packerTimeDataMapper.selectOne(beginPlqw); |
| | | if (pBeginData != null) { |
| | | currentPackerOutput -= pBeginData.getTsQty(); |
| | | |
| | | // è®°å½è¿ç¨ï¼æ£é¤å¤´é¨äº§é |
| | | StoreSilkDetailVo beginRecord = new StoreSilkDetailVo(); |
| | | beginRecord.setFsNum(fsNum.substring(2, 3)); |
| | | beginRecord.setSiloNum(containerNum); |
| | | beginRecord.setPipeNum(channel); |
| | | beginRecord.setEquNo(equNo); |
| | | beginRecord.setShiftCode(shift); |
| | | beginRecord.setShiftStartTime(calcStartDate); |
| | | beginRecord.setShiftEndTime(calcEndDate); |
| | | beginRecord.setOutput(-pBeginData.getTsQty()); // è´æ°è¡¨ç¤ºæ£é¤ |
| | | beginRecord.setCalcType("æ£é¤åºæå累计"); |
| | | beginRecord.setHitTime(pBeginData.getTime()); |
| | | packerRecordList.add(beginRecord); |
| | | } |
| | | } |
| | | } |
| | |
| | | storeSilkInfoVo.setPackerOutput(packerOutput); |
| | | storeSilkInfoVo.setRollerDetailList(rollerDetailList); |
| | | storeSilkInfoVo.setPackerDetailList(packerDetailList); |
| | | storeSilkInfoVo.setRollerRecordList(rollerRecordList); |
| | | storeSilkInfoVo.setPackerRecordList(packerRecordList); |
| | | |
| | | } |
| | | |
| | |
| | | LambdaQueryWrapper<StoreSilkInfo> lqw = Wrappers.lambdaQuery(); |
| | | lqw.orderByAsc(StoreSilkInfo::getId); |
| | | lqw.like(StringUtils.isNotBlank(bo.getMaterialname()), StoreSilkInfo::getMaterialname, bo.getMaterialname()); |
| | | lqw.eq(StringUtils.isNotBlank(bo.getBatchcode()), StoreSilkInfo::getBatchcode, bo.getBatchcode()); |
| | | lqw.eq(bo.getActualstarttime() != null, StoreSilkInfo::getActualstarttime, bo.getActualstarttime()); |
| | | lqw.like(StringUtils.isNotBlank(bo.getBatchcode()), StoreSilkInfo::getBatchcode, bo.getBatchcode()); |
| | | if (bo.getActualstarttime() != null) { |
| | | ZoneId zone = ZoneId.systemDefault(); |
| | | LocalDate day = bo.getActualstarttime().toInstant().atZone(zone).toLocalDate(); |
| | | Date dayStart = Date.from(day.atStartOfDay(zone).toInstant()); |
| | | Date nextDayStart = Date.from(day.plusDays(1).atStartOfDay(zone).toInstant()); |
| | | lqw.ge(StoreSilkInfo::getActualstarttime, dayStart); |
| | | lqw.lt(StoreSilkInfo::getActualstarttime, nextDayStart); |
| | | } |
| | | lqw.eq(bo.getDistimebegin() != null, StoreSilkInfo::getDistimebegin, bo.getDistimebegin()); |
| | | lqw.eq(bo.getDistimeend() != null, StoreSilkInfo::getDistimeend, bo.getDistimeend()); |
| | | lqw.eq(StringUtils.isNotBlank(bo.getSiloid()), StoreSilkInfo::getSiloid, bo.getSiloid()); |
| | | if (StringUtils.isNotBlank(bo.getSiloid())) { |
| | | // æ¯æå¤ä¸ªæå·æ¥è¯¢ï¼ä»¥éå·åé |
| | | String[] siloids = bo.getSiloid().split(","); |
| | | lqw.and(wrapper -> { |
| | | for (String val : siloids) { |
| | | val = val.trim(); |
| | | if (StringUtils.isBlank(val)) { |
| | | continue; |
| | | } |
| | | String finalVal = val; |
| | | // ä½¿ç¨ OR è¿æ¥å¤ä¸ªæå·æ¡ä»¶ |
| | | wrapper.or(w -> { |
| | | try { |
| | | int num = Integer.parseInt(finalVal); |
| | | String padded = String.format("%02d", num); |
| | | // å¹é
_1 æ _01 (å
¼å®¹ä¸è¡¥é¶åè¡¥é¶çæ
åµ) |
| | | w.likeLeft(StoreSilkInfo::getSiloid, "_" + num) |
| | | .or() |
| | | .likeLeft(StoreSilkInfo::getSiloid, "_" + padded); |
| | | } catch (NumberFormatException e) { |
| | | // éæ°ååæåå¼å¹é
|
| | | w.eq(StoreSilkInfo::getSiloid, finalVal); |
| | | } |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | lqw.between(params.get("beginTime") != null && params.get("endTime") != null, |
| | | StoreSilkInfo::getDistimeend, params.get("beginTime"), params.get("endTime")); |
| | | return lqw; |
| | |
| | | #### 20260302 |
| | | - å¾
åäºé¡¹ |
| | | - [ ] ç®åå¨ä¸æä¿¡æ¯ä¿¡æ¯æ²¡æä»è§å¾ä¸è·åï¼ä½¿ç¨oracle_store_silk表模æ->使ç¨å¶ä¸è½¦é´çå®è§å¾æ°æ®æº |
| | | - [ ] å¶ä¸éæ§ï¼Oracle è§å¾ï¼ä¸æ²¡æåºæç»ææ¶é´ï¼ä»¥å宿¶é鿝å¦ä½è®¡ç® |
| | | - [ ] å䏿ºå¯¹åºå
³ç³»ï¼ç®åredisæ°æ®åºå½åè§è3.4æ4å·æºï¼å®é
è½¦é´æ²¡æ4å·æºï¼éå°ç°åºæ ¡éªå¯¹åºå
³ç³» |
| | | - [ ] å䏿ºå¯¹åºå
³ç³»ï¼fså¼å¤´å¨åççå®å¼æ¯ä»ä¹ï¼ç®åæµè¯æ°æ®ä½¿ç¨çæ¯ fs11 -> å¨ä¸æå· |
| | | - [ ] 确认1å°å䏿ºå¯¹åºç2å°å¨ä¸ææ¯ä¾æ¬¡ä¾ä¸è¿æ¯å¯ä»¥å¹¶è¡ä¾ä¸(<span style="color: red;">***å¹¶è¡ä¾ä¸æ æ³å确计ç®äº§é***</span>) |
| | | - [ ] 确认 å䏿ºå¯¹åºå
³ç³»ä¸(key->pipe01 value->1#æºç»å¯¹åºçå䏿ºå管é)valueä¸ä¼éå¤ (<span style="color: red;">***éå¤å°å¯¼è´è®¡ç®é»è¾åºç°é误***</span>) |
| | |
| | | import { computed, effectScope, nextTick, onScopeDispose, shallowRef, watch } from 'vue'; |
| | | import { useElementSize } from '@vueuse/core'; |
| | | import * as echarts from 'echarts/core'; |
| | | import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts'; |
| | | import { |
| | | BarChart, |
| | | GaugeChart, |
| | | LineChart, |
| | | PictorialBarChart, |
| | | PieChart, |
| | | RadarChart, |
| | | SankeyChart, |
| | | ScatterChart |
| | | } from 'echarts/charts'; |
| | | import type { |
| | | BarSeriesOption, |
| | | GaugeSeriesOption, |
| | |
| | | PictorialBarSeriesOption, |
| | | PieSeriesOption, |
| | | RadarSeriesOption, |
| | | SankeySeriesOption, |
| | | ScatterSeriesOption |
| | | } from 'echarts/charts'; |
| | | import { |
| | |
| | | | PictorialBarSeriesOption |
| | | | RadarSeriesOption |
| | | | GaugeSeriesOption |
| | | | SankeySeriesOption |
| | | | TitleComponentOption |
| | | | LegendComponentOption |
| | | | TooltipComponentOption |
| | |
| | | PictorialBarChart, |
| | | RadarChart, |
| | | GaugeChart, |
| | | SankeyChart, |
| | | LabelLayout, |
| | | UniversalTransition, |
| | | CanvasRenderer |
| | |
| | | monitor_online: () => import("@/views/monitor/online/index.vue"), |
| | | monitor_operlog: () => import("@/views/monitor/operlog/index.vue"), |
| | | qm_batch: () => import("@/views/qm/batch/index.vue"), |
| | | qm_std: () => import("@/views/qm/std/index.vue"), |
| | | system_client: () => import("@/views/system/client/index.vue"), |
| | | system_config: () => import("@/views/system/config/index.vue"), |
| | | system_dept: () => import("@/views/system/dept/index.vue"), |
| | |
| | | title: 'qm_batch', |
| | | i18nKey: 'route.qm_batch' |
| | | } |
| | | }, |
| | | { |
| | | name: 'qm_std', |
| | | path: '/qm/std', |
| | | component: 'view.qm_std', |
| | | meta: { |
| | | title: 'qm_std', |
| | | i18nKey: 'route.qm_std' |
| | | } |
| | | } |
| | | ] |
| | | }, |
| | |
| | | "monitor_operlog": "/monitor/operlog", |
| | | "qm": "/qm", |
| | | "qm_batch": "/qm/batch", |
| | | "qm_std": "/qm/std", |
| | | "social-callback": "/social-callback", |
| | | "system": "/system", |
| | | "system_client": "/system/client", |
| | |
| | | |
| | | /** feed match search params */ |
| | | type FeedMatchSearchParams = CommonType.RecordNullable< |
| | | Pick<Api.Analy.FeedMatch, 'time' | 'key'> & Api.Common.CommonSearchParams |
| | | Pick<Api.Analy.FeedMatch, 'time' | 'key' | 'shift'> & Api.Common.CommonSearchParams |
| | | >; |
| | | |
| | | /** feed match operate params */ |
| | |
| | | "monitor_operlog": "/monitor/operlog"; |
| | | "qm": "/qm"; |
| | | "qm_batch": "/qm/batch"; |
| | | "qm_std": "/qm/std"; |
| | | "social-callback": "/social-callback"; |
| | | "system": "/system"; |
| | | "system_client": "/system/client"; |
| | |
| | | | "monitor_online" |
| | | | "monitor_operlog" |
| | | | "qm_batch" |
| | | | "qm_std" |
| | | | "system_client" |
| | | | "system_config" |
| | | | "system_dept" |
| | |
| | | pageSize: 10, |
| | | time: null, |
| | | key: null, |
| | | shift: null, |
| | | params: {} |
| | | }); |
| | | |
| | |
| | | <script setup lang="ts"> |
| | | import { toRaw } from 'vue'; |
| | | import { ref, toRaw } from 'vue'; |
| | | import { jsonClone } from '@sa/utils'; |
| | | import { useNaiveForm } from '@/hooks/common/form'; |
| | | import { $t } from '@/locales'; |
| | |
| | | const defaultModel = jsonClone(toRaw(model.value)); |
| | | |
| | | function resetModel() { |
| | | timeRange.value = null; |
| | | Object.assign(model.value, defaultModel); |
| | | } |
| | | |
| | | const timeRange = ref<[string, string] | null>(null); |
| | | |
| | | function onTimeRangeUpdate(value: [string, string] | null) { |
| | | const params = (model.value.params ||= {}); |
| | | const beginTime = value?.[0] ? String(value[0]).trim() : ''; |
| | | const endTime = value?.[1] ? String(value[1]).trim() : ''; |
| | | if (beginTime && endTime) { |
| | | params.beginTime = beginTime; |
| | | params.endTime = endTime; |
| | | } else { |
| | | delete params.beginTime; |
| | | delete params.endTime; |
| | | } |
| | | } |
| | | |
| | | const shiftOptions = [ |
| | | { label: 'æ©ç', value: 1 }, |
| | | { label: 'ä¸ç', value: 2 }, |
| | | { label: 'æç', value: 3 } |
| | | ]; |
| | | |
| | | async function reset() { |
| | | await restoreValidation(); |
| | |
| | | <NCollapseItem :title="$t('common.search')" name="analy-feed-match-search"> |
| | | <NForm ref="formRef" :model="model" label-placement="left" :label-width="80"> |
| | | <NGrid responsive="screen" item-responsive> |
| | | <NFormItemGi span="24 s:12 m:6" label="æ¶é´æ³" label-width="auto" path="time" class="pr-24px"> |
| | | <NFormItemGi span="24 s:12 m:8 l:8 xl:8" label="æ¶é´åºé´" label-width="auto" path="params.beginTime" class="pr-24px"> |
| | | <NDatePicker |
| | | v-model:formatted-value="model.time" |
| | | type="datetime" |
| | | v-model:formatted-value="timeRange" |
| | | type="datetimerange" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | clearable |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | @update:formatted-value="onTimeRangeUpdate" |
| | | /> |
| | | </NFormItemGi> |
| | | <NFormItemGi span="24 s:12 m:6" label="çæ¬¡+æºå°" label-width="auto" path="key" class="pr-24px"> |
| | | <NInput v-model:value="model.key" placeholder="请è¾å
¥ç次+æºå°" /> |
| | | <NFormItemGi span="24 s:12 m:8 l:8 xl:8" label="çæ¬¡" label-width="auto" path="shift" class="pr-24px"> |
| | | <NSelect v-model:value="model.shift" placeholder="è¯·éæ©çæ¬¡" :options="shiftOptions" clearable /> |
| | | </NFormItemGi> |
| | | <NFormItemGi :show-feedback="false" span="24" class="pr-24px"> |
| | | <NFormItemGi :show-feedback="false" span="24 s:12 m:8 l:8 xl:8" class="pr-24px"> |
| | | <NSpace class="w-full" justify="end"> |
| | | <NButton @click="reset"> |
| | | <template #icon> |
| | |
| | | <script setup lang="tsx"> |
| | | import { ref } from 'vue'; |
| | | import { computed, ref } from 'vue'; |
| | | import { NDivider } from 'naive-ui'; |
| | | import { fetchBatchDeleteStoreSilk, fetchGetStoreSilkList } from '@/service/api/analy/store-silk'; |
| | | import { useAppStore } from '@/store/modules/app'; |
| | |
| | | import StoreSilkOperateDrawer from './modules/store-silk-operate-drawer.vue'; |
| | | import StoreSilkSearch from './modules/store-silk-search.vue'; |
| | | import StoreSilkDetail from './modules/store-silk-detail.vue'; |
| | | import StoreSilkSankey from './modules/store-silk-sankey.vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'StoreSilkList' |
| | |
| | | const { download } = useDownload(); |
| | | const { hasAuth } = useAuth(); |
| | | |
| | | |
| | | |
| | | const selectedRollerDetailList = ref<any[]>([]); |
| | | const selectedPackerDetailList = ref<any[]>([]); |
| | | |
| | | // æ¡åºå¾start |
| | | const showSankey = ref(false); |
| | | const rollerRecordList = ref<any[]>([]); |
| | | const packerRecordList = ref<any[]>([]); |
| | | // æ¡åºå¾end |
| | | |
| | | const sankeyRollerBoxList = computed(() => { |
| | | return (rollerRecordList.value || []).map(item => { |
| | | const v = calcRollerBox((item as any).output); |
| | | const output = v === null ? null : Number(v.toFixed(2)); |
| | | return { ...(item as any), output }; |
| | | }); |
| | | }); |
| | | |
| | | const sankeyPackerBoxList = computed(() => { |
| | | return (packerRecordList.value || []).map(item => { |
| | | const v = calcPackerBox((item as any).output); |
| | | const output = v === null ? null : Number(v.toFixed(2)); |
| | | return { ...(item as any), output }; |
| | | }); |
| | | }); |
| | | |
| | | const searchParams = ref<Api.Analy.StoreSilkSearchParams>({ |
| | | pageNum: 1, |
| | |
| | | } |
| | | |
| | | const { columns, columnChecks, data, getData, getDataByPage, loading, mobilePagination, scrollX } = |
| | | useNaivePaginatedTable({ |
| | | useNaivePaginatedTable<any, any>({ |
| | | api: () => fetchGetStoreSilkList(searchParams.value), |
| | | transform: response => defaultTransform(response), |
| | | transform: response => { |
| | | const respData = (response as any).data; |
| | | const error = (response as any).error; |
| | | |
| | | if (!error) { |
| | | const rows = Array.isArray(respData?.rows) ? respData.rows : []; |
| | | const apiRollerRecordList = respData?.rollerRecordList; |
| | | const apiPackerRecordList = respData?.packerRecordList; |
| | | |
| | | rollerRecordList.value = |
| | | Array.isArray(apiRollerRecordList) && apiRollerRecordList.length > 0 |
| | | ? apiRollerRecordList |
| | | : rows.flatMap((r: any) => (Array.isArray(r?.rollerDetailList) ? r.rollerDetailList : [])); |
| | | |
| | | packerRecordList.value = |
| | | Array.isArray(apiPackerRecordList) && apiPackerRecordList.length > 0 |
| | | ? apiPackerRecordList |
| | | : rows.flatMap((r: any) => (Array.isArray(r?.packerDetailList) ? r.packerDetailList : [])); |
| | | } else { |
| | | rollerRecordList.value = []; |
| | | packerRecordList.value = []; |
| | | } |
| | | |
| | | return defaultTransform(response as any); |
| | | }, |
| | | onPaginationParamsChange: params => { |
| | | searchParams.value.pageNum = params.page; |
| | | searchParams.value.pageSize = params.pageSize; |
| | |
| | | key: 'materialname', |
| | | title: 'çå·', |
| | | align: 'center', |
| | | minWidth: 120 |
| | | minWidth: 96 |
| | | }, |
| | | { |
| | | key: 'batchcode', |
| | | title: 'æ¹æ¬¡å·', |
| | | align: 'center', |
| | | minWidth: 130 |
| | | minWidth: 110 |
| | | }, |
| | | { |
| | | key: 'rollerOutput', |
| | | title: 'å·æ¥äº§é(ç®±)', |
| | | align: 'center', |
| | | minWidth: 120, |
| | | minWidth: 112, |
| | | render: row => { |
| | | const v = calcRollerBox((row as any).rollerOutput); |
| | | if (v === null) return '-'; |
| | |
| | | } |
| | | }, |
| | | { |
| | | key: 'rollerUnitCost', |
| | | title: 'å·æ¥åè', |
| | | align: 'center', |
| | | minWidth: 96, |
| | | render: row => { |
| | | const box = calcRollerBox((row as any).rollerOutput); |
| | | if (box === null || box <= 0) return '-'; |
| | | const jobinput = Number((row as any).jobinput); |
| | | const weight = Number((row as any).weight); |
| | | const diff = jobinput - weight; |
| | | if (!Number.isFinite(diff)) return '-'; |
| | | const val = diff / box; |
| | | if (!Number.isFinite(val)) return '-'; |
| | | return val.toFixed(2); |
| | | } |
| | | }, |
| | | { |
| | | key: 'packerOutput', |
| | | title: 'å
è£
产é(ç®±)', |
| | | align: 'center', |
| | | minWidth: 120, |
| | | minWidth: 112, |
| | | render: row => { |
| | | const v = calcPackerBox((row as any).packerOutput); |
| | | if (v === null) return '-'; |
| | |
| | | } |
| | | }, |
| | | { |
| | | key: 'packerUnitCost', |
| | | title: 'å
è£
åè', |
| | | align: 'center', |
| | | minWidth: 96, |
| | | render: row => { |
| | | const box = calcPackerBox((row as any).packerOutput); |
| | | if (box === null || box <= 0) return '-'; |
| | | const jobinput = Number((row as any).jobinput); |
| | | const weight = Number((row as any).weight); |
| | | const diff = jobinput - weight; |
| | | if (!Number.isFinite(diff)) return '-'; |
| | | const val = diff / box; |
| | | if (!Number.isFinite(val)) return '-'; |
| | | return val.toFixed(2); |
| | | } |
| | | }, |
| | | { |
| | | key: 'actualstarttime', |
| | | title: 'æææ¥æ', |
| | | align: 'center', |
| | | width: 180 |
| | | width: 160 |
| | | }, |
| | | { |
| | | key: 'jobinput', |
| | | title: 'ææéé', |
| | | align: 'center', |
| | | minWidth: 120 |
| | | minWidth: 96 |
| | | }, |
| | | { |
| | | key: 'weight', |
| | | title: 'å¨ä¸æéé', |
| | | align: 'center', |
| | | minWidth: 120 |
| | | minWidth: 96 |
| | | }, |
| | | { |
| | | key: 'distimebegin', |
| | | title: 'å¨ä¸æåºæå¼å§æ¶é´', |
| | | align: 'center', |
| | | width: 180 |
| | | width: 160 |
| | | }, |
| | | { |
| | | key: 'distimeend', |
| | | title: 'å¨ä¸æåºæç»ææ¶é´', |
| | | align: 'center', |
| | | width: 180 |
| | | width: 160 |
| | | }, |
| | | { |
| | | key: 'siloid', |
| | | title: 'æåå·(æ«ä½)', |
| | | align: 'center', |
| | | width: 160 |
| | | width: 120 |
| | | } |
| | | ] |
| | | }); |
| | | |
| | | const { drawerVisible, operateType, editingData, handleAdd, handleEdit, checkedRowKeys, onBatchDeleted, onDeleted } = |
| | | useTableOperate(data, 'id', getData); |
| | | useTableOperate<any>(data, 'id', getData); |
| | | |
| | | async function handleBatchDelete() { |
| | | // request |
| | |
| | | :loading="loading" |
| | | :show-add="false" |
| | | :show-delete="false" |
| | | :show-export="hasAuth('analy:storeSilk:export')" |
| | | :show-export="!showSankey && hasAuth('analy:storeSilk:export')" |
| | | @add="handleAdd" |
| | | @delete="handleBatchDelete" |
| | | @export="handleExport" |
| | | @refresh="getData" |
| | | > |
| | | <template #prefix> |
| | | <NButton |
| | | size="small" |
| | | ghost |
| | | :type="showSankey ? 'primary' : 'default'" |
| | | @click="showSankey = !showSankey" |
| | | > |
| | | {{ showSankey ? 'å表' : 'æ¡åºå¾' }} |
| | | </NButton> |
| | | </template> |
| | | <template #suffix> |
| | | <NPopover placement="bottom-end" trigger="click"> |
| | | <template #trigger> |
| | |
| | | </template> |
| | | </TableHeaderOperation> |
| | | </template> |
| | | <StoreSilkSankey |
| | | v-if="showSankey" |
| | | :roller-record-list="sankeyRollerBoxList" |
| | | :packer-record-list="sankeyPackerBoxList" |
| | | :rows="data" |
| | | class="h-full" |
| | | /> |
| | | <NDataTable |
| | | :columns="columns" |
| | | v-else |
| | | :columns="columns as any" |
| | | :data="data" |
| | | :size="tableSize" |
| | | :flex-height="!appStore.isMobile" |
| | |
| | | /> |
| | | </NCard> |
| | | <StoreSilkDetail |
| | | v-if="!showSankey" |
| | | :roller-detail-list="selectedRollerDetailList" |
| | | :packer-detail-list="selectedPackerDetailList" |
| | | class="h-[192px] overflow-hidden" |
| | |
| | | <style scoped> |
| | | :deep(.n-data-table-th), |
| | | :deep(.n-data-table-td) { |
| | | padding-top: 4px; |
| | | padding-bottom: 4px; |
| | | padding: 4px 6px; |
| | | } |
| | | </style> |
| | |
| | | key: 'index', |
| | | title: $t('common.index'), |
| | | align: 'center', |
| | | width: 64, |
| | | width: 56, |
| | | render: (_: any, index: number) => index + 1 |
| | | }, |
| | | { |
| | | key: 'fsNum', |
| | | title: 'å䏿ºå·', |
| | | align: 'center', |
| | | width: 100 |
| | | width: 84 |
| | | }, |
| | | { |
| | | key: 'siloNum', |
| | | title: 'å¨ä¸æå·', |
| | | align: 'center', |
| | | width: 100 |
| | | width: 84 |
| | | }, |
| | | { |
| | | key: 'pipeNum', |
| | | title: '管éå·', |
| | | align: 'center', |
| | | width: 100 |
| | | width: 84 |
| | | }, |
| | | { |
| | | key: 'equNo', |
| | | title: 'æºå°å·', |
| | | align: 'center', |
| | | width: 100 |
| | | width: 72 |
| | | }, |
| | | { |
| | | key: 'shiftCode', |
| | | title: 'çæ¬¡ä»£ç ', |
| | | align: 'center', |
| | | width: 100, |
| | | width: 88, |
| | | render: (row: StoreSilkDetailVo) => { |
| | | const map: Record<string, string> = { |
| | | '1': 'æ©ç', |
| | |
| | | key: 'shiftStartTime', |
| | | title: 'çæ¬¡å¼å§æ¶é´', |
| | | align: 'center', |
| | | width: 160 |
| | | width: 148 |
| | | }, |
| | | { |
| | | key: 'shiftEndTime', |
| | | title: 'çæ¬¡ç»ææ¶é´', |
| | | align: 'center', |
| | | width: 160 |
| | | width: 148 |
| | | }, |
| | | { |
| | | key: 'output', |
| | | title: '产é(忝)', |
| | | align: 'center', |
| | | width: 120, |
| | | width: 96, |
| | | render: (row: StoreSilkDetailVo) => { |
| | | if (row.output === null || row.output === undefined) return '-'; |
| | | const v = Number(row.output); |
| | |
| | | key: 'outputBox', |
| | | title: '产é(ç®±)', |
| | | align: 'center', |
| | | width: 100, |
| | | width: 84, |
| | | render: (row: StoreSilkDetailVo) => { |
| | | const v = detailType.value === 'roller' ? calcRollerBox(row.output) : calcPackerBox(row.output); |
| | | if (v === null) return '-'; |
| | |
| | | :deep(.n-card__content) { |
| | | padding: 8px 12px; |
| | | } |
| | | |
| | | :deep(.n-data-table-th), |
| | | :deep(.n-data-table-td) { |
| | | padding: 4px 6px; |
| | | } |
| | | </style> |
| | |
| | | |
| | | const dateRange = ref<[string, string] | null>(null); |
| | | |
| | | onMounted(() => { |
| | | if (model.value.params?.beginTime && model.value.params?.endTime) { |
| | | dateRange.value = [model.value.params.beginTime as string, model.value.params.endTime as string]; |
| | | function onDateRangeUpdate(value: [string, string] | null) { |
| | | if (!model.value.params) { |
| | | model.value.params = {}; |
| | | } |
| | | |
| | | const beginTime = value?.[0] ? String(value[0]).trim() : ''; |
| | | const endTime = value?.[1] ? String(value[1]).trim() : ''; |
| | | |
| | | if (beginTime && endTime) { |
| | | model.value.params.beginTime = beginTime; |
| | | model.value.params.endTime = endTime; |
| | | } else { |
| | | dateRange.value = getDefaultRange(); |
| | | if (!model.value.params) { |
| | | model.value.params = {}; |
| | | } |
| | | model.value.params.beginTime = dateRange.value[0]; |
| | | model.value.params.endTime = dateRange.value[1]; |
| | | delete model.value.params.beginTime; |
| | | delete model.value.params.endTime; |
| | | } |
| | | } |
| | | |
| | | function setDefaultRange() { |
| | | const range = getDefaultRange(); |
| | | dateRange.value = range; |
| | | onDateRangeUpdate(range); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | if (!model.value.params) { |
| | | model.value.params = {}; |
| | | } |
| | | |
| | | const beginTime = model.value.params.beginTime ? String(model.value.params.beginTime).trim() : ''; |
| | | const endTime = model.value.params.endTime ? String(model.value.params.endTime).trim() : ''; |
| | | |
| | | if (beginTime && endTime) { |
| | | dateRange.value = [beginTime, endTime]; |
| | | } else { |
| | | setDefaultRange(); |
| | | } |
| | | }); |
| | | |
| | | watch( |
| | | dateRange, |
| | | val => { |
| | | if (!model.value.params) { |
| | | model.value.params = {}; |
| | | } |
| | | if (val && val[0] && val[1]) { |
| | | model.value.params.beginTime = val[0]; |
| | | model.value.params.endTime = val[1]; |
| | | } else { |
| | | model.value.params.beginTime = null; |
| | | model.value.params.endTime = null; |
| | | } |
| | | }, |
| | | { deep: true } |
| | | ); |
| | | |
| | | async function reset() { |
| | | await restoreValidation(); |
| | | resetModel(); |
| | | dateRange.value = getDefaultRange(); |
| | | if (!model.value.params) { |
| | | model.value.params = {}; |
| | | } |
| | | model.value.params.beginTime = dateRange.value[0]; |
| | | model.value.params.endTime = dateRange.value[1]; |
| | | setDefaultRange(); |
| | | emit('search'); |
| | | } |
| | | |
| | | async function search() { |
| | | await validate(); |
| | | emit('search'); |
| | | } |
| | | |
| | | const siloOptions = Array.from({ length: 12 }, (_, i) => ({ |
| | | label: `${i + 1}å·å¨ä¸æ`, |
| | | value: String(i + 1) |
| | | })); |
| | | |
| | | const selectedSilos = ref<string[]>([]); |
| | | |
| | | watch( |
| | | () => model.value.siloid, |
| | | val => { |
| | | if (val) { |
| | | selectedSilos.value = (val as string).split(','); |
| | | } else { |
| | | selectedSilos.value = []; |
| | | } |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | function handleSiloChange(val: string[]) { |
| | | selectedSilos.value = val; |
| | | model.value.siloid = val.join(','); |
| | | } |
| | | </script> |
| | | |
| | |
| | | path="materialname" |
| | | class="pr-24px" |
| | | > |
| | | <NInput v-model:value="model.materialname" placeholder="请è¾å
¥çå·" /> |
| | | <NInput v-model:value="model.materialname" clearable placeholder="请è¾å
¥çå·" /> |
| | | </NFormItemGi> |
| | | <NFormItemGi span="24 s:12 m:8 l:8 xl:8" label="æ¹æ¬¡å·" label-width="auto" path="batchcode" class="pr-24px"> |
| | | <NInput v-model:value="model.batchcode" placeholder="请è¾å
¥æ¹æ¬¡å·" /> |
| | | <NInput v-model:value="model.batchcode" clearable placeholder="请è¾å
¥æ¹æ¬¡å·" /> |
| | | </NFormItemGi> |
| | | <NFormItemGi |
| | | span="24 s:12 m:8 l:8 xl:8" |
| | |
| | | > |
| | | <NDatePicker |
| | | v-model:formatted-value="model.actualstarttime" |
| | | type="datetime" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | type="date" |
| | | value-format="yyyy-MM-dd" |
| | | clearable |
| | | class="w-full" |
| | | /> |
| | | </NFormItemGi> |
| | | <NFormItemGi |
| | |
| | | :default-time="['00:00:00', '23:59:59']" |
| | | value-format="yyyy-MM-dd HH:mm:ss" |
| | | clearable |
| | | class="w-full" |
| | | @update:formatted-value="onDateRangeUpdate" |
| | | /> |
| | | </NFormItemGi> |
| | | <NFormItemGi |
| | |
| | | path="siloid" |
| | | class="pr-24px" |
| | | > |
| | | <NInput v-model:value="model.siloid" placeholder="请è¾å
¥æåå·(æ«ä½)" /> |
| | | <NSelect |
| | | v-model:value="selectedSilos" |
| | | multiple |
| | | clearable |
| | | :options="siloOptions" |
| | | placeholder="è¯·éæ©æåå·" |
| | | @update:value="handleSiloChange" |
| | | /> |
| | | </NFormItemGi> |
| | | <NFormItemGi :show-feedback="false" span="24" class="pr-24px"> |
| | | <NSpace class="w-full" justify="end"> |