Files
jyls_front/src/views/calibration/revenueRecognition/index.vue

995 lines
30 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- 用户管理 -->
<template>
<div class="app-container">
<el-row :gutter="20">
<!-- 部门树 -->
<el-col :lg="4" :xs="24" class="mb-[12px]">
<DeptTree v-model="queryParams.department" @node-click="handleQuery" />
</el-col>
<!-- 用户列表 -->
<el-col :lg="20" :xs="24">
<!-- 搜索区域 -->
<div class="search-container">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="auto">
<el-form-item label="关键字" prop="keywords">
<el-input
v-model="queryParams.username"
placeholder="用户名/昵称/手机号"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<!-- <el-form-item label="状态" prop="status">-->
<!-- <el-select-->
<!-- v-model="queryParams.status"-->
<!-- placeholder="全部"-->
<!-- clearable-->
<!-- style="width: 100px"-->
<!-- >-->
<!-- <el-option label="正常" :value="1" />-->
<!-- <el-option label="禁用" :value="0" />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="创建时间">-->
<!-- <el-date-picker-->
<!-- v-model="queryParams.createTime"-->
<!-- :editable="false"-->
<!-- type="daterange"-->
<!-- range-separator="~"-->
<!-- start-placeholder="开始时间"-->
<!-- end-placeholder="截止时间"-->
<!-- value-format="YYYY-MM-DD"-->
<!-- />-->
<!-- </el-form-item>-->
<el-form-item class="search-buttons">
<el-button type="primary" icon="search" @click="handleQuery">搜索</el-button>
<el-button icon="refresh" @click="handleResetQuery">重置</el-button>
</el-form-item>
</el-form>
</div>
<el-card shadow="hover" class="data-table">
<div class="data-table__toolbar">
<div class="data-table__toolbar--actions">
<el-button
v-hasPerm="['sys:user:add']"
type="success"
icon="plus"
@click="handleOpenDialog()"
>
新增
</el-button>
<el-button
v-hasPerm="'sys:user:delete'"
type="danger"
icon="delete"
:disabled="!hasSelection"
@click="handleDelete()"
>
删除
</el-button>
</div>
<div class="data-table__toolbar--tools">
<!-- <el-button-->
<!-- v-hasPerm="'sys:user:import'"-->
<!-- icon="upload"-->
<!-- @click="handleOpenImportDialog"-->
<!-- >-->
<!-- 导入-->
<!-- </el-button>-->
<el-button v-hasPerm="'sys:user:export'" icon="download" @click="handleExport">
导出
</el-button>
</div>
</div>
<el-table
v-loading="loading"
:data="pageData"
border
stripe
highlight-current-row
class="data-table__content"
row-key="id"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户名" prop="account" />
<el-table-column label="昵称" align="center" prop="username" />
<!-- <el-table-column label="性别" width="100" align="center">-->
<!-- <template #default="scope">-->
<!-- <DictLabel v-model="scope.row.gender" code="gender" />-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column label="部门" align="center" prop="department" />
<el-table-column label="手机号码" align="center" prop="mobilePhone" />
<el-table-column label="入职时间" align="center" prop="Dateofjoining" />
<el-table-column label="操作" fixed="right" align="center" width="220">
<template #default="scope">
<!-- <el-button-->
<!-- v-hasPerm="'sys:user:reset-password'"-->
<!-- type="primary"-->
<!-- icon="RefreshLeft"-->
<!-- size="small"-->
<!-- link-->
<!-- @click="handleResetPassword(scope.row)"-->
<!-- >-->
<!-- 重置密码-->
<!-- </el-button>-->
<el-button
v-hasPerm="'sys:user:edit'"
type="primary"
icon="edit"
link
size="small"
@click="handleOpenDialog(scope.row)"
>
编辑
</el-button>
<el-button
v-hasPerm="'sys:user:delete'"
type="danger"
icon="delete"
link
size="small"
@click="handleDelete(scope.row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-if="total > 0"
v-model:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="fetchUserList"
/>
</el-card>
</el-col>
</el-row>
<!-- 用户表单 -->
<el-drawer
v-model="dialog.visible"
:title="dialog.title"
append-to-body
:size="drawerSize"
@close="handleCloseDialog"
>
<el-form ref="userFormRef" :model="formData" :rules="rules" label-width="120px">
<el-form-item label="姓名" prop="username">
<el-input v-model="formData.username" placeholder="请输入姓名" />
</el-form-item>
<el-form-item label="账号" prop="account">
<el-input v-model="formData.account" placeholder="请输入账号" />
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input v-model="formData.password" placeholder="请输入密码" />
</el-form-item>
<el-form-item label="民族" prop="nation">
<el-input v-model="formData.nation" placeholder="请输入民族" />
</el-form-item>
<el-form-item label="身份证号码" prop="IdCard">
<el-input v-model="formData.IdCard" placeholder="请输入身份证号码" maxlength="18" />
</el-form-item>
<el-form-item label="手机号" prop="mobilePhone">
<el-input v-model="formData.mobilePhone" placeholder="请输入手机号" maxlength="11" />
</el-form-item>
<el-form-item label="所属部门" prop="department">
<el-select v-model="formData.department" placeholder="请选择所属部门">
<el-option key="行政部" label="行政部" value="行政部" />
<el-option key="财务部" label="财务部" value="财务部" />
<el-option key="执业律师" label="执业律师" value="执业律师" />
<el-option key="实习律师" label="实习律师" value="实习律师" />
</el-select>
</el-form-item>
<el-form-item label="岗位" prop="position">
<el-select v-model="formData.position" placeholder="请选择所属部门">
<el-option key="助理" label="助理" value="助理" />
<el-option key="独立律师" label="独立律师" value="独立律师" />
<el-option key="一级主办律师" label="一级主办律师" value="一级主办律师" />
<el-option key="中级主办律师" label="中级主办律师" value="中级主办律师" />
<el-option key="高级主办律师" label="高级主办律师" value="高级主办律师" />
<el-option key="合伙人" label="合伙人" value="合伙人" />
<el-option key="已离职" label="已离职" value="已离职" />
</el-select>
</el-form-item>
<el-form-item label="所属团队" prop="team">
<el-select v-model="formData.team" placeholder="请选择所属团队">
<el-option key="团队一" label="团队一" value="团队一" />
<el-option key="团队二" label="团队二" value="团队二" />
<el-option key="团队三" label="团队三" value="团队三" />
</el-select>
</el-form-item>
<el-form-item label="入职时间" prop="Dateofjoining">
<el-date-picker
v-model="formData.Dateofjoining"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择入职时间"
/>
</el-form-item>
<el-form-item label="转正时间" prop="Confirmationtime">
<el-date-picker
v-model="formData.Confirmationtime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择转正时间"
/>
</el-form-item>
<el-form-item label="执业证时间" prop="Practicingcertificatetime">
<el-date-picker
v-model="formData.Practicingcertificatetime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择执业证时间"
/>
</el-form-item>
<!-- <el-form-item label="离职时间" prop="resignationDate">-->
<!-- <el-date-picker-->
<!-- v-model="formData.resignationDate"-->
<!-- type="date"-->
<!-- value-format="YYYY-MM-DD"-->
<!-- placeholder="请选择离职时间"-->
<!-- />-->
<!-- </el-form-item>-->
<el-form-item label="学业简历" prop="academic">
<div style="width: 440px; display: flex; flex-direction: column">
<!-- 学业简历表格样式布局 -->
<div class="education-resume-table">
<!-- 表头 -->
<div class="education-resume-header">
<div class="table-col date-col">日期区间</div>
<div class="table-col school-col">毕业院校</div>
<div class="table-col major-col">专业</div>
<div class="table-col degree-col">学历</div>
<div class="table-col action-col">操作</div>
</div>
<!-- 表体 -->
<div
v-for="(item, index) in formData.academic"
:key="index"
class="education-resume-row"
>
<div class="table-col date-col">
<el-date-picker
v-model="item.education"
type="datetimerange"
start-placeholder="开始时间"
end-placeholder="结业时间"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
/>
</div>
<div class="table-col school-col">
<el-input v-model="item.institute" placeholder="请输入毕业院校" />
</div>
<div class="table-col major-col">
<el-input v-model="item.major" placeholder="请输入专业" />
</div>
<div class="table-col degree-col">
<el-select v-model="item.educationLevel" placeholder="请选择学历">
<el-option key="高中" label="高中" value="高中" />
<el-option key="大专" label="大专" value="大专" />
<el-option key="本科" label="本科" value="本科" />
<el-option key="硕士" label="硕士" value="硕士" />
<el-option key="博士" label="博士" value="博士" />
</el-select>
</div>
<div class="table-col action-col">
<el-button type="danger" @click="handleDelete(index)">删除</el-button>
</div>
</div>
</div>
<!-- 添加按钮 -->
<div class="education-resume-actions">
<el-button type="primary" @click="AddEducationalBackground">添加教育经历</el-button>
</div>
</div>
</el-form-item>
<el-form-item label="学历证书" prop="AcademicResume">
<el-upload
class="avatar-uploader"
action="#"
:auto-upload="false"
:show-file-list="false"
:on-change="(file) => handleFileSelect(file, 'AcademicResume')"
:before-upload="handleBeforeUpload"
>
<div v-if="formData.AcademicResume" class="upload-preview">
<span>{{ formData.AcademicResume.name }}</span>
<el-button type="danger" size="small" @click.stop="removeFile('AcademicResume')">
删除
</el-button>
</div>
<el-button v-else size="small" type="primary">点击选择文件</el-button>
</el-upload>
</el-form-item>
<el-form-item label="劳动合同" prop="contract">
<el-upload
class="avatar-uploader"
action="#"
:auto-upload="false"
:show-file-list="false"
:on-change="(file) => handleFileSelect(file, 'contract')"
:before-upload="handleBeforeUpload"
>
<div v-if="formData.contract" class="upload-preview">
<span>{{ formData.contract.name }}</span>
<el-button type="danger" size="small" @click.stop="removeFile('contract')">
删除
</el-button>
</div>
<el-button v-else size="small" type="primary">点击选择文件</el-button>
</el-upload>
</el-form-item>
<el-form-item label="入职申请表" prop="ApplicationForm">
<el-upload
class="avatar-uploader"
action="#"
:auto-upload="false"
:show-file-list="false"
:on-change="(file) => handleFileSelect(file, 'ApplicationForm')"
:before-upload="handleBeforeUpload"
>
<div v-if="formData.ApplicationForm" class="upload-preview">
<span>{{ formData.ApplicationForm.name }}</span>
<el-button type="danger" size="small" @click.stop="removeFile('ApplicationForm')">
删除
</el-button>
</div>
<el-button v-else size="small" type="primary">点击选择文件</el-button>
</el-upload>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleSubmit">确 定</el-button>
<el-button @click="handleCloseDialog">取 消</el-button>
</div>
</template>
</el-drawer>
<!-- 用户导入 -->
<UserImport v-model="importDialogVisible" @import-success="handleQuery()" />
</div>
</template>
<script setup lang="ts">
// ==================== 1. Vue 核心 API ====================
import { computed, onMounted, reactive, ref } from "vue";
import { useDebounceFn } from "@vueuse/core";
// ==================== 2. Element Plus ====================
import { ElMessage, ElMessageBox } from "element-plus";
// ==================== 3. 类型定义 ====================
import type { UserPageVO } from "@/api/system/user-api";
// ==================== 4. API 服务 ====================
import UserAPI from "@/api/system/user-api";
import DeptAPI from "@/api/system/dept-api";
import RoleAPI from "@/api/system/role-api";
// ==================== 5. Store ====================
import { useAppStore } from "@/store/modules/app-store";
import { useUserStore } from "@/store";
// ==================== 6. Enums ====================
import { DeviceEnum } from "@/enums/settings/device-enum";
// ==================== 7. Composables ====================
import { useTableSelection } from "@/composables";
// ==================== 8. 组件 ====================
import DeptTree from "./components/DeptTree.vue";
import UserImport from "./components/UserImport.vue";
import {
UserCreateUser,
UserEditorialStaff,
UserPersonnelList,
} from "@/api/calibration/personnelManagement";
import { convertFilePathsToObject } from "@/utils/auxiliaryFunction";
// ==================== 组件配置 ====================
defineOptions({
name: "SystemUser",
inheritAttrs: false,
});
// ==================== Store 实例 ====================
const appStore = useAppStore();
const userStore = useUserStore();
// ==================== 响应式状态 ====================
// DOM 引用
const queryFormRef = ref();
const userFormRef = ref();
// 列表查询参数
const queryParams = reactive<any>({
pageNum: 1,
pageSize: 10,
department: undefined,
username: "",
});
// 列表数据
const pageData = ref<any[]>([]);
const total = ref(0);
const loading = ref(false);
// 弹窗状态
const dialog = reactive({
visible: false,
title: "新增用户",
});
// 表单数据
const formData = reactive<any>({
account: "",
username: "",
password: "",
nation: "",
IdCard: "",
department: "",
mobilePhone: "",
position: "",
team: "",
Dateofjoining: "",
Confirmationtime: "",
Practicingcertificatetime: "",
AcademicResume: undefined,
academic: [
{
education: [],
institute: "",
major: "",
educationLevel: "",
},
],
contract: undefined,
ApplicationForm: undefined,
});
// 下拉选项数据
const deptOptions = ref<OptionType[]>();
const roleOptions = ref<OptionType[]>();
// 导入弹窗
const importDialogVisible = ref(false);
// ==================== 计算属性 ====================
/**
* 抽屉尺寸(响应式)
*/
const drawerSize = computed(() => (appStore.device === DeviceEnum.DESKTOP ? "600px" : "90%"));
// ==================== 表单验证规则 ====================
const rules = reactive({
username: [
{
required: true,
message: "用户名不能为空",
trigger: "blur",
},
],
account: [
{
required: true,
message: "用户昵称不能为空",
trigger: "blur",
},
],
password: [
{
required: true,
message: "密码不能为空",
trigger: "blur",
},
],
nation: [
{
required: true,
message: "民族不能为空",
trigger: "blur",
},
],
IdCard: [
{
required: true,
message: "身份证不能为空",
trigger: "blur",
},
],
department: [
{
required: true,
message: "归属部门不能为空",
trigger: "blur",
},
],
mobilePhone: [
{
required: true,
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
message: "请输入正确的手机号码",
trigger: "blur",
},
],
position: [
{
required: true,
message: "岗位不能为空",
trigger: "blur",
},
],
team: [
{
required: true,
message: "所属团队不能为空",
trigger: "blur",
},
],
Dateofjoining: [
{
required: true,
message: "入职时间不能为空",
trigger: "blur",
},
],
academic: [
{
required: true,
message: "学业简历不能为空",
trigger: "blur",
},
],
AcademicResume: [
{
required: true,
message: "学历证明不能为空",
trigger: "blur",
},
],
contract: [
{
required: true,
message: "合同不能为空",
trigger: "blur",
},
],
ApplicationForm: [
{
required: true,
message: "入职申请表不能为空",
trigger: "blur",
},
],
});
// ==================== 数据加载 ====================
/**
* 获取列表数据
*/
const fetchUserList = useDebounceFn(async () => {
if (!queryParams.department) return;
loading.value = true;
try {
const res: any = await UserPersonnelList(queryParams);
pageData.value = res.data;
total.value = res.total;
} catch (error) {
ElMessage.error("获取用户列表失败");
console.error("获取用户列表失败:", error);
} finally {
loading.value = false;
}
});
// ==================== 表格选择 ====================
const { selectedIds, hasSelection, handleSelectionChange } = useTableSelection<UserPageVO>();
// ==================== 查询操作 ====================
/**
* 查询用户列表
*/
function handleQuery(): Promise<void> {
queryParams.pageNum = 1;
return fetchUserList();
}
/**
* 重置查询条件
*/
function handleResetQuery(): void {
queryFormRef.value.resetFields();
queryParams.username = "";
handleQuery();
}
// ==================== 用户操作 ====================
/**
* 重置用户密码
* @param row 用户数据
*/
// function handleResetPassword(row: UserPageVO): void {
// ElMessageBox.prompt(`请输入用户【${row.username}】的新密码`, "重置密码", {
// confirmButtonText: "确定",
// cancelButtonText: "取消",
// inputPattern: /.{6,}/,
// inputErrorMessage: "密码至少需要6位字符",
// })
// .then(({ value }) => {
// return UserAPI.resetPassword(row.id, value);
// })
// .then(() => {
// ElMessage.success("密码重置成功");
// })
// .catch((error) => {
// if (error !== "cancel") {
// ElMessage.error("密码重置失败");
// }
// });
// }
// ==================== 弹窗操作 ====================
/**
* 打开用户表单弹窗
* @param id 用户ID编辑时传入
*/
async function handleOpenDialog(data?: any): Promise<void> {
dialog.visible = true;
// 并行加载下拉选项数据
try {
[roleOptions.value, deptOptions.value] = await Promise.all([
RoleAPI.getOptions(),
DeptAPI.getOptions(),
]);
} catch (error) {
ElMessage.error("加载选项数据失败");
console.error("加载选项数据失败:", error);
}
// 编辑:加载用户数据
if (data?.id) {
dialog.title = "修改用户";
try {
const data1 = deepCloneByJSON(data);
data1.academic = parseJsonToArray(data1.academic);
data1.AcademicResume = convertFilePathsToObject(JSON.parse(data1.AcademicResume))[0];
data1.contract = convertFilePathsToObject(JSON.parse(data1.contract))[0];
data1.ApplicationForm = convertFilePathsToObject(JSON.parse(data1.ApplicationForm))[0];
Object.assign(formData, data1);
} catch (error) {
ElMessage.error("加载用户数据失败");
console.error("加载用户数据失败:", error);
}
} else {
// 新增:设置默认值
dialog.title = "新增用户";
}
}
function deepCloneByJSON(obj: any) {
try {
return JSON.parse(JSON.stringify(obj));
} catch (error) {
console.error("深拷贝失败:", error);
return obj;
}
}
// 将 JSON 字符串转换为数组对象
function parseJsonToArray(jsonString: any) {
// 检查是否已经是对象
if (typeof jsonString === "object" && jsonString !== null) {
return Array.isArray(jsonString) ? jsonString : [jsonString];
}
// 检查是否为字符串
if (typeof jsonString === "string") {
try {
const parsed = JSON.parse(jsonString);
return Array.isArray(parsed) ? parsed : [parsed];
} catch (e) {
console.error("JSON解析失败:", e);
return [];
}
}
return [];
}
/**
* 关闭用户表单弹窗
*/
function handleCloseDialog(): void {
dialog.visible = false;
userFormRef.value.resetFields();
userFormRef.value.clearValidate();
// 重置表单数据
formData.id = undefined;
}
/**
* 提交用户表单(防抖)
*/
const handleSubmit = useDebounceFn(async () => {
const valid = await userFormRef.value.validate().catch(() => false);
if (!valid) return;
const userId = formData.id;
loading.value = true;
try {
if (userId) {
await UserEditorialStaff(formData);
ElMessage.success("修改用户成功");
} else {
await UserCreateUser(formData);
ElMessage.success("新增用户成功");
}
handleCloseDialog();
handleResetQuery();
} catch (error) {
ElMessage.error(userId ? "修改用户失败" : "新增用户失败");
console.error("提交用户表单失败:", error);
} finally {
loading.value = false;
}
}, 1000);
const AddEducationalBackground = () => {
formData.academic.push({
education: [],
institute: "",
major: "",
educationLevel: "",
});
};
/**
* 删除用户
* @param id 用户ID单个删除时传入
*/
function handleDelete(id?: string | number): void {
const userIds = id ? id : selectedIds.value.join(",");
if (!userIds) {
ElMessage.warning("请勾选删除项");
return;
}
// 安全检查:防止删除当前登录用户
const currentUserId = userStore.userInfo?.userId;
if (currentUserId) {
const isCurrentUserInList = id
? id === currentUserId
: selectedIds.value.some((selectedId) => String(selectedId) === currentUserId);
if (isCurrentUserInList) {
ElMessage.error("不能删除当前登录用户");
return;
}
}
ElMessageBox.confirm("确认删除选中的用户吗", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(async () => {
loading.value = true;
try {
await UserAPI.deleteByIds(userIds);
ElMessage.success("删除成功");
handleResetQuery();
} catch (error) {
ElMessage.error("删除失败");
console.error("删除用户失败:", error);
} finally {
loading.value = false;
}
})
.catch(() => {
// 用户取消操作,无需处理
});
}
// ==================== 上传文件 ====================
/**
* 处理文件选择
* @param file 选择的文件对象
* @param field 表单字段名
*/
function handleFileSelect(file: any, field: string): void {
// 将文件对象保存到表单数据中
formData[field] = file.raw; // file.raw 是实际的 File 对象
console.log(formData[field]);
userFormRef.value.clearValidate(field);
ElMessage.success("文件选择成功");
}
/**
* 上传前的校验
* @param file 上传的文件对象
*/
function handleBeforeUpload(file: File): boolean {
// 可以在这里添加文件类型和大小的校验
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
ElMessage.error("上传文件大小不能超过 10MB!");
return false;
}
return true;
}
/**
* 处理文件上传成功后的回调
* @param res 上传响应数据
* @param file 上传的文件对象
* @param field 表单字段名
*/
// function handleFileUploadSuccess(res: any, file: File, field: string): void {
// formData[field] = res.data.url;
// userFormRef.value.clearValidate(field);
// ElMessage.success("文件上传成功");
// }
/**
* 删除已上传的文件
* @param field 表单字段名
*/
function removeFile(field: string): void {
formData[field] = undefined;
ElMessage.success("文件已删除");
}
// ==================== 导入导出 ====================
/**
* 打开导入弹窗
*/
// function handleOpenImportDialog(): void {
// importDialogVisible.value = true;
// }
/**
* 导出用户列表
*/
async function handleExport(): Promise<void> {
try {
const response = await UserAPI.export(queryParams);
const fileData = response.data;
const contentDisposition = response.headers["content-disposition"];
const fileName = decodeURI(contentDisposition.split(";")[1].split("=")[1]);
const fileType =
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
// 创建下载链接
const blob = new Blob([fileData], { type: fileType });
const downloadUrl = window.URL.createObjectURL(blob);
const downloadLink = document.createElement("a");
downloadLink.href = downloadUrl;
downloadLink.download = fileName;
// 触发下载
document.body.appendChild(downloadLink);
downloadLink.click();
// 清理
document.body.removeChild(downloadLink);
window.URL.revokeObjectURL(downloadUrl);
ElMessage.success("导出成功");
} catch (error) {
ElMessage.error("导出失败");
console.error("导出用户列表失败:", error);
}
}
// ==================== 生命周期 ====================
/**
* 组件挂载时初始化数据
*
* 注意:这里会先加载列表数据,如果 URL 中有 AI 参数(如搜索关键字),
* useAiAction 会在 nextTick 中再次执行搜索,这是预期行为
*/
onMounted(() => {
handleQuery();
});
watch(
() => queryParams.department,
() => {
fetchUserList();
}
);
</script>
<!-- 学业简历表格样式 -->
<style scoped>
.education-resume-table {
flex: 1;
border: 1px solid #dcdfe6;
border-radius: 4px;
overflow: hidden;
}
.education-resume-header {
display: flex;
background-color: #f5f7fa;
border-bottom: 1px solid #dcdfe6;
font-weight: bold;
padding: 8px 12px;
}
.education-resume-row {
display: flex;
border-bottom: 1px solid #ebeef5;
padding: 12px;
align-items: center;
}
.education-resume-row:last-child {
border-bottom: none;
}
.table-col {
display: flex;
align-items: center;
}
.date-col {
width: 25%;
}
.school-col {
width: 25%;
}
.major-col {
width: 20%;
}
.degree-col {
width: 20%;
}
.action-col {
width: 10%;
justify-content: center;
}
.education-resume-actions {
margin-top: 12px;
display: flex;
justify-content: flex-start;
}
/* 表单元素样式调整 */
.education-resume-row .el-input,
.education-resume-row .el-select,
.education-resume-row .el-date-editor {
width: 100%;
}
</style>