소스 검색

报港预约

fanzherong_v 4 일 전
부모
커밋
5bc9f3f30b
25개의 변경된 파일2048개의 추가작업 그리고 4개의 파일을 삭제
  1. 4 0
      snowy-admin-web/src/api/biz/bizLoadAppointApi.js
  2. 38 0
      snowy-admin-web/src/api/biz/bizLoadArriveApi.js
  3. 3 3
      snowy-admin-web/src/views/biz/bizloadappoint/form.vue
  4. 202 0
      snowy-admin-web/src/views/biz/bizloadarrive/detail.vue
  5. 226 0
      snowy-admin-web/src/views/biz/bizloadarrive/form.vue
  6. 327 0
      snowy-admin-web/src/views/biz/bizloadarrive/index.vue
  7. 66 0
      snowy-admin-web/src/views/biz/bizloadarrive/review.vue
  8. 12 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/controller/BizLoadAppointController.java
  9. 2 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/mapper/BizLoadAppointMapper.java
  10. 32 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/mapper/mapping/BizLoadAppointMapper.xml
  11. 3 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/param/BizLoadAppointPageParam.java
  12. 5 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/service/BizLoadAppointService.java
  13. 25 1
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/service/impl/BizLoadAppointServiceImpl.java
  14. 146 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/controller/BizLoadArriveController.java
  15. 96 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/entity/BizLoadArrive.java
  16. 34 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/enums/BizLoadArriveEnum.java
  17. 33 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/mapper/BizLoadArriveMapper.java
  18. 30 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/mapper/mapping/BizLoadArriveMapper.xml
  19. 64 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArriveAddParam.java
  20. 75 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArriveEditParam.java
  21. 78 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArriveExportResult.java
  22. 35 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArriveIdParam.java
  23. 80 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArrivePageParam.java
  24. 92 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/service/BizLoadArriveService.java
  25. 340 0
      snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/service/impl/BizLoadArriveServiceImpl.java

+ 4 - 0
snowy-admin-web/src/api/biz/bizLoadAppointApi.js

@@ -39,4 +39,8 @@ export default {
 			responseType: 'blob'
 		})
 	},
+	//获取待报港的起卸预约列表
+	getList(data){
+		return request('getList',data,'get')
+	}
 }

+ 38 - 0
snowy-admin-web/src/api/biz/bizLoadArriveApi.js

