| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- <template>
- <view class="other-report-section">
- <scroll-view class="scroll-view" scroll-y>
- <view v-for="group in dataSource" :key="group.reportType" class="group-box">
- <view class="group-header">
- <text class="group-title">{{ group.reportName }}</text>
- </view>
- <view
- v-for="(item, index) in group.data"
- :key="item.id"
- class="report-item"
- :class="{ 'first-item': index === 0 }"
- @click="handleSelectItem(item)"
- >
- <view class="item-content">
- <view class="item-left">
- <checkbox
- :checked="isSelected(item)"
- color="#4B8CD9"
- @click.stop="handleSelectItem(item)"
- />
- <text v-if="showStatusTag(item)" class="status-tag">
- {{ getStatusText(item) }}
- </text>
- <text class="report-name">{{ item.reportName }}</text>
- </view>
- <view class="item-right">
- <view
- v-if="canEdit(item)"
- class="action-btn edit-btn"
- @click.stop="handleEdit(item)"
- >
- <text>修改</text>
- </view>
- <view
- class="action-btn view-btn"
- @click.stop="handleViewDetail(item)"
- >
- <text>查看详情</text>
- </view>
- </view>
- </view>
- </view>
- </view>
- <view v-if="!dataSource || dataSource.length === 0" class="empty-state">
- <text class="empty-text">暂无项目文件</text>
- <text class="empty-sub-text">包括重大问题线索告知表、检验方案、操作指导书等</text>
- </view>
- </scroll-view>
- <view class="bottom-bar">
- <view class="select-all-box" @click="handleSelectAll">
- <checkbox
- class="square-checkbox"
- :checked="selectAll"
- color="#4B8CD9"
- @click.stop="handleSelectAll"
- />
- <text class="select-all-text">{{ selectAll ? '取消全选' : '全选' }}</text>
- </view>
-
- <view class="action-buttons">
- <view class="operate-btn delete-btn" @click="showDelReportPopup">
- <text class="operate-btn-text">作废项目</text>
- </view>
- </view>
- </view>
- <TipsPopup ref="tipsPopupRef" />
- </view>
- </template>
- <script lang="ts" setup>
- import { ref, watch, withDefaults } from 'vue'
- import { PressureReportType, PressureReportTypeMap } from '@/utils/dictMap'
- import TipsPopup from './inspectProjectComponent/TipsPopup.vue'
- import eventBus from '@/utils/eventBus'
- interface ReportItem {
- id: string
- reportName: string
- reportType?: number
- status?: number
- templateId?: string
- equipCode?: string
- [key: string]: any
- }
- interface GroupItem {
- reportType: number
- reportName: string
- data: ReportItem[]
- }
- interface Props {
- otherReportList?: ReportItem[]
- useOnline?: string
- orderItemId?: string
- }
- const props = withDefaults(defineProps<Props>(), {
- otherReportList: () => [],
- })
- const emit = defineEmits<{
- edit: [item: ReportItem]
- viewDetail: [item: ReportItem]
- handleEditWorkInstruction: [item: ReportItem]
- }>()
- const tipsPopupRef = ref<any>(null)
- const selectedProjects = ref<ReportItem[]>([])
- const selectAll = ref(false)
- const itemRefs = ref<Record<string, any>>({})
- const dataSource = ref<GroupItem[]>([])
- watch(
- () => props.otherReportList,
- (newList) => {
- if (!newList || !Array.isArray(newList)) {
- dataSource.value = []
- return
- }
- const array: GroupItem[] = []
- for (const item of newList) {
- const index = array.findIndex(ele => ele.reportType === item.reportType)
- if (index !== -1) {
- if (array[index]['data']) {
- array[index]['data'].push(item)
- } else {
- array[index]['data'] = [item]
- }
- } else {
- array.push({
- reportType: item.reportType,
- reportName: PressureReportTypeMap[item.reportType] || '其他',
- data: [item],
- })
- }
- }
- dataSource.value = array
- },
- { immediate: true }
- )
- const isSelected = (item: ReportItem): boolean => {
- return selectedProjects.value.some(p => p.id === item.id)
- }
- const handleSelectItem = (item: ReportItem) => {
- const index = selectedProjects.value.findIndex(p => p.id === item.id)
-
- if (index === -1) {
- selectedProjects.value.push(item)
- } else {
- selectedProjects.value.splice(index, 1)
- }
- selectAll.value = selectedProjects.value.length === dataSource.value.length
- }
- const handleSelectAll = () => {
- selectAll.value = !selectAll.value
- selectedProjects.value = []
- if (selectAll.value) {
- selectedProjects.value = [...(props.otherReportList || [])]
- }
- }
- const showDelReportPopup = () => {
- if (!selectedProjects.value.length) {
- uni.showToast({ title: '请选择作废的项目', icon: 'error' })
- return
- }
- const hasMain = selectedProjects.value.some(item => item.reportType === 100)
- if (hasMain) {
- uni.showToast({ title: '主报告不能作废', icon: 'error' })
- return
- }
- tipsPopupRef.value?.show({
- text: '是否作废已选择的检验项目?',
- confirm: handleDelReport,
- })
- }
- const handleDelReport = async () => {
- try {
- uni.showLoading({ title: '作废中...' })
- const cancelIds = selectedProjects.value.map(item => item.id)
- let result = null
- if (props.useOnline === '1') {
- const { delReportApi } = await import('@/api/task')
- const fetchResult = await delReportApi({ ids: cancelIds })
- result = fetchResult.data
- } else {
- uni.showToast({ title: '离线模式暂不支持作废', icon: 'none' })
- uni.hideLoading()
- return
- }
- uni.hideLoading()
- if (result) {
- eventBus.emit('RefreshOnlineData')
- uni.showToast({ title: '作废成功', icon: 'success' })
- initSelected()
- } else {
- uni.showToast({ title: '作废失败', icon: 'error' })
- }
- } catch (error) {
- uni.hideLoading()
- console.error('作废失败:', error)
- uni.showToast({ title: '作废失败', icon: 'error' })
- }
- }
- const initSelected = () => {
- selectAll.value = false
- selectedProjects.value = []
- for (const key in itemRefs.value) {
- if (itemRefs.value[key]?.setSelect) {
- itemRefs.value[key].setSelect(false)
- }
- }
- }
- const showStatusTag = (item: ReportItem): boolean => {
- return [PressureReportType.WORKINSTRUCTION].includes(item.reportType) && item.status !== undefined
- }
- const getStatusText = (item: ReportItem): string => {
- if (item.reportType === PressureReportType.WORKINSTRUCTION) {
- switch (item.status) {
- case 0:
- return '待提交'
- case 100:
- return '待批准'
- case 300:
- return '退回'
- default:
- return ''
- }
- }
- return ''
- }
- const canEdit = (item: ReportItem): boolean => {
- const { reportType, status } = item
- if (reportType === PressureReportType.WORKINSTRUCTION) {
- return [0, 200, 300].includes(status)
- } else if (reportType === PressureReportType.INSPECTIONPLAN) {
- return true
- }
- return false
- }
- const handleEdit = (item: ReportItem) => {
- emit('edit', item)
- emit('handleEditWorkInstruction', item)
- }
- const handleViewDetail = async (item: ReportItem) => {
- try {
- uni.showLoading({ title: '加载中...' })
- const { reportPreviewApi } = await import('@/api')
-
- const params = {
- reportId: item?.id,
- equipCode: item?.equipCode,
- type: 300,
- fileType: 200,
- isBase64: true,
- }
- const result = await reportPreviewApi(params)
- uni.hideLoading()
- if (result) {
- const pdfUrl = `data:application/pdf;base64,${result}`
- uni.navigateTo({
- url: `/pages/preViewPdf/PreViewPdf?title=${encodeURIComponent(item.reportName)}&url=${encodeURIComponent(pdfUrl)}`,
- })
- }
- } catch (error) {
- uni.hideLoading()
- console.error('获取报告预览失败:', error)
- uni.showToast({ title: '获取报告预览失败', icon: 'error' })
- }
- }
- </script>
- <style lang="scss" scoped>
- .other-report-section {
- display: flex;
- flex-direction: column;
- height: 100%;
- background-color: #f5f5f5;
- }
- .scroll-view {
- flex: 1;
- padding: 12px;
- padding-bottom: 80px;
- }
- .group-box {
- margin-bottom: 12px;
- padding: 15px;
- background-color: #fff;
- border-radius: 5px;
- }
- .group-header {
- padding-bottom: 10px;
- margin-bottom: 10px;
- border-bottom: 1px solid rgb(244, 244, 244);
- }
- .group-title {
- font-size: 15px;
- font-weight: 600;
- color: rgb(51, 51, 51);
- }
- .report-item {
- padding: 10px 0;
- border-bottom: 1px solid rgb(244, 244, 244);
- }
- .report-item.last {
- border-bottom: none;
- }
- .first-item {
- padding-top: 5px;
- }
- .item-content {
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- }
- .item-left {
- display: flex;
- flex: 1;
- flex-direction: row;
- align-items: center;
- min-width: 0;
- }
- .status-tag {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 25px;
- padding: 0 4px;
- margin-right: 5px;
- font-size: 12px;
- color: rgb(255, 59, 59);
- border: 1px solid rgb(255, 59, 59);
- border-radius: 3px;
- flex-shrink: 0;
- }
- .report-name {
- flex: 1;
- min-width: 0;
- font-size: 14px;
- color: rgb(51, 51, 51);
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- .item-right {
- display: flex;
- flex-direction: row;
- align-items: center;
- flex-shrink: 0;
- margin-left: 10px;
- }
- .action-btn {
- display: flex;
- align-items: center;
- justify-content: center;
- height: 25px;
- padding: 0 10px;
- border-radius: 3px;
- margin-left: 5px;
- }
- .action-btn text {
- font-size: 12px;
- color: #fff;
- }
- .edit-btn {
- background-color: rgb(230, 162, 60);
- }
- .view-btn {
- background-color: rgb(47, 142, 255);
- }
- .empty-state {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- padding: 60px 20px;
- }
- .empty-text {
- margin-bottom: 8px;
- font-size: 16px;
- color: #999;
- text-align: center;
- }
- .empty-sub-text {
- font-size: 14px;
- color: #ccc;
- text-align: center;
- }
- .bottom-bar {
- position: fixed;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 100;
- display: flex;
- flex-direction: row;
- align-items: center;
- justify-content: space-between;
- height: 68px;
- padding: 0 12px;
- background-color: #fff;
- border-top: 1px solid rgb(244, 244, 244);
- }
- .select-all-box {
- display: flex;
- flex-direction: row;
- align-items: center;
- width: 68px;
- }
- .square-checkbox {
- border-radius: 0 !important;
- transform: scale(0.9);
- }
- .select-all-text {
- width: 50px;
- margin-left: 10px;
- font-size: 15px;
- line-height: 1.4;
- color: rgb(51, 51, 51);
- white-space: pre-line;
- }
- .action-buttons {
- display: flex;
- flex-direction: row;
- align-items: center;
- }
- .operate-btn {
- display: flex;
- align-items: center;
- justify-content: center;
- min-width: 66px;
- height: 40px;
- padding: 0 5px;
- margin-left: 5px;
- border-radius: 4px;
- }
- .operate-btn-text {
- font-size: 14px;
- color: rgb(251, 253, 255);
- }
- .delete-btn {
- background-color: #ff4445;
- }
- </style>
|