123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635 |
- <template>
- <div class="quality-wrapper flex flex-col">
- <div class="search-wrapper">
- <BasicForm class="search-form" @register="registerForm">
- <template #ccmNo="{ model, field }">
- <segmented-select
- v-model:value="model[field]"
- @change="
- (v) => {
- ccmNo = v;
- getList();
- }
- "
- dict="lg_zj"
- />
- </template>
- <template #shiftObj>
- <div class="shift-performance-tags flex-1">
- <a-tag
- :color="shiftColor[index]"
- @click="
- () => {
- currentShift = index;
- getList();
- }
- "
- v-for="(item, index) in shiftPerformanceColumns"
- >
- {{ item.createTime ? item.createTime.substring(5, 16) : '' }} ~
- {{ item.changeShiftTime ? item.changeShiftTime.substring(5, 16) : '当前时间' }}
- 【{{ getTeamShift(item.shift, item.shiftGroup) }}】
- <span class="current-shift" :style="{ background: shiftColor[index] }" v-if="index === currentShift"></span>
- </a-tag>
- </div>
- </template>
- <template #advanceBefore>
- <div class="flex items-center">
- <a-button
- size="large"
- type="primary"
- @click="
- () => {
- switchMiopen = true;
- switchMiNum = 0;
- }
- "
- >
- 切换米重</a-button
- >
- <a-button
- style="margin-left: 10px"
- size="large"
- type="primary"
- @click="
- () =>
- shiftPerformanceColumns[currentShift] &&
- openPrintOriginalRecordsModal(true, {
- ccmNo: ccmNo,
- queryType: shiftPerformanceColumns[currentShift] && shiftPerformanceColumns[currentShift].changeShiftTime ? '2' : '1',
- shiftText: '',
- time:
- shiftPerformanceColumns[currentShift] && shiftPerformanceColumns[currentShift].changeShiftTime
- ? dayjs(shiftPerformanceColumns[currentShift].changeShiftTime).subtract(3, 'hour').format('YYYY-MM-DD HH:mm:ss')
- : '',
- curShiftInfo: {
- shift: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shift : '',
- shiftGroup: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].shiftGroup : '',
- },
- changeShiftId: shiftPerformanceColumns[currentShift] ? shiftPerformanceColumns[currentShift].id : '',
- })
- "
- >
- 原始记录</a-button
- >
- <a-button
- style="margin-left: 10px"
- size="large"
- type="primary"
- @click="
- () => {
- confirmedWithoutErrorOpen = true;
- }
- "
- >
- 确认无误</a-button
- >
- </div>
- </template>
- </BasicForm>
- </div>
- <BasicTable @register="registerTable">
- <template #tableTitle>
- <div class="flex table-title-info">
- <div class="table-title-info-item flex">
- <span class="line_b">{{ ccmNo }}</span>
- <span>#机</span>
- </div>
- <div class="table-title-info-item flex"><span>质检员</span><span class="line_b"></span></div>
- <div class="table-title-info-item flex flex-1 align-center justify-center">
- <span class="line_b">{{ getSelectedDate[0] }}</span>
- <span>年</span>
- <span class="line_b">{{ getSelectedDate[1] }}</span>
- <span>月</span>
- <span class="line_b">{{ getSelectedDate[2] }}</span>
- <span>日</span>
- <span class="line_b">{{
- shiftPerformanceColumns[currentShift]
- ? getTeamShift(shiftPerformanceColumns[currentShift].shift, shiftPerformanceColumns[currentShift].shiftGroup)
- : ''
- }}</span>
- </div>
- <div class="table-title-info-item flex"><span>zj/R19</span></div>
- </div>
- </template>
- <template #footer>
- <div class="flex footer-tj">
- <a-descriptions
- size="small"
- bordered
- class="remark"
- :labelStyle="labelStyle"
- :contentStyle="{
- padding: 0,
- }"
- >
- <a-descriptions-item label="备注:">
- <a-textarea :bordered="false" @blur="onTotalNoteBlur" v-model:value="statisticsInfo.remark" style="height: 116px" placeholder="备注" />
- </a-descriptions-item>
- </a-descriptions>
- <a-descriptions size="small" bordered class="produce" :labelStyle="labelStyle">
- <a-descriptions-item label="本班冶炼:"> {{ statisticsInfo.classHeatNum }} 炉</a-descriptions-item>
- <a-descriptions-item label="止上班日累计:">{{ statisticsInfo.dayStartHeatCount }} 炉</a-descriptions-item>
- <a-descriptions-item label="止本班日累计:"> {{ statisticsInfo.dayEndHeatCount }} 炉</a-descriptions-item>
- <a-descriptions-item label="本班冶炼:"> {{ statisticsInfo.classTotalWeight }} 吨</a-descriptions-item>
- <a-descriptions-item label="止上班日累计:">{{ statisticsInfo.dayStartWeight }} 吨</a-descriptions-item>
- <a-descriptions-item label="止本班日累计:">{{ statisticsInfo.dayEndWeight }} 吨</a-descriptions-item>
- <a-descriptions-item label="日冶炼:">{{ statisticsInfo.dayHeatCount }} 炉</a-descriptions-item>
- <a-descriptions-item label="日产:">{{ statisticsInfo.dayEndWeight }} 吨</a-descriptions-item>
- <a-descriptions-item> </a-descriptions-item>
- </a-descriptions>
- </div>
- </template>
- </BasicTable>
- </div>
- <!-- 打印原始数据 -->
- <printOriginalRecords @register="registerPrintOriginalRecordsModal" />
- <!-- 确认无误 -->
- <a-modal v-model:open="confirmedWithoutErrorOpen" title="确认信息" ok-text="确认" cancel-text="取消" @ok="onTotalNoteBlur(1)">
- <div style="margin: 20px">
- <a-textarea v-model:value="statisticsInfo.remark" placeholder="备注" :auto-size="{ minRows: 2, maxRows: 5 }" />
- </div>
- </a-modal>
- <!-- 编辑备注 -->
- <a-modal v-model:open="editNotesOpen" :title="'备注【' + editNotesRecord.heatNo + '】'" ok-text="确认" cancel-text="取消" @ok="editNotesSubmit">
- <div style="margin: 20px">
- <a-textarea v-model:value="editNotesTxt" placeholder="备注" :auto-size="{ minRows: 2, maxRows: 5 }" />
- </div>
- </a-modal>
- <!-- 切换米重 -->
- <a-modal v-model:open="switchMiopen" title="切换米重" ok-text="确认" cancel-text="取消" @ok="switchMiSubmit">
- <div style="margin: 20px">
- <a-input-number v-model:value="switchMiNum" placeholder="米重" :min="0" />
- </div>
- </a-modal>
- </template>
- <script setup lang="ts">
- import { computed, onMounted, ref } from 'vue';
- import { useForm, BasicForm } from '/@/components/Form';
- import SegmentedSelect from '/@/components/SegmentedSelect/index.vue';
- import { BasicTable } from '/@/components/Table';
- import dayjs, { Dayjs } from 'dayjs';
- import { useListPage } from '/@/hooks/system/useListPage';
- import { getFormSchemas, getTableColumns } from './quality.data';
- import { getTeamShift } from '../Dashboard/dashboard.api';
- import { list } from '../ShiftPerformance/ShiftPerformance.api';
- import { getQualityInspection, updateInfo, confirmRecordNote, changeMeterWeight } from './quality.api';
- import { useModal } from '/@/components/Modal';
- import printOriginalRecords from '../operator/components/printOriginalRecords.vue';
- import { useMessage } from '/@/hooks/web/useMessage';
- const { createMessage } = useMessage();
- // 注册打印原始记录modal
- const [registerPrintOriginalRecordsModal, { openModal: openPrintOriginalRecordsModal }] = useModal();
- const shiftPerformanceColumns = ref<any>([]);
- const shiftColor = ['#f50', '#2db7f5', '#87d068'];
- const currentShift = ref(-1);
- const ccmNo = ref('5');
- const labelStyle = {
- width: '100px',
- paddingRight: 0,
- paddingLeft: 0,
- textAlign: 'center',
- };
- /**
- * BasicForm绑定注册;
- */
- const [registerForm, { getFieldsValue }] = useForm({
- //注册表单列
- schemas: getFormSchemas({
- onDateChange: (v) => {
- currentShift.value = -1;
- getShiftInfo(3, dayjs(v));
- },
- }),
- //是否显示展开收起按钮,默认false
- showAdvancedButton: false,
- showResetButton: false,
- showSubmitButton: false,
- compact: true,
- //超过指定行数折叠,默认3行
- autoAdvancedCol: 3,
- //折叠时默认显示行数,默认1行
- alwaysShowLines: 3,
- //将表单内时间区域的值映射成 2个字段, 'YYYY-MM-DD'日期格式化
- fieldMapToTime: [
- ['arrivalTime', ['startTime', 'endTime'], 'YYYY-MM-DD HH:mm:ss'],
- // ['storageTime', ['storageTime_begin', 'storageTime_end'], 'YYYY-MM-DD HH:mm:ss'],
- ],
- //每列占比,默认一行为24
- baseColProps: { span: 6 },
- });
- // 获取日期
- const getSelectedDate = computed(() => {
- const formVals = getFieldsValue();
- if (formVals && formVals.queryDate) {
- return formVals.queryDate.split('-');
- }
- return dayjs().format('YYYY-MM-DD').split('-');
- });
- const columns = getTableColumns({
- onTimeChange(date, record) {
- editInfo({
- originalProductRecordId: record.originalProductRecordId,
- deliveryTime: date.format('YYYY-MM-DD HH:mm:ss'),
- });
- },
- onClickRemark(record) {
- editNotesOpen.value = true;
- editNotesTxt.value = record.notes;
- editNotesRecord.value = record;
- },
- onBrandNumChange(v, record) {
- editInfo({
- originalProductRecordId: record.originalProductRecordId,
- brandNum: v,
- });
- },
- });
- //注册table数据
- const { tableContext } = useListPage({
- tableProps: {
- columns,
- canResize: false,
- showActionColumn: false,
- useSearchForm: false,
- showTableSetting: false,
- striped: true,
- pagination: false,
- size: 'small',
- },
- });
- const [registerTable, { setLoading, setTableData, getColumns, setColumns }, {}] = tableContext;
- const getDefaulData = (total = 30) => {
- let data: any[] = [];
- for (let i = 0; i < total; i++) {
- data.push({
- heatNo: '',
- brandNum: '',
- deliveryTime: '',
- originalProductRecordId: '',
- lengthCountMap: {},
- });
- }
- return data;
- };
- const statisticsInfo = ref<any>({});
- const getList = async () => {
- try {
- setLoading(true);
- const res = await getQualityInspection({
- ccmNo: ccmNo.value,
- changeShiftId: shiftPerformanceColumns.value[currentShift.value].id,
- });
- const { records, statistics } = res;
- statisticsInfo.value = { ...statistics, orgRemark: statistics.remark };
- let sizeArr: string[] = [];
- records.forEach((item: any) => {
- if (item.lengthCountMap && typeof item.lengthCountMap === 'object') {
- sizeArr = sizeArr.concat(Object.keys(item.lengthCountMap));
- }
- });
- // 班产统计
- const workLength = JSON.parse(statistics.classLengthCountWeight ? statistics.classLengthCountWeight : '{}');
- const workLengthKeys = Object.keys(workLength);
- const workLengthArr: any[] = [];
- if (workLengthKeys.length) {
- workLengthKeys.forEach((item) => {
- const numW = workLength[item].split('/');
- workLengthArr.push({
- size: Number(item) / 1000 + 'm',
- num: numW[0],
- weight: numW[1],
- });
- });
- }
- // 日产统计
- const dayLength = JSON.parse(statistics.dayLengthCountWeight ? statistics.dayLengthCountWeight : '{}');
- const dayLengthKey: any[] = Object.keys(dayLength);
- const dayLengthArr: any[] = [];
- if (dayLengthKey.length) {
- dayLengthKey.forEach((item: any) => {
- const numW = dayLength[item].split('/');
- dayLengthArr.push({
- size: Number(item) / 1000 + 'm',
- num: numW[0],
- weight: numW[1],
- });
- });
- }
- let sizeArrChildren: any[] = [];
- [...new Set(sizeArr)].forEach((item) => {
- sizeArrChildren.push({
- title: item + 'm',
- dataIndex: ['lengthCountMap', item],
- width: 60,
- align: 'center',
- customRender({ text }) {
- return text || '';
- },
- });
- });
- const oldColumns = getColumns();
- const sizeColumnIndex = oldColumns.findIndex((item) => item.dataIndex === 'size');
- oldColumns[sizeColumnIndex].children = sizeArrChildren;
- // 设计表格
- const rowNums = records.length < 10 ? 10 : records.length;
- const datas = getDefaulData(rowNums + 3).map((item, index) => {
- return {
- ...item,
- ...(records[index] || {}),
- dayLength: dayLengthArr[index] || '',
- workLength: workLengthArr[index] || '',
- };
- });
- setColumns(oldColumns);
- setTableData(datas);
- setLoading(false);
- } catch (error) {
- console.log(error);
- setLoading(false);
- }
- };
- // 编辑信息
- const editInfo = async (params: any) => {
- try {
- setLoading(true);
- await updateInfo(params);
- getList();
- } catch (error) {
- console.log(error);
- setLoading(false);
- }
- };
- // 获取班次信息
- const getShiftInfo = async (pageSize: number = 3, date?: Dayjs) => {
- const formVals = getFieldsValue();
- try {
- if (date && !date.isValid()) {
- shiftPerformanceColumns.value = [];
- currentShift.value = -1;
- return false;
- }
- setLoading(true);
- const createTime_begin = date ? date.subtract(1, 'day').format('YYYY-MM-DD 23:55:00') : undefined;
- const createTime_end = date ? date.add(1, 'day').format('YYYY-MM-DD 00:05:00') : undefined;
- const res = await list({
- ccmNo: formVals.ccmNo || '5',
- pageNo: 1,
- pageSize: pageSize,
- column: 'createTime',
- order: 'asc',
- ...(date ? { createTime_begin, createTime_end } : {}),
- });
- const { records } = res;
- const arr = records || [];
- shiftPerformanceColumns.value = arr
- .filter((item) => item.createTime) // 过滤掉 createTime 为空的数据
- .sort((a, b) => {
- const dateA = new Date(a.createTime).getTime(); // 转换为时间戳
- const dateB = new Date(b.createTime).getTime(); // 转换为时间戳
- if (isNaN(dateA) || isNaN(dateB)) {
- console.warn('Invalid date detected:', a.createTime, b.createTime);
- return 0; // 如果日期无效,视为相等
- }
- return dateA - dateB; // 按时间戳排序
- });
- currentShift.value = shiftPerformanceColumns.value.length > 0 ? shiftPerformanceColumns.value.length - 1 : 0;
- // 获取列表
- getList();
- } catch (error) {
- console.error(error);
- setLoading(false);
- }
- };
- // 修改备注
- const editNotesOpen = ref(false);
- const editNotesTxt = ref('');
- const editNotesRecord = ref({
- heatNo: '',
- originalProductRecordId: undefined,
- });
- const editNotesSubmit = async () => {
- if (!editNotesTxt.value) {
- createMessage.error('请填写备注');
- return;
- }
- editInfo({
- originalProductRecordId: editNotesRecord.value.originalProductRecordId,
- notes: editNotesTxt.value,
- });
- editNotesOpen.value = false;
- };
- // 确认无误
- const confirmedWithoutErrorOpen = ref(false);
- // 编辑总备注
- const onTotalNoteBlur = async (t?) => {
- try {
- if (t !== 1 && statisticsInfo.value.orgRemark === statisticsInfo.value.remark) {
- return;
- }
- setLoading(true);
- await confirmRecordNote({
- id: statisticsInfo.value.id,
- remark: statisticsInfo.value.remark, // 备注
- });
- getList();
- confirmedWithoutErrorOpen.value = false;
- } catch (error) {
- setLoading(false);
- }
- };
- // 切换米重
- const switchMiopen = ref(false);
- const switchMiNum = ref(0);
- const switchMiSubmit = async () => {
- try {
- await changeMeterWeight({
- ccmNo: ccmNo.value,
- meterWeight: switchMiNum.value,
- });
- getList();
- switchMiopen.value = false;
- } catch (error) {
- console.log(error);
- }
- };
- onMounted(() => {
- getShiftInfo(3, dayjs('2025-07-07'));
- });
- </script>
- <style lang="less" scoped>
- .quality-wrapper {
- width: 100%;
- height: 100%;
- padding: 20px;
- overflow: hidden;
- background: var(--bg-s-color);
- .search-wrapper {
- margin-bottom: 10px;
- background-color: #005baf;
- padding: 20px 20px 0;
- border-radius: 4px;
- .search-form {
- :deep(.btnArea) {
- .ant-form-item-row {
- width: 100%;
- justify-content: flex-end;
- }
- }
- }
- :deep(.ant-form) {
- .ant-form-item .ant-form-item-label > label {
- color: #fff;
- }
- .ant-col-12 {
- width: 100%;
- .ant-form-item-row {
- .ant-form-item-control {
- flex: 1;
- max-width: 100%;
- }
- }
- }
- }
- .shift-performance-tags {
- margin-left: 10px;
- .ant-tag {
- padding: 6px 6px;
- position: relative;
- cursor: pointer;
- margin-bottom: 6px;
- font-size: 14px;
- }
- .current-shift {
- position: absolute;
- display: inline-block;
- width: 60px;
- height: 4px;
- border-radius: 4px;
- bottom: -8px;
- left: 50%;
- transform: translateX(-30px);
- }
- }
- }
- .table-title-info {
- width: 100%;
- font-size: 16px;
- font-weight: 600;
- line-height: 24px;
- .line_b {
- display: inline-block;
- min-width: 40px;
- height: 24px;
- text-align: center;
- border-bottom: 1px solid #ebeef5;
- padding: 0 10px;
- }
- .table-title-info-item {
- margin-right: 20px;
- }
- }
- .jeecg-basic-table {
- :deep(.ant-table-footer) {
- padding: 0;
- }
- :deep(.jeecg-basic-table-header__toolbar) {
- width: 0;
- }
- :deep(.ant-picker) {
- color: var(--fn-color);
- padding: 0;
- input {
- color: var(--fn-color);
- }
- }
- :deep(.ant-select) {
- .ant-select-selection-item {
- color: var(--fn-color);
- }
- }
- }
- .footer-tj {
- background: var(--bg-color);
- color: var(--fn-color);
- .remark {
- width: 400px;
- }
- .produce {
- flex: 1;
- }
- :deep(.ant-descriptions-item-label),
- :deep(.ant-input) {
- color: var(--fn-color);
- }
- :deep(.ant-descriptions-item-content),
- :deep(.ant-descriptions-item-label) {
- border-inline-end: 1px solid var(--fn-color);
- }
- :deep(.ant-descriptions-row) {
- border-bottom: 1px solid var(--fn-color);
- }
- }
- }
- </style>
|