@@ -0,0 +1,38 @@
+import { baseRequest } from '@/utils/request'
+
+const request = (url, ...arg) => baseRequest(`/biz/bizloadarrive/` + url, ...arg)
+
+/**
+ * 报港预约Api接口管理器
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+export default {
+	// 获取报港预约分页
+	bizLoadArrivePage(data) {
+		return request('page', data, 'get')
+	},
+	// 提交报港预约表单 edit为true时为编辑,默认为新增
+	bizLoadArriveSubmitForm(data, edit = false) {
+		return request(edit ? 'edit' : 'add', data)
+	},
+	// 删除报港预约
+	bizLoadArriveDelete(data) {
+		return request('delete', data)
+	},
+	// 获取报港预约详情
+	bizLoadArriveDetail(data) {
+		return request('detail', data, 'get')
+	},
+	//审核
+	auditArrive(data){
+		return request('auditArrive',data)
+	},
+	//导出
+	exportRecord(data){
+		return request('exportRecord', data, 'get', {
+			responseType: 'blob'
+		})
+	},
+}

+ 3 - 3
snowy-admin-web/src/views/biz/bizloadappoint/form.vue

@@ -7,8 +7,8 @@
 		@close="onClose"
 	>
 		<a-form ref="formRef" :model="formData" :rules="formRules" :wrapper-col="wrapperCol" :label-col="labelCol">
-			<a-form-item label="服务客户信息:" name="customerId">
-				<a-select v-model:value="formData.customerId" placeholder="请选择服务客户信息"
+			<a-form-item label="客户信息:" name="customerId">
+				<a-select v-model:value="formData.customerId" placeholder="请选择客户信息"
 						  :options="customerIdList"
 				> </a-select>
 			</a-form-item>
@@ -147,7 +147,7 @@
 	}
 	// 默认要校验的
 	const formRules = {
-		customerId:[required('请选择服务客户信息')],
+		customerId:[required('请选择客户信息')],
 		goodsId:[required('请选择货品信息')],
 		orderWeight:[required('请输入订单数量')],
 		orderPrice:[required('请输入单价')],

+ 202 - 0
snowy-admin-web/src/views/biz/bizloadarrive/detail.vue

@@ -0,0 +1,202 @@
+<template>
+	<xn-form-container title="详情" :width="1100" :visible="visible" :destroy-on-close="true" @close="onClose">
+		<a-form ref="formRef" :model="formData" :label-col="labelCol4" :wrapper-col="wrapperCol20">
+			<a-divider dashed style="border-color: gray">报港预约</a-divider>
+			<a-descriptions :column="4" size="middle" bordered class="mb-2" :label-style="labelStyle" :contentStyle="contentStyle">
+				<a-descriptions-item label="起卸预约单号" :span="2">{{ formData.loadNumber }}</a-descriptions-item>
+				<a-descriptions-item label="船号" :span="2">{{ formData.shipNo }}</a-descriptions-item>
+				<a-descriptions-item label="客户名称" :span="2">{{ formData.customerName }}</a-descriptions-item>
+				<a-descriptions-item label="联系人" :span="2">{{ formData.customerContact }}</a-descriptions-item>
+				<a-descriptions-item label="手机号" :span="2">{{ formData.customerPhone }}</a-descriptions-item>
+				<a-descriptions-item label="客户地址" :span="2">{{ formData.customerAddress }}</a-descriptions-item>
+				<a-descriptions-item label="货品名称" :span="2">{{ formData.goodsName }}</a-descriptions-item>
+				<a-descriptions-item label="货品编码" :span="2">{{ formData.goodsCode }}</a-descriptions-item>
+				<a-descriptions-item label="报港数量(吨)" :span="2">{{ formData.arriveNumber }}</a-descriptions-item>
+				<a-descriptions-item label="到港时间" :span="2">{{ formData.arriveTime }}</a-descriptions-item>
+				<a-descriptions-item label="创建人" :span="2">{{ formData.createUserName }}</a-descriptions-item>
+				<a-descriptions-item label="创建时间" :span="2">{{ formData.createTime }}</a-descriptions-item>
+
+				<a-descriptions-item label="状态" :span="4">
+					<a-tag
+						:color="
+							formData.status === '1'
+								? 'blue'
+								: formData.status === '2'
+								  ? 'warning'
+								  : formData.status === '3'
+								  ? 'processing'
+								  : formData.status === '4'
+								  ? 'volcano'
+								  : formData.status === '5'
+								  ? 'purple'
+								  : formData.status === '6'
+								  ? 'error'
+								  : formData.status === '7'
+								  ? 'red'
+								  : formData.status === '8'
+								  ? 'cyan'
+								  : '#f50'
+						"
+					>
+						{{ $TOOL.dictTypeData('arrive_status', formData.status) }}
+					</a-tag>
+				</a-descriptions-item>
+
+				<a-descriptions-item label="发航单" :span="4">
+					<p v-for="(item, index) in fileUpload" :key="index">
+						<a @click="downloadMaterial(item.url)" target="_blank">{{ item.name }}</a>
+					</p>
+				</a-descriptions-item>
+
+			</a-descriptions>
+
+			<a-divider dashed style="border-color: gray" v-if="auditDataSource.length > 0">审核记录</a-divider>
+			<a-table
+				:dataSource="auditDataSource"
+				:columns="auditDataColumns"
+				:pagination="false"
+				:bordered="true"
+				v-if="auditDataSource.length > 0"
+			>
+				<template #bodyCell="{ column, record }">
+					<template v-if="column.dataIndex === 'status'">
+						<a-tag :color="record.status === '1' ? 'green' : 'red'">{{
+								$TOOL.dictTypeData('examine_status', record.status)
+							}}</a-tag>
+					</template>
+				</template>
+			</a-table>
+		</a-form>
+	</xn-form-container>
+</template>
+
+<script setup name="recordDoubleForm">
+	import { cloneDeep } from 'lodash-es'
+	import bizSettleApi from "@/api/biz/bizSettleApi";
+	import sysConfig from "@/config";
+	import bizAuditLogApi from "@/api/biz/bizAuditLogApi";
+
+
+	const auditDataSource = ref([])
+
+	// 默认是关闭状态
+	const visible = ref(false)
+	const formData = ref({})
+	const table = ref()
+	const resultJson = ref()
+
+	const labelStyle = {
+		width: '20%'
+	}
+	const contentStyle = {
+		width: '30%'
+	}
+
+	const labelCol4 = ref({span: 4, style: 'width: 26%; line-height: 20px; white-space: normal',})
+	const labelCol8 = ref({span: 8, style: 'width: 26%; line-height: 20px; white-space: normal',})
+	const wrapperCol20 = ref({span: 20})
+
+	const fileUpload = ref([])
+
+	// 打开抽屉
+	const onOpen = (record) => {
+		visible.value = true
+		//getRecordDoubleDetail(record)
+		if(record){
+			let recordData = cloneDeep(record)
+			formData.value = Object.assign({}, recordData)
+
+			if (formData.value.sailFilePath) {
+				for (var i = 0; i < formData.value.sailFilePath.split(',').length; i++) {
+					fileUpload.value.push({
+						url: sysConfig.PREVIEW_PATH + formData.value.sailFilePath.split(',')[i],
+						name: formData.value.sailFileName.split(',')[i]
+					})
+				}
+
+			}
+
+			// 获取审核记录
+			bizAuditLogApi.getList({ type: 'BGYY', dataId: formData.value.id }).then((res) => {
+				auditDataSource.value = res
+			})
+		}
+
+	}
+	const getRecordDoubleDetail = (record) => {
+		const param = {
+			id: record.id
+		}
+		tbRecordDoubleApi.recordDoubleDetailPic(param).then((data) => {
+			Object.assign(record, data)
+			formData.value = record
+		})
+	}
+
+	const downloadMaterial = (url) => {
+		window.open( url)
+	}
+
+
+	const auditDataColumns = [
+		{
+			title: '审核时间',
+			dataIndex: 'createTime',
+			width: 200,
+			align: 'center'
+		},
+		{
+			title: '审核人',
+			dataIndex: 'createUserName',
+			width: 150,
+			align: 'center'
+		},
+		{
+			title: '状态',
+			dataIndex: 'status',
+			width: 200,
+			align: 'center'
+		},
+		{
+			title: '审核意见',
+			dataIndex: 'remark',
+			align: 'center'
+		}
+	]
+
+	// 关闭抽屉
+	const onClose = () => {
+		resultJson.value = ''
+		visible.value = false
+		fileUpload.value = []
+	}
+	// 调用这个函数将子组件的一些数据和方法暴露出去
+	defineExpose({
+		onOpen
+	})
+</script>
+
+<style scoped>
+	.imgDiv ::v-deep .ant-image {
+		margin-left: 20px;
+		margin-top: 10px;
+	}
+	.imgDiv ::v-deep .ant-image-mask-info {
+		margin-left: 20px;
+		margin-top: 10px;
+	}
+
+	table {
+		margin-top: 10px;
+		text-align: center;
+		width: 100%;
+	}
+
+	table td {
+		border: 1px solid #f0f2f5;
+		padding: 10px 0;
+	}
+	tr:hover {
+		background-color: #f5f5f5;
+	}
+</style>

+ 226 - 0
snowy-admin-web/src/views/biz/bizloadarrive/form.vue

@@ -0,0 +1,226 @@
+<template>
+	<xn-form-container
+		:title="formData.id ? '编辑报港预约' : '增加报港预约'"
+		:width="700"
+		v-model:open="open"
+		:destroy-on-close="true"
+		@close="onClose"
+	>
+		<a-form ref="formRef" :model="formData" :rules="formRules" :wrapper-col="wrapperCol" :label-col="labelCol">
+			<a-form-item label="起卸预约信息:" name="appointId">
+				<a-select v-model:value="formData.appointId" placeholder="请选择起卸预约信息"
+						  :options="appointIdList" @change="onChangeAppoint"
+				> </a-select>
+			</a-form-item>
+			<a-form-item label="船号:" name="shipNo" >
+				<a-input v-model:value="formData.shipNo" placeholder="请输入船号" allow-clear />
+			</a-form-item>
+			<a-form-item label="报港数量:" name="arriveNumber">
+				<a-input-number v-model:value="formData.arriveNumber" style="width:90%"  :precision="2" :min="0.01" :max="9999999"  placeholder="请输入报港数量"  allow-clear/><span style="margin-left:10px;">吨</span>
+			</a-form-item>
+			<a-form-item label="到港时间:" name="arriveTime">
+				<a-date-picker v-model:value="formData.arriveTime" value-format="YYYY-MM-DD HH:mm:ss" show-time placeholder="请选择到港时间" style="width: 100%" />
+			</a-form-item>
+			<a-form-item label="上传发航单:" name="filePathList" :rules="[{ required: true, message: '请上传发航单' }]">
+				<a-upload
+					v-model:file-list="fileList"
+					class="avatar-uploader"
+					list-type="picture"
+					:show-upload-list="true"
+					:custom-request="customRequest"
+					:remove="file => removeOtherFile(file,index)"
+					accept="image/png, image/jpeg, image/jpg"
+
+				>
+					<a-button>
+						<upload-outlined></upload-outlined>
+						upload
+					</a-button>
+				</a-upload>
+			</a-form-item>
+			<a-form-item label="客户名称:" name="customerName" v-show="customerNameFlag">
+				<a-input v-model:value="formData.customerName" placeholder="请输入客户名称" allow-clear disabled/>
+			</a-form-item>
+			<a-form-item label="联系人:" name="customerContact" v-show="customerContactFlag">
+				<a-input v-model:value="formData.customerContact" placeholder="请输入联系人" allow-clear disabled/>
+			</a-form-item>
+			<a-form-item label="联系电话:" name="customerPhone" v-show="customerPhoneFlag">
+				<a-input v-model:value="formData.customerPhone" placeholder="请输入联系电话" allow-clear disabled/>
+			</a-form-item>
+			<a-form-item label="货品名称:" name="goodsName" v-show="goodsNameFlag">
+				<a-input v-model:value="formData.goodsName" placeholder="请输入货品名称" allow-clear disabled/>
+			</a-form-item>
+			<a-form-item label="货品编码:" name="goodsCode" v-show="goodsCodeFlag">
+				<a-input v-model:value="formData.goodsCode" placeholder="请输入货品编码" allow-clear disabled/>
+			</a-form-item>
+		</a-form>
+		<template #footer>
+			<a-button style="margin-right: 8px" @click="onClose">关闭</a-button>
+			<a-button type="primary" @click="onSubmit" :loading="submitLoading">保存</a-button>
+		</template>
+	</xn-form-container>
+</template>
+
+<script setup name="bizLoadArriveForm">
+	import { cloneDeep } from 'lodash-es'
+	import { required } from '@/utils/formRules'
+	import bizLoadArriveApi from '@/api/biz/bizLoadArriveApi'
+	import bizLoadAppointApi from "@/api/biz/bizLoadAppointApi";
+	import fileApi from "@/api/dev/fileApi";
+	import sysConfig from "@/config";
+
+
+	// 抽屉状态
+	const open = ref(false)
+	const emit = defineEmits({ successful: null })
+	const formRef = ref()
+
+	//设置表单样式
+	const labelCol = ref({ span: 5})
+	const wrapperCol = ref({ span: 16})
+
+	// 表单数据
+	const formData = ref({filePathList:[],fileNameList:[]})
+	const submitLoading = ref(false)
+	const appointIdList = ref()
+	const customerNameFlag = ref(false)
+	const customerContactFlag = ref(false)
+	const customerPhoneFlag = ref(false)
+	const goodsNameFlag = ref(false)
+	const goodsCodeFlag = ref(false)
+	const fileList = ref([])
+
+	// 打开抽屉
+	const onOpen = (record) => {
+		open.value = true
+		if (record) {
+			let recordData = cloneDeep(record)
+			formData.value = Object.assign({}, recordData)
+			formData.value.filePathList = []
+			formData.value.fileNameList = []
+			fileList.value = []
+			if (formData.value.sailFilePath) {
+				for (var i = 0; i < formData.value.sailFilePath.split(',').length; i++) {
+					fileList.value.push({
+						url: sysConfig.PREVIEW_PATH + formData.value.sailFilePath.split(',')[i],
+						name: formData.value.sailFileName.split(',')[i]
+					})
+
+					formData.value.filePathList.push(formData.value.sailFilePath.split(',')[i])
+					formData.value.fileNameList.push(formData.value.sailFileName.split(',')[i])
+				}
+			}
+		}
+
+		if(!formData.value.id){
+			bizLoadAppointApi.getList({status:'2'}).then((res)=>{
+				appointIdList.value = res.map((item)=>{
+					return{
+						value:item.id,
+						label:item.loadNumber
+					}
+				})
+			})
+		}else{
+			bizLoadAppointApi.getList({status:'2,3'}).then((res)=>{
+				appointIdList.value = res.map((item)=>{
+					return{
+						value:item.id,
+						label:item.loadNumber
+					}
+				})
+			})
+		}
+
+	}
+	// 关闭抽屉
+	const onClose = () => {
+		formRef.value.resetFields()
+		formData.value = {}
+		formData.value.fileNameList = []
+		formData.value.filePathList = []
+		fileList.value = []
+		open.value = false
+		customerNameFlag.value = false
+		customerContactFlag.value = false
+		customerPhoneFlag.value = false
+		goodsNameFlag.value = false
+		goodsCodeFlag.value = false
+	}
+	// 默认要校验的
+	const formRules = {
+		appointId:[required('请选择起卸预约信息')],
+		arriveNumber:[required('请输入报港数量')],
+		arriveTime:[required('请选择到港时间')],
+		shipNo:[required('请输入船号')],
+	}
+
+	//起卸预约信息点击事件
+	const onChangeAppoint = (value) => {
+		customerNameFlag.value = true
+		customerContactFlag.value = true
+		customerPhoneFlag.value = true
+		goodsNameFlag.value = true
+		goodsCodeFlag.value = true
+		bizLoadAppointApi.bizLoadAppointDetail({id:value}).then((res)=>{
+			formData.value.customerName = res.customerName
+			formData.value.customerContact = res.customerContact
+			formData.value.customerPhone = res.customerPhone
+			formData.value.goodsName = res.goodsName
+			formData.value.goodsCode = res.goodsCode
+		})
+	}
+
+	//上传文件
+	const customRequest = (data) => {
+		//保存图片
+		const fileData = new FormData()
+		fileData.append('file', data.file)
+		fileApi
+			.uploadImgMap(fileData)
+			.then((result) => {
+				formData.value.filePathList.push(result.imageFile)
+				formData.value.fileNameList.push(data.file.name)
+			}).finally(()=>{
+			data.onSuccess()
+		})
+
+	}
+
+	//文件删除
+	const removeOtherFile = (file) => {
+		fileList.value.forEach((item,index)=>{
+			console.log(item.name+"======="+file.name)
+			if(item.name === file.name){
+
+				fileList.value.splice(index, 1);
+				formData.value.filePathList.splice(index,1)
+				formData.value.fileNameList.splice(index,1)
+			}
+		})
+	}
+
+	// 验证并提交数据
+	const onSubmit = () => {
+		formRef.value
+			.validate()
+			.then(() => {
+				submitLoading.value = true
+				const formDataParam = cloneDeep(formData.value)
+				bizLoadArriveApi
+					.bizLoadArriveSubmitForm(formDataParam, formDataParam.id)
+					.then(() => {
+						onClose()
+						emit('successful')
+					})
+					.finally(() => {
+						submitLoading.value = false
+					})
+			})
+			.catch(() => {})
+	}
+	// 抛出函数
+	defineExpose({
+		onOpen
+	})
+</script>

+ 327 - 0
snowy-admin-web/src/views/biz/bizloadarrive/index.vue

@@ -0,0 +1,327 @@
+<template>
+	<a-card :bordered="false" style="margin-bottom: 10px" class="mb-2">
+		<a-form ref="searchFormRef" name="advanced_search" :model="searchFormState" class="ant-advanced-search-form">
+			<a-row :gutter="24">
+				<a-col :span="6">
+					<a-form-item label="预约单号" name="loadNumber">
+						<a-input v-model:value="searchFormState.loadNumber" placeholder="预约单号查询" />
+					</a-form-item>
+				</a-col>
+				<a-col :span="6">
+					<a-form-item label="客户名称" name="customerName">
+						<a-input v-model:value="searchFormState.customerName" placeholder="客户名称查询" />
+					</a-form-item>
+				</a-col>
+				<a-col :span="6">
+					<a-form-item label="货品名称" name="goodsName">
+						<a-input v-model:value="searchFormState.goodsName" placeholder="货品名称查询" />
+					</a-form-item>
+				</a-col>
+				<template v-if="advanced">
+
+					<a-col :span="6">
+						<a-form-item label="船号" name="shipNo">
+							<a-input v-model:value="searchFormState.shipNo" placeholder="船号查询" />
+						</a-form-item>
+					</a-col>
+
+					<a-col :span="6">
+						<a-form-item label="状态" name="status">
+							<a-select v-model:value="searchFormState.status" placeholder="状态查询"
+									  :options="statusList"
+							> </a-select>
+						</a-form-item>
+					</a-col>
+
+					<a-col :span="6">
+						<a-form-item label="到港时间" name="arriveTime">
+							<a-range-picker
+								v-model:value="searchFormState.arriveTime"
+								value-format="YYYY-MM-DD"
+							/>
+						</a-form-item>
+					</a-col>
+				</template>
+				<a-col :span="6">
+					<a-button type="primary" @click="tableRef.refresh()">查询</a-button>
+					<a-button style="margin: 0 8px" @click="reset">重置</a-button>
+					<a @click="toggleAdvanced" style="margin-left: 8px">
+						{{ advanced ? '收起' : '展开' }}
+						<component :is="advanced ? 'up-outlined' : 'down-outlined'" />
+					</a>
+				</a-col>
+			</a-row>
+		</a-form>
+	</a-card>
+	<a-card :bordered="false">
+		<s-table
+			ref="tableRef"
+			:columns="columns"
+			:data="loadData"
+			bordered
+			:row-key="(record) => record.id"
+		>
+			<template #operator class="table-operator">
+				<a-space>
+					<a-button type="primary" @click="formRef.onOpen()" v-if="hasPerm('bizLoadArriveAdd')">
+						<template #icon><plus-outlined /></template>
+						新增
+					</a-button>
+					<a-button @click="exportTotal" v-if="hasPerm('bizLoadArriveExport')">
+						<template #icon>
+							<export-outlined/>
+						</template>
+						导出
+					</a-button>
+				</a-space>
+			</template>
+			<template #bodyCell="{ column, record }">
+				<template v-if="column.dataIndex === 'action'">
+<!--					<a-space>
+						<a @click="formRef.onOpen(record)" v-if="hasPerm('bizLoadArriveEdit')">编辑</a>
+						<a-divider type="vertical" v-if="hasPerm(['bizLoadArriveEdit', 'bizLoadArriveDelete'], 'and')" />
+						<a-popconfirm title="确定要删除吗?" @confirm="deleteBizLoadArrive(record)">
+							<a-button type="link" danger size="small" v-if="hasPerm('bizLoadArriveDelete')">删除</a-button>
+						</a-popconfirm>
+					</a-space>-->
+
+					<a-dropdown>
+						<a class="ant-dropdown-link">
+							更多
+							<DownOutlined />
+						</a>
+						<template #overlay>
+							<a-menu>
+								<a-menu-item>
+									<a size="small" type="link" @click="detailRef.onOpen(record)" >详情</a>
+								</a-menu-item>
+								<a-menu-item v-if="hasPerm('bizLoadArriveEdit') && (record.status == '3')">
+									<a style="color:blue" size="small" type="link" @click="formRef.onOpen(record)" >编辑</a>
+								</a-menu-item>
+								<a-menu-item v-if="hasPerm('bizLoadArriveDelete')">
+									<a style="color:red" size="small" type="link" @click="deleteConfig(record)">删除</a>
+								</a-menu-item>
+								<!--管理员审核-->
+								<a-menu-item v-if="hasPerm('bizLoadArriveAudit') && record.status == '1'">
+									<a style="color:blue" @click="reviewRef.showModal(record.id)" >审核</a>
+								</a-menu-item>
+							</a-menu>
+						</template>
+					</a-dropdown>
+				</template>
+				<template v-if="column.dataIndex === 'status'">
+					<a-tag
+						:color="
+							record.status === '1'
+								? 'blue'
+								: record.status === '2'
+								  ? 'warning'
+								  : record.status === '3'
+								  ? 'processing'
+								  : record.status === '4'
+								  ? 'volcano'
+								  : record.status === '5'
+								  ? 'purple'
+								  : record.status === '6'
+								  ? 'error'
+								  : record.status === '7'
+								  ? 'red'
+								  : record.status === '8'
+								  ? 'cyan'
+								  : '#f50'
+						"
+					>
+						{{ $TOOL.dictTypeData('arrive_status', record.status) }}
+					</a-tag>
+				</template>
+			</template>
+		</s-table>
+	</a-card>
+	<Form ref="formRef" @successful="tableRef.refresh()" />
+	<Review ref="reviewRef" @successful="tableRef.refresh(true)" />
+	<Detail ref="detailRef" @successful="tableRef.refresh()" />
+</template>
+
+<script setup name="bizloadarrive">
+	import { cloneDeep } from 'lodash-es'
+	import Form from './form.vue'
+	import bizLoadArriveApi from '@/api/biz/bizLoadArriveApi'
+	import tool from '@/utils/tool'
+	import {ExclamationCircleOutlined} from '@ant-design/icons-vue';
+	import {Modal} from 'ant-design-vue';
+	import {createVNode} from 'vue';
+	import Review from "./review.vue";
+	import Detail from "./detail.vue";
+	import downloadUtil from '@/utils/downloadUtil'
+
+
+	//查询数据
+	const searchFormState = ref({})
+	const searchFormRef = ref()
+	const statusList = tool.dictList('arrive_status')
+
+	// 查询区域显示更多控制
+	const advanced = ref(false)
+	const toggleAdvanced = () => {
+		advanced.value = !advanced.value
+	}
+
+	const tableRef = ref()
+	const formRef = ref()
+	const reviewRef = ref()
+	const detailRef = ref()
+	const submitLoading = ref(false)
+	const toolConfig = { refresh: true, height: true, columnSetting: true, striped: false }
+	const columns = [
+		{
+			title: '起卸预约单号',
+			dataIndex: 'loadNumber',
+			align:'center'
+		},
+		{
+			title: '船号',
+			dataIndex: 'shipNo',
+			align:'center'
+		},
+		{
+			title: '客户名称',
+			dataIndex: 'customerName',
+			align:'center'
+		},
+		{
+			title: '货品名称',
+			dataIndex: 'goodsName',
+			align:'center'
+		},
+		{
+			title: '报港数量(吨)',
+			dataIndex: 'arriveNumber',
+			align:'center'
+		},
+		{
+			title: '到港时间',
+			dataIndex: 'arriveTime',
+			align:'center'
+		},
+		{
+			title: '状态',
+			dataIndex: 'status',
+			align:'center'
+		},
+
+	]
+	// 操作栏通过权限判断是否显示
+	columns.push({
+		title: '操作',
+		dataIndex: 'action',
+		align: 'center',
+		width: 150
+	})
+
+	const selectedRowKeys = ref([])
+	// 列表选择配置
+	const options = {
+		// columns数字类型字段加入 needTotal: true 可以勾选自动算账
+		alert: {
+			show: true,
+			clear: () => {
+				selectedRowKeys.value = ref([])
+			}
+		},
+		rowSelection: {
+			onChange: (selectedRowKey, selectedRows) => {
+				selectedRowKeys.value = selectedRowKey
+			}
+		}
+	}
+	const loadData = (parameter) => {
+		const searchFormParam = cloneDeep(searchFormState.value)
+		// 报港时间范围查询条件重载
+		if (searchFormParam.arriveTime) {
+			searchFormParam.arriveTimeBegin = searchFormParam.arriveTime[0]
+			searchFormParam.arriveTimeEnd = searchFormParam.arriveTime[1]
+			delete searchFormParam.arriveTime
+		}
+		return bizLoadArriveApi.bizLoadArrivePage(Object.assign(parameter, searchFormParam)).then((data) => {
+			return data
+		})
+	}
+
+	//导出
+	const exportTotal = () => {
+		Modal.confirm({
+			title: '确定要导出记录吗?',
+			icon: createVNode(ExclamationCircleOutlined),
+			content: '',
+			onOk() {
+				submitLoading.value = true
+				const searchFormParam = cloneDeep(searchFormState.value)
+				// 报港时间范围查询条件重载
+				if (searchFormParam.arriveTime) {
+					searchFormParam.arriveTimeBegin = searchFormParam.arriveTime[0]
+					searchFormParam.arriveTimeEnd = searchFormParam.arriveTime[1]
+					delete searchFormParam.arriveTime
+				}
+				bizLoadArriveApi
+					.exportRecord(Object.assign(searchFormParam))
+					.then((res) => {
+						downloadUtil.resultDownload(res)
+					})
+					.finally(() => {
+						submitLoading.value = false
+					})
+			},
+			onCancel() {}
+		})
+	}
+
+	// 重置
+	const reset = () => {
+		searchFormRef.value.resetFields()
+		tableRef.value.refresh(true)
+	}
+	// 删除
+	const deleteBizLoadArrive = (record) => {
+		let params = [
+			{
+				id: record.id
+			}
+		]
+		bizLoadArriveApi.bizLoadArriveDelete(params).then(() => {
+			tableRef.value.refresh(true)
+		})
+	}
+	// 删除
+	const deleteConfig = (record) => {
+
+		Modal.confirm({
+			title: '确定删除该数据吗?',
+			icon: createVNode(ExclamationCircleOutlined),
+			content: '',
+			onOk() {
+				submitLoading.value = true
+				let params = [
+					{
+						id: record.id
+					}
+				]
+
+				bizLoadArriveApi
+					.bizLoadArriveDelete(params)
+					.then(() => {
+						tableRef.value.refresh(true)
+					})
+					.finally(() => {
+						submitLoading.value = false
+					})
+			},
+			onCancel() {}
+		})
+	}
+	// 批量删除
+	const deleteBatchBizLoadArrive = (params) => {
+		bizLoadArriveApi.bizLoadArriveDelete(params).then(() => {
+			tableRef.value.clearRefreshSelected()
+		})
+	}
+</script>

+ 66 - 0
snowy-admin-web/src/views/biz/bizloadarrive/review.vue

@@ -0,0 +1,66 @@
+<template>
+    <a-modal v-model:visible="visible" title="审核">
+
+        <a-form ref="formRef" :label-col="labelCol" :model="formData" layout="horizontal">
+            <a-form-item v-show="false">
+                <a-input v-model:value="formData.id"></a-input>
+            </a-form-item>
+            <a-form-item
+                    label="审核备注"
+                    name="arriveReason"
+            >
+                <a-textarea v-model:value="formData.arriveReason" placeholder="请输入审核备注"
+                            :auto-size="{ minRows: 3, maxRows: 5 }"/>
+            </a-form-item>
+        </a-form>
+        <template #footer>
+            <a-spin :spinning="submitLoading">
+                <a-button style="margin-right: 8px" @click="onsubmit(false)" type="primary" danger>审核驳回</a-button>
+                <a-button type="primary" @click="onsubmit(true)">审核通过</a-button>
+            </a-spin>
+        </template>
+    </a-modal>
+</template>
+<script setup>
+import {message} from 'ant-design-vue';
+import bizLoadArriveApi from '@/api/biz/bizLoadArriveApi'
+
+
+const emit = defineEmits({successful: null})
+const visible = ref(false);
+const submitLoading = ref(false)
+const labelCol = ref({span: 4})
+// 表单数据
+const formData = ref({})
+const showModal = (id) => {
+    formData.value.id = id
+    visible.value = true;
+};
+const onClose = () => {
+    formData.value = {}
+    visible.value = false
+};
+const onsubmit = (flag) => {
+    if (flag === false) {
+        if (!formData.value.arriveReason) {
+            message.error('审核驳回时,备注信息不能为空')
+            return
+        }
+    }
+    submitLoading.value = true
+	formData.value.auditFlag = flag
+	bizLoadArriveApi.auditArrive(formData.value).then(() => {
+        onClose()
+        emit('successful', null)
+    }).finally(() => {
+        submitLoading.value = false
+    })
+}
+// 抛出函数
+defineExpose({
+    showModal
+})
+</script>
+<style scoped>
+
+</style>

+ 12 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/controller/BizLoadAppointController.java

@@ -161,4 +161,16 @@ public class BizLoadAppointController {
     public void exportRecord(BizLoadAppointPageParam bizLoadAppointPageParam, HttpServletResponse response) throws IOException {
         bizLoadAppointService.exportRecord(bizLoadAppointPageParam,response);
     }
+
+    /**
+     * 获取起卸预约待报港列表
+     *
+     * @author fanzherong
+     * @date  2025/06/25 14:51
+     */
+    @Operation(summary = "获取起卸预约待报港列表")
+    @GetMapping("/biz/bizloadappoint/getList")
+    public CommonResult<List<BizLoadAppoint>> getList(BizLoadAppointPageParam bizLoadAppointPageParam) {
+        return CommonResult.data(bizLoadAppointService.getList(bizLoadAppointPageParam));
+    }
 }

