| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619 |
- <template>
- <div class="line-container-p24">
- <div
- class="df aic dib go-back ml8 pointer"
- @click="router.replace('/shipOwnerManage/shipOwnerList')"
- >
- <el-icon class="mr10"><ArrowLeftBold /></el-icon>
- <div>返回船员列表</div>
- </div>
- </div>
- <div class="container-title">基本信息</div>
- <div class="line-container-p24">
- <el-form
- :model="shipOwnerForm"
- :rules="rules"
- ref="shipOwnerFormRef"
- label-width="100px"
- label-position="left"
- >
- <el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="船员姓名" prop="userName" required>
- <el-input
- v-model="shipOwnerForm.userName"
- placeholder="请输入"
- :disabled="!!shipOwnerForm.shipOwnerId"
- ></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="船员手机号" prop="userPhone" required>
- <el-input
- v-model="shipOwnerForm.userPhone"
- placeholder="请输入"
- :disabled="!!shipOwnerForm.shipOwnerId"
- @blur="handlePhoneBlur"
- ></el-input>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="船员身份证号">
- <el-input
- v-model="shipOwnerForm.idcardNo"
- placeholder="请输入"
- :disabled="!!shipOwnerForm.shipOwnerId"
- ></el-input>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="身份证人像面">
- <Uploader
- :action-url="uploadConfig.uploadUrl"
- :file-list="idCardFrontFileList"
- :params="{ type: 'idCardFront' }"
- @on-upload-file-list="handleIdCardFrontUpload"
- @on-remove-file-list="handleIdCardFrontRemove"
- :limit="1"
- upload-text="点击上传人像面"
- :disabled="!!shipOwnerForm.shipOwnerId"
- />
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="身份证国徽面">
- <Uploader
- :action-url="uploadConfig.uploadUrl"
- :file-list="idCardBackFileList"
- :params="{ type: 'idCardBack' }"
- @on-upload-file-list="handleIdCardBackUpload"
- @on-remove-file-list="handleIdCardBackRemove"
- :limit="1"
- upload-text="点击上传国徽面"
- :disabled="!!shipOwnerForm.shipOwnerId"
- />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </div>
- <div class="container-title">船员证书信息</div>
- <div class="line-container-p24">
- <el-form
- :model="shipOwnerForm.cerificate"
- :rules="certificateRules"
- ref="certificateFormRef"
- label-width="100px"
- label-position="left"
- >
- <el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="性别">
- <el-select
- v-model="shipOwnerForm.cerificate.gender"
- placeholder="请选择"
- >
- <el-option label="男" :value="1"></el-option>
- <el-option label="女" :value="2"></el-option>
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="证书编号" prop="certNo" required>
- <el-input
- v-model="shipOwnerForm.cerificate.certNo"
- placeholder="请输入"
- ></el-input>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="证书类型">
- <el-input
- v-model="shipOwnerForm.cerificate.certType"
- placeholder="请输入"
- ></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="职务资格" prop="postRole" required>
- <el-select
- v-model="shipOwnerForm.cerificate.postRole"
- placeholder="请选择"
- >
- <el-option label="大副" value="大副"></el-option>
- <el-option label="二副" value="二副"></el-option>
- <el-option label="三副" value="三副"></el-option>
- <el-option label="船长" value="船长"></el-option>
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="发证日期" prop="issuerAt" required>
- <el-date-picker
- v-model="shipOwnerForm.cerificate.issuerAt"
- type="date"
- placeholder="选择日期"
- format="YYYY/MM/DD"
- />
- </el-form-item>
- </el-col>
- <el-col :span="8">
- <el-form-item label="截止日期" prop="expiryAt" required>
- <el-date-picker
- v-model="shipOwnerForm.cerificate.expiryAt"
- type="date"
- placeholder="选择日期"
- format="YYYY/MM/DD"
- />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="20">
- <el-col :span="8">
- <el-form-item label="签发机构" prop="issuerAuthority" required>
- <el-input
- v-model="shipOwnerForm.cerificate.issuerAuthority"
- placeholder="请输入"
- ></el-input>
- </el-form-item>
- </el-col>
- <el-col :span="16">
- <el-form-item label="适用限制">
- <el-input
- type="textarea"
- v-model="shipOwnerForm.cerificate.applicableRestrictions"
- :rows="4"
- placeholder="请输入"
- ></el-input>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row>
- <el-col :span="8">
- <el-form-item label="证书照片" prop="certFile" required>
- <Uploader
- :action-url="uploadConfig.uploadUrl"
- :file-list="certFileList"
- :params="{ type: 'certFile', docType: 1 }"
- @on-upload-file-list="handleCertUpload"
- @on-remove-file-list="handleCertRemove"
- :limit="1"
- upload-text="点击上传证书"
- />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- </div>
- <div class="container-title">其他文件</div>
- <div class="line-container-p24">
- <div class="mb20">健康证明</div>
- <Uploader
- :action-url="uploadConfig.uploadUrl"
- :file-list="healthFileList"
- :params="{ type: 'healthFile', docType: 2 }"
- @on-upload-file-list="handleHealthUpload"
- @on-remove-file-list="handleHealthRemove"
- :limit="2"
- upload-text="点击上传"
- />
- <div class="mb20 mt30">服务簿</div>
- <Uploader
- :action-url="uploadConfig.uploadUrl"
- :file-list="serviceFileList"
- :params="{ type: 'serviceFile', docType: 3 }"
- @on-upload-file-list="handleServiceUpload"
- @on-remove-file-list="handleServiceRemove"
- :limit="2"
- upload-text="点击上传"
- />
- </div>
- <div class="df jcc mt30 mb30">
- <el-button @click="router.replace('/shipOwnerManage/shipOwnerList')">
- 取消
- </el-button>
- <el-button type="primary" @click="saveShipOwner">保存</el-button>
- </div>
- </template>
- <script setup>
- import { ref, h, reactive, toRefs, onMounted, computed } from "vue";
- import { ElNotification, ElMessageBox, ElMessage } from "element-plus";
- import store from "../../store";
- import router from "../../router";
- import md5 from "md5";
- import api from "../../apis/fetch";
- import { useRoute } from "vue-router";
- import _ from "lodash";
- const route = useRoute();
- const uploadConfig = ref({});
- const shipOwnerFormRef = ref(null);
- const certificateFormRef = ref(null);
- // 表单验证规则
- const rules = {
- userName: [{ required: true, message: "请输入船员姓名", trigger: "blur" }],
- userPhone: [
- { required: true, message: "请输入船员手机号", trigger: "blur" },
- {
- pattern: /^1[3-9]\d{9}$/,
- message: "请输入正确的手机号格式",
- trigger: "blur",
- },
- ],
- };
- // 验证证书照片
- const validateCertFile = (rule, value, callback) => {
- if (!certFileList.value || certFileList.value.length === 0) {
- callback(new Error("请上传证书照片"));
- } else {
- callback();
- }
- };
- // 验证截止日期
- const validateExpiryDate = (rule, value, callback) => {
- if (!value) {
- callback(new Error("请选择截止日期"));
- } else {
- if (shipOwnerForm.value.cerificate.issuerAt) {
- // 确保截止日期晚于发证日期
- if (
- new Date(value) <= new Date(shipOwnerForm.value.cerificate.issuerAt)
- ) {
- callback(new Error("截止日期必须晚于发证日期"));
- }
- }
- callback();
- }
- };
- // 验证发证日期
- const validateIssuerDate = (rule, value, callback) => {
- if (!value) {
- callback(new Error("请选择发证日期"));
- } else {
- if (shipOwnerForm.value.cerificate.expiryAt) {
- // 如果已选择截止日期,确保发证日期早于截止日期
- if (
- new Date(value) >= new Date(shipOwnerForm.value.cerificate.expiryAt)
- ) {
- callback(new Error("发证日期必须早于截止日期"));
- }
- }
- callback();
- }
- };
- // 证书表单验证规则
- const certificateRules = {
- certNo: [{ required: true, message: "请输入证书编号", trigger: "blur" }],
- postRole: [{ required: true, message: "请选择职务资格", trigger: "change" }],
- issuerAt: [
- { required: true, message: "请选择发证日期", trigger: "change" },
- { validator: validateIssuerDate, trigger: "change" },
- ],
- expiryAt: [
- { required: true, message: "请选择截止日期", trigger: "change" },
- { validator: validateExpiryDate, trigger: "change" },
- ],
- issuerAuthority: [
- { required: true, message: "请输入签发机构", trigger: "blur" },
- ],
- certFile: [{ validator: validateCertFile, trigger: "change" }],
- };
- // 初始化船员表单数据结构
- const shipOwnerForm = ref({
- shipOwnerId: 0, // 船员ID,匹配时返回,未匹配到为0,非0时下方内容无效
- userName: "", // 船员姓名(必填)
- userPhone: "", // 船员手机(必填)
- idcardNo: "", // 船员身份证号(非必填)
- idcardFrontFileKey: "", // 船员身份证正面文件key(非必填)
- idcardFrontViewUrl: "", // 船员身份证正面文件预览地址(非必填)
- idcardFrontDownloadUrl: "", // 船员身份证正面文件下载地址(非必填)
- idcardBackFileKey: "", // 船员身份证反面文件key(非必填)
- idcardBackViewUrl: "", // 船员身份证反面文件预览地址(非必填)
- idcardBackDownloadUrl: "", // 船员身份证反面文件下载地址(非必填)
- cerificate: {
- gender: "", // 性别(1-男;2-女)
- certNo: "", // 证书编号(必填)
- certType: "", // 证书类型(非必填)
- postRole: "", // 职务资格(必填)
- issuerAt: "", // 发证日期(必填)
- expiryAt: "", // 截止日期(必填)
- issuerAuthority: "", // 签发机构(必填)
- applicableRestrictions: "", // 适用限制(非必填)
- },
- documents: [], // 文件信息数组
- });
- // 计算属性 - 文件列表
- const idCardFrontFileList = computed(() => {
- if (
- shipOwnerForm.value.idcardFrontFileKey &&
- shipOwnerForm.value.idcardFrontViewUrl
- ) {
- return [
- {
- fileKey: shipOwnerForm.value.idcardFrontFileKey,
- viewUrl: shipOwnerForm.value.idcardFrontViewUrl,
- downloadUrl: shipOwnerForm.value.idcardFrontDownloadUrl,
- },
- ];
- }
- return [];
- });
- const idCardBackFileList = computed(() => {
- if (
- shipOwnerForm.value.idcardBackFileKey &&
- shipOwnerForm.value.idcardBackViewUrl
- ) {
- return [
- {
- fileKey: shipOwnerForm.value.idcardBackFileKey,
- viewUrl: shipOwnerForm.value.idcardBackViewUrl,
- downloadUrl: shipOwnerForm.value.idcardBackDownloadUrl,
- },
- ];
- }
- return [];
- });
- const certFileList = computed(() => {
- return (
- shipOwnerForm.value.documents?.filter((doc) => doc.docType === 1) || []
- );
- });
- const healthFileList = computed(() => {
- return (
- shipOwnerForm.value.documents?.filter((doc) => doc.docType === 2) || []
- );
- });
- const serviceFileList = computed(() => {
- return (
- shipOwnerForm.value.documents?.filter((doc) => doc.docType === 3) || []
- );
- });
- // 初始化数据
- onMounted(() => {
- // 如果有ID参数,获取船员详情
- if (route.query.id) {
- api.getShipOwnerDetail({ id: route.query.id }).then((res) => {
- if (res.data.code === 0) {
- const data = res.data.data;
- // 直接使用API返回的数据结构
- Object.assign(shipOwnerForm.value, data);
- }
- });
- }
- });
- // 手机号失去焦点时检查是否已存在船员信息
- const handlePhoneBlur = () => {
- if (!shipOwnerForm.value.userPhone) return;
- // 如果已经有shipOwnerId,说明已经匹配到了船员,不需要再查询
- if (shipOwnerForm.value.shipOwnerId) return;
- api
- .getShipOwnerDetail({ phone: shipOwnerForm.value.userPhone })
- .then((res) => {
- if (res.data.code === 0 && res.data.data && res.data.data.shipOwnerId) {
- // 匹配到船员信息,更新表单
- Object.assign(shipOwnerForm.value, res.data.data);
- ElMessage.info("已匹配到船员信息");
- }
- });
- };
- // 身份证人像面上传处理
- const handleIdCardFrontUpload = ({ response }) => {
- if (response.code === 0) {
- shipOwnerForm.value.idcardFrontFileKey = response.data.fileKey;
- shipOwnerForm.value.idcardFrontViewUrl = response.data.viewUrl;
- shipOwnerForm.value.idcardFrontDownloadUrl = response.data.downloadUrl;
- } else {
- ElMessage.error(response.msg || "上传失败");
- }
- };
- // 身份证人像面删除处理
- const handleIdCardFrontRemove = () => {
- shipOwnerForm.value.idcardFrontFileKey = "";
- shipOwnerForm.value.idcardFrontViewUrl = "";
- shipOwnerForm.value.idcardFrontDownloadUrl = "";
- };
- // 身份证国徽面上传处理
- const handleIdCardBackUpload = ({ response }) => {
- if (response.code === 0) {
- shipOwnerForm.value.idcardBackFileKey = response.data.fileKey;
- shipOwnerForm.value.idcardBackViewUrl = response.data.viewUrl;
- shipOwnerForm.value.idcardBackDownloadUrl = response.data.downloadUrl;
- } else {
- ElMessage.error(response.msg || "上传失败");
- }
- };
- // 身份证国徽面删除处理
- const handleIdCardBackRemove = () => {
- shipOwnerForm.value.idcardBackFileKey = "";
- shipOwnerForm.value.idcardBackViewUrl = "";
- shipOwnerForm.value.idcardBackDownloadUrl = "";
- };
- // 证书上传处理
- const handleCertUpload = ({ response }) => {
- if (response.code === 0) {
- if (!shipOwnerForm.value.documents) {
- shipOwnerForm.value.documents = [];
- }
- shipOwnerForm.value.documents.push({
- docType: 1, // 船员适任证书
- fileKey: response.data.fileKey,
- viewUrl: response.data.viewUrl,
- downloadUrl: response.data.downloadUrl,
- });
- } else {
- ElMessage.error(response.msg || "上传失败");
- }
- };
- // 证书删除处理
- const handleCertRemove = ({ fileIndex }) => {
- const certDocs = shipOwnerForm.value.documents.filter(
- (doc) => doc.docType === 1
- );
- const docToRemove = certDocs[fileIndex];
- shipOwnerForm.value.documents = shipOwnerForm.value.documents.filter(
- (doc) => doc !== docToRemove
- );
- };
- // 健康证明上传处理
- const handleHealthUpload = ({ response }) => {
- if (response.code === 0) {
- if (!shipOwnerForm.value.documents) {
- shipOwnerForm.value.documents = [];
- }
- shipOwnerForm.value.documents.push({
- docType: 2, // 体检表
- fileKey: response.data.fileKey,
- viewUrl: response.data.viewUrl,
- downloadUrl: response.data.downloadUrl,
- });
- } else {
- ElMessage.error(response.msg || "上传失败");
- }
- };
- // 健康证明删除处理
- const handleHealthRemove = ({ fileIndex }) => {
- const healthDocs = shipOwnerForm.value.documents.filter(
- (doc) => doc.docType === 2
- );
- const docToRemove = healthDocs[fileIndex];
- shipOwnerForm.value.documents = shipOwnerForm.value.documents.filter(
- (doc) => doc !== docToRemove
- );
- };
- // 服务簿上传处理
- const handleServiceUpload = ({ response }) => {
- if (response.code === 0) {
- if (!shipOwnerForm.value.documents) {
- shipOwnerForm.value.documents = [];
- }
- shipOwnerForm.value.documents.push({
- docType: 3, // 服务簿
- fileKey: response.data.fileKey,
- viewUrl: response.data.viewUrl,
- downloadUrl: response.data.downloadUrl,
- });
- } else {
- ElMessage.error(response.msg || "上传失败");
- }
- };
- // 服务簿删除处理
- const handleServiceRemove = ({ fileIndex }) => {
- const serviceDocs = shipOwnerForm.value.documents.filter(
- (doc) => doc.docType === 3
- );
- const docToRemove = serviceDocs[fileIndex];
- shipOwnerForm.value.documents = shipOwnerForm.value.documents.filter(
- (doc) => doc !== docToRemove
- );
- };
- // 保存船员信息
- const saveShipOwner = () => {
- // 使用Element Plus表单验证
- shipOwnerFormRef.value.validate((valid1) => {
- if (!valid1) return;
- certificateFormRef.value.validate((valid2) => {
- if (!valid2) return;
- // 验证证书照片是否上传
- if (!certFileList.value.length) {
- ElMessage.warning("请上传证书照片");
- return;
- }
- // 表单验证通过,继续保存操作
- });
- });
- // 如果有ID,则更新,否则新增
- const apiMethod = route.query.id ? api.updateShipOwner : api.addShipOwner;
- const successMsg = route.query.id ? "更新成功" : "添加成功";
- // 构建保存数据
- const saveData = { ...shipOwnerForm.value };
- if (route.query.id) {
- saveData.id = route.query.id;
- }
- apiMethod(saveData)
- .then((res) => {
- if (res.data.code === 0) {
- ElMessage.success(successMsg);
- router.replace("/shipOwnerManage/shipOwnerList");
- } else {
- ElMessage.error(res.data.msg || "保存失败");
- }
- })
- .catch((err) => {
- console.error(err);
- ElMessage.error("保存失败");
- });
- };
- </script>
- <style scoped>
- :deep().el-upload-list__item-thumbnail {
- object-fit: contain;
- }
- .upload-plus-icon {
- height: 15%;
- color: rgb(139, 147, 156);
- line-height: 100px;
- font-size: 40px;
- font-weight: 200;
- }
- .upload-text {
- height: 25%;
- color: rgb(139, 147, 156);
- }
- :deep().el-upload--picture-card {
- border: none;
- width: auto;
- }
- .unit {
- width: 40px;
- text-align: center;
- color: #555;
- }
- </style>
|