ren
This commit is contained in:
@@ -1,20 +1,17 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="驳回" width="600px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="姓名:">
|
||||
<el-tag>{{ dataForm.name }}</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="工号:">
|
||||
<el-tag>{{ dataForm.teacherNo }}</el-tag>
|
||||
<el-form-item label="姓名 / 工号:">
|
||||
<el-tag>{{ dataForm.name }} - {{ dataForm.teacherNo }}</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型:">
|
||||
<el-tag>{{ typeName }}</el-tag>
|
||||
<el-input v-model="typeName" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="驳回理由">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="dataForm.backReason"
|
||||
:rows="4"
|
||||
:rows="3"
|
||||
placeholder="请输入驳回理由"
|
||||
maxlength="500"
|
||||
show-word-limit
|
||||
@@ -24,8 +21,8 @@
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="visible = false">关 闭</el-button>
|
||||
<el-button @click="saveData" :loading="loading" type="primary">保 存</el-button>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button @click="saveData" :loading="loading" type="primary">保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 搜索表单 -->
|
||||
<el-row shadow="hover" v-show="showSearch" class="ml10">
|
||||
<el-row shadow="hover" v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
|
||||
<el-form-item label="单位名称" prop="companyName">
|
||||
<el-input
|
||||
@@ -29,12 +29,12 @@
|
||||
@click="handleAdd"
|
||||
v-if="permissions.professional_outercompany_add">新 增
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
<!-- <right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
class="ml10"
|
||||
style="float: right; margin-right: 20px"
|
||||
@queryTable="getDataList"
|
||||
></right-toolbar>
|
||||
></right-toolbar> -->
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
@@ -60,9 +60,9 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="updateTime" label="更新时间" width="180" align="center" />
|
||||
<el-table-column prop="updateTime" label="更新时间" min-width="180" align="center" />
|
||||
|
||||
<el-table-column label="操作" width="150" align="center" fixed="right">
|
||||
<el-table-column label="操作" min-width="150" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="permissions.professional_outercompany_edit"
|
||||
@@ -76,7 +76,6 @@
|
||||
icon="delete"
|
||||
link
|
||||
type="primary"
|
||||
style="margin-left: 12px"
|
||||
@click="handleDel(scope.row)">删除
|
||||
</el-button>
|
||||
</template>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 搜索表单 -->
|
||||
<el-row shadow="hover" v-show="showSearch" class="ml10">
|
||||
<el-row shadow="hover" v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
|
||||
<el-form-item label="单位名称" prop="companyName">
|
||||
<el-input
|
||||
|
||||
@@ -163,6 +163,7 @@ interface Props {
|
||||
remarks?: string
|
||||
}
|
||||
companyList: any[]
|
||||
saveApi?: (data: any) => Promise<any> // 自定义保存 API 函数(用于培训单位、二期单位等)
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
@@ -180,7 +181,8 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
inoutFlag: '',
|
||||
remarks: ''
|
||||
}),
|
||||
companyList: () => []
|
||||
companyList: () => [],
|
||||
saveApi: undefined
|
||||
})
|
||||
|
||||
// Emits
|
||||
@@ -223,7 +225,7 @@ const formRules = {
|
||||
idCard: [
|
||||
{ required: true, message: '请输入正确身份证', trigger: 'blur' },
|
||||
{ min: 15, max: 18, message: '长度在 15 到 18 个字符', trigger: 'blur' },
|
||||
{ pattern: /^(\d{15}|\d{17}[\dXx])$/, message: '身份证号格式不正确(15位或18位,18位最后一位可以是X)', trigger: 'blur' }
|
||||
{ pattern: /^(\d{15}|\d{17}[\dXx])$/, message: '身份证号格式不正确', trigger: 'blur' }
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: '请填写手机号', trigger: 'blur' },
|
||||
@@ -271,7 +273,12 @@ const handleSubmit = async () => {
|
||||
await putObj(submitData)
|
||||
message.success('修改成功')
|
||||
} else {
|
||||
await addObj(submitData)
|
||||
// 如果提供了自定义保存函数,使用它;否则使用默认的 addObj
|
||||
if (props.saveApi) {
|
||||
await props.saveApi(submitData)
|
||||
} else {
|
||||
await addObj(submitData)
|
||||
}
|
||||
message.success('添加成功')
|
||||
}
|
||||
handleClose()
|
||||
|
||||
284
src/views/professional/outercompanyemployee/formTrain.vue
Normal file
284
src/views/professional/outercompanyemployee/formTrain.vue
Normal file
@@ -0,0 +1,284 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:title="formData.id ? '编辑' : '新增'"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="120px"
|
||||
class="form-content"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="班级名称" prop="companyId">
|
||||
<el-select
|
||||
v-model="formData.companyId"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择班级"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in companyList"
|
||||
:key="item.id"
|
||||
:label="item.companyName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学员编号" prop="employeeNo">
|
||||
<el-input
|
||||
v-model="formData.employeeNo"
|
||||
placeholder="系统自动生成"
|
||||
disabled
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="姓名" prop="realName">
|
||||
<el-input
|
||||
v-model="formData.realName"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="身份证" prop="idCard">
|
||||
<el-input
|
||||
v-model="formData.idCard"
|
||||
placeholder="请输入身份证号"
|
||||
clearable
|
||||
maxlength="18"
|
||||
@input="handleIdCardInput"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机" prop="mobile">
|
||||
<el-input
|
||||
v-model="formData.mobile"
|
||||
type="number"
|
||||
placeholder="请输入手机号"
|
||||
clearable
|
||||
maxlength="11"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="允许进出" prop="inoutFlag">
|
||||
<el-select
|
||||
v-model="formData.inoutFlag"
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in yesNoDict"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="备注" prop="remarks">
|
||||
<el-input
|
||||
v-model="formData.remarks"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入备注"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { useDict } from '/@/hooks/dict'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { putObj } from '/@/api/professional/stayschool/outercompanyemployee'
|
||||
|
||||
// Props
|
||||
interface Props {
|
||||
modelValue: boolean
|
||||
formData: {
|
||||
id?: string
|
||||
companyId?: string
|
||||
companyName?: string
|
||||
employeeNo?: string
|
||||
realName?: string
|
||||
idCard?: string
|
||||
mobile?: string
|
||||
inoutFlag?: string
|
||||
remarks?: string
|
||||
}
|
||||
companyList: any[]
|
||||
saveApi?: (data: any) => Promise<any> // 自定义保存 API 函数
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
formData: () => ({
|
||||
id: '',
|
||||
companyId: '',
|
||||
companyName: '',
|
||||
employeeNo: '',
|
||||
realName: '',
|
||||
idCard: '',
|
||||
mobile: '',
|
||||
inoutFlag: '',
|
||||
remarks: ''
|
||||
}),
|
||||
companyList: () => [],
|
||||
saveApi: undefined
|
||||
})
|
||||
|
||||
// Emits
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: boolean): void
|
||||
(e: 'success'): void
|
||||
}>()
|
||||
|
||||
// 字典数据
|
||||
const { yes_no_type: yesNoDict } = useDict('yes_no_type')
|
||||
|
||||
// 消息提示
|
||||
const message = useMessage()
|
||||
|
||||
// 表单引用
|
||||
const formRef = ref()
|
||||
|
||||
// 提交加载状态
|
||||
const submitLoading = ref(false)
|
||||
|
||||
// 弹窗显示状态
|
||||
const visible = ref(false)
|
||||
|
||||
watch(() => props.modelValue, (val) => {
|
||||
visible.value = val
|
||||
})
|
||||
|
||||
watch(visible, (val) => {
|
||||
emit('update:modelValue', val)
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = {
|
||||
companyId: [
|
||||
{ required: true, message: '请选择班级', trigger: 'change' }
|
||||
],
|
||||
realName: [
|
||||
{ required: true, message: '请填写姓名', trigger: 'blur' }
|
||||
],
|
||||
idCard: [
|
||||
{ required: true, message: '请输入正确身份证', trigger: 'blur' },
|
||||
{ min: 15, max: 18, message: '长度在 15 到 18 个字符', trigger: 'blur' },
|
||||
{ pattern: /^(\d{15}|\d{17}[\dXx])$/, message: '身份证号格式不正确', trigger: 'blur' }
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: '请填写手机号', trigger: 'blur' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
|
||||
],
|
||||
inoutFlag: [
|
||||
{ required: true, message: '请选择是否允许进出', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
const handleClose = () => {
|
||||
visible.value = false
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
|
||||
// 身份证号输入限制:只允许数字和X/x,最大长度18
|
||||
const handleIdCardInput = (value: string) => {
|
||||
// 只保留数字和X/x
|
||||
const filtered = value.replace(/[^\dXx]/g, '')
|
||||
if (filtered !== value) {
|
||||
props.formData.idCard = filtered
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return
|
||||
|
||||
await formRef.value.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true
|
||||
try {
|
||||
// 设置班级名称
|
||||
const selectedCompany = props.companyList.find(item => item.id === props.formData.companyId)
|
||||
const submitData = {
|
||||
...props.formData,
|
||||
companyName: selectedCompany?.companyName || ''
|
||||
}
|
||||
|
||||
if (props.formData.id) {
|
||||
await putObj(submitData)
|
||||
message.success('修改成功')
|
||||
} else {
|
||||
// 使用自定义保存函数
|
||||
if (props.saveApi) {
|
||||
await props.saveApi(submitData)
|
||||
} else {
|
||||
message.error('请提供保存 API 函数')
|
||||
return
|
||||
}
|
||||
message.success('添加成功')
|
||||
}
|
||||
handleClose()
|
||||
emit('success')
|
||||
} catch (error: any) {
|
||||
message.error(error?.msg || '操作失败')
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.form-content {
|
||||
:deep(.el-row) {
|
||||
margin-bottom: 18px;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-row .el-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
<div class="mb15">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="Plus"
|
||||
icon="FolderAdd"
|
||||
@click="handleAdd"
|
||||
v-if="permissions.professional_outercompanyemployee_add">新 增
|
||||
</el-button>
|
||||
@@ -86,7 +86,7 @@
|
||||
v-if="permission.scope == '1'"
|
||||
>导 入
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@@ -100,7 +100,7 @@
|
||||
icon="Delete"
|
||||
class="ml10"
|
||||
@click="batchDelect">批量删除
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
@@ -136,18 +136,18 @@
|
||||
|
||||
<el-table-column label="头像" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<img
|
||||
width="50px"
|
||||
height="50px"
|
||||
@click="handlePictureCardPreview(scope.row.employeeNo)"
|
||||
:src="getImageView(scope.row.employeeNo)"
|
||||
@error="handleImageError"
|
||||
style="cursor: pointer; object-fit: cover; border-radius: 4px;"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Picture"
|
||||
@click="handlePictureCardPreview(scope.row.employeeNo)"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="updateTime" label="更新时间" width="180" align="center" />
|
||||
<!-- <el-table-column prop="updateTime" label="更新时间" width="180" align="center" /> -->
|
||||
|
||||
<el-table-column label="操作" width="250" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
@@ -163,17 +163,15 @@
|
||||
icon="RefreshLeft"
|
||||
link
|
||||
type="primary"
|
||||
style="margin-left: 12px"
|
||||
@click="resetPassword(scope.row)">重置密码
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
v-if="permissions.professional_outercompanyemployee_del"
|
||||
icon="delete"
|
||||
link
|
||||
type="primary"
|
||||
style="margin-left: 12px"
|
||||
@click="handleDel(scope.row)">删除
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -198,28 +196,6 @@
|
||||
<img width="100%" :src="dialogImageUrl" alt="" style="max-height: 600px; object-fit: contain;" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 上传头像对话框 -->
|
||||
<el-dialog v-model="dialogAvatarVisible" title="上传头像" width="50%" append-to-body>
|
||||
<el-upload
|
||||
action="/basic/basicstudent/uploadAvatarBase64"
|
||||
list-type="picture-card"
|
||||
name="file"
|
||||
:headers="headers"
|
||||
:limit="1"
|
||||
:data="uploadData"
|
||||
:file-list="fileList"
|
||||
:before-upload="beforeUpload"
|
||||
:on-remove="removeHandler"
|
||||
:http-request="httpRequest"
|
||||
:on-success="uploadSuccess"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">上传头像,人脸识别用</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 导入对话框 -->
|
||||
<el-dialog v-model="dialogViewVisible" title="导入文件" append-to-body>
|
||||
<el-upload
|
||||
@@ -265,7 +241,7 @@ import { Session } from '/@/utils/storage'
|
||||
import { validateNull } from '/@/utils/validate'
|
||||
import axios from 'axios'
|
||||
import request from '/@/utils/request'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import { Plus, Picture } from '@element-plus/icons-vue'
|
||||
import {
|
||||
fetchList,
|
||||
getObj,
|
||||
@@ -294,7 +270,7 @@ const message = useMessage()
|
||||
const messageBox = useMessageBox()
|
||||
|
||||
// 字典数据
|
||||
const { yes_no: yesNoDict } = useDict('yes_no')
|
||||
const { yes_no_type: yesNoDict } = useDict('yes_no_type')
|
||||
|
||||
// 获取字典标签的辅助函数
|
||||
const getDictLabel = (value: string | number) => {
|
||||
@@ -313,7 +289,6 @@ const showSearch = ref(true)
|
||||
// 弹窗状态
|
||||
const dialogVisible = ref(false)
|
||||
const dialogUploadVisible = ref(false)
|
||||
const dialogAvatarVisible = ref(false)
|
||||
const dialogViewVisible = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
|
||||
@@ -344,28 +319,12 @@ const form = reactive({
|
||||
|
||||
// 头像相关
|
||||
const dialogImageUrl = ref('')
|
||||
const fileList = ref<any[]>([])
|
||||
const rowData = ref<any>({})
|
||||
const fileReader = ref<FileReader | null>(null)
|
||||
|
||||
// 上传相关
|
||||
const uploadData = reactive({
|
||||
bucketName: "base",
|
||||
module: "basic",
|
||||
username: ""
|
||||
})
|
||||
|
||||
// 导入相关
|
||||
const fileName = ref('')
|
||||
const filesList = ref<any[]>([])
|
||||
let files: File | null = null
|
||||
|
||||
// 请求头
|
||||
const headers = computed(() => {
|
||||
return {
|
||||
"Authorization": 'Bearer ' + Session.getToken()
|
||||
}
|
||||
})
|
||||
|
||||
// 配置 useTable - 注意这个 API 返回的数据结构特殊
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
@@ -521,98 +480,12 @@ const getImageView = (employeeNo: string) => {
|
||||
return `${baseUrl}/admin/user/photo/${employeeNo}?${timestamp}`
|
||||
}
|
||||
|
||||
// 图片加载错误处理
|
||||
const handleImageError = (event: Event) => {
|
||||
const img = event.target as HTMLImageElement
|
||||
img.src = '/img/default/no_pic.png'
|
||||
}
|
||||
|
||||
// 预览头像
|
||||
const handlePictureCardPreview = (employeeNo: string) => {
|
||||
dialogImageUrl.value = getImageView(employeeNo)
|
||||
dialogUploadVisible.value = true
|
||||
}
|
||||
|
||||
// 上传头像对话框
|
||||
const uploadAvatarDialog = (row: any) => {
|
||||
rowData.value = row
|
||||
fileList.value = []
|
||||
uploadData.username = row.employeeNo
|
||||
dialogAvatarVisible.value = true
|
||||
}
|
||||
|
||||
// 上传前验证
|
||||
const beforeUpload = (file: File) => {
|
||||
const isLt5M = file.size < 1 * 1024 * 1024
|
||||
if (fileList.value.length >= 1) {
|
||||
message.warning('只能上传一张头像')
|
||||
return false
|
||||
}
|
||||
if (!isLt5M) {
|
||||
message.warning('文件大小不能超过1M')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 自定义上传
|
||||
const httpRequest = (options: any) => {
|
||||
const file = options.file
|
||||
if (!fileReader.value) {
|
||||
fileReader.value = new FileReader()
|
||||
}
|
||||
|
||||
if (file) {
|
||||
fileReader.value.readAsDataURL(file)
|
||||
}
|
||||
|
||||
fileReader.value.onload = () => {
|
||||
const base64Str = fileReader.value?.result as string
|
||||
|
||||
const config = {
|
||||
url: '/basic/basicstudent/uploadAvatarBase64',
|
||||
method: 'post',
|
||||
data: {
|
||||
base64Str: base64Str.split(',')[1],
|
||||
username: rowData.value.employeeNo
|
||||
},
|
||||
timeout: 10000,
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
progressEvent.percent = progressEvent.loaded / progressEvent.total * 100
|
||||
options.onProgress(progressEvent, file)
|
||||
}
|
||||
}
|
||||
|
||||
axios(config)
|
||||
.then(res => {
|
||||
options.onSuccess(res, file)
|
||||
getDataList()
|
||||
})
|
||||
.catch(err => {
|
||||
options.onError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 移除文件
|
||||
const removeHandler = (file: any) => {
|
||||
const index = fileList.value.findIndex(f => f.uid === file.uid)
|
||||
if (index !== -1) {
|
||||
fileList.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 上传成功
|
||||
const uploadSuccess = (res: any, file: any) => {
|
||||
if (res.data) {
|
||||
const data = res.data
|
||||
file.key = data.key
|
||||
fileList.value.push(file)
|
||||
message.success('上传成功')
|
||||
dialogAvatarVisible.value = false
|
||||
getDataList()
|
||||
}
|
||||
}
|
||||
|
||||
// 导入
|
||||
const handleExportIn = () => {
|
||||
@@ -718,11 +591,6 @@ const handleExportScore = async () => {
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
if (!window.FileReader) {
|
||||
console.error('Your browser does not support FileReader API!')
|
||||
} else {
|
||||
fileReader.value = new FileReader()
|
||||
}
|
||||
loadCompanyList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 搜索表单 -->
|
||||
<el-row shadow="hover" v-show="showSearch" class="ml10">
|
||||
<el-row shadow="hover" v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="handleFilter">
|
||||
<el-form-item label="单位名称" prop="companyId">
|
||||
<el-select
|
||||
@@ -76,35 +76,50 @@
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<el-row>
|
||||
<div class="mb15" style="width: 100%;">
|
||||
<div class="mb15" style="width: 100%; position: relative;">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="FolderAdd"
|
||||
icon="FolderAdd"
|
||||
@click="handleAdd"
|
||||
v-if="permissions.professional_outercompanyemployee_add">新 增
|
||||
v-if="permissions.professional_outercompanyemployee_add"
|
||||
>
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="UploadFilled"
|
||||
@click="handleExportIn"
|
||||
v-if="permission.scope == '1'"
|
||||
>导 入
|
||||
class="ml10"
|
||||
>
|
||||
导 入
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExportScore"
|
||||
:loading="exportLoading"
|
||||
icon="Download">导出
|
||||
class="ml10"
|
||||
>
|
||||
导出
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="batchDelect">批量删除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
@click="batchDelect"
|
||||
class="ml10"
|
||||
>
|
||||
批量删除
|
||||
</el-button> -->
|
||||
<!-- <right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
class="ml10"
|
||||
style="float: right; margin-right: 20px"
|
||||
style="position: absolute; right: 0; top: 0;"
|
||||
@queryTable="getDataList"
|
||||
></right-toolbar>
|
||||
></right-toolbar> -->
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
@@ -140,18 +155,18 @@
|
||||
|
||||
<el-table-column label="头像" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<img
|
||||
width="50px"
|
||||
height="50px"
|
||||
@click="handlePictureCardPreview(scope.row.employeeNo)"
|
||||
:src="getImageView(scope.row.employeeNo)"
|
||||
@error="handleImageError"
|
||||
style="cursor: pointer; object-fit: cover; border-radius: 4px;"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Picture"
|
||||
@click="handlePictureCardPreview(scope.row.employeeNo)"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="updateTime" label="更新时间" width="180" align="center" />
|
||||
<!-- <el-table-column prop="updateTime" label="更新时间" width="180" align="center" /> -->
|
||||
|
||||
<el-table-column label="操作" width="250" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
@@ -167,17 +182,15 @@
|
||||
icon="RefreshLeft"
|
||||
link
|
||||
type="primary"
|
||||
style="margin-left: 12px"
|
||||
@click="resetPassword(scope.row)">重置密码
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
v-if="permissions.professional_outercompanyemployee_del"
|
||||
icon="delete"
|
||||
link
|
||||
type="primary"
|
||||
style="margin-left: 12px"
|
||||
@click="handleDel(scope.row)">删除
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -190,167 +203,19 @@
|
||||
/>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog
|
||||
<form-dialog
|
||||
v-model="dialogVisible"
|
||||
:title="form.id ? '编辑' : '新增'"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="formRules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="单位名称" prop="companyId">
|
||||
<el-select
|
||||
v-model="form.companyId"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择单位"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in companyList"
|
||||
:key="item.id"
|
||||
:label="item.companyName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="职员编号" prop="employeeNo">
|
||||
<el-input
|
||||
v-model="form.employeeNo"
|
||||
placeholder="系统自动生成"
|
||||
disabled
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="姓名" prop="realName">
|
||||
<el-input
|
||||
v-model="form.realName"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="身份证" prop="idCard">
|
||||
<el-input
|
||||
v-model="form.idCard"
|
||||
placeholder="请输入身份证号"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机" prop="mobile">
|
||||
<el-input
|
||||
v-model="form.mobile"
|
||||
placeholder="请输入手机号"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="职位" prop="position">
|
||||
<el-input
|
||||
v-model="form.position"
|
||||
placeholder="请输入职位"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="家庭地址" prop="address">
|
||||
<el-input
|
||||
v-model="form.address"
|
||||
placeholder="请输入家庭地址"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="允许进出" prop="inoutFlag">
|
||||
<el-select
|
||||
v-model="form.inoutFlag"
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in yesNoDict"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="备注" prop="remarks">
|
||||
<el-input
|
||||
v-model="form.remarks"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入备注"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
:form-data="form"
|
||||
:company-list="companyList"
|
||||
:save-api="saveSecond"
|
||||
@success="handleFormSuccess"
|
||||
/>
|
||||
|
||||
<!-- 头像预览对话框 -->
|
||||
<el-dialog v-model="dialogUploadVisible" title="头像预览" append-to-body>
|
||||
<img width="100%" :src="dialogImageUrl" alt="" style="max-height: 600px; object-fit: contain;" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 上传头像对话框 -->
|
||||
<el-dialog v-model="dialogAvatarVisible" title="上传头像" width="50%" append-to-body>
|
||||
<el-upload
|
||||
action="/basic/basicstudent/uploadAvatarBase64"
|
||||
list-type="picture-card"
|
||||
name="file"
|
||||
:headers="headers"
|
||||
:limit="1"
|
||||
:data="uploadData"
|
||||
:file-list="fileList"
|
||||
:before-upload="beforeUpload"
|
||||
:on-remove="removeHandler"
|
||||
:http-request="httpRequest"
|
||||
:on-success="uploadSuccess"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">上传头像,人脸识别用</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 导入对话框 -->
|
||||
<el-dialog v-model="dialogViewVisible" title="导入文件" append-to-body>
|
||||
<el-upload
|
||||
@@ -396,18 +261,17 @@ import { Session } from '/@/utils/storage'
|
||||
import { validateNull } from '/@/utils/validate'
|
||||
import axios from 'axios'
|
||||
import request from '/@/utils/request'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
fetchList,
|
||||
getObj,
|
||||
saveSecond,
|
||||
putObj,
|
||||
delObj,
|
||||
batchDel,
|
||||
resetPassWord
|
||||
} from '/@/api/professional/stayschool/outercompanyemployee'
|
||||
import { getList as getCompanyList } from '/@/api/professional/stayschool/outercompany'
|
||||
import FormDialog from './form.vue'
|
||||
|
||||
// 使用 Pinia store
|
||||
const userInfoStore = useUserInfo()
|
||||
@@ -427,7 +291,7 @@ const message = useMessage()
|
||||
const messageBox = useMessageBox()
|
||||
|
||||
// 字典数据
|
||||
const { yes_no: yesNoDict } = useDict('yes_no')
|
||||
const { yes_no_type: yesNoDict } = useDict('yes_no_type')
|
||||
|
||||
// 获取字典标签的辅助函数
|
||||
const getDictLabel = (value: string | number) => {
|
||||
@@ -437,7 +301,6 @@ const getDictLabel = (value: string | number) => {
|
||||
|
||||
// 表格引用
|
||||
const tableRef = ref()
|
||||
const formRef = ref()
|
||||
const queryRef = ref()
|
||||
const uploadFormRef = ref()
|
||||
|
||||
@@ -447,9 +310,7 @@ const showSearch = ref(true)
|
||||
// 弹窗状态
|
||||
const dialogVisible = ref(false)
|
||||
const dialogUploadVisible = ref(false)
|
||||
const dialogAvatarVisible = ref(false)
|
||||
const dialogViewVisible = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
|
||||
// 选中的行数据
|
||||
@@ -477,52 +338,15 @@ const form = reactive({
|
||||
remarks: ''
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = {
|
||||
companyId: [
|
||||
{ required: true, message: '请选择单位', trigger: 'change' }
|
||||
],
|
||||
realName: [
|
||||
{ required: true, message: '请填写姓名', trigger: 'blur' }
|
||||
],
|
||||
idCard: [
|
||||
{ required: true, message: '请填写身份证号', trigger: 'blur' }
|
||||
],
|
||||
mobile: [
|
||||
{ required: true, message: '请填写手机号', trigger: 'blur' }
|
||||
],
|
||||
address: [
|
||||
{ required: true, message: '请填写家庭住址', trigger: 'blur' }
|
||||
],
|
||||
inoutFlag: [
|
||||
{ required: true, message: '请选择是否允许进出', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
|
||||
// 头像相关
|
||||
const dialogImageUrl = ref('')
|
||||
const fileList = ref<any[]>([])
|
||||
const rowData = ref<any>({})
|
||||
const fileReader = ref<FileReader | null>(null)
|
||||
|
||||
// 上传相关
|
||||
const uploadData = reactive({
|
||||
bucketName: "base",
|
||||
module: "basic",
|
||||
username: ""
|
||||
})
|
||||
|
||||
// 导入相关
|
||||
const fileName = ref('')
|
||||
const filesList = ref<any[]>([])
|
||||
let files: File | null = null
|
||||
|
||||
// 请求头
|
||||
const headers = computed(() => {
|
||||
return {
|
||||
"Authorization": 'Bearer ' + Session.getToken()
|
||||
}
|
||||
})
|
||||
|
||||
// 配置 useTable - 注意这个 API 返回的数据结构特殊
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
@@ -666,36 +490,9 @@ const resetPassword = (row: any) => {
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return
|
||||
|
||||
await formRef.value.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true
|
||||
try {
|
||||
// 设置单位名称
|
||||
const selectedCompany = companyList.value.find(item => item.id === form.companyId)
|
||||
if (selectedCompany) {
|
||||
form.companyName = selectedCompany.companyName
|
||||
}
|
||||
|
||||
if (form.id) {
|
||||
await putObj(form)
|
||||
message.success('修改成功')
|
||||
} else {
|
||||
await saveSecond(form) // 使用 saveSecond API
|
||||
message.success('添加成功')
|
||||
}
|
||||
dialogVisible.value = false
|
||||
getDataList()
|
||||
} catch (error: any) {
|
||||
message.error(error.msg)
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
// 表单提交成功回调
|
||||
const handleFormSuccess = () => {
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 获取图片 URL
|
||||
@@ -705,90 +502,12 @@ const getImageView = (employeeNo: string) => {
|
||||
return `${baseUrl}/admin/user/photo/${employeeNo}?${timestamp}`
|
||||
}
|
||||
|
||||
// 图片加载错误处理
|
||||
const handleImageError = (event: Event) => {
|
||||
const img = event.target as HTMLImageElement
|
||||
img.src = '/img/default/no_pic.png'
|
||||
}
|
||||
|
||||
// 预览头像
|
||||
const handlePictureCardPreview = (employeeNo: string) => {
|
||||
dialogImageUrl.value = getImageView(employeeNo)
|
||||
dialogUploadVisible.value = true
|
||||
}
|
||||
|
||||
// 上传前验证
|
||||
const beforeUpload = (file: File) => {
|
||||
const isLt5M = file.size < 1 * 1024 * 1024
|
||||
if (fileList.value.length >= 1) {
|
||||
message.warning('只能上传一张头像')
|
||||
return false
|
||||
}
|
||||
if (!isLt5M) {
|
||||
message.warning('文件大小不能超过1M')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 自定义上传
|
||||
const httpRequest = (options: any) => {
|
||||
const file = options.file
|
||||
if (!fileReader.value) {
|
||||
fileReader.value = new FileReader()
|
||||
}
|
||||
|
||||
if (file) {
|
||||
fileReader.value.readAsDataURL(file)
|
||||
}
|
||||
|
||||
fileReader.value.onload = () => {
|
||||
const base64Str = fileReader.value?.result as string
|
||||
|
||||
const config = {
|
||||
url: '/basic/basicstudent/uploadAvatarBase64',
|
||||
method: 'post',
|
||||
data: {
|
||||
base64Str: base64Str.split(',')[1],
|
||||
username: rowData.value.employeeNo
|
||||
},
|
||||
timeout: 10000,
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
progressEvent.percent = progressEvent.loaded / progressEvent.total * 100
|
||||
options.onProgress(progressEvent, file)
|
||||
}
|
||||
}
|
||||
|
||||
axios(config)
|
||||
.then(res => {
|
||||
options.onSuccess(res, file)
|
||||
getDataList()
|
||||
})
|
||||
.catch(err => {
|
||||
options.onError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 移除文件
|
||||
const removeHandler = (file: any) => {
|
||||
const index = fileList.value.findIndex(f => f.uid === file.uid)
|
||||
if (index !== -1) {
|
||||
fileList.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 上传成功
|
||||
const uploadSuccess = (res: any, file: any) => {
|
||||
if (res.data) {
|
||||
const data = res.data
|
||||
file.key = data.key
|
||||
fileList.value.push(file)
|
||||
message.success('上传成功')
|
||||
dialogAvatarVisible.value = false
|
||||
getDataList()
|
||||
}
|
||||
}
|
||||
|
||||
// 导入
|
||||
const handleExportIn = () => {
|
||||
@@ -894,12 +613,6 @@ const handleExportScore = async () => {
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
if (!window.FileReader) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Your browser does not support FileReader API!')
|
||||
} else {
|
||||
fileReader.value = new FileReader()
|
||||
}
|
||||
loadCompanyList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<!-- 搜索表单 -->
|
||||
<el-row shadow="hover" v-show="showSearch" class="ml10">
|
||||
<el-row shadow="hover" v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="handleFilter">
|
||||
<el-form-item label="班级名称" prop="companyId">
|
||||
<el-select
|
||||
@@ -79,32 +79,47 @@
|
||||
<div class="mb15" style="width: 100%;">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="FolderAdd"
|
||||
icon="FolderAdd"
|
||||
@click="handleAdd"
|
||||
v-if="permissions.professional_outercompanyemployee_add">新 增
|
||||
v-if="permissions.professional_outercompanyemployee_add"
|
||||
>
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="UploadFilled"
|
||||
@click="handleExportIn"
|
||||
v-if="permission.scope == '1'"
|
||||
>导 入
|
||||
class="ml10"
|
||||
>
|
||||
导 入
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExportScore"
|
||||
:loading="exportLoading"
|
||||
icon="Download">导出
|
||||
class="ml10"
|
||||
>
|
||||
导出
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="batchDelect">批量删除
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
@click="batchDelect"
|
||||
class="ml10"
|
||||
>
|
||||
批量删除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
class="ml10"
|
||||
style="float: right; margin-right: 20px"
|
||||
@queryTable="getDataList"
|
||||
></right-toolbar>
|
||||
></right-toolbar> -->
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
@@ -140,18 +155,18 @@
|
||||
|
||||
<el-table-column label="头像" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<img
|
||||
width="50px"
|
||||
height="50px"
|
||||
@click="handlePictureCardPreview(scope.row.employeeNo)"
|
||||
:src="getImageView(scope.row.employeeNo)"
|
||||
@error="handleImageError"
|
||||
style="cursor: pointer; object-fit: cover; border-radius: 4px;"
|
||||
/>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
icon="Picture"
|
||||
@click="handlePictureCardPreview(scope.row.employeeNo)"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="updateTime" label="更新时间" width="180" align="center" />
|
||||
<!-- <el-table-column prop="updateTime" label="更新时间" width="180" align="center" /> -->
|
||||
|
||||
<el-table-column label="操作" width="250" align="center" fixed="right">
|
||||
<template #default="scope">
|
||||
@@ -167,17 +182,15 @@
|
||||
icon="RefreshLeft"
|
||||
link
|
||||
type="primary"
|
||||
style="margin-left: 12px"
|
||||
@click="resetPassword(scope.row)">重置密码
|
||||
</el-button>
|
||||
<el-button
|
||||
<!-- <el-button
|
||||
v-if="permissions.professional_outercompanyemployee_del"
|
||||
icon="delete"
|
||||
link
|
||||
type="primary"
|
||||
style="margin-left: 12px"
|
||||
@click="handleDel(scope.row)">删除
|
||||
</el-button>
|
||||
</el-button> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -190,146 +203,19 @@
|
||||
/>
|
||||
|
||||
<!-- 新增/编辑弹窗 -->
|
||||
<el-dialog
|
||||
<form-train
|
||||
v-model="dialogVisible"
|
||||
:title="form.id ? '编辑' : '新增'"
|
||||
width="800px"
|
||||
:close-on-click-modal="false"
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="form"
|
||||
:rules="formRules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="班级名称" prop="companyId">
|
||||
<el-select
|
||||
v-model="form.companyId"
|
||||
filterable
|
||||
clearable
|
||||
placeholder="请选择班级"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in companyList"
|
||||
:key="item.id"
|
||||
:label="item.companyName"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="学员编号" prop="employeeNo">
|
||||
<el-input
|
||||
v-model="form.employeeNo"
|
||||
placeholder="系统自动生成"
|
||||
disabled
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="姓名" prop="realName">
|
||||
<el-input
|
||||
v-model="form.realName"
|
||||
placeholder="请输入姓名"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="身份证" prop="idCard">
|
||||
<el-input
|
||||
v-model="form.idCard"
|
||||
placeholder="请输入身份证号"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="手机" prop="mobile">
|
||||
<el-input
|
||||
v-model="form.mobile"
|
||||
placeholder="请输入手机号"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="允许进出" prop="inoutFlag">
|
||||
<el-select
|
||||
v-model="form.inoutFlag"
|
||||
clearable
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in yesNoDict"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="备注" prop="remarks">
|
||||
<el-input
|
||||
v-model="form.remarks"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入备注"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">确定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
:form-data="form"
|
||||
:company-list="companyList"
|
||||
:save-api="saveSecond"
|
||||
@success="handleFormSuccess"
|
||||
/>
|
||||
|
||||
<!-- 头像预览对话框 -->
|
||||
<el-dialog v-model="dialogUploadVisible" title="头像预览" append-to-body>
|
||||
<img width="100%" :src="dialogImageUrl" alt="" style="max-height: 600px; object-fit: contain;" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 上传头像对话框 -->
|
||||
<el-dialog v-model="dialogAvatarVisible" title="上传头像" width="50%" append-to-body>
|
||||
<el-upload
|
||||
action="/basic/basicstudent/uploadAvatarBase64"
|
||||
list-type="picture-card"
|
||||
name="file"
|
||||
:headers="headers"
|
||||
:limit="1"
|
||||
:data="uploadData"
|
||||
:file-list="fileList"
|
||||
:before-upload="beforeUpload"
|
||||
:on-remove="removeHandler"
|
||||
:http-request="httpRequest"
|
||||
:on-success="uploadSuccess"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">上传头像,人脸识别用</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 导入对话框 -->
|
||||
<el-dialog v-model="dialogViewVisible" title="导入文件" append-to-body>
|
||||
<el-upload
|
||||
@@ -375,18 +261,18 @@ import { Session } from '/@/utils/storage'
|
||||
import { validateNull } from '/@/utils/validate'
|
||||
import axios from 'axios'
|
||||
import request from '/@/utils/request'
|
||||
import { Plus } from '@element-plus/icons-vue'
|
||||
import { Plus, UploadFilled, Download, Delete, Picture } from '@element-plus/icons-vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import {
|
||||
fetchList,
|
||||
getObj,
|
||||
saveSecond,
|
||||
putObj,
|
||||
delObj,
|
||||
batchDel,
|
||||
resetPassWord
|
||||
} from '/@/api/professional/stayschool/outercompanyemployee'
|
||||
import { getList as getCompanyList } from '/@/api/professional/stayschool/outercompany'
|
||||
import FormTrain from './formTrain.vue'
|
||||
|
||||
// 使用 Pinia store
|
||||
const userInfoStore = useUserInfo()
|
||||
@@ -406,7 +292,7 @@ const message = useMessage()
|
||||
const messageBox = useMessageBox()
|
||||
|
||||
// 字典数据
|
||||
const { yes_no: yesNoDict } = useDict('yes_no')
|
||||
const { yes_no_type: yesNoDict } = useDict('yes_no_type')
|
||||
|
||||
// 获取字典标签的辅助函数
|
||||
const getDictLabel = (value: string | number) => {
|
||||
@@ -416,7 +302,6 @@ const getDictLabel = (value: string | number) => {
|
||||
|
||||
// 表格引用
|
||||
const tableRef = ref()
|
||||
const formRef = ref()
|
||||
const queryRef = ref()
|
||||
const uploadFormRef = ref()
|
||||
|
||||
@@ -426,9 +311,7 @@ const showSearch = ref(true)
|
||||
// 弹窗状态
|
||||
const dialogVisible = ref(false)
|
||||
const dialogUploadVisible = ref(false)
|
||||
const dialogAvatarVisible = ref(false)
|
||||
const dialogViewVisible = ref(false)
|
||||
const submitLoading = ref(false)
|
||||
const exportLoading = ref(false)
|
||||
|
||||
// 选中的行数据
|
||||
@@ -454,37 +337,15 @@ const form = reactive({
|
||||
remarks: ''
|
||||
})
|
||||
|
||||
// 表单验证规则 - 培训单位没有必填验证
|
||||
const formRules = {
|
||||
companyId: [
|
||||
{ required: true, message: '请选择班级', trigger: 'change' }
|
||||
]
|
||||
}
|
||||
|
||||
// 头像相关
|
||||
const dialogImageUrl = ref('')
|
||||
const fileList = ref<any[]>([])
|
||||
const rowData = ref<any>({})
|
||||
const fileReader = ref<FileReader | null>(null)
|
||||
|
||||
// 上传相关
|
||||
const uploadData = reactive({
|
||||
bucketName: "base",
|
||||
module: "basic",
|
||||
username: ""
|
||||
})
|
||||
|
||||
// 导入相关
|
||||
const fileName = ref('')
|
||||
const filesList = ref<any[]>([])
|
||||
let files: File | null = null
|
||||
|
||||
// 请求头
|
||||
const headers = computed(() => {
|
||||
return {
|
||||
"Authorization": 'Bearer ' + Session.getToken()
|
||||
}
|
||||
})
|
||||
|
||||
// 配置 useTable - 注意这个 API 返回的数据结构特殊
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
@@ -624,36 +485,9 @@ const resetPassword = (row: any) => {
|
||||
}).catch(() => {})
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return
|
||||
|
||||
await formRef.value.validate(async (valid: boolean) => {
|
||||
if (valid) {
|
||||
submitLoading.value = true
|
||||
try {
|
||||
// 设置单位名称
|
||||
const selectedCompany = companyList.value.find(item => item.id === form.companyId)
|
||||
if (selectedCompany) {
|
||||
form.companyName = selectedCompany.companyName
|
||||
}
|
||||
|
||||
if (form.id) {
|
||||
await putObj(form)
|
||||
message.success('修改成功')
|
||||
} else {
|
||||
await saveSecond(form) // 使用 saveSecond API
|
||||
message.success('添加成功')
|
||||
}
|
||||
dialogVisible.value = false
|
||||
getDataList()
|
||||
} catch (error: any) {
|
||||
message.error(error.msg)
|
||||
} finally {
|
||||
submitLoading.value = false
|
||||
}
|
||||
}
|
||||
})
|
||||
// 表单提交成功回调
|
||||
const handleFormSuccess = () => {
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 获取图片 URL
|
||||
@@ -663,90 +497,12 @@ const getImageView = (employeeNo: string) => {
|
||||
return `${baseUrl}/admin/user/photo/${employeeNo}?${timestamp}`
|
||||
}
|
||||
|
||||
// 图片加载错误处理
|
||||
const handleImageError = (event: Event) => {
|
||||
const img = event.target as HTMLImageElement
|
||||
img.src = '/img/default/no_pic.png'
|
||||
}
|
||||
|
||||
// 预览头像
|
||||
const handlePictureCardPreview = (employeeNo: string) => {
|
||||
dialogImageUrl.value = getImageView(employeeNo)
|
||||
dialogUploadVisible.value = true
|
||||
}
|
||||
|
||||
// 上传前验证
|
||||
const beforeUpload = (file: File) => {
|
||||
const isLt5M = file.size < 1 * 1024 * 1024
|
||||
if (fileList.value.length >= 1) {
|
||||
message.warning('只能上传一张头像')
|
||||
return false
|
||||
}
|
||||
if (!isLt5M) {
|
||||
message.warning('文件大小不能超过1M')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// 自定义上传
|
||||
const httpRequest = (options: any) => {
|
||||
const file = options.file
|
||||
if (!fileReader.value) {
|
||||
fileReader.value = new FileReader()
|
||||
}
|
||||
|
||||
if (file) {
|
||||
fileReader.value.readAsDataURL(file)
|
||||
}
|
||||
|
||||
fileReader.value.onload = () => {
|
||||
const base64Str = fileReader.value?.result as string
|
||||
|
||||
const config = {
|
||||
url: '/basic/basicstudent/uploadAvatarBase64',
|
||||
method: 'post',
|
||||
data: {
|
||||
base64Str: base64Str.split(',')[1],
|
||||
username: rowData.value.employeeNo
|
||||
},
|
||||
timeout: 10000,
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
progressEvent.percent = progressEvent.loaded / progressEvent.total * 100
|
||||
options.onProgress(progressEvent, file)
|
||||
}
|
||||
}
|
||||
|
||||
axios(config)
|
||||
.then(res => {
|
||||
options.onSuccess(res, file)
|
||||
getDataList()
|
||||
})
|
||||
.catch(err => {
|
||||
options.onError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 移除文件
|
||||
const removeHandler = (file: any) => {
|
||||
const index = fileList.value.findIndex(f => f.uid === file.uid)
|
||||
if (index !== -1) {
|
||||
fileList.value.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
// 上传成功
|
||||
const uploadSuccess = (res: any, file: any) => {
|
||||
if (res.data) {
|
||||
const data = res.data
|
||||
file.key = data.key
|
||||
fileList.value.push(file)
|
||||
message.success('上传成功')
|
||||
dialogAvatarVisible.value = false
|
||||
getDataList()
|
||||
}
|
||||
}
|
||||
|
||||
// 导入
|
||||
const handleExportIn = () => {
|
||||
@@ -852,12 +608,6 @@ const handleExportScore = async () => {
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
if (!window.FileReader) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('Your browser does not support FileReader API!')
|
||||
} else {
|
||||
fileReader.value = new FileReader()
|
||||
}
|
||||
loadCompanyList()
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
@click="handleEdit(scope.row)">编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
type="primary"
|
||||
link
|
||||
icon="Delete"
|
||||
v-if="permissions.professional_professionalpartybranch_del"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
ref="formRef"
|
||||
:model="dataForm"
|
||||
:rules="formRules"
|
||||
:validate-on-rule-change="false"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item label="毕业时间" prop="graduateTime">
|
||||
@@ -198,14 +199,14 @@ const needDegreeImg = computed(() => {
|
||||
return true
|
||||
})
|
||||
|
||||
// 动态验证规则
|
||||
// 验证规则
|
||||
const formRules = computed(() => {
|
||||
const rules: any = {
|
||||
graduateTime: [
|
||||
{ required: true, message: '请选择毕业时间', trigger: 'change' }
|
||||
{ required: true, message: '请选择毕业时间', trigger: 'blur' }
|
||||
],
|
||||
type: [
|
||||
{ required: true, message: '请选择教育类型', trigger: 'change' }
|
||||
{ required: true, message: '请选择教育类型', trigger: 'blur' }
|
||||
],
|
||||
graduateSchool: [
|
||||
{ required: true, message: '请输入毕业学校', trigger: 'blur' }
|
||||
@@ -222,14 +223,14 @@ const formRules = computed(() => {
|
||||
// 只有当需要学历证书时才添加验证规则
|
||||
if (needQualificationImg.value) {
|
||||
rules.qualificationImg = [
|
||||
{ required: true, message: '请上传学历证书', trigger: 'change' }
|
||||
{ required: true, message: '请上传学历证书', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
// 只有当需要学位证书时才添加验证规则
|
||||
if (needDegreeImg.value) {
|
||||
rules.degreeImg = [
|
||||
{ required: true, message: '请上传学位证书', trigger: 'change' }
|
||||
{ required: true, message: '请上传学位证书', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -299,6 +300,11 @@ const handleQualificationChange = () => {
|
||||
dataForm.qualificationImg = ''
|
||||
fileList.value = []
|
||||
formRef.value?.clearValidate('qualificationImg')
|
||||
} else {
|
||||
// 如果需要学历证书,延迟清除验证(等字段显示后)
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate('qualificationImg')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,6 +315,11 @@ const handleDegreeChange = () => {
|
||||
dataForm.degreeImg = ''
|
||||
fileListB.value = []
|
||||
formRef.value?.clearValidate('degreeImg')
|
||||
} else {
|
||||
// 如果需要学位证书,延迟清除验证(等字段显示后)
|
||||
nextTick(() => {
|
||||
formRef.value?.clearValidate('degreeImg')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,6 +406,9 @@ const openDialog = async (row?: any) => {
|
||||
await nextTick()
|
||||
showForm.value = true
|
||||
dialogVisible.value = true
|
||||
// 对话框打开后,清除所有验证错误,避免立即显示验证提示
|
||||
await nextTick()
|
||||
formRef.value?.clearValidate()
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
|
||||
@@ -26,10 +26,14 @@
|
||||
|
||||
<el-form-item label="证明材料" prop="attachment" required>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:headers="headers"
|
||||
:limit="1"
|
||||
:action="url"
|
||||
:before-upload="beforeUpload"
|
||||
:on-success="materiaUploadSuccess"
|
||||
:on-remove="handleRemove"
|
||||
:on-exceed="handleExceed"
|
||||
:file-list="fileList"
|
||||
:accept="'.jpg,.jpeg,.png,.pdf'"
|
||||
>
|
||||
@@ -45,15 +49,15 @@
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="dialogVisible = false">关 闭</el-button>
|
||||
<el-button @click="dialogSubmit" type="primary" :loading="submitLoading">保 存</el-button>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button @click="dialogSubmit" type="primary" :loading="submitLoading">保存</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { ref, reactive, computed, nextTick } from 'vue'
|
||||
import { Session } from '/@/utils/storage'
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { addObj } from '/@/api/professional/professionaluser/professionalteacherhonor'
|
||||
@@ -69,6 +73,7 @@ const message = useMessage()
|
||||
|
||||
// 表单引用
|
||||
const formRef = ref()
|
||||
const uploadRef = ref()
|
||||
const submitLoading = ref(false)
|
||||
|
||||
// 对话框显示状态(内部管理)
|
||||
@@ -126,14 +131,65 @@ const initDicData = async () => {
|
||||
// 综合表彰不需要额外的字典数据
|
||||
}
|
||||
|
||||
// 上传前的处理
|
||||
const beforeUpload = () => {
|
||||
return true
|
||||
}
|
||||
|
||||
// 文件超出限制时的处理(当 limit=1 且已有文件时,用户上传新文件会触发此事件)
|
||||
// 根据 Element Plus 官方文档,在 on-exceed 中清空文件列表并添加新文件
|
||||
const handleExceed = (files: File[]) => {
|
||||
// 清空当前文件列表
|
||||
uploadRef.value?.clearFiles()
|
||||
fileList.value = []
|
||||
dataForm.attachment = ''
|
||||
|
||||
// 等待 DOM 更新后,手动触发新文件的上传
|
||||
nextTick(() => {
|
||||
const newFile = files[0]
|
||||
if (newFile && uploadRef.value) {
|
||||
// 通过 input 元素手动触发文件上传
|
||||
const input = uploadRef.value.$el?.querySelector('input[type="file"]')
|
||||
if (input) {
|
||||
// 创建新的 DataTransfer 对象并添加新文件
|
||||
const dataTransfer = new DataTransfer()
|
||||
dataTransfer.items.add(newFile)
|
||||
input.files = dataTransfer.files
|
||||
|
||||
// 触发 change 事件,让 Element Plus 自动处理上传
|
||||
const changeEvent = new Event('change', { bubbles: true })
|
||||
input.dispatchEvent(changeEvent)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 文件上传成功
|
||||
const materiaUploadSuccess = (response: any) => {
|
||||
const materiaUploadSuccess = (response: any, file: any) => {
|
||||
if (response.data && response.data.code === "-1") {
|
||||
message.error("当前不允许上传文件")
|
||||
// 上传失败,移除文件
|
||||
fileList.value = []
|
||||
uploadRef.value?.clearFiles()
|
||||
return
|
||||
}
|
||||
dataForm.attachment = response.data.url
|
||||
// 清除验证错误
|
||||
if (response.data && response.data.url) {
|
||||
dataForm.attachment = response.data.url
|
||||
// 更新文件列表,确保显示新上传的文件(替换旧文件)
|
||||
fileList.value = [{
|
||||
name: file.name || '证明材料',
|
||||
url: response.data.url,
|
||||
uid: file.uid || Date.now(),
|
||||
status: 'success'
|
||||
}]
|
||||
formRef.value?.clearValidate('attachment')
|
||||
}
|
||||
}
|
||||
|
||||
// 文件删除处理
|
||||
const handleRemove = () => {
|
||||
dataForm.attachment = ''
|
||||
fileList.value = []
|
||||
formRef.value?.clearValidate('attachment')
|
||||
}
|
||||
|
||||
|
||||
@@ -291,7 +291,6 @@ const changeState = (row: any, val: number) => {
|
||||
} else if (val === -2) {
|
||||
// 驳回
|
||||
const newRow = JSON.parse(JSON.stringify(row))
|
||||
newRow.realName = newRow.teacherName
|
||||
backReasonRef.value?.init(newRow, 'honor')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<el-dialog v-model="dialogEmptyFromVisible" title="教职工信息导出" width="80%">
|
||||
<el-form style="margin-left: 7px" :inline="true">
|
||||
<el-form :inline="true" label-width="100px" style="margin-bottom: 20px;">
|
||||
<el-form-item>
|
||||
<el-tag>导出教职工人数,依据'职工信息'页面检索条件,如部门,职称等级等条件</el-tag>
|
||||
<el-tag type="warning">*请在'职工信息'页面点击搜索后,再点开当前导出页面</el-tag>
|
||||
<el-tag type="info">导出依据"职工信息"页面的检索条件</el-tag>
|
||||
<el-tag type="warning" style="margin-left: 10px;">请在搜索后再打开导出页面</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否退休">
|
||||
<el-select
|
||||
@@ -11,7 +11,7 @@
|
||||
filterable
|
||||
reserve-keyword
|
||||
clearable
|
||||
>
|
||||
style="width: 200px;">
|
||||
<el-option
|
||||
v-for="item in YES_OR_NO"
|
||||
:key="item.value"
|
||||
@@ -25,52 +25,54 @@
|
||||
type="primary"
|
||||
@click="exportTeacherInfo"
|
||||
:loading="exportLoading"
|
||||
size="small">导出</el-button>
|
||||
:icon="Download">导出</el-button>
|
||||
</el-form-item>
|
||||
|
||||
</el-form>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<div class="div_stuData" style="margin-bottom: 5px;margin-top: 5px;">基础信息
|
||||
<el-checkbox v-model="allCheckTeacherBaseInfo" style="margin-left:20px">全选</el-checkbox>
|
||||
</div>
|
||||
<el-tabs type="border-card" tab-position="left">
|
||||
<el-form ref="baseForm" label-width="120px">
|
||||
<el-row>
|
||||
<el-checkbox-group v-model="checkedTeacherBaseInfo">
|
||||
<el-checkbox v-for="(item,index) in teacherBasicCheckData" :label="item.value" :key="index">{{item.label}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-tabs>
|
||||
<!-- 基础信息 -->
|
||||
<el-card shadow="never" style="margin-bottom: 20px;">
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>基础信息</span>
|
||||
<el-checkbox v-model="allCheckTeacherBaseInfo">全选</el-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
<el-checkbox-group v-model="checkedTeacherBaseInfo">
|
||||
<el-checkbox v-for="(item, index) in teacherBasicCheckData" :label="item.value" :key="index" style="margin-right: 20px; margin-bottom: 10px;">
|
||||
{{item.label}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-card>
|
||||
|
||||
<!-- 岗位信息 -->
|
||||
<div class="div_stuData" style="margin-bottom: 5px;margin-top: 5px;">岗位信息
|
||||
<el-checkbox v-model="allCheckStationInfo">全选</el-checkbox>
|
||||
</div>
|
||||
<el-tabs type="border-card" tab-position="left">
|
||||
<el-form ref="baseForm" label-width="120px">
|
||||
<el-row>
|
||||
<el-checkbox-group v-model="checkedTeacherStationInfo">
|
||||
<el-checkbox v-for="(item, index) in teacherStationData" :key="index" :label="item.value">{{item.label}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-tabs>
|
||||
<!-- 岗位信息 -->
|
||||
<el-card shadow="never" style="margin-bottom: 20px;">
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>岗位信息</span>
|
||||
<el-checkbox v-model="allCheckStationInfo">全选</el-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
<el-checkbox-group v-model="checkedTeacherStationInfo">
|
||||
<el-checkbox v-for="(item, index) in teacherStationData" :key="index" :label="item.value" style="margin-right: 20px; margin-bottom: 10px;">
|
||||
{{item.label}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-card>
|
||||
|
||||
<!-- 其他 -->
|
||||
<div class="div_stuData" style="margin-bottom: 5px;margin-top: 5px;">其他
|
||||
<el-checkbox v-model="allCheckedother" style="margin-left: 20px">全选</el-checkbox>
|
||||
</div>
|
||||
<el-tabs type="border-card" tab-position="left">
|
||||
<el-form ref="baseForm" label-width="120px">
|
||||
<el-row>
|
||||
<el-checkbox-group v-model="checkedTeacherOtherInfo">
|
||||
<el-checkbox v-for="(item, index) in teacherOtherData" :key="index" :label="item.value">{{item.label}}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-tabs>
|
||||
<!-- 其他 -->
|
||||
<el-card shadow="never">
|
||||
<template #header>
|
||||
<div style="display: flex; justify-content: space-between; align-items: center;">
|
||||
<span>其他</span>
|
||||
<el-checkbox v-model="allCheckedother">全选</el-checkbox>
|
||||
</div>
|
||||
</template>
|
||||
<el-checkbox-group v-model="checkedTeacherOtherInfo">
|
||||
<el-checkbox v-for="(item, index) in teacherOtherData" :key="index" :label="item.value" style="margin-right: 20px; margin-bottom: 10px;">
|
||||
{{item.label}}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-card>
|
||||
|
||||
</el-dialog>
|
||||
|
||||
@@ -79,6 +81,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { Download } from '@element-plus/icons-vue'
|
||||
import global from '/@/components/tools/commondict.vue'
|
||||
import request from '/@/utils/request'
|
||||
|
||||
@@ -250,5 +253,4 @@
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,39 +1,46 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="导入" width="80%" append-to-body>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<a href="excel/dictlist.xlsx" rel="external nofollow" download="职工信息字典下载">
|
||||
<el-button style="margin-left: 20px" size="small" type="success">职工信息字典下载</el-button>
|
||||
</a>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col>
|
||||
<el-tag>导入时,部分字段需严格按照字典值填写</el-tag>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog v-model="visible" title="导入职工信息" width="600" append-to-body>
|
||||
<el-alert
|
||||
type="warning"
|
||||
:closable="false"
|
||||
show-icon
|
||||
style="margin-bottom: 20px;">
|
||||
<template #title>
|
||||
<span>导入前请先下载字典文件,部分字段需严格按照字典值填写</span>
|
||||
</template>
|
||||
</el-alert>
|
||||
|
||||
<el-row>
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action="/professional/file/importTeacherInfoSimple"
|
||||
:headers="headers"
|
||||
:accept="'.xls,.xlsx'"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleAvatarError"
|
||||
list-type="picture">
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">只能上传后缀为xls,xlsx的文件</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-row>
|
||||
<div style="text-align: center; margin-bottom: 20px;">
|
||||
<a href="excel/dictlist.xlsx" rel="external nofollow" download="职工信息字典下载" style="text-decoration: none;">
|
||||
<el-button type="success" :icon="Download">下载字典文件</el-button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action="/professional/file/importTeacherInfoSimple"
|
||||
:headers="headers"
|
||||
:accept="'.xls,.xlsx'"
|
||||
:on-success="handleUploadSuccess"
|
||||
:on-error="handleAvatarError"
|
||||
drag>
|
||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或<em>点击上传</em>
|
||||
</div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">
|
||||
只能上传 .xls 或 .xlsx 格式的 Excel 文件
|
||||
</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { ElNotification } from 'element-plus'
|
||||
import { Download, UploadFilled } from '@element-plus/icons-vue'
|
||||
import { Session } from '/@/utils/storage'
|
||||
|
||||
// 响应式数据
|
||||
@@ -77,6 +84,10 @@
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.upload-demo {
|
||||
:deep(.el-upload-dragger) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1940,7 +1940,7 @@
|
||||
return [
|
||||
{
|
||||
command: 'export',
|
||||
label: '导出',
|
||||
label: '导出信息',
|
||||
icon: Download,
|
||||
visible: () => permissions.value.professional_teacherbase_export
|
||||
},
|
||||
|
||||
@@ -2,20 +2,15 @@
|
||||
<el-dialog v-model="dialogVisible" width="600" :title="waitShenheForm.title" append-to-body>
|
||||
<!--人员调动-->
|
||||
<el-form v-if="waitShenheForm.isPersonnelTransfer" ref="stationChangeFormRef" :model="waitShenheForm.form" :rules="stationChangeRules" label-width="120px">
|
||||
<el-form-item label="工号">
|
||||
<el-tag>{{waitShenheForm.form.teacherNo}}</el-tag>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="姓名">
|
||||
<el-tag>{{waitShenheForm.form.realName}}</el-tag>
|
||||
<el-form-item label="工号 / 姓名">
|
||||
<el-tag>{{waitShenheForm.form.teacherNo}} - {{waitShenheForm.form.realName}}</el-tag>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="原部门名称">
|
||||
<el-tag disabled>{{waitShenheForm.form.deptName}}</el-tag>
|
||||
<el-input v-model="waitShenheForm.form.deptName" disabled />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="现二级部门" prop="newDeptCode">
|
||||
<el-select v-model="newSecDeptCode" @change="getDeptListByParent" placeholder="请选择二级部门" style="width: 100%">
|
||||
<el-select v-model="newSecDeptCode" @change="getDeptListByParent" placeholder="请选择二级部门">
|
||||
<el-option v-for="item in secDeptList"
|
||||
:key="item.deptCode"
|
||||
:label="item.deptName"
|
||||
@@ -68,12 +63,8 @@
|
||||
</el-form>
|
||||
<!--党员调动-->
|
||||
<el-form v-if="waitShenheForm.isPartyTransfer" ref="partChangeFormRef" :model="waitShenheForm.form" :rules="partChangeRules" label-width="120px">
|
||||
<el-form-item label="工号">
|
||||
<el-tag>{{waitShenheForm.form.teacherNo}}</el-tag>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="用户名">
|
||||
<el-tag>{{waitShenheForm.form.realName}}</el-tag>
|
||||
<el-form-item label="工号 / 用户名">
|
||||
<el-tag>{{waitShenheForm.form.teacherNo}} - {{waitShenheForm.form.realName}}</el-tag>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="原支部名">
|
||||
@@ -113,7 +104,7 @@
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="备注" prop="remarks">
|
||||
<el-input v-model="waitShenheForm.form.remarks" placeholder="请输入备注" />
|
||||
<el-input v-model="waitShenheForm.form.remarks" type="textarea" :rows="3" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
@@ -127,7 +118,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'vue'
|
||||
import { ref, reactive, nextTick } from 'vue'
|
||||
import { useMessage, useMessageBox } from '/@/hooks/message'
|
||||
import { getAllInfoAboutList } from '/@/api/professional/professionaluser/teacherbase'
|
||||
import { getDeptListByLevelTwo, getDeptListByParent as getDeptListByParentApi } from '/@/api/basic/basicdept'
|
||||
@@ -177,15 +168,15 @@
|
||||
|
||||
// 人员调动验证规则
|
||||
const stationChangeRules = {
|
||||
newDeptCode: [{ required: true, message: '请选择要调入的二级部门', trigger: 'change' }],
|
||||
changeDate: [{ required: true, message: '请选择调令日期', trigger: 'change' }],
|
||||
pos: [{ required: true, message: '请选择岗位类型', trigger: 'change' }]
|
||||
newDeptCode: [{ required: true, message: '请选择要调入的二级部门', trigger: 'blur' }],
|
||||
changeDate: [{ required: true, message: '请选择调令日期', trigger: 'blur' }],
|
||||
pos: [{ required: true, message: '请选择岗位类型', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
// 党员调动验证规则
|
||||
const partChangeRules = {
|
||||
branchName: [{ required: true, message: '请选择现支部', trigger: 'change' }],
|
||||
changeTime: [{ required: true, message: '请选择变动时间', trigger: 'change' }]
|
||||
branchName: [{ required: true, message: '请选择现支部', trigger: 'blur' }],
|
||||
changeTime: [{ required: true, message: '请选择变动时间', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,6 +264,7 @@
|
||||
waitShenheForm.title = "人员调动"
|
||||
waitShenheForm.isPersonnelTransfer = true
|
||||
waitShenheForm.form = { ...props.nowRow }
|
||||
waitShenheForm.form.id = ''
|
||||
waitShenheForm.form.newDeptCodeList = []
|
||||
waitShenheForm.form.deptCodeList = []
|
||||
newSecDeptCode.value = ''
|
||||
@@ -281,6 +273,10 @@
|
||||
getDeptListByLevelTwo().then((res: any) => {
|
||||
secDeptList.value = res.data || []
|
||||
dialogVisible.value = true
|
||||
// 弹窗打开后,清除表单验证状态,避免立即显示验证提示
|
||||
nextTick(() => {
|
||||
stationChangeFormRef.value?.clearValidate()
|
||||
})
|
||||
})
|
||||
} else if (val === FORM_TYPE.PARTY_TRANSFER) {
|
||||
// 党员调动:设置原支部
|
||||
@@ -291,6 +287,10 @@
|
||||
waitShenheForm.form.realName = waitShenheForm.form.userName || waitShenheForm.form.realName
|
||||
waitShenheForm.form.oldBranchName = waitShenheForm.form.oldBranchId
|
||||
dialogVisible.value = true
|
||||
// 弹窗打开后,清除表单验证状态,避免立即显示验证提示
|
||||
nextTick(() => {
|
||||
partChangeFormRef.value?.clearValidate()
|
||||
})
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -312,12 +312,8 @@
|
||||
|
||||
const formRef = formRefMap[val]
|
||||
|
||||
// 人员调动:需要选择部门
|
||||
// 人员调动:在验证前同步数据
|
||||
if (val === FORM_TYPE.PERSONNEL_TRANSFER) {
|
||||
if (!newSecDeptCode.value) {
|
||||
message.info("请选择要调入的部门")
|
||||
return
|
||||
}
|
||||
waitShenheForm.form.newDeptCode = newSecDeptCode.value
|
||||
waitShenheForm.form.newSecDeptCode = newSecChildDeptCode.value || newSecDeptCode.value
|
||||
}
|
||||
@@ -331,8 +327,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 先确认,用户取消时不执行后续操作
|
||||
try {
|
||||
await messageBox.confirm('确认提交?')
|
||||
} catch (err: any) {
|
||||
// 用户取消操作,直接返回,不显示错误提示
|
||||
return
|
||||
}
|
||||
|
||||
// 用户确认后,执行提交操作
|
||||
try {
|
||||
let res: any
|
||||
|
||||
if (val === FORM_TYPE.PERSONNEL_TRANSFER) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="薪资导出" width="500px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="120px">
|
||||
<el-dialog v-model="visible" title="薪资导出" width="650px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="chooseDate"
|
||||
@@ -9,7 +9,6 @@
|
||||
value-format="YYYY-M"
|
||||
placeholder="请选择日期"
|
||||
@change="handleChange"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="劳务日期锁定">
|
||||
@@ -18,7 +17,7 @@
|
||||
<el-radio :label="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-form-item label-width="0px">
|
||||
<el-tag type="warning">选择是,则本月其他造单批次无法指定到当前月份。如需解锁,请前往「薪资导出记录」删除记录即可。</el-tag>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" title="薪资导出" width="500px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="120px">
|
||||
<el-dialog v-model="visible" title="薪资导出" width="650px" :close-on-click-modal="false" destroy-on-close>
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="日期">
|
||||
<el-date-picker
|
||||
v-model="chooseDate"
|
||||
@@ -8,8 +8,7 @@
|
||||
format="YYYY-M"
|
||||
value-format="YYYY-M"
|
||||
placeholder="请选择日期"
|
||||
@change="handleChange"
|
||||
style="width: 100%"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="劳务日期锁定">
|
||||
@@ -18,7 +17,7 @@
|
||||
<el-radio :label="0">否</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-form-item label-width="0px">
|
||||
<el-tag type="warning">选择是,则本月其他造单批次无法指定到当前月份。如需解锁,请前往「薪资导出记录」删除记录即可。</el-tag>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
Reference in New Issue
Block a user