+ 2 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/mapper/BizLoadAppointMapper.java

@@ -30,4 +30,6 @@ public interface BizLoadAppointMapper extends BaseMapper<BizLoadAppoint> {
     Page<BizLoadAppoint> getPage(@Param("page") Page<BizLoadAppoint> page, @Param("ew") QueryWrapper<BizLoadAppoint> ew);
 
     List<BizLoadAppoint> getPage(@Param("ew") QueryWrapper<BizLoadAppoint> ew);
+
+    BizLoadAppoint getDetail(@Param("ew") QueryWrapper<BizLoadAppoint> ew);
 }

+ 32 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/mapper/mapping/BizLoadAppointMapper.xml

@@ -33,4 +33,36 @@
          left join biz_supplier bs on bs.id = bla.supplier_id
          ${ew.customSqlSegment}
     </select>
+
+    <select id="getDetail" resultType="vip.xiaonuo.biz.modular.bizloadappoint.entity.BizLoadAppoint">
+        select
+            bla.id,
+            bla.load_number,
+            bsc.`name` customerName,
+            bsc.contact customerContact,
+            bsc.phone customerPhone,
+            bsc.address customerAddress,
+            bla.customer_id,
+            bla.goods_id,
+            bg.GOODS_NAME goodsName,
+            bg.GOODS_CODE goodsCode,
+            ifnull(bla.order_weight/1000,0) order_weight,
+            bla.order_price,
+            bla.order_amount,
+            bs.supplier_name,
+            bla.supplier_id,
+            bla.freight_price,
+            bla.pay_type,
+            bla.order_type,
+            bla.status,
+            bla.create_user,
+            bla.create_time,
+            bla.customer_sign,
+            bla.sign_time
+        from biz_load_appoint bla
+                 left join biz_service_customer bsc on bla.customer_id = bsc.id
+                 left join biz_goods bg on bg.id = bla.goods_id
+                 left join biz_supplier bs on bs.id = bla.supplier_id
+            ${ew.customSqlSegment}
+    </select>
 </mapper>

