From 295bdcf5c1c434604d35bdb592660284870014d7 Mon Sep 17 00:00:00 2001
From: zhuguifei <312353457@qq.com>
Date: 星期三, 18 三月 2026 13:36:58 +0800
Subject: [PATCH] feat: 1.新增判定规程明细项目维护 2.新增储丝单柜产量报表 3.新增exceljs、dompdf等文件导出工具 4.修改启动loading、icon、fav
---
ruoyi-plus-soybean/src/views/qm/std/modules/std-sub-table.vue | 279 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 268 insertions(+), 11 deletions(-)
diff --git a/ruoyi-plus-soybean/src/views/qm/std/modules/std-sub-table.vue b/ruoyi-plus-soybean/src/views/qm/std/modules/std-sub-table.vue
old mode 100644
new mode 100755
index 301a5c2..8aad960
--- a/ruoyi-plus-soybean/src/views/qm/std/modules/std-sub-table.vue
+++ b/ruoyi-plus-soybean/src/views/qm/std/modules/std-sub-table.vue
@@ -1,9 +1,14 @@
<script setup lang="tsx">
-import { computed, ref, watch } from 'vue';
-import { useLoading } from '@sa/hooks';
-import { $t } from '@/locales';
-import { fetchGetCheckitemTree } from '@/service/api/qm/checkitem';
+import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue';
import type { DataTableColumns, DataTableRowKey } from 'naive-ui';
+import { NDivider } from 'naive-ui';
+import { useLoading } from '@sa/hooks';
+import { jsonClone } from '@sa/utils';
+import { fetchBatchDeleteCheckitem, fetchGetCheckitemTree } from '@/service/api/qm/checkitem';
+import { useAuth } from '@/hooks/business/auth';
+import { $t } from '@/locales';
+import ButtonIcon from '@/components/custom/button-icon.vue';
+import CheckitemOperateDrawer from '@/views/qm/checkitem/modules/checkitem-operate-drawer.vue';
defineOptions({
name: 'StdSubTable'
@@ -11,10 +16,12 @@
interface Props {
stdId?: CommonType.IdType | null;
+ stdCode?: string | '';
}
const props = withDefaults(defineProps<Props>(), {
- stdId: null
+ stdId: null,
+ stdCode: ''
});
interface StdSubRow extends Api.Qm.Checkitem {
@@ -22,10 +29,24 @@
}
const { loading, startLoading, endLoading } = useLoading();
+const { hasAuth } = useAuth();
const rows = ref<StdSubRow[]>([]);
+const checkedRowKeys = ref<CommonType.IdType[]>([]);
+const drawerVisible = ref(false);
+const operateType = ref<NaiveUI.TableOperateType>('add');
+const editingData = ref<Api.Qm.Checkitem | null>(null);
+const showFullscreen = ref(false);
+const fullscreenStyle = ref<Record<string, string>>({});
+const onFullscreenKeydown = (event: KeyboardEvent) => {
+ if (event.key === 'Escape') {
+ showFullscreen.value = false;
+ }
+};
+
+const cardTitle = computed(() => `瑙勭▼鏄庣粏${props.stdCode || ''}`);
async function getSubList() {
- if (!props.stdId) {
+ if (!props.stdId && !props.stdCode) {
rows.value = [];
return;
}
@@ -35,7 +56,7 @@
const { data, error } = await fetchGetCheckitemTree({
pageNum: 1,
pageSize: 9999,
- stdCode: String(props.stdId)
+ stdCode: props.stdId != null ? String(props.stdId) : String(props.stdCode)
});
if (error) {
rows.value = [];
@@ -49,14 +70,100 @@
}
watch(
- () => props.stdId,
+ () => [props.stdId, props.stdCode],
async () => {
+ checkedRowKeys.value = [];
await getSubList();
},
{ immediate: true }
);
+watch(
+ showFullscreen,
+ visible => {
+ if (visible) {
+ updateFullscreenStyle();
+ window.addEventListener('keydown', onFullscreenKeydown);
+ window.addEventListener('resize', updateFullscreenStyle);
+ window.addEventListener('scroll', updateFullscreenStyle, true);
+ return;
+ }
+ window.removeEventListener('keydown', onFullscreenKeydown);
+ window.removeEventListener('resize', updateFullscreenStyle);
+ window.removeEventListener('scroll', updateFullscreenStyle, true);
+ },
+ { immediate: true }
+);
+
+onBeforeUnmount(() => {
+ window.removeEventListener('keydown', onFullscreenKeydown);
+ window.removeEventListener('resize', updateFullscreenStyle);
+ window.removeEventListener('scroll', updateFullscreenStyle, true);
+});
+
+onMounted(() => {
+ updateFullscreenStyle();
+});
+
+function updateFullscreenStyle() {
+ const container = document.querySelector<HTMLElement>('.std-content-area');
+ if (!container) {
+ fullscreenStyle.value = {
+ position: 'fixed',
+ inset: '0',
+ zIndex: '20'
+ };
+ return;
+ }
+ const rect = container.getBoundingClientRect();
+ fullscreenStyle.value = {
+ position: 'fixed',
+ left: `${rect.left}px`,
+ top: `${rect.top}px`,
+ width: `${rect.width}px`,
+ height: `${rect.height}px`,
+ zIndex: '20'
+ };
+}
+
+function handleAdd() {
+ if (!props.stdId && !props.stdCode) {
+ window.$message?.warning('璇峰厛閫夋嫨瑙勭▼');
+ return;
+ }
+ operateType.value = 'add';
+ editingData.value = null;
+ drawerVisible.value = true;
+}
+
+function handleEdit(row: StdSubRow) {
+ operateType.value = 'edit';
+ editingData.value = jsonClone(row);
+ drawerVisible.value = true;
+}
+
+async function handleBatchDelete() {
+ if (checkedRowKeys.value.length === 0) return;
+ const { error } = await fetchBatchDeleteCheckitem(checkedRowKeys.value);
+ if (error) return;
+ window.$message?.success($t('common.deleteSuccess'));
+ checkedRowKeys.value = [];
+ await getSubList();
+}
+
+async function handleDelete(id: CommonType.IdType) {
+ const { error } = await fetchBatchDeleteCheckitem([id]);
+ if (error) return;
+ window.$message?.success($t('common.deleteSuccess'));
+ await getSubList();
+}
+
const columns = computed<DataTableColumns<StdSubRow>>(() => [
+ {
+ type: 'selection',
+ align: 'center',
+ width: 48
+ },
{
key: 'index',
title: $t('common.index'),
@@ -101,6 +208,59 @@
title: '鎻忚堪',
align: 'center',
minWidth: 160
+ },
+ {
+ key: 'operate',
+ title: $t('common.operate'),
+ align: 'center',
+ width: 130,
+ render: row => {
+ const divider = () => {
+ if (!hasAuth('qm:checkitem:edit') || !hasAuth('qm:checkitem:remove')) {
+ return null;
+ }
+ return <NDivider vertical />;
+ };
+
+ const editBtn = () => {
+ if (!hasAuth('qm:checkitem:edit')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="primary"
+ icon="material-symbols:drive-file-rename-outline-outline"
+ tooltipContent={$t('common.edit')}
+ onClick={() => handleEdit(row)}
+ />
+ );
+ };
+
+ const deleteBtn = () => {
+ if (!hasAuth('qm:checkitem:remove')) {
+ return null;
+ }
+ return (
+ <ButtonIcon
+ text
+ type="error"
+ icon="material-symbols:delete-outline"
+ tooltipContent={$t('common.delete')}
+ popconfirmContent={$t('common.confirmDelete')}
+ onPositiveClick={() => handleDelete(row.id)}
+ />
+ );
+ };
+
+ return (
+ <div class="flex-center gap-8px">
+ {editBtn()}
+ {divider()}
+ {deleteBtn()}
+ </div>
+ );
+ }
}
]);
@@ -111,20 +271,40 @@
<template>
<NCard
- title="瑙勭▼鏄庣粏"
+ :title="cardTitle"
:bordered="false"
size="small"
class="flex-col-stretch card-wrapper"
:content-style="{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }"
>
<template #header-extra>
- <span class="text-13px text-gray-500">{{ props.stdId ? `STD CODE锛�${props.stdId}` : '' }}</span>
+ <NSpace align="center">
+ <TableHeaderOperation
+ :disabled-delete="checkedRowKeys.length === 0"
+ :loading="loading"
+ :show-add="hasAuth('qm:checkitem:add')"
+ :show-delete="hasAuth('qm:checkitem:remove')"
+ :show-export="false"
+ @add="handleAdd"
+ @delete="handleBatchDelete"
+ @refresh="getSubList"
+ />
+ <NButton size="small" @click="showFullscreen = true">
+ <template #icon>
+ <icon-mdi-fullscreen class="text-icon" />
+ </template>
+ 鍏ㄥ睆
+ </NButton>
+ </NSpace>
</template>
<NSpin :show="loading" class="h-full" content-class="h-full">
- <div v-if="!props.stdId" class="h-full flex-center text-gray-400">璇风偣鍑讳笂鏂硅〃鏍艰鏌ョ湅鏄庣粏</div>
+ <div v-if="!props.stdId && !props.stdCode" class="h-full flex-center text-gray-400">
+ 璇风偣鍑讳笂鏂硅〃鏍艰鏌ョ湅鏄庣粏
+ </div>
<NDataTable
v-else
+ v-model:checked-row-keys="checkedRowKeys"
:columns="columns as any"
:data="rows"
size="small"
@@ -137,6 +317,65 @@
/>
</NSpin>
</NCard>
+
+ <Teleport to="body">
+ <div v-if="showFullscreen" class="fullscreen-mask" :style="fullscreenStyle" @click.self="showFullscreen = false">
+ <NCard
+ :title="cardTitle"
+ :bordered="false"
+ size="small"
+ class="flex-col-stretch fullscreen-card"
+ :content-style="{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }"
+ >
+ <template #header-extra>
+ <NSpace align="center">
+ <TableHeaderOperation
+ :disabled-delete="checkedRowKeys.length === 0"
+ :loading="loading"
+ :show-add="hasAuth('qm:checkitem:add')"
+ :show-delete="hasAuth('qm:checkitem:remove')"
+ :show-export="false"
+ @add="handleAdd"
+ @delete="handleBatchDelete"
+ @refresh="getSubList"
+ />
+ <NButton size="small" ghost type="error" @click="showFullscreen = false">
+ <template #icon>
+ <icon-mdi-close class="text-icon" />
+ </template>
+ 鍏抽棴
+ </NButton>
+ </NSpace>
+ </template>
+
+ <NSpin :show="loading" class="h-full" content-class="h-full">
+ <div v-if="!props.stdId && !props.stdCode" class="h-full flex-center text-gray-400">
+ 璇风偣鍑讳笂鏂硅〃鏍艰鏌ョ湅鏄庣粏
+ </div>
+ <NDataTable
+ v-else
+ v-model:checked-row-keys="checkedRowKeys"
+ :columns="columns as any"
+ :data="rows"
+ size="small"
+ flex-height
+ children-key="children"
+ :row-key="rowKey"
+ striped
+ class="fullscreen-table"
+ />
+ </NSpin>
+ </NCard>
+ </div>
+ </Teleport>
+
+ <CheckitemOperateDrawer
+ v-model:visible="drawerVisible"
+ :operate-type="operateType"
+ :row-data="editingData"
+ :std-code="props.stdId"
+ @submitted="getSubList"
+ />
</template>
<style scoped>
@@ -148,4 +387,22 @@
:deep(.n-data-table-td) {
padding: 4px 6px;
}
+
+.fullscreen-mask {
+ position: absolute;
+ inset: 0;
+ z-index: 20;
+ background: #fff;
+ padding: 0;
+ display: flex;
+}
+
+.fullscreen-card {
+ width: 100%;
+ height: 100%;
+}
+
+.fullscreen-table {
+ height: 100%;
+}
</style>
--
Gitblit v1.9.3