This commit is contained in:
18631081161 2026-01-15 17:17:27 +08:00
parent a3f4714c09
commit 29cfc4d700
14 changed files with 613 additions and 31 deletions

View File

@ -229,6 +229,39 @@ public class AllocationsController : BaseApiController
}
}
/// <summary>
/// 上报消耗 - 更新单个分配记录的实际完成数量
/// 团部及以下单位可以上报自己的消耗数据
/// </summary>
[HttpPut("distributions/{distributionId}")]
public async Task<IActionResult> UpdateDistribution(int distributionId, [FromBody] UpdateDistributionRequest request)
{
var unitId = GetCurrentUnitId();
var userId = GetCurrentUserId();
if (unitId == null || userId == null)
return Unauthorized(new { message = "无法获取用户信息" });
try
{
var distribution = await _allocationService.UpdateDistributionCompletionAsync(
distributionId,
unitId.Value,
userId.Value,
request.ActualCompletion);
return Ok(MapDistributionToResponse(distribution));
}
catch (UnauthorizedAccessException ex)
{
return Forbid();
}
catch (ArgumentException ex)
{
return BadRequest(new { message = ex.Message });
}
}
/// <summary>
/// 删除物资配额
/// </summary>

View File

@ -162,6 +162,7 @@ public class PersonnelController : BaseApiController
var personnel = new Personnel
{
Name = request.Name,
Unit = request.Unit,
Position = request.Position,
Rank = request.Rank,
Gender = "男", // 默认值
@ -235,6 +236,7 @@ public class PersonnelController : BaseApiController
var personnel = new Personnel
{
Name = request.Name,
Unit = request.Unit,
Position = request.Position,
Rank = request.Rank,
Gender = "男", // 默认值

View File

@ -92,6 +92,19 @@ public class UpdateAllocationRequest
public decimal TotalQuota { get; set; }
}
/// <summary>
/// 更新配额分配实际完成数量请求(上报消耗)
/// </summary>
public class UpdateDistributionRequest
{
/// <summary>
/// 实际完成数量
/// </summary>
[Required(ErrorMessage = "实际完成数量为必填项")]
[Range(0, double.MaxValue, ErrorMessage = "实际完成数量不能为负数")]
public decimal ActualCompletion { get; set; }
}
/// <summary>
/// 物资配额响应
/// </summary>

View File

@ -12,6 +12,9 @@ public class CreatePersonnelRequest
[StringLength(50, MinimumLength = 2, ErrorMessage = "姓名长度应在2-50个字符之间")]
public string Name { get; set; } = string.Empty;
[StringLength(100, ErrorMessage = "单位长度不能超过100个字符")]
public string? Unit { get; set; }
[Required(ErrorMessage = "职位不能为空")]
[StringLength(100, ErrorMessage = "职位长度不能超过100个字符")]
public string Position { get; set; } = string.Empty;
@ -176,6 +179,9 @@ public class SubmitPersonnelRequest
[StringLength(50, MinimumLength = 2, ErrorMessage = "姓名长度应在2-50个字符之间")]
public string Name { get; set; } = string.Empty;
[StringLength(100, ErrorMessage = "单位长度不能超过100个字符")]
public string? Unit { get; set; }
[Required(ErrorMessage = "职位不能为空")]
[StringLength(100, ErrorMessage = "职位长度不能超过100个字符")]
public string Position { get; set; } = string.Empty;

View File

@ -10,6 +10,7 @@ public class Personnel
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? PhotoPath { get; set; }
public string? Unit { get; set; } // 单位
public string Position { get; set; } = string.Empty;
public string Rank { get; set; } = string.Empty;
public string Gender { get; set; } = string.Empty;

View File

@ -155,6 +155,25 @@ using (var scope = app.Services.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
var authService = scope.ServiceProvider.GetRequiredService<IAuthenticationService>();
var environment = scope.ServiceProvider.GetRequiredService<IWebHostEnvironment>();
// 确保uploads目录存在并有写入权限
try
{
var uploadsPath = Path.Combine(environment.WebRootPath ?? environment.ContentRootPath, "uploads");
var photosPath = Path.Combine(uploadsPath, "photos");
var documentsPath = Path.Combine(uploadsPath, "documents");
Directory.CreateDirectory(uploadsPath);
Directory.CreateDirectory(photosPath);
Directory.CreateDirectory(documentsPath);
Console.WriteLine($"Uploads 目录已创建: {uploadsPath}");
}
catch (Exception ex)
{
Console.WriteLine($"创建 uploads 目录时出错: {ex.Message}");
}
// 确保数据库已创建
context.Database.EnsureCreated();
@ -187,6 +206,9 @@ using (var scope = app.Services.CreateScope())
try
{
context.Database.ExecuteSqlRaw(@"
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'Unit')
ALTER TABLE Personnel ADD Unit nvarchar(100) NULL;
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('Personnel') AND name = 'Ethnicity')
ALTER TABLE Personnel ADD Ethnicity nvarchar(50) NULL;

View File

@ -58,13 +58,25 @@ public class AllocationService : IAllocationService
var allUnitIds = new HashSet<int>(subordinateIds) { unitId };
// 获取分配给这些单位的配额
return await _context.MaterialAllocations
var allocations = await _context.MaterialAllocations
.Include(a => a.CreatedByUnit)
.Include(a => a.Distributions)
.ThenInclude(d => d.TargetUnit)
.Include(a => a.Distributions)
.ThenInclude(d => d.ReportedByUser)
.Where(a => a.Distributions.Any(d => allUnitIds.Contains(d.TargetUnitId)))
.OrderByDescending(a => a.CreatedAt)
.ToListAsync();
// 过滤每个配额的分配记录,只保留分配给当前单位及其下级的记录
foreach (var allocation in allocations)
{
allocation.Distributions = allocation.Distributions
.Where(d => allUnitIds.Contains(d.TargetUnitId))
.ToList();
}
return allocations;
}
public async Task<IEnumerable<AllocationDistribution>> GetDistributionsForUnitAsync(int unitId)
@ -229,6 +241,42 @@ public class AllocationService : IAllocationService
return await GetByIdAsync(allocationId) ?? allocation;
}
public async Task<AllocationDistribution> UpdateDistributionCompletionAsync(
int distributionId,
int unitId,
int userId,
decimal actualCompletion)
{
var distribution = await _context.AllocationDistributions
.Include(d => d.Allocation)
.Include(d => d.TargetUnit)
.Include(d => d.ReportedByUser)
.FirstOrDefaultAsync(d => d.Id == distributionId);
if (distribution == null)
throw new ArgumentException("配额分配记录不存在");
// 验证权限:只能更新分配给自己单位的记录
if (distribution.TargetUnitId != unitId)
throw new UnauthorizedAccessException("无权更新此配额分配记录");
// 验证实际完成数量
if (actualCompletion < 0)
throw new ArgumentException("实际完成数量不能为负数");
if (actualCompletion > distribution.UnitQuota)
throw new ArgumentException($"实际完成数量不能超过分配配额({distribution.UnitQuota})");
// 更新实际完成数量
distribution.ActualCompletion = actualCompletion;
distribution.ReportedAt = DateTime.UtcNow;
distribution.ReportedByUserId = userId;
await _context.SaveChangesAsync();
return distribution;
}
public async Task DeleteAsync(int id)
{
var allocation = await _context.MaterialAllocations.FindAsync(id);

View File

@ -52,6 +52,11 @@ public interface IAllocationService
/// </summary>
Task<MaterialAllocation> UpdateDistributionsAsync(int allocationId, Dictionary<int, decimal> distributions);
/// <summary>
/// 更新单个分配记录的实际完成数量(上报消耗)
/// </summary>
Task<AllocationDistribution> UpdateDistributionCompletionAsync(int distributionId, int unitId, int userId, decimal actualCompletion);
/// <summary>
/// 删除物资配额
/// </summary>

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

View File

@ -53,6 +53,12 @@ const routes: RouteRecordRaw[] = [
component: () => import('@/views/allocations/AllocationForm.vue'),
meta: { title: '编辑配额', minLevel: 1 }
},
{
path: 'allocations/:id/report',
name: 'AllocationReport',
component: () => import('@/views/allocations/AllocationReport.vue'),
meta: { title: '上报消耗' }
},
{
path: 'reports',
name: 'Reports',

View File

@ -203,6 +203,18 @@
<span class="time-cell">{{ row.reportedAt ? formatDate(row.reportedAt) : '-' }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100" align="center">
<template #default="{ row }">
<el-button
v-if="canReportConsumption(row)"
type="primary"
size="small"
@click="handleReportConsumption(row)"
>
上报消耗
</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
@ -280,6 +292,23 @@ function getTotalDistributed(): number {
return distributions.value.reduce((sum, d) => sum + (d.unitQuota || 0), 0)
}
function canReportConsumption(distribution: AllocationDistribution): boolean {
//
if (!authStore.user) return false
return distribution.targetUnitId === authStore.user.organizationalUnitId
}
function handleReportConsumption(distribution: AllocationDistribution) {
if (!selectedAllocation.value) return
router.push({
path: `/allocations/${selectedAllocation.value.id}/report`,
query: {
distributionId: distribution.id,
targetUnitId: distribution.targetUnitId
}
})
}
function handleSearch() {
pagination.pageNumber = 1
}

View File

@ -0,0 +1,393 @@
<template>
<div class="allocation-report">
<el-card class="report-card" shadow="hover">
<template #header>
<div class="card-header">
<div class="header-title">
<el-icon class="title-icon" :size="22"><DocumentAdd /></el-icon>
<span>上报消耗</span>
</div>
<el-button @click="handleBack">
<el-icon><Back /></el-icon>
返回
</el-button>
</div>
</template>
<div v-if="loading" class="loading-container">
<el-skeleton :rows="6" animated />
</div>
<div v-else-if="distribution" class="report-content">
<!-- 配额信息 -->
<div class="info-section">
<h3 class="section-title">配额信息</h3>
<el-descriptions :column="2" border>
<el-descriptions-item label="物资名称">
<span class="material-name">{{ allocation?.materialName }}</span>
</el-descriptions-item>
<el-descriptions-item label="物资类别">
<el-tag :type="getCategoryTagType(allocation?.category)" size="small">
{{ allocation?.category }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="单位">
{{ allocation?.unit }}
</el-descriptions-item>
<el-descriptions-item label="目标单位">
{{ distribution.targetUnitName }}
</el-descriptions-item>
<el-descriptions-item label="分配配额">
<span class="quota-value">{{ formatNumber(distribution.unitQuota) }} {{ allocation?.unit }}</span>
</el-descriptions-item>
<el-descriptions-item label="当前完成">
<span :class="['completion-value', distribution.actualCompletion ? '' : 'no-data']">
{{ distribution.actualCompletion ? formatNumber(distribution.actualCompletion) : '未上报' }}
</span>
</el-descriptions-item>
</el-descriptions>
</div>
<!-- 上报表单 -->
<div class="form-section">
<h3 class="section-title">消耗数据</h3>
<el-form
ref="formRef"
:model="form"
:rules="rules"
label-width="120px"
@submit.prevent="handleSubmit"
>
<el-form-item label="实际完成数量" prop="actualCompletion">
<el-input-number
v-model="form.actualCompletion"
:min="0"
:max="distribution.unitQuota"
:precision="2"
:step="1"
style="width: 300px"
/>
<span class="unit-hint">{{ allocation?.unit }}</span>
</el-form-item>
<el-form-item label="完成率">
<div class="completion-rate">
<el-progress
:percentage="getCompletionPercentage()"
:status="getProgressStatus()"
:stroke-width="20"
style="width: 300px"
/>
<span class="rate-text">{{ getCompletionPercentage() }}%</span>
</div>
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input
v-model="form.remarks"
type="textarea"
:rows="4"
placeholder="请输入备注信息(可选)"
maxlength="500"
show-word-limit
style="width: 500px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" :loading="submitting" @click="handleSubmit">
<el-icon><Check /></el-icon>
提交上报
</el-button>
<el-button @click="handleBack">
<el-icon><Close /></el-icon>
取消
</el-button>
</el-form-item>
</el-form>
</div>
<!-- 历史记录 -->
<div v-if="distribution.reportedAt" class="history-section">
<h3 class="section-title">上报历史</h3>
<el-alert
type="info"
:closable="false"
show-icon
>
<template #title>
<span>上次上报时间: {{ formatDate(distribution.reportedAt) }}</span>
</template>
<div>上次上报数量: {{ formatNumber(distribution.actualCompletion || 0) }} {{ allocation?.unit }}</div>
</el-alert>
</div>
</div>
<el-empty v-else description="未找到配额分配信息" />
</el-card>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, computed, onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { DocumentAdd, Back, Check, Close } from '@element-plus/icons-vue'
import { allocationsApi } from '@/api'
import type { MaterialAllocation, AllocationDistribution } from '@/types'
const router = useRouter()
const route = useRoute()
const loading = ref(false)
const submitting = ref(false)
const allocation = ref<MaterialAllocation | null>(null)
const distribution = ref<AllocationDistribution | null>(null)
const formRef = ref<FormInstance>()
const form = reactive({
actualCompletion: 0,
remarks: ''
})
const rules: FormRules = {
actualCompletion: [
{ required: true, message: '请输入实际完成数量', trigger: 'blur' },
{
type: 'number',
min: 0,
message: '数量不能小于0',
trigger: 'blur'
},
{
validator: (_rule, value, callback) => {
if (value > (distribution.value?.unitQuota || 0)) {
callback(new Error(`数量不能超过分配配额 ${distribution.value?.unitQuota}`))
} else {
callback()
}
},
trigger: 'blur'
}
]
}
function formatDate(dateStr: string): string {
return new Date(dateStr).toLocaleString('zh-CN')
}
function formatNumber(num: number): string {
return num.toLocaleString('zh-CN')
}
function getCategoryTagType(category?: string): string {
switch (category) {
case '弹药': return 'danger'
case '装备': return 'warning'
case '物资': return 'success'
case '器材': return 'info'
default: return ''
}
}
function getCompletionPercentage(): number {
if (!distribution.value || !form.actualCompletion) return 0
return Math.round((form.actualCompletion / distribution.value.unitQuota) * 100)
}
function getProgressStatus(): string {
const percentage = getCompletionPercentage()
if (percentage >= 100) return 'success'
if (percentage >= 60) return ''
return 'warning'
}
function handleBack() {
router.back()
}
async function handleSubmit() {
if (!formRef.value) return
try {
await formRef.value.validate()
await ElMessageBox.confirm(
`确认上报实际完成数量为 ${form.actualCompletion} ${allocation.value?.unit} 吗?`,
'确认上报',
{
type: 'warning',
confirmButtonText: '确认上报',
cancelButtonText: '取消'
}
)
submitting.value = true
if (!distribution.value) return
await allocationsApi.updateDistribution(distribution.value.id, {
actualCompletion: form.actualCompletion
})
ElMessage.success('上报成功')
router.back()
} catch (error: any) {
if (error !== 'cancel') {
ElMessage.error(error.response?.data?.message || '上报失败')
}
} finally {
submitting.value = false
}
}
async function loadData() {
loading.value = true
try {
const allocationId = Number(route.params.id)
const distributionId = Number(route.query.distributionId)
if (!allocationId || !distributionId) {
ElMessage.error('参数错误')
router.back()
return
}
// ()
allocation.value = await allocationsApi.getById(allocationId)
//
distribution.value = allocation.value.distributions?.find(d => d.id === distributionId) || null
if (!distribution.value) {
ElMessage.error('未找到配额分配信息')
router.back()
return
}
// ,
if (distribution.value.actualCompletion) {
form.actualCompletion = distribution.value.actualCompletion
}
} catch {
ElMessage.error('加载数据失败')
router.back()
} finally {
loading.value = false
}
}
onMounted(() => {
loadData()
})
</script>
<style scoped>
.allocation-report {
padding: 0;
}
.report-card {
border-radius: 8px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.header-title {
display: flex;
align-items: center;
font-size: 18px;
font-weight: 600;
color: #303133;
}
.title-icon {
margin-right: 8px;
color: #409EFF;
}
.loading-container {
padding: 20px;
}
.report-content {
padding: 0;
}
.info-section,
.form-section,
.history-section {
margin-bottom: 30px;
}
.section-title {
font-size: 16px;
font-weight: 600;
color: #303133;
margin-bottom: 16px;
padding-bottom: 8px;
border-bottom: 2px solid #409EFF;
}
.material-name {
font-weight: 600;
color: #303133;
}
.quota-value {
font-weight: 600;
color: #409EFF;
font-size: 14px;
}
.completion-value {
font-weight: 500;
color: #67C23A;
}
.completion-value.no-data {
color: #C0C4CC;
font-weight: normal;
}
.unit-hint {
margin-left: 12px;
color: #909399;
font-size: 14px;
}
.completion-rate {
display: flex;
align-items: center;
gap: 16px;
}
.rate-text {
font-size: 16px;
font-weight: 600;
color: #409EFF;
min-width: 50px;
}
:deep(.el-card__header) {
padding: 16px 20px;
border-bottom: 1px solid #ebeef5;
}
:deep(.el-descriptions) {
margin-top: 0;
}
:deep(.el-descriptions__label) {
width: 120px;
background-color: #fafafa;
}
:deep(.el-form-item__label) {
font-weight: 500;
}
</style>

View File

@ -27,36 +27,38 @@
<el-col :span="18">
<el-descriptions :column="3" border>
<el-descriptions-item label="姓名">{{ person.name }}</el-descriptions-item>
<el-descriptions-item label="性别">{{ person.gender }}</el-descriptions-item>
<el-descriptions-item label="年龄">{{ person.age }}</el-descriptions-item>
<el-descriptions-item label="身份证号">{{ person.idNumber }}</el-descriptions-item>
<el-descriptions-item label="联系方式">{{ person.contactInfo }}</el-descriptions-item>
<el-descriptions-item label="籍贯">{{ person.hometown }}</el-descriptions-item>
<el-descriptions-item label="职位">{{ person.position }}</el-descriptions-item>
<el-descriptions-item label="单位">{{ person.unit || '-' }}</el-descriptions-item>
<el-descriptions-item label="部职别">{{ person.position }}</el-descriptions-item>
<el-descriptions-item label="军衔">{{ person.rank }}</el-descriptions-item>
<el-descriptions-item label="专业职位">{{ person.professionalTitle }}</el-descriptions-item>
<el-descriptions-item label="文化程度">{{ person.educationLevel }}</el-descriptions-item>
<el-descriptions-item label="身高">{{ person.height }} cm</el-descriptions-item>
<el-descriptions-item label="士兵证号">{{ person.idNumber || '-' }}</el-descriptions-item>
<el-descriptions-item label="专业岗位">{{ person.professionalTitle || '-' }}</el-descriptions-item>
<el-descriptions-item label="政治面貌">{{ person.politicalStatus || '-' }}</el-descriptions-item>
<el-descriptions-item label="文化程度">{{ person.educationLevel || '-' }}</el-descriptions-item>
<el-descriptions-item label="民族">{{ person.ethnicity || '-' }}</el-descriptions-item>
<el-descriptions-item label="籍贯">{{ person.hometown || '-' }}</el-descriptions-item>
<el-descriptions-item label="出生年月">{{ person.birthDate || '-' }}</el-descriptions-item>
<el-descriptions-item label="入伍年月">{{ person.enlistmentDate || '-' }}</el-descriptions-item>
<el-descriptions-item label="特长" :span="3">{{ person.specialty || '-' }}</el-descriptions-item>
<el-descriptions-item label="人员等级">
<el-tag v-if="person.approvedLevel" :type="getLevelTagType(person.approvedLevel)">
{{ getLevelName(person.approvedLevel) }}
</el-tag>
<span v-else>-</span>
</el-descriptions-item>
<el-descriptions-item label="提交单位" :span="2">{{ person.submittedByUnitName }}</el-descriptions-item>
<el-descriptions-item label="提交单位">{{ person.submittedByUnitName }}</el-descriptions-item>
<el-descriptions-item label="审批单位">{{ person.approvedByUnitName || '-' }}</el-descriptions-item>
<el-descriptions-item label="提交时间" :span="2">{{ formatDate(person.submittedAt) }}</el-descriptions-item>
<el-descriptions-item label="审批时间">{{ person.approvedAt ? formatDate(person.approvedAt) : '-' }}</el-descriptions-item>
<el-descriptions-item label="提交时间">{{ formatDate(person.submittedAt) }}</el-descriptions-item>
<el-descriptions-item label="审批时间" :span="2">{{ person.approvedAt ? formatDate(person.approvedAt) : '-' }}</el-descriptions-item>
</el-descriptions>
<el-divider />
<el-descriptions :column="1" border>
<el-descriptions-item label="参加培训情况">
<div class="text-content">{{ person.trainingParticipation }}</div>
<div class="text-content">{{ person.trainingParticipation || '-' }}</div>
</el-descriptions-item>
<el-descriptions-item label="取得成绩">
<div class="text-content">{{ person.achievements }}</div>
<div class="text-content">{{ person.achievements || '-' }}</div>
</el-descriptions-item>
</el-descriptions>
@ -195,4 +197,10 @@ onMounted(() => {
margin-bottom: 12px;
color: #303133;
}
/* 缩短标签列宽度 */
:deep(.el-descriptions__label) {
width: 120px !important;
min-width: 120px !important;
}
</style>

View File

@ -33,32 +33,37 @@
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="单位" prop="unit">
<el-input v-model="form.unit" placeholder="请输入单位" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="部职别" prop="position">
<el-input v-model="form.position" placeholder="请输入部职别" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="军衔" prop="rank">
<el-input v-model="form.rank" placeholder="请输入军衔" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="士兵证号" prop="idNumber">
<el-input v-model="form.idNumber" placeholder="请输入士兵证号" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="专业岗位" prop="professionalTitle">
<el-input v-model="form.professionalTitle" placeholder="请输入专业岗位" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="政治面貌" prop="politicalStatus">
<el-select v-model="form.politicalStatus" placeholder="请选择政治面貌" style="width: 100%">
@ -69,6 +74,9 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="文化程度" prop="educationLevel">
<el-select v-model="form.educationLevel" placeholder="请选择文化程度" style="width: 100%">
@ -82,22 +90,19 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="民族" prop="ethnicity">
<el-input v-model="form.ethnicity" placeholder="请输入民族" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="籍贯" prop="hometown">
<el-input v-model="form.hometown" placeholder="请输入籍贯" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="出生年月" prop="birthDate">
<el-date-picker
@ -110,6 +115,9 @@
/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="入伍年月" prop="enlistmentDate">
<el-date-picker
@ -122,12 +130,13 @@
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="特长" prop="specialty">
<el-input v-model="form.specialty" placeholder="请输入特长" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="特长" prop="specialty">
<el-input v-model="form.specialty" placeholder="请输入特长" />
</el-form-item>
<el-form-item label="参加培训、集训情况" prop="trainingParticipation">
<el-input v-model="form.trainingParticipation" type="textarea" :rows="3" placeholder="请输入参加培训、集训情况" />
</el-form-item>
@ -185,6 +194,7 @@ const documentList = ref<UploadFile[]>([])
const form = reactive({
name: '',
unit: '',
position: '',
rank: '',
idNumber: '',
@ -205,6 +215,10 @@ const rules: FormRules = {
{ required: true, message: '请输入姓名', trigger: 'blur' },
{ min: 2, max: 50, message: '姓名长度应在2-50个字符之间', trigger: 'blur' }
],
unit: [
{ required: true, message: '请输入单位', trigger: 'blur' },
{ max: 100, message: '单位长度不能超过100个字符', trigger: 'blur' }
],
position: [
{ required: true, message: '请输入部职别', trigger: 'blur' },
{ max: 100, message: '部职别长度不能超过100个字符', trigger: 'blur' }
@ -283,6 +297,7 @@ async function loadPersonnel() {
try {
const person = await personnelApi.getById(Number(route.params.id))
form.name = person.name
form.unit = person.unit || ''
form.position = person.position
form.rank = person.rank
form.idNumber = person.idNumber || ''
@ -338,6 +353,7 @@ async function handleSubmit() {
formData.append('rank', form.rank)
// -
if (form.unit) formData.append('unit', form.unit)
if (form.idNumber) formData.append('idNumber', form.idNumber)
if (form.professionalTitle) formData.append('professionalTitle', form.professionalTitle)
if (form.politicalStatus) formData.append('politicalStatus', form.politicalStatus)