+ 3 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/param/BizLoadAppointPageParam.java

@@ -64,4 +64,7 @@ public class BizLoadAppointPageParam {
     private String createTimeBegin;
     private String createTimeEnd;
 
+    /**状态*/
+    private String status;
+
 }

+ 5 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/service/BizLoadAppointService.java

@@ -94,4 +94,9 @@ public interface BizLoadAppointService extends IService<BizLoadAppoint> {
      * 导出
      */
     void exportRecord(BizLoadAppointPageParam bizLoadAppointPageParam,HttpServletResponse response);
+
+    /**
+     * 获取起卸预约待报港列表
+     */
+    List<BizLoadAppoint> getList(BizLoadAppointPageParam bizLoadAppointPageParam);
 }

+ 25 - 1
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadappoint/service/impl/BizLoadAppointServiceImpl.java

@@ -12,6 +12,7 @@
  */
 package vip.xiaonuo.biz.modular.bizloadappoint.service.impl;
 
+import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollStreamUtil;
 import cn.hutool.core.date.DateUtil;
@@ -27,6 +28,7 @@ import jakarta.servlet.http.HttpServletResponse;
 import org.apache.commons.compress.utils.Lists;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
 import vip.xiaonuo.biz.modular.bizloadappoint.param.*;
 import vip.xiaonuo.biz.modular.bizloadappointsupplier.entity.BizLoadAppointSupplier;
 import vip.xiaonuo.biz.modular.bizloadappointsupplier.service.BizLoadAppointSupplierService;
