提交资质对接

This commit is contained in:
wangchengming 2025-07-02 21:00:57 +08:00
parent e95fe4f759
commit 36737ad17a
12 changed files with 816 additions and 304 deletions

View File

@ -34,6 +34,7 @@
"splitpanes": "3.1.5",
"vue": "3.4.31",
"vue-cropper": "1.1.1",
"vue-pdf-embed": "^2.1.2",
"vue-router": "4.4.0",
"vuedraggable": "4.1.0"
},

View File

@ -1,6 +1,43 @@
import request from '@/utils/request'
// 获取我的资质申请记录列表
// 获取我的资质证书情况列表
export function getCurrentUserList(query) {
return request({
url: '/admin/busUserQualificationCertificate/getCurrentUserList',
method: 'post',
data: query
})
}
// 修改我的资质证书情况
export function updateCurrentCertificate(data) {
return request({
url: '/admin/busUserQualificationCertificate/update',
method: 'post',
data: data
})
}
// 获取我的单个资质证书详情
export function getCurrentCertificateDetail(Id) {
return request({
url: '/admin/busUserQualificationCertificate/detail/' + Id,
method: 'post'
})
}
// 上传文件 单个
export function uploadFile(data) {
return request({
url: '/common/upload',
method: 'post',
data: data,
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
// 获取资质申请记录列表
export function getBusUserQualification(query) {
return request({
url: '/admin/busUserQualification/pageList',
@ -8,37 +45,39 @@ export function getBusUserQualification(query) {
data: query
})
}
// 查询属地详细
export function getBusDependency(busDependencyId) {
// 提交资质申请记录
export function submitBusUserQualification(query) {
return request({
url: '/admin/busDependency/getBusDependency/' + busDependencyId,
method: 'post'
})
}
// 新增属地
export function addBusDependency(data) {
return request({
url: '/admin/busDependency/addBusDependency',
method: 'post',
data: data
})
}
// 修改属地
export function updateBusDependency(data) {
return request({
url: '/admin/busDependency/updateBusDependency',
method: 'post',
data: data
})
}
// 删除属地
export function deleteBusDependency(busDependencyId) {
return request({
url: '/admin/busDependency/deleteBusDependency/' + busDependencyId,
url: '/admin/busUserQualification/submit',
method: 'post',
data: query
})
}
// 修改(重新申请)资质 待替换接口
export function updateBusUserQualification(query) {
return request({
url: '/admin/busUserQualification/updateBusUserQualification',
method: 'post',
data: query
})
}
// 查询一条资质申请记录详情
export function getBusUserQualificationDetail(query) {
return request({
url: '/admin/busUserQualification/detail',
method: 'post',
params: query
})
}
// 删除资质申请记录
export function deleteBusUserQualification(busQualificationId) {
return request({
url: '/admin/busUserQualification/deleteBusUserQualification/' + busQualificationId,
method: 'post'
})
}

View File

@ -1,4 +1,12 @@
import request from '@/utils/request'
// 获取当前登录人车型培训列表
export function getCurVehicleTrainingList(query) {
return request({
url: '/admin/vehicleModelTraining/currentPageList',
method: 'post',
data: query
})
}
// 获取车型培训列表
export function getVehicleTrainingPageList(query) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -0,0 +1,72 @@
<template>
<div class="pdf-viewer">
<vue-pdf-embed :source="pdfUrl" :page="currentPage" :style="`transform: scale(${scale})`"
class="pdf-document" />
<div class="pdf-controls">
<el-button @click="prevPage" :disabled="currentPage <= 1">上一页</el-button>
<span> {{ currentPage }} / {{ pageCount }} </span>
<el-button @click="nextPage" :disabled="currentPage >= pageCount">下一页</el-button>
<!-- <el-button @click="zoomIn">放大</el-button>
<el-button @click="zoomOut">缩小</el-button> -->
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import VuePdfEmbed from 'vue-pdf-embed'
const props = defineProps({
pdfUrl: {
type: String,
required: true
},
pageCount: {
type: Number,
default: 1
}
})
const currentPage = ref(1)
const scale = ref(1)
const prevPage = () => {
if (currentPage.value > 1) currentPage.value--
}
const nextPage = () => {
if (currentPage.value < props.pageCount) currentPage.value++
}
const zoomIn = () => {
scale.value += 0.1
}
const zoomOut = () => {
if (scale.value > 0.5) scale.value -= 0.1
}
</script>
<style scoped>
.pdf-viewer {
display: flex;
flex-direction: column;
height: 100%;
}
.pdf-document {
flex: 1;
overflow: auto;
transform-origin: top left;
}
.pdf-controls {
display: flex;
align-items: center;
gap: 10px;
padding: 10px;
background: #f5f5f5;
border-top: 1px solid #ddd;
}
</style>

View File

@ -7,7 +7,7 @@
</el-button>
</div>
<div class="borderLine"></div>
<el-table :data="tableData" height="calc(100% - 170px)" style="width: 100%">
<el-table v-loading="loading" :data="tableData" height="calc(100% - 170px)" style="width: 100%">
<el-table-column label="序号" width="60">
<template #default="scope">
{{ scope.$index + 1 }}
@ -32,52 +32,47 @@
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageIndex"
v-model:limit="queryParams.pageSize" @pagination="getBusUserQualificationPageList" />
</div>
<QualificationApplyForm v-else ref="qualificationApplyFormRef" @refresh="reloadList" />
</template>
<script setup>
import { ref } from 'vue'
import { onMounted, ref } from 'vue'
import applyIcon from '@/assets/images/applyIcon.png'
import QualificationApplyForm from './QualificationApplyForm.vue'
import { getBusUserQualification } from "@/api/qualification/myQualifications"
const isShowForm = ref(false)
const tableData = [
{
jobNumber: '3523213',
name: '赵丽娟',
curQualification: '-',
objectiveQualification: 'SH',
status: 0
},
{
jobNumber: '3523213',
name: '赵丽娟',
curQualification: '-',
objectiveQualification: 'SH',
status: 1
},
{
jobNumber: '3523213',
name: '赵丽娟',
curQualification: '-',
objectiveQualification: 'SH',
status: 2
},
{
jobNumber: '3523213',
name: '赵丽娟',
curQualification: '-',
objectiveQualification: 'SH',
status: 0
},
]
const queryParams = ref({
pageIndex: 1,
pageSize: 10,
node: 0
})
const loading = ref(true)
const title = ref("")
const tableData = ref([])
//
onMounted(() => {
getBusUserQualificationPageList();
});
const getBusUserQualificationPageList = () => {
loading.value = true
getBusUserQualification(queryParams.value).then(res => {
console.log('资质申请结论', res)
if (res.code == 200) tableData.value = res.data
loading.value = false
}).catch(() => {
loading.value = false
})
}
//
const handleOpenApplyForm = () => {
isShowForm.value = true
}
//
const reloadList = () => {
const reloadList = () => {
isShowForm.value = false
}
</script>

View File

@ -6,161 +6,99 @@
<div class="applyFormContainer">
<el-row class="myRow" :gutter="20">
<el-col :span="8">
<el-form-item label="目标资质" prop="targetQualification">
<el-select v-model="ruleForm.targetQualification" placeholder="请选择目标资质">
<el-option label="Zone one" value="shanghai" />
<el-option label="Zone two" value="beijing" />
<el-form-item label="目标资质" prop="qualificationId">
<el-select v-model="ruleForm.qualificationId" placeholder="请选择目标资质" clearable>
<el-option v-for="dict in bus_qualification" :key="dict.value" :label="dict.label"
:value="dict.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="员工工号" prop="employeeNumber">
<el-input v-model="ruleForm.employeeNumber" placeholder="请输入员工工号" />
<el-form-item label="员工工号" prop="workNo">
<el-input v-model="ruleForm.workNo" placeholder="请输入员工工号" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="员工姓名(中文)" prop="employeeChineseName">
<el-input v-model="ruleForm.employeeChineseName" placeholder="请输入员工姓名(中文)" />
<el-form-item label="员工姓名(中文)" prop="nickName">
<el-input v-model="ruleForm.nickName" placeholder="请输入员工姓名(中文)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="员工姓名(英文)" prop="employeeEnglishName">
<el-input v-model="ruleForm.employeeEnglishName" placeholder="请输入员工姓名(英文)" />
<el-form-item label="员工姓名(英文)" prop="englishName">
<el-input v-model="ruleForm.englishName" placeholder="请输入员工姓名(英文)" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="部门" prop="departmentName">
<el-select v-model="ruleForm.departmentName" placeholder="请选择部门">
<el-option label="Zone one" value="shanghai" />
<el-option label="Zone two" value="beijing" />
<el-form-item label="部门" prop="deptId">
<el-tree-select v-model="ruleForm.deptId" :data="enabledDeptOptions" disabled
:props="{ value: 'id', label: 'label', children: 'children' }" value-key="id"
placeholder="请选择部门" check-strictly />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="科室" prop="sectionId">
<el-select v-model="ruleForm.sectionId" placeholder="请选择科室" disabled>
<el-option v-for="item in sectionData" :key="item.sectionId" :label="item.sectionName"
:value="item.sectionId" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="科室" prop="officeName">
<el-select v-model="ruleForm.officeName" placeholder="请选择科室">
<el-option label="Zone one" value="shanghai" />
<el-option label="Zone two" value="beijing" />
<el-form-item label="属地" prop="dependencyId">
<el-select v-model="ruleForm.dependencyId" placeholder="请选择属地" disabled>
<el-option v-for="item in busDependencyData" :key="item.id" :label="item.dependencyName"
:value="item.id" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="属地" prop="localityName">
<el-select v-model="ruleForm.localityName" placeholder="请选择属地">
<el-option label="Zone one" value="shanghai" />
<el-option label="Zone two" value="beijing" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="属地ESC" prop="localityManager">
<el-input v-model="ruleForm.localityManager" />
<el-form-item label="属地ESC" prop="escUserName">
<el-input v-model="ruleForm.escUserName" disabled />
</el-form-item>
</el-col>
</el-row>
</div>
<div class="headerTitle">前置条件</div>
<div class="applyFormContainer">
<el-row class="myRow" :gutter="20">
<el-col :span="8">
<el-form-item label="电工证初领日期" prop="collectionDate">
<el-date-picker v-model="ruleForm.collectionDate" type="date"
placeholder="请选择电工证初领日期"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电工证复审日期" prop="reviewDate">
<el-date-picker v-model="ruleForm.reviewDate" type="date"
placeholder="请选择电工证复审日期"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电工证状态">
<!-- <el-input v-model="ruleForm.employeeNumber" placeholder="请输入员工工号" /> -->
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="培训紧迫程度" prop="urgency">
<el-radio-group v-model="ruleForm.urgency">
<el-radio value="1">紧急</el-radio>
<el-radio value="2">一般</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电工证照片" prop="urgency">
<el-upload v-model:file-list="fileList"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
list-type="picture-card" :on-remove="handleRemove">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="SH资质上传" prop="urgency">
<el-upload v-model:file-list="fileList"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
list-type="picture-card" :on-remove="handleRemove">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="ES资质上传" prop="urgency">
<el-upload v-model:file-list="fileList"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
list-type="picture-card" :on-remove="handleRemove">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="资质申请表单" prop="urgency">
<el-upload v-model:file-list="fileList"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
list-type="picture-card" :on-remove="handleRemove">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="6个月实操经验" prop="urgency">
<el-radio-group v-model="ruleForm.urgency">
<el-radio value="1"></el-radio>
<el-radio value="2"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实操经验表单" prop="urgency">
<el-upload v-model:file-list="fileList"
action="https://run.mocky.io/v3/9d059bf9-4660-45f2-925d-ce80ad6c4d15"
list-type="picture-card" :on-remove="handleRemove">
<el-icon>
<Plus />
</el-icon>
</el-upload>
</el-form-item>
</el-col>
<div v-if="ruleForm.sourceQualificationId == '2'">
<el-row class="myRow" :gutter="20">
<el-col :span="8">
<el-form-item label="电工证初领日期" prop="beforeCondition.collectionDate">
<el-date-picker v-model="ruleForm.beforeCondition.collectionDate" type="date"
format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="请选择电工证初领日期"
style="width: 100%;" @change="handleCollectionDateChange" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电工证复审日期" prop="beforeCondition.reviewDate">
<el-date-picker v-model="ruleForm.beforeCondition.reviewDate" type="date"
format="YYYY-MM-DD" value-format="YYYY-MM-DD" placeholder="请选择电工证复审日期"
style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="培训紧迫程度" prop="beforeCondition.urgency">
<el-radio-group v-model="ruleForm.beforeCondition.urgency">
<el-radio value="1">紧急</el-radio>
<el-radio value="2">一般</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="电工证照片" prop="beforeCondition.certificatePhoto">
<myFileUpload ref="certificatePhotoRef" @set-form-file="handleSetCertificatePhoto" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="资质申请表单" prop="beforeCondition.qualificationForm">
<myFileUpload ref="qualificationFormRef" @set-form-file="handleSetQualificationForm" />
</el-form-item>
</el-col>
</el-row>
</div>
<!-- <el-col :span="12"></el-col>
<el-col :span="12"></el-col>
<el-col :span="12"></el-col>
<el-col :span="12"></el-col>
<el-col :span="12"></el-col> -->
</el-row>
</div>
</el-form>
</div>
@ -170,24 +108,153 @@
</div>
</template>
<script setup>
import { reactive, defineEmits } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import { onMounted, reactive, defineEmits, ref } from 'vue'
import { deptTreeSelect, getUserInfo } from "@/api/system/user"
import { getBusDependencyPage } from "@/api/system/dependency"
import { getSysSectionPage } from "@/api/system/section"
import { submitBusUserQualification } from "@/api/qualification/myQualifications"
import myFileUpload from './myFileUpload.vue'
import moment from 'moment'
const emit = defineEmits(['refresh'])
const { proxy } = getCurrentInstance()
const { bus_qualification } = proxy.useDict("bus_qualification")
const data = reactive({
ruleForm: {},
rules: {
targetQualification: [{ required: true, message: "目标资质不能为空", trigger: "change" }],
employeeNumber: [{ required: true, message: "员工工号不能为空", trigger: "blur" }],
employeeChineseName: [{ required: true, message: "员工姓名(中文)不能为空", trigger: "blur" }],
employeeEnglishName: [{ required: true, message: "员工姓名(英文)", trigger: "blur" }],
departmentName: [{ required: true, message: "部门不能为空", trigger: "change" }],
officeName: [{ required: true, message: "科室不能为空", trigger: "change" }],
localityName: [{ required: true, message: "属地不能为空", trigger: "change" }],
localityManager: [{ required: true, message: "属地ESC不能为空", trigger: "blur" }],
qualificationId: [{ required: true, message: "目标资质不能为空", trigger: "change" }],
workNo: [{ required: true, message: "员工工号不能为空", trigger: "blur" }],
nickName: [{ required: true, message: "员工姓名(中文)不能为空", trigger: "blur" }],
englishName: [{ required: true, message: "员工姓名(英文)", trigger: "blur" }],
deptId: [{ required: true, message: "部门不能为空", trigger: "change" }],
sectionId: [{ required: true, message: "科室不能为空", trigger: "change" }],
dependencyId: [{ required: true, message: "属地不能为空", trigger: "change" }],
escUserName: [{ required: true, message: "属地ESC不能为空", trigger: "blur" }],
beforeCondition: {
collectionDate: [
{ required: true, message: '电工证初领日期不能为空', trigger: 'change' }
],
reviewDate: [
{ required: true, message: '电工证复审日期不能为空', trigger: 'change' }
],
urgency: [
{ required: true, message: '培训紧迫程度不能为空', trigger: 'change' }
],
certificatePhoto: [
{ required: true, message: '电工证照片不能为空', trigger: 'change' }
],
qualificationForm: [
{ required: true, message: '资质申请表单不能为空', trigger: 'change' }
]
}
},
})
//
const handleSetCertificatePhoto = (filePath) => {
console.log('接收电工证照片', filePath)
ruleForm.value.beforeCondition.certificatePhoto = filePath
}
//
const handleSetQualificationForm = (filePath) => {
console.log('接收资质表单照片', filePath)
ruleForm.value.beforeCondition.qualificationForm = filePath
}
//
const handleCollectionDateChange = (val) => {
ruleForm.value.beforeCondition.reviewDate = moment(val).add(3, 'years').format('YYYY-MM-DD')
}
//
onMounted(() => {
getUserInfos()
getBusDependencyData()
getDeptTree()
getSysSectionData()
});
//
const getUserInfos = () => {
getUserInfo().then(response => {
console.log('用户详情', response)
if (response.code == 200) {
ruleForm.value = {
sourceQualificationId: undefined,
workNo: response.data.workNo,
nickName: response.data.nickName,
englishName: response.data.englishName,
deptId: response.data.deptId,
sectionId: response.data.sectionId,
dependencyId: response.data.dependencyId,
escUserName: response.data.escUserName,
beforeCondition: {
//
collectionDate: null,
//
reviewDate: null,
//
certificateStatus: null,
//
urgency: null,
//
certificatePhoto: null,
//
qualificationForm: null
}
}
}
})
}
//
const busDependencyData = ref([])
//
const getBusDependencyData = () => {
getBusDependencyPage({
pageIndex: 1,
pageSize: 100,
}).then(response => {
if (response.code == 200) {
busDependencyData.value = response.data.list
}
})
}
//
const enabledDeptOptions = ref(undefined)
//
const getDeptTree = () => {
deptTreeSelect().then(res => {
enabledDeptOptions.value = filterDisabledDept(JSON.parse(JSON.stringify(res.data)))
})
}
/** 过滤禁用的部门 */
const filterDisabledDept = (deptList) => {
return deptList.filter(dept => {
if (dept.disabled) {
return false
}
if (dept.children && dept.children.length) {
dept.children = filterDisabledDept(dept.children)
}
return true
})
}
//
const sectionData = ref([])
//
const getSysSectionData = () => {
getSysSectionPage({
pageIndex: 1,
pageSize: 100,
}).then(res => {
if (res.code == 200) {
sectionData.value = res.data.list
}
})
}
const { ruleForm, rules } = toRefs(data)
const handleCancel = () => {
proxy.resetForm("ruleFormRef")
@ -196,24 +263,19 @@ const handleCancel = () => {
const handleSubmit = () => {
proxy.$refs["ruleFormRef"].validate(valid => {
if (valid) {
// if (form.value.roleId != undefined) {
// form.value.menuIds = getMenuAllCheckedKeys()
// updateRole(form.value).then(response => {
// proxy.$modal.msgSuccess("")
// open.value = false
// getList()
// })
// } else {
// form.value.menuIds = getMenuAllCheckedKeys()
// addRole(form.value).then(response => {
// proxy.$modal.msgSuccess("")
// open.value = false
// getList()
// })
// }
console.log('bioa', ruleForm.value)
ruleForm.value.beforeCondition = JSON.stringify(ruleForm.value.beforeCondition)
ruleForm.value.node = 0
submitBusUserQualification(ruleForm.value).then(res => {
if (res.code == 200) {
proxy.$modal.msgSuccess("提交成功")
emit('refresh')
} else proxy.$modal.msgSuccess(res.msg)
})
}
})
}
</script>
<style lang='scss'>
.qualification-rootContainer {

View File

@ -1,90 +1,183 @@
<template>
<div class="borderLine"></div>
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="name" label="资质名称" width="100" />
<el-table-column prop="certificate" label="资质证书" align="center">
<el-table v-loading="loading" :data="tableData" style="width: 100%">
<el-table-column prop="qualificationName" label="资质名称" width="100" />
<el-table-column prop="certificateUrl" label="资质证书" align="center">
<template #default="scope">
<el-image v-if="scope.row.certificate" style="width: 70px; height: 44px;line-height: 50px;"
:src="scope.row.certificate" fit="fill" />
<el-image v-if="scope.row.certificateUrl" style="width: 70px; height: 44px;line-height: 50px;"
:src="baseUrl + scope.row.certificateUrl" fit="fill" />
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="expired" label="是否过期" width="120">
<el-table-column prop="status" label="是否过期" width="120">
<template #default="scope">
<el-text v-if="scope.row.expired == false && scope.row.certificate" type="success" class="successText">正常</el-text>
<el-text v-if="scope.row.expired == true && scope.row.certificate" type="danger" class="dangerText">过期</el-text>
<el-text v-if="scope.row.status == 1 && scope.row.certificateUrl" type="success"
class="successText">正常</el-text>
<el-text v-else-if="scope.row.status == 2 && scope.row.certificateUrl" type="danger"
class="dangerText">过期</el-text>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="startTime" label="有效开始日期" width="150">
<template #default="scope">
<span v-if="scope.row.startTime && scope.row.certificate"> {{ scope.row.startTime }}</span>
<span v-if="scope.row.startTime"> {{ moment(scope.row.startTime).format('YYYY-MM-DD') }}</span>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column prop="expireTime" label="到期日期" width="130">
<template #default="scope">
<span v-if="scope.row.expireTime && scope.row.certificate"> {{ scope.row.expireTime }}</span>
<span v-else>-</span>
<template #default="scope">
<span v-if="scope.row.expireFlag == 0">长期</span>
<template v-else>
<span v-if="scope.row.expireTime"> {{ moment(scope.row.startTime).format('YYYY-MM-DD') }}</span>
<span v-else>-</span>
</template>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<template #default="scope">
<el-button type="primary" text class="editTextBtn">编辑</el-button>
<el-button type="primary" text class="editTextBtn" @click="handleEdit(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :title="title" v-model="open" width="800px" append-to-body>
<el-form ref="postRef" :model="form" :rules="rules" label-width="150px">
<el-form-item label="证书名称" prop="factoryArea">
<el-input v-model="form.qualificationName" disabled />
</el-form-item>
<el-form-item label="上传证书" prop="certificateUrl">
<el-upload action='#' :http-request="requestUpload" list-type="picture-card" :file-list="fileList"
:on-change="handleChange" :before-upload="beforeUpload">
<Plus class="myIcon" />
</el-upload>
</el-form-item>
<el-form-item label="有效开始日期" prop="startTime">
<el-date-picker v-model="form.startTime" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
placeholder="请选择有效开始日期" style="width: 100%;" />
</el-form-item>
<el-form-item label="到期日期" :prop="form.expireFlag == 1 ? 'expireTime' : ''">
<el-date-picker v-model="form.expireTime" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
placeholder="请选择到期日期" style="width: 100%;" @change="handleDateChange" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
const tableData = [
{
name: '电工证',
certificate: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
expired: false,
startTime: '2016-05-03',
expireTime: '2019-05-03',
},
{
name: 'SH',
certificate: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
expired: false,
startTime: '2016-05-03',
expireTime: '2019-05-03',
},
{
name: 'ES',
certificate: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
expired: false,
startTime: '2016-05-03',
expireTime: '2019-05-03',
},
{
name: 'ESC',
certificate: null,
expired: null,
startTime: '2016-05-03',
expireTime: '2019-05-03',
},
{
name: 'CESC',
certificate: null,
expired: null,
startTime: '2016-05-03',
expireTime: '2019-05-03',
},
{
name: '急救证',
certificate: null,
expired: null,
startTime: '2016-05-03',
expireTime: '2019-05-03',
},
{
name: 'LLP',
certificate: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg',
expired: true,
startTime: '2016-05-03',
expireTime: '2019-05-03',
},
]
import { onMounted, ref } from 'vue'
import { getCurrentUserList, uploadFile, updateCurrentCertificate, getCurrentCertificateDetail } from "@/api/qualification/myQualifications"
import { Plus } from '@element-plus/icons-vue'
import moment from 'moment'
const queryParams = ref({
pageIndex: 1,
pageSize: 10,
})
const loading = ref(true)
const tableData = ref([])
const open = ref(false)
const title = ref("")
const form = ref({})
const rules = ref({
certificateUrl: [{ required: true, message: "请上传资质证书照片" }],
startTime: [{ required: true, message: "请选择有效开始日期", trigger: "change" }],
expireTime: [{ required: true, message: "请选择到期日期", trigger: "change" }],
})
const fileList = ref([])
const baseUrl = import.meta.env.VITE_APP_BASE_API
const { proxy } = getCurrentInstance()
//
onMounted(() => {
getCurUserQualification();
});
const getCurUserQualification = () => {
loading.value = true
getCurrentUserList(queryParams.value).then(res => {
if (res.code == 200) tableData.value = res.data
loading.value = false
}).catch(() => {
loading.value = false
})
}
const handleDateChange = (val) => {
if(val) form.value.expireFlag = 1
else form.value.expireFlag = 0
};
/** 取消按钮 */
const cancel = () => {
open.value = false
reset()
}
/** 表单重置 */
const reset = () => {
form.value = {
id: undefined,
certificateUrl: undefined,
startTime: undefined,
expireTime: undefined,
expireFlag: 1
}
proxy.resetForm("postRef")
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["postRef"].validate(valid => {
if (valid) {
if (form.value.id != undefined) {
if (form.value.expireTime) form.value.expireFlag = 1
else form.value.expireFlag = 0
updateCurrentCertificate(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
}
}
})
}
const handleEdit = (record) => {
reset()
getCurrentCertificateDetail(record.id).then(res => {
form.value = res.data
if (form.value.expireTime) form.value.expireFlag = 1 //
else form.value.expireFlag = 0
form.value.qualificationName = record.qualificationName
fileList.value = [{ url: baseUrl + res.data.certificateUrl }]
open.value = true
title.value = "编辑"
})
}
//logo
const requestUpload = (options) => {
const { file } = options
var formData = new FormData();
formData.append('file', file);
uploadFile(formData).then(res => {
if (res.code == 200) {
fileList.value = [{ name: res.originalFilename, url: baseUrl + res.fileName }]
form.value.certificateUrl = res.fileName
}
})
}
//logo
const beforeUpload = (file) => {
const type = ["image/jpeg", "image/jpg", "image/png"];
const isJPG = type.includes(file.type);
//
if (!isJPG) {
proxy.$modal.msgError("文件格式错误,请上传图片类型,如JPGjpegPNG后缀的文件。");
return false;
}
}
const handleChange = (file, fileList) => {
fileList.value = []
}
</script>
<style lang='scss'>
.editTextBtn {
@ -108,4 +201,9 @@ const tableData = [
font-size: 18px;
color: #E13434;
}
.myIcon {
width: 40px;
height: 40px;
}
</style>

View File

@ -1,35 +1,53 @@
<template>
<div class="headerTitle">车型培训情况</div>
<div class="borderLine"></div>
<el-table :data="tableData" height="calc(100% - 170px)" style="width: 100%">
<el-table v-loading="loading" :data="tableData" height="calc(100vh - 332px)" style="width: 100%">
<el-table-column label="序号" width="60">
<template #default="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="车型" />
<el-table-column prop="date" label="培训日期" width="130" />
<el-table-column prop="vehicleModel" align="center" label="车型" />
<el-table-column prop="trainingTime" label="培训日期" width="130">
<template #default="scope">
<span v-if="scope.row.trainingTime"> {{ moment(scope.row.trainingTime).format('YYYY-MM-DD')
}}</span>
<span v-else>-</span>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageIndex"
v-model:limit="queryParams.pageSize" @pagination="getCurUserTrain" />
</template>
<script setup>
const tableData = [
{
date: '2016-05-03',
name: 'BR 205 Plugin Hybrid',
},
{
date: '2016-05-02',
name: 'BR 206 Electrical Vehicle',
},
{
date: '2016-05-04',
name: 'N293 Electrical Vehicle',
},
{
date: '2016-05-01',
name: 'V206 Plugin Hybrid',
},
]
import { onMounted, ref } from 'vue'
import moment from 'moment'
import { getCurVehicleTrainingList } from "@/api/qualification/vehicleTrain"
const total = ref(0)
const queryParams = ref({
pageIndex: 1,
pageSize: 10,
})
const loading = ref(true)
const tableData = ref([])
//
onMounted(() => {
getCurUserTrain();
});
const getCurUserTrain = () => {
loading.value = true
getCurVehicleTrainingList(queryParams.value).then(res => {
if (res.code == 200) {
tableData.value = res.data.list
total.value = res.data.total
}
loading.value = false
}).catch(() => {
loading.value = false
})
}
</script>
<style lang='scss'>
.headerTitle {

View File

@ -0,0 +1,204 @@
<template>
<div>
<el-upload action="#" :http-request="requestUpload" list-type="picture-card" :file-list="fileList"
:on-change="handleChange" :show-file-list="false" :before-upload="beforeUpload" :limit="1">
<div v-if="fileList.length > 0 && fileList[0].url" class="image-wrapper">
<img :src="isImageFile(suffix) ? fileList[0].url : pdfIcon" class="avatar viewFile"
@click.stop="handleCardPreview(fileList[0].url, fileList[0].suffix)" />
<div class="actions">
<span class="delete" @click.stop="handleRemoveImage">
<el-icon>
<Delete />
</el-icon>
</span>
</div>
</div>
<el-icon v-else class="avatar-uploader-icon">
<Plus />
</el-icon>
</el-upload>
<!-- 图片预览 -->
<el-dialog v-model="dialogVisible" title="图片预览">
<img v-if="isImageFile(suffix)" :src="dialogImageUrl" class="preview-image" alt="Preview Image" />
<div v-else class="unsupported-file">
<pdf-preview :pdf-url="dialogImageUrl" />
</div>
</el-dialog>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { Plus, Delete } from '@element-plus/icons-vue'
import { uploadFile } from "@/api/qualification/myQualifications"
import pdfIcon from '@/assets/images/pdfIcon.png'
import PdfPreview from './PdfPreview.vue'
const { proxy } = getCurrentInstance()
const emit = defineEmits(['setFormFile'])
//
const fileList = ref([])
const baseUrl = import.meta.env.VITE_APP_BASE_API
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const suffix = ref('')
//
const isImageFile = (suffix) => {
return ['jpeg', 'jpg', 'png'].includes(suffix?.toLowerCase())
}
//
const handleCardPreview = (filePath, _suffix) => {
suffix.value = _suffix
dialogImageUrl.value = filePath
dialogVisible.value = true
}
//
const handleRemoveImage = () => {
fileList.value = []
emit('setFormFile', null)
}
//
const requestUpload = async (options) => {
const { file } = options
const formData = new FormData()
formData.append('file', file)
try {
const res = await uploadFile(formData)
if (res.code === 200) {
fileList.value = [{
name: res.originalFilename,
url: baseUrl + res.fileName,
suffix: res.suffix
}]
emit('setFormFile', res.fileName)
}
} catch (error) {
console.error('上传失败:', error)
}
}
//
const beforeUpload = (file) => {
const validTypes = [
//
"image/jpeg",
"image/jpg",
"image/png",
// PDF
"application/pdf",
"application/x-pdf",
"application/acrobat",
"applications/vnd.pdf",
"text/pdf",
"text/x-pdf"]
const isValidType = validTypes.includes(file.type)
// const isLt5M = file.size / 1024 / 1024 < 5
if (!isValidType) {
proxy.$modal.msgError("文件格式错误,请上传 JPG/JPEG/PNG/PDF 后缀的文件。");
return false
}
// if (!isLt5M) {
// proxy.$modal.msgError("5MB");
// return false
// }
return true
}
//
const handleChange = (file, files) => {
//
// fileList
fileList.value = []
}
</script>
<style lang="scss" scoped>
.viewFile {
width: 148px;
height: 148px;
border: 1px solid #dedede;
border-radius: 6px;
}
.upload-container {
position: relative;
display: inline-block;
}
.image-wrapper {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}
.avatar {
width: 100%;
height: 100%;
object-fit: cover;
}
.actions {
position: absolute;
top: 0;
right: 0;
display: none;
}
:deep(.el-upload--picture-card) {
position: relative;
}
.image-wrapper:hover .actions {
display: block;
}
.delete {
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
background: rgba(0, 0, 0, 0.5);
color: white;
border-radius: 50%;
cursor: pointer;
margin: 5px;
transition: background 0.3s;
&:hover {
background: rgba(0, 0, 0, 0.7);
}
}
.preview-image {
width: 100%;
max-height: 70vh;
object-fit: contain;
}
.unsupported-file {
padding: 0px;
text-align: center;
color: #999;
height: 70vh;
}
.myIcon {
width: 40px;
height: 40px;
color: #d2d2d2;
}
</style>

View File

@ -24,28 +24,43 @@
<el-avatar shape="square" :size="16" :src="jobNumberIcon" />
</span>
<span class="infoLable">所属部门</span>
<span class="infoValue">{{ curUserInfo.dept?.deptName }}</span>
<span class="infoValue">
<el-tooltip class="box-item" effect="dark" :content="curUserInfo.dept?.deptName"
placement="top-start">
{{ curUserInfo.dept?.deptName }}
</el-tooltip>
</span>
</div>
<div class="info-item">
<span class="icon-container">
<el-avatar shape="square" :size="16" :src="jobNumberIcon" />
</span>
<span class="infoLable">所属科室</span>
<span class="infoValue">{{ curUserInfo.workNo }}</span>
<span class="infoValue">
<el-tooltip class="box-item" effect="dark" :content="curUserInfo.sectionName"
placement="top-start">
{{ curUserInfo.sectionName }}
</el-tooltip>
</span>
</div>
<div class="info-item">
<span class="icon-container">
<el-avatar shape="square" :size="16" :src="jobNumberIcon" />
</span>
<span class="infoLable lableSpacing">属地</span>
<span class="infoValue">{{ curUserInfo.workNo }}</span>
<span class="infoValue">
<el-tooltip class="box-item" effect="dark" :content="curUserInfo.dependencyName"
placement="top-start">
{{ curUserInfo.dependencyName }}
</el-tooltip>
</span>
</div>
<div class="info-item">
<span class="icon-container">
<el-avatar shape="square" :size="16" :src="jobNumberIcon" />
</span>
<span class="infoLable">所属ESC</span>
<span class="infoValue">{{ curUserInfo.workNo }}</span>
<span class="infoValue">{{ curUserInfo.escUserName }}</span>
</div>
<div class="info-item">
<span class="icon-container">

View File

@ -72,7 +72,7 @@
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageIndex"
v-model:limit="queryParams.pageSize" @pagination="getList" />
</div>
</div>