@@ -43,6 +45,7 @@ import vip.xiaonuo.biz.modular.bizloadappoint.service.BizLoadAppointService;
 
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.concurrent.locks.ReentrantLock;
@@ -103,6 +106,11 @@ public class BizLoadAppointServiceImpl extends ServiceImpl<BizLoadAppointMapper,
             queryWrapper.between("bla.create_time",bizLoadAppointPageParam.getCreateTimeBegin()+" 00:00:00",
                     bizLoadAppointPageParam.getCreateTimeEnd()+" 23:59:59");
         }
+        // 校验数据范围
+        List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
+        if(ObjectUtil.isEmpty(loginUserDataScope)) {
+            queryWrapper.eq("bla.customer_id", StpLoginUserUtil.getLoginUser().getCustomerId());
+        }
         queryWrapper.eq("bla.delete_flag","NOT_DELETE");
         queryWrapper.orderByDesc("bla.create_time");
         return queryWrapper;
@@ -170,7 +178,12 @@ public class BizLoadAppointServiceImpl extends ServiceImpl<BizLoadAppointMapper,
 
     @Override
     public BizLoadAppoint detail(BizLoadAppointIdParam bizLoadAppointIdParam) {
-        return this.queryEntity(bizLoadAppointIdParam.getId());
+        QueryWrapper<BizLoadAppoint> queryWrapper = new QueryWrapper<>();
+        if(ObjectUtil.isNotEmpty(bizLoadAppointIdParam.getId())){
+            queryWrapper.eq("bla.id",bizLoadAppointIdParam.getId());
+        }
+        BizLoadAppoint detail = this.getBaseMapper().getDetail(queryWrapper);
+        return detail;
     }
 
     @Override
@@ -227,6 +240,17 @@ public class BizLoadAppointServiceImpl extends ServiceImpl<BizLoadAppointMapper,
         CommonExportUtil.export(fileName, BizLoadAppointExportResult.class,list,response,"起卸预约报表");
     }
 
+    @Override
+    public List<BizLoadAppoint> getList(BizLoadAppointPageParam bizLoadAppointPageParam) {
+        QueryWrapper<BizLoadAppoint> queryWrapper = new QueryWrapper<>();
+        if(ObjectUtil.isNotEmpty(bizLoadAppointPageParam.getStatus())){
+            List<String> statusList = Arrays.asList(bizLoadAppointPageParam.getStatus().split(","));
+            queryWrapper.lambda().in(BizLoadAppoint::getStatus,statusList);
+        }
+        List<BizLoadAppoint> list = this.list(queryWrapper);
+        return list;
+    }
+
 
     public String getNumber(){
         lock.lock();

+ 146 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/controller/BizLoadArriveController.java

@@ -0,0 +1,146 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.controller;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import vip.xiaonuo.biz.modular.bizloadappoint.param.BizLoadAppointPageParam;
+import vip.xiaonuo.common.annotation.CommonLog;
+import vip.xiaonuo.common.pojo.CommonResult;
+import vip.xiaonuo.biz.modular.bizloadarrive.entity.BizLoadArrive;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.BizLoadArriveAddParam;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.BizLoadArriveEditParam;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.BizLoadArriveIdParam;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.BizLoadArrivePageParam;
+import vip.xiaonuo.biz.modular.bizloadarrive.service.BizLoadArriveService;
+
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotEmpty;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * 报港预约控制器
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ */
+@Tag(name = "报港预约控制器")
+@RestController
+@Validated
+public class BizLoadArriveController {
+
+    @Resource
+    private BizLoadArriveService bizLoadArriveService;
+
+    /**
+     * 获取报港预约分页
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    @Operation(summary = "获取报港预约分页")
+    @SaCheckPermission("/biz/bizloadarrive/page")
+    @GetMapping("/biz/bizloadarrive/page")
+    public CommonResult<Page<BizLoadArrive>> page(BizLoadArrivePageParam bizLoadArrivePageParam) {
+        return CommonResult.data(bizLoadArriveService.page(bizLoadArrivePageParam));
+    }
+
+    /**
+     * 添加报港预约
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    @Operation(summary = "添加报港预约")
+    @CommonLog("添加报港预约")
+    @PostMapping("/biz/bizloadarrive/add")
+    public CommonResult<String> add(@RequestBody @Valid BizLoadArriveAddParam bizLoadArriveAddParam) {
+        bizLoadArriveService.add(bizLoadArriveAddParam);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 编辑报港预约
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    @Operation(summary = "编辑报港预约")
+    @CommonLog("编辑报港预约")
+    @PostMapping("/biz/bizloadarrive/edit")
+    public CommonResult<String> edit(@RequestBody @Valid BizLoadArriveEditParam bizLoadArriveEditParam) {
+        bizLoadArriveService.edit(bizLoadArriveEditParam);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 删除报港预约
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    @Operation(summary = "删除报港预约")
+    @CommonLog("删除报港预约")
+    @PostMapping("/biz/bizloadarrive/delete")
+    public CommonResult<String> delete(@RequestBody @Valid @NotEmpty(message = "集合不能为空")
+                                                   List<BizLoadArriveIdParam> bizLoadArriveIdParamList) {
+        bizLoadArriveService.delete(bizLoadArriveIdParamList);
+        return CommonResult.ok();
+    }
+
+    /**
+     * 获取报港预约详情
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    @Operation(summary = "获取报港预约详情")
+    @GetMapping("/biz/bizloadarrive/detail")
+    public CommonResult<BizLoadArrive> detail(@Valid BizLoadArriveIdParam bizLoadArriveIdParam) {
+        return CommonResult.data(bizLoadArriveService.detail(bizLoadArriveIdParam));
+    }
+
+    /**
+     * 报港预约审核
+     */
+    @Operation(summary = "报港预约审核")
+    @CommonLog("报港预约审核")
+    @PostMapping("/biz/bizloadarrive/auditArrive")
+    public CommonResult<String> auditArrive(@RequestBody @Valid BizLoadArriveEditParam bizLoadArriveEditParam) {
+        bizLoadArriveService.auditArrive(bizLoadArriveEditParam);
+        return CommonResult.ok();
+    }
+
+
+    /**
+     * 导出报港预约报表
+     */
+    @Operation(summary = "导出报港预约报表")
+    @SaCheckPermission("/biz/bizloadarrive/exportRecord")
+    @GetMapping(value = "/biz/bizloadarrive/exportRecord", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+    public void exportRecord(BizLoadArrivePageParam bizLoadArrivePageParam, HttpServletResponse response) throws IOException {
+        bizLoadArriveService.exportRecord(bizLoadArrivePageParam,response);
+    }
+}

+ 96 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/entity/BizLoadArrive.java

@@ -0,0 +1,96 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fhs.core.trans.anno.Trans;
+import com.fhs.core.trans.constant.TransType;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import vip.xiaonuo.common.pojo.CommonEntity;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 报港预约实体
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+@Getter
+@Setter
+@TableName("biz_load_arrive")
+public class BizLoadArrive extends CommonEntity {
+
+    /** 主键ID */
+    @TableId
+    @Schema(description = "主键ID")
+    private String id;
+
+    /** 起卸预约id */
+    @Schema(description = "起卸预约id")
+    private String appointId;
+
+    /** 报港数量 */
+    @Schema(description = "报港数量")
+    private BigDecimal arriveNumber;
+
+    /** 到港时间 */
+    @Schema(description = "到港时间")
+    private Date arriveTime;
+
+    /** 发航单名称 */
+    @Schema(description = "发航单名称")
+    private String sailFileName;
+
+    /** 发航单路径 */
+    @Schema(description = "发航单路径")
+    private String sailFilePath;
+
+    /**船号**/
+    private String shipNo;
+
+    /**状态*/
+    @Trans(type = TransType.DICTIONARY, key = "arrive_status")
+    private String status;
+
+    /**客户名称*/
+    @TableField(exist = false)
+    private String customerName;
+
+    /**客户联系人*/
+    @TableField(exist = false)
+    private String customerContact;
+
+    /**联系方式*/
+    @TableField(exist = false)
+    private String customerPhone;
+
+    /**客户地址**/
+    @TableField(exist = false)
+    private String customerAddress;
+
+    /**货品名称*/
+    @TableField(exist = false)
+    private String goodsName;
+
+    /**货品编码*/
+    @TableField(exist = false)
+    private String goodsCode;
+
+    /***起卸预约单号*/
+    @TableField(exist = false)
+    private String loadNumber;
+}

+ 34 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/enums/BizLoadArriveEnum.java

@@ -0,0 +1,34 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.enums;
+
+import lombok.Getter;
+
+/**
+ * 报港预约枚举
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+@Getter
+public enum BizLoadArriveEnum {
+
+    /** 测试 */
+    TEST("TEST");
+
+    private final String value;
+
+    BizLoadArriveEnum(String value) {
+        this.value = value;
+    }
+}

+ 33 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/mapper/BizLoadArriveMapper.java

@@ -0,0 +1,33 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import org.apache.ibatis.annotations.Param;
+import vip.xiaonuo.biz.modular.bizloadarrive.entity.BizLoadArrive;
+
+import java.util.List;
+
+/**
+ * 报港预约Mapper接口
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+public interface BizLoadArriveMapper extends BaseMapper<BizLoadArrive> {
+    Page<BizLoadArrive> getPage(@Param("page") Page<BizLoadArrive> page, @Param("ew") QueryWrapper<BizLoadArrive> ew);
+
+    List<BizLoadArrive> getPage(@Param("ew") QueryWrapper<BizLoadArrive> ew);
+}

+ 30 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/mapper/mapping/BizLoadArriveMapper.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="vip.xiaonuo.biz.modular.bizloadarrive.mapper.BizLoadArriveMapper">
+
+    <select id="getPage" resultType="vip.xiaonuo.biz.modular.bizloadarrive.entity.BizLoadArrive">
+        select
+            blv.id,
+            blv.appoint_id,
+            blv.ship_no,
+            ifnull(blv.arrive_number/1000,0) arrive_number,
+            blv.arrive_time,
+            blv.sail_file_name,
+            blv.sail_file_path,
+            blv.status,
+            blv.create_time,
+            blv.create_user,
+            bla.load_number,
+            bsc.`name` customerName,
+            bsc.contact customerContact,
+            bsc.phone customerPhone,
+            bsc.address customerAddress,
+            bg.GOODS_NAME goodsName,
+            bg.GOODS_CODE goodsCode
+        from biz_load_arrive blv
+         left join biz_load_appoint bla on blv.appoint_id = bla.id
+         left join biz_service_customer bsc on bla.customer_id = bsc.id
+         left join biz_goods bg on bg.id = bla.goods_id
+         ${ew.customSqlSegment}
+    </select>
+</mapper>

+ 64 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArriveAddParam.java

@@ -0,0 +1,64 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 报港预约添加参数
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+@Getter
+@Setter
+public class BizLoadArriveAddParam {
+
+    /** 起卸预约id */
+    @Schema(description = "起卸预约id")
+    private String appointId;
+
+    /** 报港数量 */
+    @Schema(description = "报港数量")
+    private BigDecimal arriveNumber;
+
+    /** 到港时间 */
+    @Schema(description = "到港时间")
+    private Date arriveTime;
+
+    /** 发航单名称 */
+    @Schema(description = "发航单名称")
+    private String sailFileName;
+
+    /** 发航单路径 */
+    @Schema(description = "发航单路径")
+    private String sailFilePath;
+
+    /**文件路径集合*/
+    private List<String> filePathList;
+
+    /**文件名称集合*/
+    private List<String> fileNameList;
+
+    /**船号**/
+    private String shipNo;
+
+}

+ 75 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArriveEditParam.java

@@ -0,0 +1,75 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 报港预约编辑参数
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+@Getter
+@Setter
+public class BizLoadArriveEditParam {
+
+    /** 主键ID */
+    @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotBlank(message = "id不能为空")
+    private String id;
+
+    /** 起卸预约id */
+    @Schema(description = "起卸预约id")
+    private String appointId;
+
+    /** 报港数量 */
+    @Schema(description = "报港数量")
+    private BigDecimal arriveNumber;
+
+    /** 到港时间 */
+    @Schema(description = "到港时间")
+    private Date arriveTime;
+
+    /** 发航单名称 */
+    @Schema(description = "发航单名称")
+    private String sailFileName;
+
+    /** 发航单路径 */
+    @Schema(description = "发航单路径")
+    private String sailFilePath;
+
+    /**文件路径集合*/
+    private List<String> filePathList;
+
+    /**文件名称集合*/
+    private List<String> fileNameList;
+
+    /**船号**/
+    private String shipNo;
+
+    /**审核标识*/
+    private String auditFlag;
+
+    /**审核备注*/
+    private String arriveReason;
+
+}

+ 78 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArriveExportResult.java

@@ -0,0 +1,78 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.param;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.HeadStyle;
+import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+import vip.xiaonuo.common.pojo.CommonEntity;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 报港预约实体
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+@Data
+public class BizLoadArriveExportResult{
+
+    /***起卸预约单号*/
+    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 120)
+    @ExcelProperty({"报港预约报表", "起卸预约单号"})
+    private String loadNumber;
+
+    /**船号**/
+    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 120)
+    @ExcelProperty({"报港预约报表", "船号"})
+    private String shipNo;
+
+    /**客户名称*/
+    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 120)
+    @ExcelProperty({"报港预约报表", "客户名称"})
+    private String customerName;
+
+    /**货品名称*/
+    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 120)
+    @ExcelProperty({"报港预约报表", "货品名称"})
+    private String goodsName;
+
+    /** 报港数量 */
+    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 120)
+    @ExcelProperty({"报港预约报表", "报港数量(吨)"})
+    private BigDecimal arriveNumber;
+
+    /** 到港时间 */
+    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 120)
+    @ExcelProperty({"报港预约报表", "到港时间"})
+    private Date arriveTime;
+
+    /**状态*/
+    @HeadStyle(fillPatternType = FillPatternTypeEnum.SOLID_FOREGROUND, fillForegroundColor = 120)
+    @ExcelProperty({"报港预约报表", "状态"})
+    private String status;
+
+
+
+
+
+}

+ 35 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArriveIdParam.java

@@ -0,0 +1,35 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.param;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+import jakarta.validation.constraints.NotBlank;
+
+/**
+ * 报港预约Id参数
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+@Getter
+@Setter
+public class BizLoadArriveIdParam {
+
+    /** 主键ID */
+    @Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED)
+    @NotBlank(message = "id不能为空")
+    private String id;
+}

+ 80 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/param/BizLoadArrivePageParam.java

@@ -0,0 +1,80 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.param;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 报港预约查询参数
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+@Getter
+@Setter
+public class BizLoadArrivePageParam {
+
+    /** 当前页 */
+    @Schema(description = "当前页码")
+    private Integer current;
+
+    /** 每页条数 */
+    @Schema(description = "每页条数")
+    private Integer size;
+
+    /** 排序字段 */
+    @Schema(description = "排序字段,字段驼峰名称,如:userName")
+    private String sortField;
+
+    /** 排序方式 */
+    @Schema(description = "排序方式,升序:ASCEND;降序:DESCEND")
+    private String sortOrder;
+
+    /** 关键词 */
+    @Schema(description = "关键词")
+    private String searchKey;
+
+    /**客户单位*/
+    private String customerName;
+
+    /**客户联系人*/
+    private String customerContact;
+
+    /**联系方式*/
+    private String customerPhone;
+
+    /**客户地址**/
+    private String customerAddress;
+
+    /**船号**/
+    private String shipNo;
+
+    /**货品名称*/
+    private String goodsName;
+
+    /**到港时间*/
+    private String arriveTimeBegin;
+    private String arriveTimeEnd;
+
+    /**预约单号**/
+    private String loadNumber;
+
+    /**状态**/
+    private String status;
+
+}

+ 92 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/service/BizLoadArriveService.java

@@ -0,0 +1,92 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import jakarta.servlet.http.HttpServletResponse;
+import vip.xiaonuo.biz.modular.bizloadappoint.param.BizLoadAppointPageParam;
+import vip.xiaonuo.biz.modular.bizloadarrive.entity.BizLoadArrive;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.BizLoadArriveAddParam;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.BizLoadArriveEditParam;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.BizLoadArriveIdParam;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.BizLoadArrivePageParam;
+
+import java.util.List;
+
+/**
+ * 报港预约Service接口
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+public interface BizLoadArriveService extends IService<BizLoadArrive> {
+
+    /**
+     * 获取报港预约分页
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    Page<BizLoadArrive> page(BizLoadArrivePageParam bizLoadArrivePageParam);
+
+    /**
+     * 添加报港预约
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    void add(BizLoadArriveAddParam bizLoadArriveAddParam);
+
+    /**
+     * 编辑报港预约
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    void edit(BizLoadArriveEditParam bizLoadArriveEditParam);
+
+    /**
+     * 删除报港预约
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    void delete(List<BizLoadArriveIdParam> bizLoadArriveIdParamList);
+
+    /**
+     * 获取报港预约详情
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     */
+    BizLoadArrive detail(BizLoadArriveIdParam bizLoadArriveIdParam);
+
+    /**
+     * 获取报港预约详情
+     *
+     * @author fanzherong
+     * @date  2025/06/26 14:12
+     **/
+    BizLoadArrive queryEntity(String id);
+
+    /**
+     * 审核
+     */
+    void auditArrive(BizLoadArriveEditParam bizLoadArriveEditParam);
+
+    /**
+     * 导出
+     */
+    void exportRecord(BizLoadArrivePageParam bizLoadArrivePageParam, HttpServletResponse response);
+}

+ 340 - 0
snowy-plugin/snowy-plugin-biz/src/main/java/vip/xiaonuo/biz/modular/bizloadarrive/service/impl/BizLoadArriveServiceImpl.java

@@ -0,0 +1,340 @@
+/*
+ * Copyright [2022] [https://www.xiaonuo.vip]
+ *
+ * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
+ *
+ * 1.请不要删除和修改根目录下的LICENSE文件。
+ * 2.请不要删除和修改Snowy源码头部的版权声明。
+ * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
+ * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
+ * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
+ * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
+ */
+package vip.xiaonuo.biz.modular.bizloadarrive.service.impl;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollStreamUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fhs.trans.service.impl.TransService;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.commons.compress.utils.Lists;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import vip.xiaonuo.auth.core.util.StpLoginUserUtil;
+import vip.xiaonuo.biz.modular.bizauditlog.entity.BizAuditLog;
+import vip.xiaonuo.biz.modular.bizauditlog.service.BizAuditLogService;
+import vip.xiaonuo.biz.modular.bizloadappoint.entity.BizLoadAppoint;
+import vip.xiaonuo.biz.modular.bizloadappoint.param.BizLoadAppointExportResult;
+import vip.xiaonuo.biz.modular.bizloadappoint.service.BizLoadAppointService;
+import vip.xiaonuo.biz.modular.bizloadarrive.param.*;
+import vip.xiaonuo.biz.modular.bizsettle.entity.BizSettle;
+import vip.xiaonuo.biz.modular.bizsupplier.entity.BizSupplierTransport;
+import vip.xiaonuo.biz.modular.bizsupplier.service.BizSupplierTransportService;
+import vip.xiaonuo.biz.modular.utils.CommonExportUtil;
+import vip.xiaonuo.common.enums.CommonSortOrderEnum;
+import vip.xiaonuo.common.exception.CommonException;
+import vip.xiaonuo.common.page.CommonPageRequest;
+import vip.xiaonuo.biz.modular.bizloadarrive.entity.BizLoadArrive;
+import vip.xiaonuo.biz.modular.bizloadarrive.mapper.BizLoadArriveMapper;
+import vip.xiaonuo.biz.modular.bizloadarrive.service.BizLoadArriveService;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 报港预约Service接口实现类
+ *
+ * @author fanzherong
+ * @date  2025/06/26 14:12
+ **/
+@Service
+public class BizLoadArriveServiceImpl extends ServiceImpl<BizLoadArriveMapper, BizLoadArrive> implements BizLoadArriveService {
+
+    @Resource
+    private BizLoadAppointService bizLoadAppointService;
+
+    @Resource
+    private BizSupplierTransportService bizSupplierTransportService;
+
+    @Resource
+    private BizAuditLogService bizAuditLogService;
+
+    @Resource
+    private TransService transService;
+
+    @Override
+    public Page<BizLoadArrive> page(BizLoadArrivePageParam bizLoadArrivePageParam) {
+        QueryWrapper<BizLoadArrive> queryWrapper = getQueryWrapper(bizLoadArrivePageParam);
+        Page<BizLoadArrive> page = this.getBaseMapper().getPage(CommonPageRequest.defaultPage(), queryWrapper);
+        return page;
+    }
+
+    public QueryWrapper<BizLoadArrive> getQueryWrapper(BizLoadArrivePageParam bizLoadArrivePageParam){
+        QueryWrapper<BizLoadArrive> queryWrapper = new QueryWrapper<BizLoadArrive>().checkSqlInjection();
+        //客户名称
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getCustomerName())){
+            queryWrapper.like("bsc.`name`",bizLoadArrivePageParam.getCustomerName());
+        }
+        //联系人
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getCustomerContact())){
+            queryWrapper.like("bsc.contact",bizLoadArrivePageParam.getCustomerContact());
+        }
+        //联系方式
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getCustomerPhone())){
+            queryWrapper.like("bsc.phone",bizLoadArrivePageParam.getCustomerPhone());
+        }
+        //客户i地址
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getCustomerAddress())){
+            queryWrapper.like("bsc.address",bizLoadArrivePageParam.getCustomerAddress());
+        }
+        //货品名称
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getGoodsName())){
+            queryWrapper.like("bg.GOODS_NAME",bizLoadArrivePageParam.getGoodsName());
+        }
+        //船号
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getShipNo())){
+            queryWrapper.like("blv.ship_no",bizLoadArrivePageParam.getShipNo());
+        }
+        //到港时间
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getArriveTimeBegin()) &&
+                ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getArriveTimeEnd())){
+            queryWrapper.between("blv.arrive_time",bizLoadArrivePageParam.getArriveTimeBegin()+" 00:00:00",
+                    bizLoadArrivePageParam.getArriveTimeEnd()+ " 23:59:59");
+        }
+        //起卸预约单号
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getLoadNumber())){
+            queryWrapper.like("bla.load_number",bizLoadArrivePageParam.getLoadNumber());
+        }
+        //状态查询
+        if(ObjectUtil.isNotEmpty(bizLoadArrivePageParam.getStatus())){
+            queryWrapper.eq("blv.status",bizLoadArrivePageParam.getStatus());
+        }
+        // 校验数据范围
+        List<String> loginUserDataScope = StpLoginUserUtil.getLoginUserDataScope();
+        if(ObjectUtil.isEmpty(loginUserDataScope)) {
+            queryWrapper.eq("blv.create_user", StpUtil.getLoginIdAsString());
+        }
+        queryWrapper.eq("blv.delete_flag","NOT_DELETE");
+        queryWrapper.orderByDesc("blv.create_time");
+        return queryWrapper;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void add(BizLoadArriveAddParam bizLoadArriveAddParam) {
+        checkParam(bizLoadArriveAddParam);
+        BizLoadArrive bizLoadArrive = BeanUtil.toBean(bizLoadArriveAddParam, BizLoadArrive.class);
+        if(ObjectUtil.isNotEmpty(bizLoadArriveAddParam.getFileNameList())){
+            StringBuffer nameBuffer = new StringBuffer();
+            for(String name : bizLoadArriveAddParam.getFileNameList()){
+                nameBuffer.append(name+",");
+            }
+            bizLoadArrive.setSailFileName(nameBuffer.substring(0,nameBuffer.length()-1));
+        }
+        if(ObjectUtil.isNotEmpty(bizLoadArriveAddParam.getFilePathList())){
+            StringBuffer pathBuffer = new StringBuffer();
+            for(String path : bizLoadArriveAddParam.getFilePathList()){
+                pathBuffer.append(path+",");
+            }
+            bizLoadArrive.setSailFilePath(pathBuffer.substring(0,pathBuffer.length()-1));
+        }
+        bizLoadArrive.setArriveNumber(bizLoadArrive.getArriveNumber().multiply(new BigDecimal(1000)));
+        this.save(bizLoadArrive);
+
+        //修改状态
+        if(ObjectUtil.isNotEmpty(bizLoadArriveAddParam.getAppointId())){
+            BizLoadAppoint loadAppoint = bizLoadAppointService.getById(bizLoadArriveAddParam.getAppointId());
+            if(ObjectUtil.isNotNull(loadAppoint)){
+                loadAppoint.setStatus("3");
+                bizLoadAppointService.updateById(loadAppoint);
+            }
+        }
+    }
+
+    public void checkParam(BizLoadArriveAddParam bizLoadArriveAddParam){
+        if(ObjectUtil.isNotEmpty(bizLoadArriveAddParam.getShipNo())){
+            bizLoadArriveAddParam.setShipNo(bizLoadArriveAddParam.getShipNo().toUpperCase().trim());
+        }
+        if(ObjectUtil.isNotEmpty(bizLoadArriveAddParam.getAppointId())){
+            //查询起卸预约信息
+            BizLoadAppoint bizLoadAppoint = bizLoadAppointService.getById(bizLoadArriveAddParam.getAppointId());
+            if(ObjectUtil.isNotNull(bizLoadAppoint)){
+                //查询船号是否在船运供应商下
+                BizSupplierTransport transport = bizSupplierTransportService.getOne(new QueryWrapper<BizSupplierTransport>().lambda().
+                        eq(BizSupplierTransport::getSupplierId, bizLoadAppoint.getSupplierId()).
+                        eq(BizSupplierTransport::getTransportNo, bizLoadArriveAddParam.getShipNo()).
+                        eq(BizSupplierTransport::getAuditStatus,"2").
+                        last("limit 1"));
+                if(ObjectUtil.isNull(transport)){
+                    throw new CommonException("该船号没有绑定供应商!");
+                }
+            }
+
+            //判断起卸预约是否添加过
+            long count = this.count(new QueryWrapper<BizLoadArrive>().lambda().eq(BizLoadArrive::getAppointId, bizLoadArriveAddParam.getAppointId()));
+            if(count>0){
+                throw new CommonException("起卸预约已经添加过!");
+            }
+        }
+
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void edit(BizLoadArriveEditParam bizLoadArriveEditParam) {
+        BizLoadArrive bizLoadArrive = this.queryEntity(bizLoadArriveEditParam.getId());
+        checkParam(bizLoadArriveEditParam,bizLoadArrive);
+        if(!StringUtils.equals(bizLoadArrive.getAppointId(),bizLoadArriveEditParam.getAppointId())){
+            //修改原起卸预约单状态
+            BizLoadAppoint loadAppoint = bizLoadAppointService.getById(bizLoadArrive.getAppointId());
+            if(ObjectUtil.isNotNull(loadAppoint)){
+                loadAppoint.setStatus("2");
+                bizLoadAppointService.updateById(loadAppoint);
+            }
+
+            //修改现起卸预约单状态
+            BizLoadAppoint loadAppointNew = bizLoadAppointService.getById(bizLoadArriveEditParam.getAppointId());
+            if(ObjectUtil.isNotNull(loadAppointNew)){
+                loadAppointNew.setStatus("3");
+                bizLoadAppointService.updateById(loadAppointNew);
+            }
+        }
+        BeanUtil.copyProperties(bizLoadArriveEditParam, bizLoadArrive);
+        if(ObjectUtil.isNotEmpty(bizLoadArriveEditParam.getFileNameList())){
+            StringBuffer nameBuffer = new StringBuffer();
+            for(String name : bizLoadArriveEditParam.getFileNameList()){
+                nameBuffer.append(name+",");
+            }
+            bizLoadArrive.setSailFileName(nameBuffer.substring(0,nameBuffer.length()-1));
+        }
+        if(ObjectUtil.isNotEmpty(bizLoadArriveEditParam.getFilePathList())){
+            StringBuffer pathBuffer = new StringBuffer();
+            for(String path : bizLoadArriveEditParam.getFilePathList()){
+                pathBuffer.append(path+",");
+            }
+            bizLoadArrive.setSailFilePath(pathBuffer.substring(0,pathBuffer.length()-1));
+        }
+        bizLoadArrive.setArriveNumber(bizLoadArrive.getArriveNumber().multiply(new BigDecimal(1000)));
+        if(StringUtils.equals(bizLoadArrive.getStatus(),"3")){
+            bizLoadArrive.setStatus("1");
+        }
+        this.updateById(bizLoadArrive);
+    }
+
+    public void checkParam(BizLoadArriveEditParam bizLoadArriveEditParam,BizLoadArrive bizLoadArrive){
+        if(ObjectUtil.isNotEmpty(bizLoadArriveEditParam.getShipNo())){
+            bizLoadArriveEditParam.setShipNo(bizLoadArriveEditParam.getShipNo().toUpperCase().trim());
+        }
+        if(!StringUtils.equals(bizLoadArrive.getAppointId(),bizLoadArriveEditParam.getAppointId()) ||
+            !StringUtils.equals(bizLoadArrive.getShipNo(),bizLoadArriveEditParam.getShipNo())){
+            //如果船号和起卸预约订单有变化,判断船号是否绑定供应商
+            //查询起卸预约信息
+            BizLoadAppoint bizLoadAppoint = bizLoadAppointService.getById(bizLoadArriveEditParam.getAppointId());
+            if(ObjectUtil.isNotNull(bizLoadAppoint)){
+                //查询船号是否在船运供应商下
+                BizSupplierTransport transport = bizSupplierTransportService.getOne(new QueryWrapper<BizSupplierTransport>().lambda().
+                        eq(BizSupplierTransport::getSupplierId, bizLoadAppoint.getSupplierId()).
+                        eq(BizSupplierTransport::getTransportNo, bizLoadArriveEditParam.getShipNo()).
+                        eq(BizSupplierTransport::getAuditStatus,"2").
+                        last("limit 1"));
+                if(ObjectUtil.isNull(transport)){
+                    throw new CommonException("该船号没有绑定供应商!");
+                }
+            }
+
+        }
+
+        if(!StringUtils.equals(bizLoadArrive.getAppointId(),bizLoadArriveEditParam.getAppointId())){
+            //判断起卸预约是否添加过
+            long count = this.count(new QueryWrapper<BizLoadArrive>().lambda().eq(BizLoadArrive::getAppointId, bizLoadArriveEditParam.getAppointId()));
+            if(count>0){
+                throw new CommonException("起卸预约已经添加过!");
+            }
+        }
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void delete(List<BizLoadArriveIdParam> bizLoadArriveIdParamList) {
+        //修改起卸预约状态
+        for(BizLoadArriveIdParam bizLoadArriveIdParam : bizLoadArriveIdParamList){
+            BizLoadArrive bizLoadArrive = this.queryEntity(bizLoadArriveIdParam.getId());
+            BizLoadAppoint loadAppoint = bizLoadAppointService.getById(bizLoadArrive.getAppointId());
+            if(ObjectUtil.isNotNull(loadAppoint)){
+                loadAppoint.setStatus("2");
+                bizLoadAppointService.updateById(loadAppoint);
+            }
+        }
+        // 执行删除
+        this.removeByIds(CollStreamUtil.toList(bizLoadArriveIdParamList, BizLoadArriveIdParam::getId));
+    }
+
+    @Override
+    public BizLoadArrive detail(BizLoadArriveIdParam bizLoadArriveIdParam) {
+        return this.queryEntity(bizLoadArriveIdParam.getId());
+    }
+
+    @Override
+    public BizLoadArrive queryEntity(String id) {
+        BizLoadArrive bizLoadArrive = this.getById(id);
+        if(ObjectUtil.isEmpty(bizLoadArrive)) {
+            throw new CommonException("报港预约不存在,id值为:{}", id);
+        }
+        return bizLoadArrive;
+    }
+
+    @Override
+    public void auditArrive(BizLoadArriveEditParam bizLoadArriveEditParam) {
+        BizLoadArrive bizLoadArrive = this.queryEntity(bizLoadArriveEditParam.getId());
+        String status = "";
+        String auditStatus = "";
+        if(StringUtils.equals(bizLoadArriveEditParam.getAuditFlag(),"true")){
+            //审核通过
+            status="2";
+            auditStatus = "1";
+        }else{
+            status = "3";
+            auditStatus = "2";
+        }
+
+        //修改状态
+        UpdateWrapper<BizLoadArrive> updateWrapper = new UpdateWrapper<>();
+        updateWrapper.set("status",status).eq("id",bizLoadArrive.getId());
+        this.update(updateWrapper);
+
+        //插入审核记录
+        BizAuditLog bizAuditLog = new BizAuditLog();
+        bizAuditLog.setType("BGYY");
+        bizAuditLog.setDataId(bizLoadArrive.getId());
+        bizAuditLog.setStatus(auditStatus);
+        bizAuditLog.setRemark(bizLoadArriveEditParam.getArriveReason());
+        bizAuditLogService.save(bizAuditLog);
+    }
+
+    @Override
+    public void exportRecord(BizLoadArrivePageParam bizLoadArrivePageParam, HttpServletResponse response) {
+        QueryWrapper<BizLoadArrive> queryWrapper = getQueryWrapper(bizLoadArrivePageParam);
+        List<BizLoadArrive> arriveList = this.getBaseMapper().getPage(queryWrapper);
+        if(ObjectUtil.isEmpty(arriveList)){
+            throw new CommonException("无数据可导出!");
+        }
+        String fileName = "报港预约报表.xlsx";
+        List<BizLoadArriveExportResult> list = Lists.newArrayList();
+        transService.transBatch(arriveList);
+        for(BizLoadArrive bizLoadArrive : arriveList){
+            BizLoadArriveExportResult bizLoadArriveExportResult = new BizLoadArriveExportResult();
+            BeanUtil.copyProperties(bizLoadArrive, bizLoadArriveExportResult);
+            bizLoadArriveExportResult.setStatus((String) bizLoadArrive.getTransMap().get("statusName"));
+            list.add(bizLoadArriveExportResult);
+        }
+        CommonExportUtil.export(fileName, BizLoadArriveExportResult.class,list,response,"报港预约报表");
+    }
+}